盛京大剧院哪些座位好:struts2学习笔记(9)——自定义拦截器

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 17:52:28

如果要编写自定义拦截器,那么可以只用实现com.opensymphony.xwork2.interceptor.Interceptor这个接口即可。

在这个类中,需要实现3个方法:destroy(),init(),intercept(),核心方法是intercept(),该方法完成了主要逻辑。

在该方法中有个参数invocation,类型为ActionInvocation接口,这个接口中最重要的是invoke方法。

intercept 方法可以如此实现:

 

 

view plaincopy to clipboardprint?

  1. String result = invocation.invoke();   
  2.   
  3. return result;   

 

 

例如,可以这样来实现自定义拦截器

 

 

view plaincopy to clipboardprint?

  1. package cn.tshining.interceptor;   
  2.   
  3. import com.opensymphony.xwork2.ActionInvocation;   
  4. import com.opensymphony.xwork2.interceptor.Interceptor;   
  5.   
  6. public class MyInterceptor implements Interceptor {   
  7.   
  8.     public void destroy() {   
  9.         System.out.println("destory");   
  10.     }   
  11.   
  12.     public void init() {   
  13.         System.out.println("init");   
  14.     }   
  15.   
  16.     public String intercept(ActionInvocation invocation) throws Exception {   
  17.         String result = invocation.invoke();   
  18.         return result;   
  19.     }   
  20.   
  21. }   

 

 

配置拦截器

定义好拦截器后,需要在struts.xml中配置使用拦截器,配置使用拦截器有2步:

1.声明拦截器。

在 struts.xml中package元素下增加元素

view plaincopy to clipboardprint?

  1.    
  2.        
  3.    

 


2.使用拦截器

首先需要了解的是,struts2已经定义了一个默认的拦截器栈,拦截器栈就是若干个拦截器或拦截器栈组成的一系列拦截器的集合。

在 struts2-core-2.1.8.jar下struts-default.xml中定义了这个默认的拦截器栈。

在 struts中所有的action都使用了默认的拦截器栈,若想使用自定义的拦截器栈,只用在action中配置即可,但是此时必须显式的写出使用默认拦截器栈的配置信息。

 

view plaincopy to clipboardprint?

  1.    
  2.     /success.jsp   
  3.     /register2.jsp   
  4.        
  5.        
  6.    

 

 


同时可以在控制台上看到输出的"init",这是由于拦截器在服务器启动时会自动加载,完成初始化。拦截器中定义的intercept方法就是在提交请求时执行的。

用户输入的数据会自动赋值到action中,实际上是底层拦截器起的作用。

在 struts-default.xml中可以看到名为params的拦截器,这个拦截器的作用就是将用户输入的数据注入到Action中的字段中。

使用拦截器参数

在定义拦截器,或者在使用拦截器时可以给拦截器传递参数。

首先在 MyInterceptor类中声明一下字段

public int myparam;

修改 intercept方法:

 

view plaincopy to clipboardprint?

  1. public String intercept(ActionInvocation invocation) throws Exception {   
  2.     String result = invocation.invoke();   
  3.     System.out.println(myparam);   
  4.     return result;   
  5. }   

 

 


修改struts.xml中拦截器的定义:

 

view plaincopy to clipboardprint?

  1.    
  2.         
  3.         1    
  4.         
  5.    

 

 


然后运行该程序,在register2.jsp中输入正确数据提交后就会在控制台中输出1.

也可以在拦截器调用时再传入参数:

 

view plaincopy to clipboardprint?

  1.    
  2.     /success.jsp   
  3.     /register2.jsp   
  4.        
  5.         2   
  6.        
  7.        
  8.    

 


此时重启服务器,在register2.jsp中输入正确的数据之后,可以看到控制台中输出2.

注意此时并没有删除之前拦截器定义时的参数,由此可见,在拦截器调用时的参数比拦截器定义时优先级高。

上面的拦截器调用中使用到了默认拦截器栈,当然自己也可以自定义默认拦截器栈。

view plaincopy to clipboardprint?

  1.    
  2.        
  3.         1   
  4.        
  5.        
  6.            
  7.            
  8.        
  9.    
  10.   

 

 

