九、Struts2之拦截器


一、拦截器介绍


拦截器是Struts2最重要的组成部分,因为Struts2的大部分操作都是通过他完成的,以下列举了一些内建拦截器:

(1)params :拦截HTTP请求参数,并完成类型转换

(2)fileUpload:文件上传拦截器;

(3)conversionError:处理类型转换错误的拦截器;

(4)exception:处理异常的拦截器,因此在execute方法中,才可以安心抛出异常;

(5)i18n:处理国际化拦截器;

(6)static-params:用于在struts.xml中注入action属性值;

(7)validation:在xml文件中配置的输入校验拦截器;

(8)workflow:处理手动校验的拦截器

以上内建拦截器都在struts2-core-Xxx.jar\struts-default.xml中定义,因此在定义<package>时需要填写 extends="struts-default",这样能够自动继承这些拦截器;

而我们还可以自己定义拦截器,不过注意,如果配置了自定义拦截器,则会让内建拦截器消失,因此我们必须要显式地引用内建拦截器,如下 <interceptor name="defaultStack"/>;

Struts2通过可插拔设计,可以添加、删除任意拦截器,非常灵活;


拦截器&拦截器栈

拦截器栈是由多个拦截器构成的,在使用时可以把他当作一个“大一点的拦截器”,除了定义不同,使用起来是相同的;

拦截器栈应用:多个拦截器同时使用时,方便管理;

拦截器栈

    拦截器1

    拦截器2

    拦截器3

 

拦截器的使用:拦截器配置在<action>中,即为某个Action配置一个或多个拦截器, 即执行Action方法之前会被拦截器拦截,并执行拦截器方法;


二、自定义拦截器

 

1.配置自定义拦截器和拦截器栈

 

定义拦截器或拦截器栈的根元素为<interceptors>,而此元素是<package>的子元素;


(1)定义拦截器:<interceptors>的子元素

<interceptor name="拦截器名" class="实现类"/>

注:如果需要传入参数,则表示拦截器类属性的默认值;

<interceptor name="拦截器名" class="实现类">
    <param name="name">value</param>
</interceptor>

(2)引用拦截器:<action>或<interceptor-stack>的子元素

如果是<action>的子元素,则表示在action中配置一个拦截器;

<interceptor-ref name="拦截器名"/>

注:如果需要传入参数,则表示使用拦截器时类属性的值,将覆盖定义拦截器时传入的参数;

<interceptor-ref name="拦截器名">
    <param name="name">value</param>
</interceptor-ref>

(3)定义拦截器栈:<interceptors>的子元素

<interceptor-stack name="拦截器栈名">

    <interceptor-ref name="拦截器名"/>

    <interceptor-ref name="拦截器名"/>

</interceptor-stack>

(4)引用拦截器栈:<action>的子元素

<interceptor-ref name="拦截器栈名"/>

注:这里传递参数方法比较特殊,因为拦截器栈中有多个拦截器,因此必须以如下形式执行参数:

<interceptor-ref name="拦截器栈名">

<param name="interceptorName.attrName">value</param>

</interceptor-ref>

(5)定义默认拦截器:<package>的子元素

<default-interceptor-ref name="拦截器或拦截器栈名"/>

注:可以在此处传入参数:

<default-interceptor-ref name="默认拦截器名">

    <param name="name">value</param>

</default-interceptor-ref>

默认拦截器使用时机:当action中没有显式地引用拦截器,则会使用默认拦截器;

 

2.定义拦截器类

实现Interceptor接口,并实现方法:

(1)public void init();        //初始化,一般为空

(2)public void destroy();        //销毁,一般为空

(3)public String interceptor(ActionInvocation invocation)throws Exception;    //实现拦截功能,返回值为execute方法返回值;

String result = invocation.invoke()即可调用拦截器拦截的Action的execute()方法,并返回逻辑视图;
public String interceptor(ActionInvocation invocation)throws Exception{

        //调用execute()方法之前

        String result = invocation.invoke();

        //调用execute()方法之后

        return result;

注意:

(1)在使用自定义拦截器时,会丢失默认内建拦截器,因此需要显式引用默认拦截器栈:<interceptor-ref name="defaultStack"/>

(2)如果在一个Action中配置了两个拦截器,则如果拦截器A在拦截器B之前引用,即:

<action>

<interceptor-ref name="A"/>

<interceptor-ref name="B"/>

</action>

则虽然在两个拦截器中都调用了invocation.invoke(),但是只会执行一遍Action方法;Action方法执行之前,拦截器A比拦截器B先执行;Action方法执行之后,则拦截器B比拦截器A先执行;

即结果为:

 A拦截器语句

B拦截器语句

execute

B拦截器语句

A拦截器语句


代码实例:

HelloAction.java


package org.xiazdong.action;

import com.opensymphony.xwork2.ActionSupport;

public class HelloAction extends ActionSupport {
	public String execute()throws Exception{
		System.out.println("execute...");
		return SUCCESS;
		
	}
}


Interceptor01.java


package org.xiazdong.interceptor;

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

public class Interceptor01 implements Interceptor {
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public void destroy() {
	}
	@Override
	public void init() {
	}
	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		System.out.println("name属性:"+name);
		System.out.println("execute方法之前...");
		String result = invocation.invoke();
		System.out.println("execute方法之后...");
		return result;
	}
}


