UtilTimerStatck类:用于记录代码执行的时间工具类
ProfilingTimerBean类:javabean类,包含一些startTime,totalTime,resource,parent,children等属性
用于时间的记录以及堆栈的实现。
使用步骤:
1.struts2配置文件配置:<constant name="struts.devMode" value="true"/>
2.在指定的action中进行配置:
<interceptor-ref name="profiling">
<param name="profilingKey">profiling</param>
</interceptor-ref>
3.访问时例如:http://localhost:8000/StrutsStudy/action001.do?profiling=true
结果:
[2000ms] - EncodingFilter_doFilter:
[2000ms] - FilterDispatcher_doFilter:
[2000ms] - Handling request from Dispatcher
[0ms] - create DefaultActionProxy:
[0ms] - create DefaultActionInvocation:
[0ms] - actionCreate: action001
[2000ms] - invoke:
[2000ms] - interceptor: profiling
[2000ms] - invoke:
[2000ms] - invokeAction: action001
[0ms] - executeResult: success
源码如下:
UtilTimerStack类:
public class UtilTimerStack
{
// A reference to the current ProfilingTimerBean
protected static ThreadLocal<ProfilingTimerBean> current = new ThreadLocal<ProfilingTimerBean>();
/**
* System property that controls whether this timer should be used or not. Set to "true" activates
* the timer. Set to "false" to disactivate.
*/
public static final String ACTIVATE_PROPERTY = "xwork.profile.activate";
/**
* System property that controls the min time, that if exceeded will cause a log (at INFO level) to be
* created.
*/
public static final String MIN_TIME = "xwork.profile.mintime";
private static final Log log = LogFactory.getLog(UtilTimerStack.class);
/**
* Create and start a performance profiling with the <code>name</code> given. Deal with
* profile hierarchy automatically, so caller don't have to be concern about it.
*
*
*
*
*
* @param name profile name
*/
public static void push(String name)
{ //判断该诊断工具是否激活
if (!isActive())
return;
//create a new timer and start it
//本地线程变量-相关时间配置bean
ProfilingTimerBean newTimer = new ProfilingTimerBean(name);
newTimer.setStartTime();
//if there is a current timer - add the new timer as a child of it
//如果当前线程未绑定,那么进行绑定,否则直接获取
ProfilingTimerBean currentTimer = (ProfilingTimerBean) current.get();
if (currentTimer != null)
{
//当且仅当继续使用本地线程并同时调用push操作时,即添加其儿子节点,并同时添加当前儿子节点的父节点
/**
*很给力的设计:更改currentTimer(bean)的内容(添加子节点),同时将该父亲bean添加到newTimer中去
* 因此我觉得bean的设计不是树的结构,而是堆栈的思路
* public void addChild(ProfilingTimerBean child){
children.add(child);
child.addParent(this);
}
*/
currentTimer.addChild(newTimer);
}
//set the new timer to be the current timer
//设置新的线程变量
current.set(newTimer);
}
/**
* End a preformance profiling with the <code>name</code> given. Deal with
* profile hierarchy automatically, so caller don't have to be concern about it.
*
* @param name profile name
*/
public static void pop(String name)
{
if (!isActive())
return;
//获取本地线程变量bean
ProfilingTimerBean currentTimer = (ProfilingTimerBean) current.get();
//if the timers are matched up with each other (ie push("a"); pop("a"));
if (currentTimer != null && name != null && name.equals(currentTimer.getResource()))
{
//设置本地线程变量bean的终结时间
currentTimer.setEndTime();
ProfilingTimerBean parent = currentTimer.getParent();
//if we are the root timer, then print out the times
if (parent == null)
{
//且只有当线程变量的父节点为null时,才会答应
printTimes(currentTimer);
current.set(null); //for those servers that use thread pooling
}
else
{
current.set(parent);
}
}
else
{
//if timers are not matched up, then print what we have, and then print warning.
if (currentTimer != null)
{
printTimes(currentTimer);
current.set(null); //prevent printing multiple times
log.warn("Unmatched Timer. Was expecting " + currentTimer.getResource() + ", instead got " + name);
}
}
}
/**
* Do a log (at INFO level) of the time taken for this particular profiling.
*
* @param currentTimer profiling timer bean
*/
private static void printTimes(ProfilingTimerBean currentTimer)
{
log.info(currentTimer.getPrintable(getMinTime()));
}
/**
* Get the min time for this profiling, it searches for a System property
* 'xwork.profile.mintime' and default to 0.
*
* @return long
*/
private static long getMinTime()
{
try
{
return Long.parseLong(System.getProperty(MIN_TIME, "0"));
}
catch (NumberFormatException e)
{
return -1;
}
}
/**
* Determine if profiling is being activated, by searching for a system property
* 'xwork.profile.activate', default to false (profiling is off).
*
* @return <tt>true</tt>, if active, <tt>false</tt> otherwise.
*/
public static boolean isActive()
{
return System.getProperty(ACTIVATE_PROPERTY) != null;
}
/**
* Turn profiling on or off.
* 诊断工具开启与否的设计,通过System.setProperty
* @param active
*/
public static void setActive(boolean active)
{
if (active)
System.setProperty(ACTIVATE_PROPERTY, "true");
else
System.clearProperty(ACTIVATE_PROPERTY);
}
/**
* A convenience method that allows <code>block</code> of code subjected to profiling to be executed
* and avoid the need of coding boiler code that does pushing (UtilTimeBean.push(...)) and
* poping (UtilTimerBean.pop(...)) in a try ... finally ... block.
*
* <p/>
*
* Example of usage:
* <pre>
* // we need a returning result
* String result = UtilTimerStack.profile("purchaseItem: ",
* new UtilTimerStack.ProfilingBlock<String>() {
* public String doProfiling() {
* getMyService().purchaseItem(....)
* return "Ok";
* }
* });
* </pre>
* or
* <pre>
* // we don't need a returning result
* UtilTimerStack.profile("purchaseItem: ",
* new UtilTimerStack.ProfilingBlock<String>() {
* public String doProfiling() {
* getMyService().purchaseItem(....)
* return null;
* }
* });
* </pre>
*
* @param <T> any return value if there's one.
* @param name profile name
* @param block code block subjected to profiling
* @return T
* @throws Exception
*/
public static <T> T profile(String name, ProfilingBlock<T> block) throws Exception {
UtilTimerStack.push(name);
try {
return block.doProfiling();
}
finally {
UtilTimerStack.pop(name);
}
}
/**
* A callback interface where code subjected to profile is to be executed. This eliminates the need
* of coding boiler code that does pushing (UtilTimerBean.push(...)) and poping (UtilTimerBean.pop(...))
* in a try ... finally ... block.
*
* @version $Date$ $Id$
*
* @param <T>
*/
public static interface ProfilingBlock<T> {
/**
* Method that execute the code subjected to profiling.
*
* @return profiles Type
* @throws Exception
*/
T doProfiling() throws Exception;
}
}
ProfilingTimerBean类:这个类比较容易看懂,因此未加任何注释。
public class ProfilingTimerBean implements java.io.Serializable {
private static final long serialVersionUID = -6180672043920208784L;
List<ProfilingTimerBean> children = new ArrayList<ProfilingTimerBean>();
ProfilingTimerBean parent = null;
String resource;
long startTime;
long totalTime;
public ProfilingTimerBean(String resource)
{
this.resource = resource;
}
protected void addParent(ProfilingTimerBean parent)
{
this.parent = parent;
}
public ProfilingTimerBean getParent()
{
return parent;
}
public void addChild(ProfilingTimerBean child)
{
children.add(child);
child.addParent(this);
}
public void setStartTime()
{
this.startTime = System.currentTimeMillis();
}
public void setEndTime()
{
this.totalTime = System.currentTimeMillis() - startTime;
}
public String getResource()
{
return resource;
}
/**
* Get a formatted string representing all the methods that took longer than a specified time.
*/
public String getPrintable(long minTime)
{
return getPrintable("", minTime);
}
protected String getPrintable(String indent, long minTime)
{
//only print the value if we are larger or equal to the min time.
if (totalTime >= minTime)
{
StringBuffer buffer = new StringBuffer();
buffer.append(indent);
buffer.append("[" + totalTime + "ms] - " + resource);
buffer.append("\n");
Iterator childrenIt = children.iterator();
while (childrenIt.hasNext())
{
buffer.append(((ProfilingTimerBean) childrenIt.next()).getPrintable(indent + " ", minTime));
}
return buffer.toString();
}
else
return "";
}
}
总结:需慢慢回味:
1.栈的设计思路
2.ThreadLocal的理解使用(同步访问解决的新思路)
3.设置启动与否的新思路(System.property)
4.log4g的简单使用
分享到:
相关推荐
Struts2源码阅读
struts2 源码分析struts2 源码分析struts2 源码分析struts2 源码分析struts2 源码分析struts2 源码分析
struts2 源码绝对完整,struts2 源码绝对完整。
struts2源码 struts2案例 struts2使用包
struts4 使用Struts2中内部类中的方法进行自定义类型转换,用到的类StrutsTypeConverter struts5 增加集合类型,使用范型 struts6 直接设置要进行类型转换的字段值 struts7 制作一个表单,对表单中的内容进行...
struts2源码struts2源码struts2源码
struts源码struts源码struts源码struts源码
struts2源码分析总结 是我在网上找到的关于源码讲解比较深刻的资料总结。对于研究struts2源码很有价值。
struts2源码详细解析51CTO下载-struts2源代码分析(个人觉得非常经典)
Struts2源码,让你一眼看穿struts2的原理和运行机制
STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析...
java最新struts2源码,刚才github官网下载:https://github.com/apache/struts
struts2.1.8 struts2源码 Eclipse关联这个可以
struts2源码解析.pdf
已struts 2 源码 导入eclipse工程
struts2学习笔记和源码,struts2原理。文件上传、i18n等等
Strut2源码分析,写的非常好, 喜欢Struts2的人可以看一看
struts2源码还有插件源码xwork-core源码
内容简介 Struts 2 是Java Web 应用首选的MVC 框架。《深入浅出Struts2》对Struts 2 的工作机理进行了透彻的阐述。...《深入浅出Struts2》适合Java Web 程序员阅读和参考,也可以作为计算机相关专业教材。