在Java的Struts中判断是否调用AJAX及用拦截 器对其优化
作者:cdai 发布时间:2023-11-25 00:40:40
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的渲染时间都会分别列出。


猜你喜欢
- 单例模式单例模式顾名思义就是单一的实例,涉及到一个单一的类,该类负责创建自己的对象,同时确保只有一个对象被创建,并且提供一种可以访问这个对象
- SpringBoot对actuator进行关闭management: endpoint: health
- 本文实例讲述了C#图像处理之边缘检测(Sobel)的方法。分享给大家供大家参考。具体如下://定义sobel算子函数private stat
- 初学线程时,总是将 run 方法和 start 方法搞混,虽然二者是完全不同的两个方法,但刚开始使用时很难分清,原因就是因为初次使用时效果貌
- 一、@RestController 注解在 Spring Boot 中的 Controller 中使用 @RestController 注解
- 本文实例为大家分享了Drawerlayout侧滑菜单的具体代码,供大家参考,具体内容如下1、Drawerlayout的xml布局<?x
- 一、简介构造函数,基本用法是在类对象声明的时候完成初始化工作。二、实例构造函数1、构造函数的名字与类名相同。2、使用 new 表达式创建类的
- 本文实例为大家分享了Springboot POI导出Excel的具体代码,供大家参考,具体内容如下需求:页面根据查询条件导出(浏览器)由于本
- 利用Android的ApiDemos的Rotate3dAnimation实现了个图片3D旋转的动画,围绕Y轴进行旋转,还可以实现Z轴的缩放。
- 本篇文章主要介绍了C# DateTime与时间戳(11位与13)转换实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过
- Android中的翻转动画效果的实现,首先看一下运行效果如上图所示. Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画
- 🚀 ChatGPT是最近很热门的AI智能聊天机器人🚀 本文使用SpringBoot+OpenAI的官方API接口,自己实现一个可以返回对话数
- 目录一、常用属性、方法和事件1.常用属性2.常用方法3.常用事件二、应用实例1.实例描述2.属性设置3.事件处理4.实现代码总结一、常用属性
- 我们都知道取消标题栏有两种方式,一种是在Java代码中取消,另一种通过设置styles.xml文件中的Theme即可;如下图:第一种:第二种
- 简介Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法
- 废话不多说了,直接给大家贴java代码了。 import java.io.IOException;import sun.net.Telnet
- 在java程序开发中,ftp用的比较多,经常打交道,比如说向FTP服务器上传文件、下载文件,本文给大家介绍如何利用jakarta commo
- 在Word文档中,超链接是指在特定文本或者图片中插入的能跳转到其他位置或网页的链接,它也是我们在编辑制作Word文档时广泛使用到的功能之一。
- RecyclerView 滑动时的优化处理,在滑动时停止加载图片,在滑动停止时开始加载图片,这里用了Glide.pause 和Glide.r
- Java服务出现了OOM(Out Of Memory)问题,总结了一些相对通用的方案,希望能帮助到Java技术栈的同学。某Java服务(假设