struts.xml


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
	<constant name="struts.devMode" value="true" />
	<package name="default" namespace="/" extends="struts-default">
		<interceptors>
			<interceptor name="interceptor01" class="org.xiazdong.interceptor.Interceptor01">
				<param name="name">xiazdong</param>
			</interceptor>
			<interceptor-stack name="stack">
				<interceptor-ref name="defaultStack"></interceptor-ref>
				<interceptor-ref name="interceptor01"></interceptor-ref>
			</interceptor-stack>
		</interceptors>
		<action name="hello" class="org.xiazdong.action.HelloAction">
			<interceptor-ref name="stack"></interceptor-ref>
			<result>/index.jsp</result>
		</action>
	</package>
</struts>

3.方法过滤


默认自定义拦截器将会拦截Action的所有方法,比如在Action中定义了login()方法、regist()方法,则默认会拦截两个方法,如果只想拦截login()方法,则需要通过如下步骤实现过滤:

(1)继承 MethodFilterInterceptor类;

(2)重写public String doIntercept(ActionInvocation invocation)throws Exception;此方法和intercept方法功能一致,只是名字不一样;

(3)在struts.xml中配置参数进行过滤:在<interceptor-ref>的子元素中设置:

<param name="excludeMethods">不过滤的方法1,不过滤的方法2</param>、<param name="includeMethods">需要过滤的方法</param>


注意:如果一个方法在includeMethods和excludeMethods参数中同时列出,则还是会被拦截;


代码实例:
如果Action中提供了login()、regist()方法,则struts.xml中如下配置,可以实现login()不被拦截器拦截:

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

	<constant name="struts.devMode" value="true" />

	<package name="default" namespace="/" extends="struts-default">

		<interceptors>
			<interceptor name="interceptor01"
				class="org.xiazdong.interceptor.Interceptor01">
				<param name="name">xiazdong</param>
			</interceptor>
			<interceptor-stack name="stack">
				<interceptor-ref name="defaultStack">

				</interceptor-ref>
				<interceptor-ref name="interceptor01">
					<param name="excludeMethods">login</param>
				</interceptor-ref>
			</interceptor-stack>
		</interceptors>
		<action name="hello" class="org.xiazdong.action.HelloAction">
			<interceptor-ref name="stack"></interceptor-ref>
			<result>/index.jsp</result>
		</action>
	</package>
</struts>


补充:PreResultListener应用


在Action的介绍中也介绍过这个类,是用于在Action方法执行之后、转入物理视图之前被调用;
这个类也可以在拦截器类中被添加,则只要应用该拦截器的action都会起作用,步骤如下:
(1)定义MyPreResultListener:
public class MyPreResultListener implements PreResultListener{
public void beforeResult(ActionInvocation invocation,String resultCode);
}
(2)在intercept方法中添加invocation.addPreResultListener(new MyPreResultListener());
即可;

代码:

MyPreResultListener.java
package org.xiazdong.interceptor;

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

public class MyPreResultListener implements PreResultListener {

	@Override
	public void beforeResult(ActionInvocation arg0, String arg1) {
		System.out.println("beforeResult...");
	}

}

Interceptor01.java

package org.xiazdong.interceptor;

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

public class Interceptor01 extends MethodFilterInterceptor{

	@Override
	public String doIntercept(ActionInvocation invocation) throws Exception {
		
		invocation.addPreResultListener(new MyPreResultListener());
		System.out.println("execute1方法之前...");
		String result = invocation.invoke();
		System.out.println("execute1方法之后...");
		return result;
	}
}

结果如下:

 execute1方法之前...
regist...
beforeResult...
execute1方法之后...

可以看出,此方法在Action方法一执行完就触发PreResultListener,比拦截器先执行;




最后配上一张图作为结尾:








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值