8 Struts 2拦截器

8.1 理解拦截器

拦截器是Struts 2的核心Struts 2的大部分功能都是由拦截器实现的。

在执行Actionexecute方法之前,Struts 2会首先执行在struts.xml中引用的拦截器,在执行完所有引用的拦截器intercept方法后,会执行Actionexecute方法。

8.1.1 拦截器的实现原理

当请求Action时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个的调用列表中的拦截器。

ServletDispatcher初始化一个ActionProxy实例,并调用execute方法拦截器首先拦截用户请求,然后交给Action处理Action处理完毕,返回给用户一个逻辑视图

类似此功能的类:

TokenInterceptor

TokenSessionStoreInterceptor

DefaultWorkflowInterceptor

ValidationInterceptor

8.1.2 实现一个简单拦截器

用户自定义拦截器,三步:

1、自定义拦截器类(必须实现Interceptor接口或继承AbstractInterceptor抽象类)

/**

* 用户自定义的拦截器类必须实行interceptor接口或继承已实现了interceptor接口的抽象类AbstractInterceptor

* 推荐使用抽象类AbstractInterceptor

*/

publicclass HelloInterceptor extends AbstractInterceptor{

**

* intercept方法:实现拦截器动作,参数ActionInvocation是被拦截Action的一个引用,

* 可以调用该参数的invoke()方法,将控制器传给下一个拦截器或Action的execute方法。

*/

@Override

public String intercept(ActionInvocation actionInvocation) throws Exception {

System.out.println("拦截器开始运行。。。。");

String result = actionInvocation.invoke();

System.out.println("!拦截器结束了。。。。");

return result;

}}

2、struts.xml中定义自定义的拦截器

<interceptor>中定义拦截器

3、struts.xml<action>中使用拦截器

<interceptor-ref>中使用拦截器

<packagename="helloInterceptor"extends="struts-default">

<!-- interceptor标记:用来定义一个具体的拦截器 -->

<interceptors>

<interceptor name="helloInterceptor" class="com.inter.HelloInterceptor"></interceptor>

</interceptors>

<!-- 拦截器使用:在一个具体的Action中,interceptor-ref标记就是使用已在interceptor标记中定义好的拦截器 -->

<actionname="helloAction"class="com.action.HelloAction">

<resultname="success">/success.jsp</result>

<resultname="input">/reg.jsp</result>

<!--拦截器使用 -->

<interceptor-refname="defaultStack"></interceptor-ref>

<interceptor-refname="helloInterceptor">

</interceptor-ref>

</action>

</package>

8.2 拦截器配置初步

8.2.1 struts-default.xml中拦截器的定义:

<interceptors>

<interceptorname="conversionError"class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>

<interceptorname="exception"class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>

<interceptorname="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

<interceptorname="actionMappingParams"class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>

<interceptorname="prepare"class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>

<interceptorname="checkbox"class="org.apache.struts2.interceptor.CheckboxInterceptor"/>

<!-- Basic stack -->

<interceptor-stackname="basicStack">

<interceptor-refname="exception"/>

<interceptor-refname="servletConfig"/>

<interceptor-refname="prepare"/>

<interceptor-refname="checkbox"/>

<interceptor-refname="multiselect"/>

<interceptor-refname="actionMappingParams"/>

<interceptor-refname="params">

<paramname="excludeParams">dojo\..*,^struts\..*</param>

</interceptor-ref>

<interceptor-refname="conversionError"/>

</interceptor-stack>

</interceptors>

8.2.2 使用拦截器

只需在struts.xml<action>中添加<interceptor-ref>标记中配置已定义好的拦截器。

<actionname="helloAction"class="com.action.HelloAction">

<interceptor-refname="defaultStack"></interceptor-ref>

<interceptor-refname="helloInterceptor"></interceptor-ref>

</action>

当用户使用了一个自定义的拦截器后,系统默认的拦截器defaultStack就会失效。所以必须添加上默认拦截器的配置代码:

<interceptor-refname="defaultStack"></interceptor-ref>

8.2.3 使用拦截器的过滤方法特性

如何实现对Action的部分方法进行拦截?

Struts 2为了实现方法过滤功能,定义了MethodFilterInterceptor类,该类继承了AbstractInterceptor类。该类重写了AbstractInterceptor类的intercept方法,提供了一个doIntercept的抽象方法,自定义拦截逻辑。

1)在Action中进行配置

publicclass FilterHelloInterceptor extends MethodFilterInterceptor{

@Override

protected String doIntercept(ActionInvocation arg0) throws Exception {

System.out.println("逻辑实现过程是一样的,只是方法名不同而已。");

String res = arg0.invoke();

return res;}

* MethodFilterInterceptor类中两个重要的方法可用于方法的过滤:

* setExcludeMethods(排除过滤)setIncludeMethods(要过滤)

* 冲突时,以setIncludeMethods为准

* 这两个方法灵活性不够,所以可以在struts.xml中进行方法是否过滤的配置

@Override

publicvoid setExcludeMethods(String excludeMethods) {

super.setExcludeMethods(excludeMethods);

}

@Override

publicvoid setIncludeMethods(String includeMethods) {

super.setIncludeMethods(includeMethods);

}}

(2)struts.xml中配置

<packagename="filterHelloInterceptor"extends="struts-default">

<interceptors>

<interceptorname="filterHelloInterceptor"class="com.inter.FilterHelloInterceptor"></interceptor>

</interceptors>

<actionname="sayHello"class="com.action.SayHelloAction">

<result>success.jsp</result>

<!--name="excludeMethods"表示要添加排除过滤的方法,当前配置要排除的拦截方法是execute-->

<interceptor-refname="filterHelloInterceptor">

<paramname="excludeMethods">execute</param>

</interceptor-ref>

</action>

</package>

8.3 Struts 2内建的拦截器

8.4 使用拦截器进行权限控制

检测用户是否登录,通常是跟踪用户的session来完成的。通过ActionContext访问session中的属性。

拦截器代码:

publicclass CheckInterceptor extends AbstractInterceptor{

/**

* 用intercept方法对session中是否存在admin用户作了验证,若用户名为admin,则 为合法用户,可跳转到success.jsp页面,否则留在登录界面,并给出错误提示。 */

@Override

public String intercept(ActionInvocation arg0) throws Exception {

ActionContext ac = arg0.getInvocationContext();

Map<?, ?> sessionMap = ac.getSession();

String user = (String) sessionMap.get("name");//从sessionMap中得到用户实例

if(user!=null&&user.equals("admin")){

return arg0.invoke();

}

ac.put("tip","请先登录!");

return Action.LOGIN;

}}

ActionContext中的tipJSP页面中取出:${requestScope.tip }