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

 更新时间:2016年01月13日 08:54:08   作者:cdai  
这篇文章主要介绍了在Java的Struts中判断是否调用AJAX及用拦截器对其优化的方法,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下

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)

相关文章

  • idea中配置tomcat启动jsp项目过程

    idea中配置tomcat启动jsp项目过程

    在IntelliJ IDEA中配置Tomcat并启动JSP项目,首先需要在IDEA中安装和配置Tomcat服务器,接着将项目与Tomcat关联,设置正确的部署路径和端口号,通过这些步骤,可以实现JSP项目的本地运行和调试,使得开发和测试工作更加高效
    2024-10-10
  • java 键盘输入的多种实现方法

    java 键盘输入的多种实现方法

    java不像C中拥有scanf这样功能强大的函数,大多是通过定义输入输出流对象。常用的类有BufferedReader,Scanner。
    2013-03-03
  • java 线程方法join简单用法实例总结

    java 线程方法join简单用法实例总结

    这篇文章主要介绍了java 线程方法join简单用法,结合实例形式总结分析了Java线程join方法的功能、原理及使用技巧,需要的朋友可以参考下
    2019-11-11
  • jdk17 SpringBoot JPA集成多数据库的示例详解

    jdk17 SpringBoot JPA集成多数据库的示例详解

    这篇文章主要介绍了jdk17 SpringBoot JPA集成多数据库的示例代码,包括配置类、请求拦截器、线程上下文等相关知识,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • 浅谈Spring boot cache使用和原理

    浅谈Spring boot cache使用和原理

    这篇文章主要介绍了浅谈Spring boot cache使用和原理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • SpringBoot和前端Vue的跨域问题及解决方案

    SpringBoot和前端Vue的跨域问题及解决方案

    所谓跨域就是从 A 向 B 发请求,如若他们的地址协议、域名、端口都不相同,直接访问就会造成跨域问题,跨域是非常常见的现象,这篇文章主要介绍了解决SpringBoot和前端Vue的跨域问题,需要的朋友可以参考下
    2023-11-11
  • Java实现抽奖算法的示例代码

    Java实现抽奖算法的示例代码

    这篇文章主要为大家详细介绍了如何利用Java语言实现抽奖算法,文中的示例代码讲解详细,对我们学习Java有一定帮助,需要的可以参考一下
    2022-04-04
  • springBoot启动时让方法自动执行的几种实现方式

    springBoot启动时让方法自动执行的几种实现方式

    这篇文章主要介绍了springBoot启动时让方法自动执行的几种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Java基于动态规划法实现求最长公共子序列及最长公共子字符串示例

    Java基于动态规划法实现求最长公共子序列及最长公共子字符串示例

    这篇文章主要介绍了Java基于动态规划法实现求最长公共子序列及最长公共子字符串,简单描述了动态规划法的概念、原理,并结合实例形式分析了Java使用动态规划法求最长公共子序列以及最长公共子字符串相关实现技巧,需要的朋友可以参考下
    2018-08-08
  • Springboot项目快速实现拦截器功能

    Springboot项目快速实现拦截器功能

    上一篇文章介绍了Springboot项目如何快速实现过滤器功能,本篇文章接着来盘一盘拦截器,仔细研究后会发现,其实拦截器和过滤器的功能非常类似,可以理解为面向切面编程的一种具体实现。感兴趣的小伙伴可以参考阅读
    2023-03-03

最新评论