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);] |   
 
 
 
 |