这样,这个自定义的默认拦截器栈中包含了自定义的拦截器和struts2定义的默认拦截器栈。

在拦截器栈的定义中,既可以引用拦截器,也可以引用拦截器栈。

在 action中没定义拦截器时,会使用默认拦截器。

当然 struts2提供了一个简便的创建自定义拦截器的方法。

只需要继承AbstractInterceptor类,该类空实现了Interceptor接口的init和destroy方法,因此只用实现 intercept方法即可。

在这里我们override AbstractInterceptor的init方法。

 

 

view plaincopy to clipboardprint?

  1. package cn.tshining.interceptor;   
  2.   
  3. import com.opensymphony.xwork2.ActionInvocation;   
  4. import com.opensymphony.xwork2.interceptor.AbstractInterceptor;   
  5.   
  6. public class MyInterceptor2 extends AbstractInterceptor {   
  7.   
  8.     @Override   
  9.     public String intercept(ActionInvocation invocation) throws Exception {   
  10.         String result = invocation.invoke();   
  11.         return result;   
  12.     }   
  13.   
  14.     @Override   
  15.     public void init() {   
  16.         System.out.println("init2");   
  17.     }   
  18. }   

 

 

下面增加以下内容:

 

view plaincopy to clipboardprint?

  1.    

 

 

这样就将myinterceptor2增加到了默认拦截器栈中,查看控制台输出会看到:

init

init2

销毁时会看到:

destory2

destory

这是由于先配置的拦截器先执行,结束时后配置的拦截器先执行

在这里拦截器的执行顺序为:

myintercept——myintercept2——action——myintercept2——myintercept

需要说明的是一定要在action中引用拦截器才会使用拦截器,拦截器拦截的是Action中的execute或自定义的逻辑处理方法。

当然也可以让拦截器拦截指定的方法,那么我们需要继承MethodFilterinterceptor类

 

view plaincopy to clipboardprint?

  1. package cn.tshining.interceptor;   
  2.   
  3. import com.opensymphony.xwork2.ActionInvocation;   
  4. import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;   
  5.   
  6. public class MyInterceptor3 extends MethodFilterInterceptor {   
  7.   
  8.     @Override   
  9.     protected String doIntercept(ActionInvocation invocation) throws Exception {   
  10.         String result = invocation.invoke();   
  11.         System.out.println("doing");   
  12.         return result;   
  13.     }   
  14. }   

 

 


在struts.xml中声明拦截器

 

view plaincopy to clipboardprint?

  1.    

 

 

然后在 Action中引用此拦截器。

首先查看MethodFilterinterceptor,它接受两个参数,

excludeMethods:排除的方法,多个方法间用逗号隔开

includeMethods:包含的方法,多个方法间用逗号隔开

在 struts.xml中如下配置

 

view plaincopy to clipboardprint?

  1.    
  2.     test,execute   
  3.     test   
  4.    

 

 

那么该拦截其将会拦截test方法,因为include比exclude优先级高

在 com.opensymphony.xwork2.interceptor包里面还有一个重要的接口PreResultListener,查看文档。

  * PreResultListeners may be registered with an ActionInvocation to get a callback after the Action has been executed but before the Result is executed.

注释:

    PreResultListeners 可以注册到ActionInvocation,当Action执行完毕但是在返回结果之前调用。
也就是在action的execute执行结束之后,在渲染页面前调用。

首先实现自己的PreResultListeners类

 

view plaincopy to clipboardprint?

  1. package cn.tshining.interceptor;   
  2.   
  3. import com.opensymphony.xwork2.ActionInvocation;   
  4. import com.opensymphony.xwork2.interceptor.PreResultListener;   
  5.   
  6. public class MyListener implements PreResultListener {   
  7.   
  8.     public void beforeResult(ActionInvocation invocation, String resultCode) {   
  9.         System.out.println(resultCode);   
  10.     }   
  11. }   

 


修改自己的拦截器MyInterceptor3中的 doIntercept方法。

 

view plaincopy to clipboardprint?

  1. protected String doIntercept(ActionInvocation invocation) throws Exception {   
  2.     invocation.addPreResultListener(new MyListener());   
  3.     String result = invocation.invoke();   
  4.     System.out.println("doing");   
  5.     return result;   
  6. }   

 


