Struts2有默认的庞大的拦截器,所有的action请求都会先被拦截器拦截,在执行一系列的工作后(校验,类型转换等)再被转发到要去的action
当然默认拦截器远远不能满足我们各种各样的开发需求,比如我们在开发时会遇到很多在调用业务逻辑模块之前需要验证判断的情况,最常见的登录状态验证就是如此
当然我们通过自己编码是可以解决这个问题的,但是struts2给我们提供了更简洁可重复使用的方法:自定义拦截器
那么我们该如何定义自己的拦截器:
1创建一个类,实现Interceptor接口(com.opensymphony.xwork2.interceptor.Interceptor)
2重写interceptor接口的intercept方法,按照自己需要的业务逻辑在方法中进行判断,
如通过判断,则return ActionInvocation(对象,intercept方法的参数).invoke()方法
如未通过判断,则return String;String用来匹配struts.xml中的result,使跳转到指定的处理判断失败的页面。
注:这个类中可以使用ActionContent,也就是说可以获取和设置request和session中的值
3在struts.xml文件中配置拦截器,拦截器只能配置在<package>下面,但是对拦截器的引用在<action>下面
具体配置如下
这样配置之后,每次调用引用了自定义拦截器的action的时候会触发自定义拦截器,
4我们可以通过设置拦截器栈实现既调用自定义拦截器,有调用默认拦截器
具体是在<interceptors>标签下新增如下配置
当然默认拦截器远远不能满足我们各种各样的开发需求,比如我们在开发时会遇到很多在调用业务逻辑模块之前需要验证判断的情况,最常见的登录状态验证就是如此
当然我们通过自己编码是可以解决这个问题的,但是struts2给我们提供了更简洁可重复使用的方法:自定义拦截器
那么我们该如何定义自己的拦截器:
1创建一个类,实现Interceptor接口(com.opensymphony.xwork2.interceptor.Interceptor)
2重写interceptor接口的intercept方法,按照自己需要的业务逻辑在方法中进行判断,
如通过判断,则return ActionInvocation(对象,intercept方法的参数).invoke()方法
如未通过判断,则return String;String用来匹配struts.xml中的result,使跳转到指定的处理判断失败的页面。
注:这个类中可以使用ActionContent,也就是说可以获取和设置request和session中的值
public class LoginInterceptor implements Interceptor {
@Override
public String intercept(ActionInvocation arg0) throws Exception {
Object obj = ActionContext.getContext().getSession().get("loginUser");
if(obj==null) {
ActionContext.getContext().put("msg", "你还未登录,请登录后再试");
return "failed";
} else {
return arg0.invoke();
}
}
}
3在struts.xml文件中配置拦截器,拦截器只能配置在<package>下面,但是对拦截器的引用在<action>下面
具体配置如下
<package name="TestManager" namespace="/test" extends="struts-default">
<!-- 配置拦截器 -->
<interceptors>
<!-- 配置自定义拦截器 name自定义-->
<interceptor name="permission" class="com.xiaogang.interceptor.PermissionInterceptor"/>
</interceptors>
<!-- 定义默认拦截器:对当前所在包下的所有action都进行拦截功能 -->
<!--
<default-interceptor-ref name="permissionStack"/>
-->
<action name="look" class="com.xiaogang.action.TestAction">
<result name="success">/message.jsp</result>
<result name="permission_faild">/noPermission.jsp</result>
<!-- 在action中引用需要使用的拦截器 name要与上面配置的一致-->
<interceptor-ref name="permissionStack"/>
</action>
</package>
这样配置之后,每次调用引用了自定义拦截器的action的时候会触发自定义拦截器,
但同时不会调用默认拦截器(即失去了校验,类型转换等功能),而且在你本来要去的action中只能通过ActionContent.getContent().get(key)才能拿到前台传过来的值,action中定义的私有同名属性将拿不到值
如果<package>下有多个<action>,而所有action都要使用自定义的拦截器,可以通过在<package>标签下面<default-interceptor-ref name=“拦截器或拦截器栈的名字”/>把拦截器或拦截器栈定义为默认拦截器,而不用再<action>中引用。
4我们可以通过设置拦截器栈实现既调用自定义拦截器,有调用默认拦截器
具体是在<interceptors>标签下新增如下配置
<!-- 配置拦截器栈 name自定义 在action中要引用这个名字-->
<interceptor-stack name="permissionStack">
<!-- 引用 拦截器栈包含的拦截器 name只能是defaultStack -->
<interceptor-ref name="defaultStack"/>
<!--引用自定义的拦截器-->
<interceptor-ref name="permission"/>
</interceptor-stack>
注:拦截器栈可以配置多个拦截器,那个顺序在前,就先调用哪个,即如果自定义拦截器在前,且未通过自定义拦截器,那么就不会继续进入默认拦截器,即失去了校验和类型转换等默认功能,所以我们一般把默认拦截器放在前面。
这样也同样不能通过设置同名私有属性拿到前台的值,只能用ActionContent.getContent().get(key)拿页面参数