當我們在工作中需要實現某些小需求時,不妨先進行下簡單的調研,看看正在使用的開源框架是否已經具備了我們需要的功能,這樣就不用重復發明輪子了。
下面以性能測試為例,看看如何調查Struts2框架是否具備這種功能。
1. struts-default.xml
因為Struts2的許多核心功能都是基於內部攔截器來實現的,所以我們首先要看看它是否有性能調優相關的攔截器。這就需要查看strut2-core-2.3.1.2.jar中的默認配置文件struts-default.xml了。
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
<interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>
<interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />
<interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />
<interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
<interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
<interceptorname="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>
<interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
<interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />
<interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />
<interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
<interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />
<interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />
<interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />
Struts2像個百寶箱一樣內置了很多攔截器,可以看到profiling很可能就是符合我們需求的攔截器,那現在就打開源碼一探究竟。
2. ProfilingActivationInterceptor
org.apache.struts2.interceptor.ProfilingActivationInterceptor.java
public class ProfilingActivationInterceptor extendsAbstractInterceptor {
private String profilingKey = "profiling";
private boolean devMode;
@Inject(StrutsConstants.STRUTS_DEVMODE)
public void setDevMode(String mode) {
this.devMode = "true".equals(mode);
}
@Override
public String intercept(ActionInvocationinvocation) throws Exception {
if (devMode) {
Object val =invocation.getInvocationContext().getParameters().get(profilingKey);
if (val != null) {
String sval = (val instanceof String ?(String)val : ((String[])val)[0]);
boolean enable = "yes".equalsIgnoreCase(sval)|| "true".equalsIgnoreCase(sval);
UtilTimerStack.setActive(enable);
invocation.getInvocationContext().getParameters().remove(profilingKey);
}
}
return invocation.invoke();
}
}
從源碼中可以看到,只要浏覽器發過來的HTTP請求參數中包含profiling=true或者yes,性能攔截器就會開啟Timer工具類,打印出Action的執行消耗時間。