注意PreResultListeners必须向 ActionInvocation实例去注册,而且注册要在调用ActionInvocation实例的invoke方法之前。

当在 register2.jsp中输入正确的数据时,在控制台上可以看到输出的success信息。

该执行过程为:

拦截器 ——validate——execute——beforeResult——结束

拦截器的应用

用拦截器进行权限校验

首先分析一下这个示例的工作流程:

首先用户从login2.jsp登陆,只有username输入hello,password输入world,然后跳转到register2.jsp进行注册操作。

如果用户直接访问register2.jsp,提交后将直接跳转回login2.jsp。

1.首先我们修改struts2.xml,让用户在login2.jsp中输入正确页面之后,将页面转到register2.jsp。

 

view plaincopy to clipboardprint?

  1.    
  2.     /register2.jsp   
  3.     /login2.jsp   
  4.     /login2.jsp   
  5.    

 


2.修改LoginAction类中execute方法

 

view plaincopy to clipboardprint?

  1. public String execute() throws Exception {   
  2.   
  3.     if ("hello".equals(this.getUsername())   
  4.             && "world".equals(this.getPassword())) {   
  5.         Map map = ActionContext.getContext().getSession();   
  6.         map.put("user", "login");   
  7.         return "success";   
  8.     } else {   
  9.         this.addFieldError("username", "username or password error");   
  10.         return "failer";   
  11.     }   
  12.   
  13. }   

 


在该方法中,若用户输入正确信息后,会获得session对象,并把 user和login存到session中。

struts2 的Action中获得session对象的方法是

Map map = ActionContext.getContext().getSession();

struts 将session从servlet容器中抽离出来了,形成了一个map,更利于单元测试
3.新建一个拦截器。

 

 

view plaincopy to clipboardprint?

  1. package cn.tshining.interceptor;   
  2.   
  3. import java.util.Map;   
  4.   
  5. import com.opensymphony.xwork2.Action;   
  6. import com.opensymphony.xwork2.ActionInvocation;   
  7. import com.opensymphony.xwork2.interceptor.AbstractInterceptor;   
  8.   
  9. public class AuthInterceptor extends AbstractInterceptor {   
  10.   
  11.     @Override   
  12.     public String intercept(ActionInvocation invocation) throws Exception {   
  13.         Map map = invocation.getInvocationContext().getSession();   
  14.         if(map.get("user") == null){   
  15.             return Action.LOGIN;   
  16.         }else{   
  17.             return invocation.invoke();   
  18.         }   
  19.     }   
  20. }   

 

 

在这个拦截器中,获得session对象的方法是

 

view plaincopy to clipboardprint?

  1. Map map = invocation.getInvocationContext().getSession();   

 

 

因此,当session中不存在user的值为login时,拦截器将返回Action.LOGIN,在struts.xml中返回结果为login将跳转到 login2.jsp。

这样便可以实现一个简单的用户校验了。

4.配置action

 

view plaincopy to clipboardprint?

  1.    
  2.     /success.jsp   
  3.     /register2.jsp   
  4.     /login2.jsp   
  5.        
  6.        
  7.    

 

 

这样就可以正常工作了。

当然也可以不在Action中定义login的结果跳转,而直接在全局结果中配置。将下面代码放到Action配置前即可正常工作。

 

view plaincopy to clipboardprint?

  1.    
  2.     /login2.jsp   
  3.    

 


这样就定义了一个全局结果页面。

直接进入到register2.jsp,点提交后,会发现地址栏跳到了http://localhost:8888/struts2 /register.action

结果重定向

前面在结果转发时都是用到了请求转发,实际上struts2定义了很多结果类型,我们可以使用重定向试试。

打开 struts2-core-2.1.8.jar,查看里面的struts-default.xml,其中定义了很多结果类型。

其中的 redirect代表的就是重定向。

然后将上面Action配置中作如下修改:

 

view plaincopy to clipboardprint?

  1. /login2.jsp   

 

 

然后重启服务器,直接进入到register2.jsp,点提交后,会发现地址栏跳到了http://localhost:8888/struts2 /login2.jsp

这就是重定向。在struts2中默认是dispatcher。

下次将学习struts2的文件上传与下载。