在Java的Struts中判斷是否調(diào)用AJAX及用攔截器對其優(yōu)化
Strut2判斷是否是AJAX調(diào)用
1. AJAX與傳統(tǒng)Form表單
實際上,兩者一般都是通過HTTP的POST請求。區(qū)別是瀏覽器提交Form表單后,期望服務(wù)器返回一個完整的HTML頁面。而AJAX調(diào)用是由XMLHttpRequest對象(不同瀏覽器可能不一樣)發(fā)出,瀏覽器期望服務(wù)器返回HTML片段即可,具體是JSON、XML等都沒有要求。返回到瀏覽器后如何使用,也是由JS腳本自己決定的。
2. 請求是不是AJAX
那么對于服務(wù)器端,如何判斷一個HTTP請求是不是AJAX調(diào)用?這需要看HTTP的Header。
我們可以通過Header中的x-request-with來判斷。盡管不同瀏覽器發(fā)送AJAX請求的對象不同,但是如果使用jQuery發(fā)送AJAX請求的話,jQuery內(nèi)部實現(xiàn)ajax的時候,已經(jīng)加入了標識。jQuery源碼中是這樣的:xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");
所以,如果項目的前臺頁面都是通過jQuery發(fā)送AJAX請求的話,這樣判斷是安全的。
下面是HTTP請求攜帶的Header信息。
普通Form表單提交
===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調(diào)用(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. 在Action中獲得HTTP請求頭
在Action類中,通過ServletRequestAware接口獲得HttpServletRequest對象,再通過getHeader方法得到我們想要的頭信息。
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調(diào)用 */ 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; } }
Struts2性能調(diào)優(yōu)攔截器
當(dāng)我們在工作中需要實現(xiàn)某些小需求時,不妨先進行下簡單的調(diào)研,看看正在使用的開源框架是否已經(jīng)具備了我們需要的功能,這樣就不用重復(fù)發(fā)明輪子了。
下面以性能測試為例,看看如何調(diào)查Struts2框架是否具備這種功能。
1. struts-default.xml
因為Struts2的許多核心功能都是基于內(nèi)部攔截器來實現(xiàn)的,所以我們首先要看看它是否有性能調(diào)優(yōu)相關(guān)的攔截器。這就需要查看strut2-core-2.3.1.2.jar中的默認配置文件struts-default.xml了。
<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" />
Struts2像個百寶箱一樣內(nèi)置了很多攔截器,可以看到profiling很可能就是符合我們需求的攔截器,那現(xiàn)在就打開源碼一探究竟。
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(); } }
從源碼中可以看到,只要瀏覽器發(fā)過來的HTTP請求參數(shù)中包含profiling=true或者yes,性能攔截器就會開啟Timer工具類,打印出Action的執(zhí)行消耗時間。
3. struts.xml
因為profiling攔截器沒有包含到默認的defaultStack中,所以我們要先將它追加到我們自定義的攔截器棧中。
<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>
4. userview.js
現(xiàn)在就可以修改AJAX調(diào)用參數(shù),追加上profiling參數(shù)就可以開始性能調(diào)優(yōu)了。
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("創(chuàng)建成功"); generateTableFromJson("result", data.resultRows); } else { alert("創(chuàng)建失敗"); } } }); }
5. 最終效果
打印結(jié)果就是下面這樣。除了總執(zhí)行時間外,Action方法的執(zhí)行時間和Result的渲染時間都會分別列出。
- jQuery+datatables插件實現(xiàn)ajax加載數(shù)據(jù)與增刪改查功能示例
- MVC+jQuery.Ajax異步實現(xiàn)增刪改查和分頁
- jQuery的Ajax接收java返回數(shù)據(jù)方法
- ajax提交到j(luò)ava后臺之后處理數(shù)據(jù)的實現(xiàn)
- ajax java 實現(xiàn)自動完成功能
- AJAX+JAVA用戶登陸注冊驗證的實現(xiàn)代碼
- 詳解Java Ajax jsonp 跨域請求
- Java使用Ajax實現(xiàn)跨域上傳圖片功能
- Javaweb使用cors完成跨域ajax數(shù)據(jù)交互
- 深入Ajax代理的Java Servlet的實現(xiàn)詳解
- AJAX實現(xiàn)數(shù)據(jù)的增刪改查操作詳解【java后臺】
相關(guān)文章
Springboot?上傳文件或頭像(MultipartFile、transferTo)
本文主要介紹了Springboot?上傳文件或頭像(MultipartFile、transferTo),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04使用Eclipse開發(fā)工具如何解決Java Compiler中Annotation Processin不出現(xiàn)的問題
這篇文章主要介紹了使用Eclipse開發(fā)工具如何解決Java Compiler中Annotation Processin不出現(xiàn)的相關(guān)資料,需要的朋友可以參考下2015-11-11Spring Data JPA進行數(shù)據(jù)分頁與排序的方法
這篇文章主要介紹了Spring Data JPA進行數(shù)據(jù)分頁與排序的方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11使用cmd根據(jù)WSDL網(wǎng)址生成java客戶端代碼的實現(xiàn)
這篇文章主要介紹了使用cmd根據(jù)WSDL網(wǎng)址生成java客戶端代碼的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03SpringBoot中@MessageMapping注解的原理及使用詳解
這篇文章主要介紹了SpringBoot中@MessageMapping注解的原理及使用詳解,@MessageMapping注解是Spring Boot提供的一個重要的注解之一,它可以幫助我們處理WebSocket消息,需要的朋友可以參考下2023-07-07