当前位置: 移动技术网 > IT编程>开发语言>Java > 在Java的Struts中判断是否调用AJAX及用拦截器对其优化

在Java的Struts中判断是否调用AJAX及用拦截器对其优化

2019年07月22日  | 移动技术网IT编程  | 我要评论

strut2判断是否是ajax调用
1.   ajax与传统form表单
实际上,两者一般都是通过http的post请求。区别是浏览器提交form表单后,期望服务器返回一个完整的html页面。而ajax调用是由xmlhttprequest对象(不同浏览器可能不一样)发出,浏览器期望服务器返回html片段即可,具体是json、xml等都没有要求。返回到浏览器后如何使用,也是由js脚本自己决定的。
 
2. 请求是不是ajax
那么对于服务器端,如何判断一个http请求是不是ajax调用?这需要看http的header。
 
我们可以通过header中的x-request-with来判断。尽管不同浏览器发送ajax请求的对象不同,但是如果使用jquery发送ajax请求的话,jquery内部实现ajax的时候,已经加入了标识。jquery源码中是这样的:xhr.setrequestheader("x-requested-with","xmlhttprequest");
所以,如果项目的前台页面都是通过jquery发送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调用(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调用 
   */ 
  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性能调优拦截器
当我们在工作中需要实现某些小需求时,不妨先进行下简单的调研,看看正在使用的开源框架是否已经具备了我们需要的功能,这样就不用重复发明轮子了。
 下面以性能测试为例,看看如何调查struts2框架是否具备这种功能。

1.   struts-default.xml

因为struts2的许多核心功能都是基于内部拦截器来实现的,所以我们首先要看看它是否有性能调优相关的拦截器。这就需要查看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像个百宝箱一样内置了很多拦截器,可以看到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的执行消耗时间。

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

现在就可以修改ajax调用参数,追加上profiling参数就可以开始性能调优了。

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.   最终效果
 
打印结果就是下面这样。除了总执行时间外,action方法的执行时间和result的渲染时间都会分别列出。

201611385424070.png (411×59)

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网