SSH学习-拦截器的使用

与Spring类似,Struts2也有拦截器Interceptor,拦截器是java动态拦截action请求的对象,其可以复用,扩展,适合封装通用的处理。下面将学习拦截器作用的时机,以及如何使用拦截器,做简单的记录。

拦截器作用时机

浏览器发送请求到服务端,正常会经历如下几步:浏览器发送请求→filter处理→action处理→result→返回浏览器。

加上拦截器后的过程:浏览器发送请求→filter处理→拦截器处理→action处理→拦截器处理→result→返回浏览器。

也就是说正常的访问过程,浏览器发送请求后,filter先进行处理,并读取struts.xml配置文件,进行action具体路径的匹配并处理,最后将结果返回给浏览器。如果加上拦截器,相当如filter接受到请求到转发给具体action处理前,先调用拦截器进行处理,处理完成后再交给action进行处理,然后action处理完请求后,拦截器再进行一次拦截处理,最后再将结果返回给result进行处理,返回给浏览器。

拦截器的使用

拦截器的使用基本就是三步:创建拦截器,注册拦截器,引用拦截器,接下来以一个简单的案例,说明如何使用拦截器。案例在SSH02的基础上进行,基本的Struts2+Spring的配置省略。

(1)创建拦截器,需要创建一个拦截器类,并实现Interceptor接口,其中invocation.invoke()方法起到放行的作用,如果拦截器逻辑执行完能到这里,就将执行接下来的action请求对应的逻辑。

package Controller;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

/**
 * 自定义拦截器,实现简单的拦截*/
@Controller("demoInterceptor")
@Scope("prototype")
public class demoInterceptor implements Interceptor{

    public void destroy() {
        System.out.println("拦截器销毁了");
        
    }

    public void init() {
        System.out.println("拦截器初始化了");
        
    }
    
    //拦截逻辑写在这里
    public String intercept(ActionInvocation invocation) throws Exception {
        System.out.println("开始拦截");
        
        invocation.invoke();//action请求放行
        
        System.out.println("结束拦截");
        return null;
    }

}

(2)注册拦截器

在package标签下,action标签前,注册拦截器,其中可以注册多个拦截器,name属性对应注册的拦截器名,class属性对应拦截器处理类。其中myInterceptor就是这次注册的拦截器名,其实现类为上面创建的demoInterceptor。

  <package name="demo" namespace="/hello" extends="struts-default">
    <!-- 添加自定义拦截器 -->
    <!-- 注册拦截器 -->
    <interceptors>
       <interceptor name="myInterceptor" class="demoInterceptor"></interceptor>
    </interceptors>
    <action name="helloStruts" class="helloStruts"> 
       <result name="success">
         /WEB-INF/helloStruts.jsp
       </result>
    </action>
  </package>

(3)引用拦截器

在action标签下,引用注册的拦截器,name属性值就是注册的拦截器名称。其中name属性值就是上面注册的拦截器名myInterceptor。补充引用拦截器配置后,上面的配置变成如下。

  <package name="demo" namespace="/hello" extends="struts-default">
    <!-- 添加自定义拦截器 -->
    <!-- 注册拦截器 -->
    <interceptors>
       <interceptor name="myInterceptor" class="demoInterceptor"></interceptor>
    </interceptors>
    <action name="helloStruts" class="helloStruts"> 
       <result name="success">
         /WEB-INF/helloStruts.jsp
       </result>
       <!-- 引用拦截器 -->
       <interceptor-ref name="myInterceptor"></interceptor-ref>
    </action>
  </package>

部署测试结果

Interceptor初始化

在action逻辑处理前后执行了开始拦截和结束拦截

浏览器输出结果

测试结果说明拦截器按照上面说的正常执行了。

拦截器栈失效问题

如果不配置拦截器,框架会默认调用自己的拦截器,其在struts-default.xml中有配置,然后消息传递的数据也是拦截器进行处理的。如果引用了自己定义的拦截器,按照如上配置的话,系统默认的拦截器栈将撤销,导致部分功能不可以用,如消息传递机制失效,下面使用SSH01中的登录功能,配置自定义拦截器进行测试。

(1)struts-default.xml中定义的拦截器栈

(2)在登录验证中配置拦截器

  <!-- 登录,提交用户名和密码,采用基本属性提交方式 -->
  <package name="login" namespace="/login" extends="struts-default">
    <!-- 注册自定义拦截器,消息传递机制失效测试 -->
    <interceptors>
      <interceptor name="myInterceptor" class="com.boe.Filter.demoInterceptor"></interceptor>
    </interceptors>
    <!-- 进入登录页面,没有业务逻辑处理 -->
    <action name="toLogin">
      <result name="success">
        /WEB-INF/login.jsp
      </result>
    </action> 
    <!-- 验证用户名和密码 -->
    <action name="login" class="com.boe.Filter.Login">
      <result name="success">
        /WEB-INF/msg.jsp
      </result>
      <!-- 引入自定义拦截器 -->
      <interceptor-ref name="myInterceptor"></interceptor-ref>
    </action>
  </package>

(3)登录验证

测试发现,action方法中打印用户名和密码得到的结果都为null,说明没有获取到浏览器发送的数据。

拦截器栈失效问题解决方法

如果想同时实现系统默认的拦截器,以及自己定义的拦截器,需要定义一个拦截器栈,里面引入系统默认的拦截器栈,以及自己定义的拦截器。下面在域模型传递方式中,配置拦截器栈,并测试。

(1)在登录中配置拦截器栈

  <!-- 登录,使用域模型传递方式 -->
  <package name="loginWithEntity" namespace="/loginWithEntity" extends="struts-default">
    <!-- 注册拦截器,并创建interceptor-stack,既导入自己写的拦截器也导入框架默认的拦截器栈 -->
    <interceptors>
      <!-- 自定义拦截器 -->
      <interceptor name="myInterceptor" class="com.boe.Filter.demoInterceptor"></interceptor>
      <interceptor-stack name="myInterceptorStack">
          <!-- 引入自己定义的拦截器和框架默认的 -->
          <interceptor-ref name="myInterceptor"></interceptor-ref>
          <interceptor-ref name="defaultStack"></interceptor-ref>
      </interceptor-stack>
    </interceptors>
    <!-- 进入登录页面 -->
    <action name="toLogin">
      <result name="success">
        /WEB-INF/loginWithEntity.jsp
      </result>
    </action>
    <!-- 登录验证 -->
    <action name="login" class="com.boe.Filter.LoginWithEntity">   
      <result name="success">
        /WEB-INF/msg.jsp
      </result> 
      <!-- 引入自己定义的拦截器栈 -->
      <interceptor-ref name="myInterceptorStack"></interceptor-ref>
    </action>
  </package>

(2)登录验证

测试发现配置自定义拦截器栈,并引入自定义的拦截器,以及框架默认的拦截器栈后,数据传递机制生效。说明框架默认的拦截器有获取数据的功能。其中自定义拦截器栈和拦截器标签名是同级关系。

结论

(1)Struts2的拦截器会作用于action请求开始前和结束后,其可以复用,扩展。

(2)拦截器的配置按照三步走:创建拦截器,注册拦截器和引入拦截器。

(3)配置自定义拦截器会有导致框架默认拦截器栈功能撤销的可能,如果想同时实现自定义拦截器和框架默认拦截器栈的功能,需将两者配置到自定义拦截器栈中,并在action引入后才能都生效。

原文地址:https://www.cnblogs.com/youngchaolin/p/10879344.html