struts2自定义拦截器

本文详细介绍了Struts2中自定义拦截器的实现过程,包括拦截器的结构图、编写、配置使用、执行顺序、intercept方法的返回值以及在实际应用中的问题和解决方案。通过实例展示了如何解决多个拦截器配置、默认拦截器的使用以及特定动作方法的拦截控制。
摘要由CSDN通过智能技术生成

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 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>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值