Strut2 Determine whether it is an AJAX call
1. AJAX and traditional Form form
In fact, both are generally POST requests through HTTP. The difference is that after the browser submits the Form, it expects the server to return a complete HTML page. The AJAX call is issued by the XMLHttpRequest object (different browsers may be different). The browser expects the server to return an HTML fragment. Specifically, there are no requirements for JSON, XML, etc. How to use it after returning to the browser is also determined by the JS script itself.
2. Whether the request is AJAX
So for the server side, how to determine whether an HTTP request is an AJAX call? This requires looking at the HTTP Header.
We can judge by x-request-with in the Header. Although different browsers send AJAX requests to different objects, if jQuery is used to send AJAX requests, the identifier has been added when jQuery implements ajax internally. The jQuery source code looks like this: xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
So, if the front-end page of the project sends AJAX requests through jQuery, this judgment is safe.
The following is the Header information carried by the HTTP request.
Normal Form form submission
===MimeHeaders === accept = */* referer =http://localhost:8080/user2/toQueryPage.action accept-language = zh-CN user-agent = Mozilla/4.0 (compatible; MSIE8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C;.NET4.0E) accept-encoding = gzip, deflate host = localhost:8080 connection = Keep-Alive cache-control = no-cache
AJAX call (IE)
===MimeHeaders === x-requested-with = XMLHttpRequest accept-language = zh-cn referer =http://localhost:8080/user2/toQueryPage.action accept = application/json, text/javascript,*/*; q=0.01 content-type =application/x-www-form-urlencoded accept-encoding = gzip, deflate user-agent = Mozilla/4.0 (compatible; MSIE8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C;.NET4.0E) host = localhost:8080 content-length = 57 connection = Keep-Alive cache-control = no-cache
##3. Obtained in Action HTTP request header
In the Action class, obtain the HttpServletRequest object through the ServletRequestAware interface, and then obtain the header information we want through the getHeader method.
public abstract class BaseAction <ParamVo extends BaseParamVo, ResultVo extends BaseResultVo> extends ActionSupport implements ServletRequestAware { private static final String AJAX_RESULT_NAME = "ajaxResult"; private static final String XHR_OBJECT_NAME = "XMLHttpRequest"; private static final String HEADER_REQUEST_WITH = "x-requested-with"; /** * Request对象,用来判断请求是否是AJAX调用 */ private HttpServletRequest request; private ParamVo paramVo; private ResultVo resultVo; @Override public String execute() { String resultPage = SUCCESS; try { resultVo = doExecute(paramVo); } catch (BaseException e) { resultPage = ERROR; } if (XHR_OBJECT_NAME.equals(request.getHeader(HEADER_REQUEST_WITH))) { resultPage = AJAX_RESULT_NAME; } return resultPage; } }
When we need to implement some small requirements at work, we might as well conduct a simple survey first and see Does the open source framework we are using already have the functions we need, so we don’t have to reinvent the wheel?
Let’s take performance testing as an example to see how to investigate whether the Struts2 framework has this function.
<span style="white-space:pre"> </span><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"/> <interceptornameinterceptorname="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" />
2. ProfilingActivationInterceptor
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(); } }
From source code As can be seen in , as long as the HTTP request parameter sent by the browser contains profiling=true or yes, the performance interceptor will open the Timer tool class and print out the execution time of the Action.
<package name="ajax-default" extends="velocity-default"> <result-types> <result-type name="json" class="org.apache.struts2.json.JSONResult"/> </result-types> <interceptors> <interceptor-stacknameinterceptor-stackname="ajaxInterceptorStack"> <interceptor-refnameinterceptor-refname="defaultStack" /> <interceptor-ref name="profiling"/> </interceptor-stack> </interceptors> <default-interceptor-refnamedefault-interceptor-refname="ajaxInterceptorStack" /> <global-results> <result name="comAjaxResult" type="json"> <param name="excludeNullProperties">true</param> <param name="root">result</param> <param name="ignoreHierarchy">false</param> </result> </global-results> </package>
function searchAllUser(){ jQuery.ajax({ type:"post", url: "searchAllUser.action", processData:true, dataType:'json', data:jQuery("#userQueryForm").serialize() + "&profiling=yes", success:function(data) { if (data.status == 1) { alert("创建成功"); generateTableFromJson("result", data.resultRows); } else { alert("创建失败"); } } }); }
5. The final effect
The printed result is as follows. In addition to the total execution time, the execution time of the Action method and the rendering time of the Result will be listed separately.