您的位置:首页 > 编程语言 > Java开发

struts2自定义拦截器

2016-12-27 23:30 591 查看

struts2拦截器的结构图



自定义拦截器编写

定义一个拦截器

从上面的其结构图来看,我们要定义一个拦截器,只需继承AbstractInterceptor或者实现Interceptor接口,然后实现intercept方法

public class MyInterceptor extends AbstractInterceptor {

@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("自定义拦截器执行了");
return null;
}

}


现在创建了一个拦截器就可以使用了嘛,当然不是,

配置该拦截器使用

配置拦截器使用有两个步骤

 第一:声明拦截器(在使用前一定要声明)]

<package name="p1" extends="struts-default" >
<!--声明拦截器  -->
<interceptors>
<interceptor name="myinterceptor" class="com.yu.web.action.MyInterceptor"></interceptor>
</interceptors>


第二步:使用拦截器

<action name="hello" class="com.yu.web.action.HelloAction" method="saveUser">
<!--使用拦截器,使用拦截器之前,必须声明它  -->
<!--在这里配置拦截器之后,默认配置的拦截器将会失效  -->
<interceptor-ref name="myinterceptor"></interceptor-ref>
<result>/success.jsp</result><!-- 当注册成功之后重定向的结果视图 -->
<result name="exists">/message.jsp</result><!-- 当用户名已经存在之后,转向的结果视图 -->
<result name="input">/register.jsp</result>
</action>


测试拦截器是否起作用,触发上面配置的action



而我们的动作方法是:

public String saveUser(){

System.out.println("动作方法执行了");
return SUCCESS;
}


所以看到,动作方法并没有执行,这是什么原因了,我们看struts2的结构流程图可知,动作方法执行之前是先执行其拦截器的,我们在前面的拦截器中只是打印了y一句话,并没有做其它操作,我们想要动作方法也执行,就必须放行此拦截器。

public class MyInterceptor extends AbstractInterceptor {

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("自定义拦截器执行了");
        String result=invocation.invoke(); //放行次拦截器向下执行
        //执行完结果视图后,反向执行拦截器
        System.out.println("反向执行");
        //放行后结果返回的结果是结果视图的名称
        System.out.println(result);
        return null;
    }

}


打印结果:

自定义拦截器执行了

动作方法执行了

反向执行

多个拦截器的执行顺序

 创建一个同样的interceptor

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

public class MyInterceptor2 extends
4000
AbstractInterceptor {

@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("自定义拦截器2执行了");
String result=invocation.invoke(); //放行次拦截器向下执行
//执行完结果视图后,反向执行拦截器
System.out.println("自定义拦截器2反向执行");
//放行后结果返回的结果是结果视图的名称
System.out.println(result+"视图结果");
return null;
}

}


声明和配置定义过滤器

<package name="p1" extends="struts-default" >
<!--声明拦截器  -->
<interceptors>
<interceptor name="myinterceptor1" class="com.yu.web.action.MyInterceptor1"></interceptor>
<interceptor name="myinterceptor2" class="com.yu.web.action.MyInterceptor2"></interceptor>
</interceptors>
<action name="findAll" class="com.yu.web.action.HelloAction" method="findAll">
<result>/findall.jsp</result>
</action>
<action name="hello" class="com.yu.web.action.HelloAction" method="saveUser">
<!--使用拦截器,使用拦截器之前,必须声明它  -->
<!--在这里配置拦截器之后,默认配置的拦截器将会失效  -->
<interceptor-ref name="myinterceptor1"></interceptor-ref>
<interceptor-ref name="myinterceptor2"></interceptor-ref>
<result>/success.jsp</result><!-- 当注册成功之后重定向的结果视图 -->
<result name="exists">/message.jsp</result><!-- 当用户名已经存在之后,转向的结果视图 -->
<result name="input">/register.jsp</result>
</action>
</package>


打印结果:

自定义拦截器1执行了

自定义拦截器2执行了

动作方法执行了

自定义拦截器2反向执行

自定义拦截器1反向执行

如果我们改变拦截器配置的顺序

<interceptor-ref name="myinterceptor2"></interceptor-ref>
<interceptor-ref name="myinterceptor1"></interceptor-ref>


打印结果:

自定义拦截器2执行了

自定义拦截器1执行了

动作方法执行了

自定义拦截器1反向执行

自定义拦截器2反向执行

所以从上面可以看到,拦截器的执行顺序和配置拦截器的顺序有关

intercept的返回值

其放行方法有个返回值,我们可以打印此值,看其结果.

