TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
拦截器interceptor类似于Filter,在执行Action方法前后执行。拦截器是一种AOP(Aspect-Oriented Programming,面向切面的编程)思想的编程方式。它提供一种机制使开发者能把独立的代码抽象出来,配置到Action前后执行。
就像多个Filter组成了Filter链,多个拦截器也组成了拦截器链。Struts2中称拦截器链为拦截器栈。拦截器栈是按顺序配置的多个拦截器,在执行Action前后被依次调用。
Struts2内置了许多现成的拦截器,Struts2的某些功能如数据转换,数据校验等也是基于拦截器实现的。这些拦截器配置在struts2-core-2.0.1.jar中的struts-default.xml文件中,如果需要这些功能,直接使用即可。
1,timer计时拦截器
timer拦截器能够统计每个Action方法运行所需的时间。它的原理是在Action执行前开启记录一下时间,然后计算两个时间的差,并将时间差打印出来(在Filter中也能实现类似的功能)。下面使用timer拦截器统计一个Action的运行时间。
[color=#990066,strength=3);]TimerAction.java
public class TimerAction extends ActionSupport {
public String execute() throws Exception{
Thread.sleep(1000); //线程沉睡1秒钟
return "success"; //返回成功页面
}
}
该Action非常简单,让当前线程沉睡1秒钟,模拟一下繁忙的业务。Action配置中要配置上timer拦截器。代码如下:
[color=#990066,strength=3);]struts.xml
<action name="timer" class="com.zhangjie.struts2.action.TimerAction"> <!-- 使用timer.action测试拦截器 -->
<interceptor-ref name="timer"></interceptor-ref> <!-- 配置Timer拦截器 -->
<result name="success">/timeSuccess.jsp</result>
</action>
注意:package需要继承struts-default才能使用Struts里的拦截器,因为time计时拦截器是配置在struts-default包里的。
部署后访问:http://localhost:2010/struts2/timer.action 控制台会输出如下信息:
显示的是执行timer!execute所消耗的时间(1031毫秒)。第一次访问时由于需要加载拦截器,消耗的时间可能要多一些。显示执行Action所需的时间,在粗略地估计系统性能时很有用。
2,token防重复提交拦截器
如果网络不好,提交数据后可能就没有反应了。这时候用户不知道数据是否已经提交到服务器了,往往还会单击提交按钮再提交一次。对于某些应用,例如网络购物,银行转账等,重复提交会导致严重的后果。
token拦截器用于保证表单只被提交一次,如果再次提交该表单,拦截器会拦截该请求,防止提交重复数据。它的原理是显示表单的时候,在Session中对该表单做一个标记,该标记只能使用一次,使用过后就失效了,从而保证表单最多只提交一次数据。重复提交数据会因为已失效而提交失败。
下面用token拦截器测试下面的TokenAction,保证在提交该表单数据时只能提交一次。TokenAction中有一个NAMES属性,用来存储提交过的所有的数据。重复提交数据时,如果能提交进来,NAMES中将会积累重复的数据,以此来判断是否被重复提交。TokenAction代码如下:
[color=#990066,strength=3);]TokenAction.java
public class TokenAction extends ActionSupport {
public static final List<String> NAMES = new ArrayList<String>(); //static属性,模拟数据库
private String name;
public String execute(){
NAMES.add(name); //添加到NAMES中
return Action.SUCCESS; //返回成功页面
}
public static List<String> getNAMES() {
return NAMES;
}
public void setName(String name) {
this.name = name;
}
}
注:token拦截器是配置使用的,只需在Action中配置一下即可。配置代码如下:
[color=#990066,strength=3);]struts.xml
<action name="token" class="com.zhangjie.struts2.action.TokenAction">
<interceptor-ref name="token"/> <!-- token拦截器 -->
<interceptor-ref name="basicStack" /> <!-- basicStack拦截器 -->
<result name="input">/tokenInput.jsp</result>
<result name="success">/tokenSuccess.jsp</result>
<result name="invalid.token">/tokenInvalid.jsp</result>
</action>
注:代码中配置了token拦截器与basicStack拦截器栈。basicStack是几个常用的拦截器的集合,必须配置的拦截器,如果不配置,Struts2就不会自动向Action赋值。Action中还必须配置一个名为invalid.token的result页面。如果重复提交数据,struts2将转到该页面中。该结果页是必须要配置的。
[color=#990033,strength=3);]tokenInput.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="struts" %>
<HTML>
<struts:head theme="ajax" debug="false"/>
<body>
<struts:form action="token">
<struts:token/> <!-- token标记 -->
<struts:label value="避免重复输入"></struts:label>
<struts:textfield name="name" label="请输入姓名"></struts:textfield>
<struts:submit name=" 提交 "></struts:submit>
</struts:form>
</body>
</html>
注:<struts:token/>标签一定要添加在Form中,否则该拦截器无效。
输入姓名,然后单击“提交”按钮提交数据后,会转到成功页面,并显示已经提交的所有数据。成功页面的代码如下:
[color=#990066,strength=3);]tokenSuccess.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="struts" %>
<html>
<body>
已输入的姓名。<br/>
已经输入的姓名:<struts:property value="NAMES"/><br/><br/>
<a href="tokenInput.action"><<重新输入</a>
</body>
</html>
提交完成后,单击浏览器的“刷新”按钮。浏览器会弹出对话框,询问是否重新提交数据。单击“是”按钮,浏览器会重新提交数据,然后转到tokenInvalid.jsp页面提示输入无效。
[color=#990066,strength=3);]tokenInvalid.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="struts" %>
<html>
<struts:head theme="ajax" debug="false"/>
<body>
输入无效。<br/>
已经输入的姓名:<struts:property value="NAMES"/><br/><br/>
<a href="tokenInput.action"><<重新输入</a>
</body>
</html>
在浏览器中输入http://localhost:2010/struts2/tokenInput.jsp 运行效果如下:
3,execAndWait执行等待拦截器
如果某个 Action运行时间比较长,浏览器会因为等待服务器响应而长时间显示空白。execAndWait拦截器就是实现这种效果的。execAndWait拦截器接受请求后,能判断上一个请求是否处理完毕。如果处理完毕,则显示结果页面。否则显示等待页面。Action代码如下:
[color=#990066,strength=3);]WaitAction.java
public class WaitAction extends ActionSupport {
public String execute() throws Exception{
Thread.sleep(10000); //沉睡10秒钟,模拟大数据量处理
return SUCCESS; //返回成功页面
}
}
代码让给Action所在的线程沉睡10秒,模拟处理繁忙。在10秒钟之内,将会显示等待页面。execAndWait拦截器配置在Action中。Action配置如下:
[color=#990066,strength=3);]struts.xml
<action name="wait" class="com.zhangjie.struts2.action.WaitAction">
<interceptor-ref name="completeStack"/> <!-- completeStack拦截器 -->
<interceptor-ref name="execAndWait"/> <!-- execAndWait拦截器 -->
<result>/waitSuccess.jsp</result>
<result name="wait">/wait.jsp</result>
</action>
Action中配置了complateStack拦截器栈与execAndWait拦截器,还配置了一个名为wait的JSP页面。如果Action繁忙,就显示wait页面。
[color=#990066,strength=3);]wait.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<body>
页面提交(下载)中。。。请等待。。。
<script type="text/javascript">
setTimeout("location=location;",1000);//一秒钟后刷新本页
</script>
</body>
</html>
运行效果:
­[color=#990066,strength=3);]
[color=#990066,strength=3);][color=#990066,strength=3);] |
|