@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("自定义拦截器2执行了");
String result=invocation.invoke(); //放行次拦截器向下执行
//执行完结果视图后,反向执行拦截器
System.out.println("自定义拦截器2反向执行");
System.out.println(result);
return result;
}


打印结果:

自定义拦截器1执行了

动作方法执行了

jsp执行了

自定义拦截器1反向执行

success

自定义拦截器2反向执行

success

从上面可以看到,拦截器返回的就是其结果视图

拦截器的一个应用

在没有登录之前,不能查看其它页面。 那么就给其它页面一个检查是否已经登录的拦截器

拦截器:

@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
//获取登陆标志
HttpSession session = ServletActionContext.getRequest().getSession();
//有user标志,表示已经登录
Object obj=session.getAttribute("user");
if(obj!=null){
String result=	invocation.invoke();
return result;
}else{
//如果没有登录,则返回到登录页面
return "register";
}
}


拦截器配置:

<action name="findAll" class="com.yu.web.action.HelloAction" method="findAll">
<interceptor-ref name="myinterceptor1"></interceptor-ref>
<result>/findall.jsp</result>
<result name="register">/register.jsp</result>
</action>


触发此action,发现,如果没有登录标记,就会跳到登录页面.

先登录设置一个登录标记,检测是否可以进入其它页面

设置登录标记

public String saveUser(){
HttpSession session = ServletActionContext.getRequest().getSession();
session.setAttribute("user", "aaa");
System.out.println("动作方法执行了");
return SUCCESS;
}


现在可以进入其它页面

存在的问题

 问题一:上述配置自己的拦截器后,默认的拦截器不起作用了,

a.解决办法:加入默认的拦截器

<action name="findAll" class="com.yu.web.action.HelloAction" method="findAll">
<!--为什么是defaultStack了,因为struts-default.xml文件中 所有默认拦截器的栈名是defaultStack  -->
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="myinterceptor1"></interceptor-ref>
<result>/findall.jsp</result>
<result name="register">/register.jsp</result>
</action>


b.上述办法也会出现一个问题
当有拦截器,多个动作要写配置多个拦截器的时候,这样写比较麻烦,解决办法是可以,配置一个全局的拦截器栈

<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<constant name="struts.custom.i18n.resources" value="com.yu.web.resources.message"></constant>
<package name="mydefault" extends="struts-default">
<!--声明拦截器 -->
<interceptors>
<interceptor name="myinterceptor1" class="com.yu.web.action.MyInterceptor1"></interceptor>
<interceptor name="myinterceptor2" class="com.yu.web.action.MyInterceptor2"></interceptor>
<!--声明拦截器栈 -->
<interceptor-stack name="mydefaultStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="myinterceptor1"></interceptor-ref>
</interceptor-stack>
</interceptors>
</package>
<!--注意:现在继承mydefault -->
<package name="p1" extends="mydefault" >

<action name="findAll" class="com.yu.web.action.HelloAction" method="findAll">
<!--为什么是defaultStack了,因为struts-default.xml文件中 所有默认拦截器的栈名是defaultStack -->
<interceptor-ref name="mydefaultStack"></interceptor-ref>
<result>/findall.jsp</result>
<result name="register">/register.jsp</result>
</action>
<action name="hello" class="com.yu.web.action.HelloAction" method="saveUser">
<result>/success.jsp</result><!-- 当注册成功之后重定向的结果视图 -->
<result name="exists">/message.jsp</result><!-- 当用户名已经存在之后,转向的结果视图 -->
<result name="input">/register.jsp</result>
</action>
</package>
</struts>
c.上述办法虽然解决了写多个拦截器的麻烦
但是仍然每个动作方法都要配置其拦截器,那有没直接配置一个就可以的了,当然,默认拦截器,我们并没有配置,但是执行每个动作方法前,都有被执行,其实,在struts-default.xml中,有配置默认的拦截器

<default-interceptor-ref name="defaultStack"/>

所以,我们也可以配置一个默认的拦截器
<struts>
  <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
  <constant name="struts.custom.i18n.resources" value="com.yu.web.resources.message"></constant>
 <package name="mydefault" extends="struts-default">
   <!--声明拦截器  -->
  <interceptors>
  <interceptor name="myinterceptor1" class="com.yu.web.action.MyInterceptor1"></interceptor>
  <interceptor name="myinterceptor2" class="com.yu.web.action.MyInterceptor2"></interceptor>
  <!--声明拦截器栈  -->
  <interceptor-stack name="mydefaultStack">
  <interceptor-ref name="defaultStack"></interceptor-ref>
  <interceptor-ref name="myinterceptor1"></interceptor-ref>
  </interceptor-stack>
  </interceptors>
  <!--默认拦截器栈  -->
  <default-interceptor-ref name="mydefaultStack"></default-interceptor-ref>
 </package>
 <!--注意:现在继承mydefault  -->
  <package name="p1" extends="mydefault" >

  <action name="findAll" class="com.yu.web.action.HelloAction" method="findAll">
  <result>/findall.jsp</result>
  <result name="register">/register.jsp</result>
  </action>
  <action name="hello" class="com.yu.web.action.HelloAction" method="saveUser">
 <result>/success.jsp</result><!-- 当注册成功之后重定向的结果视图 -->
<result name="exists">/message.jsp</result><!-- 当用户名已经存在之后,转向的结果视图 -->
<result name="input">/register.jsp</result>
  </action>
  </package>
</struts>
d.在使用了默认拦截器后,就给所有的动作方法都加上了拦截器
但是可能我们有些动作方法不需要加拦截器,这个怎么解决了

AbstractInterceptor有个子类,MethodFilterInterceptor,它有两个方法

public void setExcludeMethods(String excludeMethods) {
this.excludeMethods = TextParseUtil.commaDelimitedStringToSet(excludeMethods);
}
   public void setIncludeMethods(String includeMethods) {
        this.includeMethods = TextParseUtil.commaDelimitedStringToSet(includeMethods);
    }


这两个方法表示,在一个拦截器中,可以配置那些方法不拦截,那些方法拦截
setIncludeMethods:表示拦截那些方法

setExcludeMethods:表示不拦截那些方法

首先:自定义拦截器继承MethodFilterInterceptor

public class MyInterceptor1 extends MethodFilterInterceptor {

@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
//获取登陆标志
HttpSession session = ServletActionContext.getRequest().getSession();
//有user标志,表示已经登录
Object obj=session.getAttribute("user");
if(obj!=null){
String result= invocation.invoke();
return result;
}else{
//如果没有登录,则返回到登录页面
return "register";
}
}

}

为什么重写方法是doIntercept,难道是拦截器的方法改变了嘛,当然不是,拦截器执行的默认方法还是intercept(ActionInvocation invocation)这个方法,只是
MethodFilterInterceptor中intercept(ActionInvocation invocation)调用的是 doIntercept(ActionInvocation invocation)

@Override
public String intercept(ActionInvocation invocation) throws Exception {
if (applyInterceptor(invocation)) {
return doIntercept(invocation);
}
return invocation.invoke();
}

现在,我们配置我们要哪个方法需要拦截,哪个方法不需要,比如,我们在登录的时候,不需要检测用户是否登录 
在申明拦截器栈的拦截器中配置(因为声明拦截器栈的过程中,相当于调用了拦截器)

<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<constant name="struts.custom.i18n.resources" value="com.yu.web.resources.message"></constant>
<package name="mydefault" extends="struts-default">
<!--声明拦截器 -->
<interceptors>
<interceptor name="myinterceptor1" class="com.yu.web.action.MyInterceptor1"></interceptor>
<interceptor name="myinterceptor2" class="com.yu.web.action.MyInterceptor2"></interceptor>
<!--声明拦截器栈 -->
<interceptor-stack name="mydefaultStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="myinterceptor1">
<param name="excludeMethods">login</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<!--默认拦截器栈 -->
<default-interceptor-ref name="mydefaultStack"></default-interceptor-ref>
</package>
<!--注意:现在继承mydefault -->
<package name="p1" extends="mydefault" >

<action name="findAll" class="com.yu.web.action.HelloAction" method="findAll">
<result>/findall.jsp</result>
<result name="register">/register.jsp</result>
</action>
<action name="hello" class="com.yu.web.action.HelloAction" method="saveUser">
<result>/success.jsp</result><!-- 当注册成功之后重定向的结果视图 -->
<result name="exists">/message.jsp</result><!-- 当用户名已经存在之后,转向的结果视图 -->
<result name="input">/register.jsp</result>
</action>
</package>
</struts>
e.上述解决就已经完善了嘛,当然不是
我们在登录之前,拦截器怎么知道,我们的动作方法叫什么了,解决办法是,在动作方法中,注入其参数

<action name="login" class="com.yu.web.action.HelloAction" method="login">
<param name="myinterceptor1.excludeMethods">login</param>
<result>/success.jsp</result>
</action>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: