现在的位置: 首页 > 综合 > 正文

Struts2 拦截器

2013年11月09日 ⁄ 综合 ⁄ 共 6069字 ⁄ 字号 评论关闭

1、Struts2实现原理:

当请求到达Struts 2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器,如图所示。

图1 拦截器调用序列图

2、Struts2默认的所有拦截器:

             <interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/><!-- 用于捕获异常 -->
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/><!-- 将源于Servlet API的各种对象注入到Action -->
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="scopedModelDriven"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/><!-- 将文件和元数据从多重请求转换为常规请求 -->
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="staticParams"/><!-- 将在配置文件中配置的参数注入到Action中对应的属性 -->
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params"><!-- 将请求的数据设置到Action中的属性上 -->
                    <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,
                                 ^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
                </interceptor-ref>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation"><!-- 执行数据验证 -->
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow"><!-- 当数据验证错误时,提供终止流程的功能 -->
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="debugging"/>
            </interceptor-stack>

在struts-default.xml中已经配置了以上的拦截器。如果您想要使用上述拦截器,只需要在应用程序struts.xml文件中通过“<include
file="struts-default.xml" />”将struts-default.xml文件包含进来,并继承其中的struts-default包(package),最后在定义Action时,使用“<interceptor-ref name="xx" />”引用拦截器或拦截器栈(interceptor stack)。一旦您继承了struts-default包(package),所有Action都会调用拦截器栈 ——defaultStack。当然,在Action配置中加入“<interceptor-ref
name="xx" />”可以覆盖defaultStack。

3、Struts2为我们提供了一个Interceptor接口,该接口源代码如下:

publicinterface Interceptor extends Serializable {
    void destroy();
    void init();
    String intercept(ActionInvocation invocation) throws Exception;
}

1)    init():在拦截器执行之前调用,主要用于初始化系统资源。

2)    destroty():init()对应,用于拦截器执行之后销毁资源。

3)    intercept():拦截器的核心方法,实现具体的拦截操作。与action一样,该方法也返回一个字符串作为逻辑视图。如果拦截器成功调用了action,则返回该actionexecute()方法返回的逻辑视图,反之,则返回一个自定义的逻辑视图。

Struts2还为我们提供了一个AbstractInterceptor类,该类的init()destroy()都是空实现。我们开发自己的拦截器只需要继承这个类就行了。

4、下面以一个登录的例子为例自定义拦截器:

首先自定义一个拦截器类,该类可以实现Interceptor接口或继承AbstractInterceptor类:

public class PermissionInterceptor implements Interceptor {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
	}
	@Override
	public void init() {
		// TODO Auto-generated method stub
	}
	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		// TODO Auto-generated method stub
		Long startTime=System.currentTimeMillis();
		LoginAction login=(LoginAction)invocation.getAction();
//		login.setName("zhangsan");
		System.out.println(System.currentTimeMillis()-startTime);
		return invocation.invoke();
	}
}

在struts.xml配置拦截器:

<struts>
	<package name="base" extends="struts-default">
		<global-results><!-- 定义全局视图 -->
				<result name="login" type="redirect" >/login.jsp</result>
		</global-results>
	</package>

	<package name="default" namespace="/test" extends="base">
		<interceptors>
			<interceptor name="permission" class="org.han.interceptor.PermissionInterceptor" />
			<interceptor-stack name="permissionStack"><!-- 拦截器栈 -->
				<interceptor-ref name="defaultStack" />
				<interceptor-ref name="permission" /><!-- 如果需要加载默认拦截器,自定义拦截器要放默认拦截器后面 -->
			</interceptor-stack>
		</interceptors>
	</package>
</struts>


因为Struts2中许多功能都是由系统默认的defaultStack中的拦截器实现的,所以我们定义的拦截器需要引用系统默认的defaultStack,并且要比自定义拦截器提前加载,这样应用才能使用struts2框架提供的众多功能。

如果希望包下的所有action都使用自定义的拦截器,可以通过<default-interceptor-ref
name="permissionStack" />把拦截器定义为默认的拦截器。注意:
每个包只能指定一个默认拦截器,另外,一旦我们为该包中的某个action显示指定了某个拦截器,则默认拦截器不会起作用

<struts>
	<package name="base" extends="struts-default">
		<global-results><!-- 定义全局视图 -->
				<result name="login" type="redirect" >/login.jsp</result>
		</global-results>
	</package>

	<package name="default" namespace="/test" extends="base">
		<interceptors>
			<interceptor name="permission" class="org.han.interceptor.PermissionInterceptor" />
			<interceptor-stack name="permissionStack"><!-- 拦截器栈 -->
				<interceptor-ref name="defaultStack" />
				<interceptor-ref name="permission" /><!-- 如果需要加载默认拦截器,自定义拦截器要放默认拦截器后面 -->
			</interceptor-stack>
		</interceptors>
                <default-interceptor-ref name="permissionStack" /><!-- 配置后所有action都默认这个拦截器了 -->
	</package>
</struts>

配置后所有action默认拦截器都是permissionStack了,如果当需求需要为某个单独的action引入拦截器,又需要保留默认的拦截器permissionStack,就应该在action下做

以下配置:

		<action name="helloword" class="org.han.action.HelloWorldAction"
			method="execute">
			<result name="success" type="dispatcher">/WEB-INF/page/hello.jsp</result>
			<interceptor-ref name="permissionStack"></interceptor-ref>
			<interceptor-ref name="addpermission"></interceptor-ref>
		</action>

5、方法拦截

Struts2提供MethodFilterInterceptor类,该类是AbstractInerceptor的子类,

protected abstract String doIntercept(ActionInvocation invocation) throws Exception; 
必须重写此方法,实现拦截。

②String interceptor(ActionInvocation invocation):继承自AbstractInterceptor类,方法不需要强制重写

③void setExcludeMethods(String excludeMethods):设置拦截器黑名单,参数为Action一方法名。拦截器不拦截该方法

④void setIncludeMethods(String includeMethods):设置拦截器白名单,参数为Action一方法名。拦截器会拦截该方法

⑤Set<String> getExcludeMethodsSet():获得拦截器的黑名单

⑥Set<String> getIncludeMethodsSet():获得拦截器的白名单

	<package name="de" extends="base">
		<interceptors>
			<interceptor name="permission" class="org.han.interceptor.MethodInterceptor" />
		</interceptors>
		<action name="helloword" class="org.han.action.HelloWorldAction">
			<result name="success" type="dispatcher">/WEB-INF/page/hello.jsp</result>
			<interceptor-ref name="permission">
				<param name="exculdeMethods">execute</param>
				<param name="includeMethods">index</param><!-- 该方法将会被拦截 -->
			</interceptor-ref>
		</action>
	</package>

public class MethodInterceptor extends MethodFilterInterceptor {

	@Override
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		// TODO Auto-generated method stub
	        HelloWorldAction hello=(HelloWorldAction)invocation.getAction();
	        hello.setName("张三");
	        String result=invocation.invoke();
		return result;
	}
}

在使用方法拦截器的action只要不在<param name="exculdeMethods"></param>节点内的当前action方法就会被拦截,当同时出现在黑白名单时也会被拦截。也可以用通配符或逗号隔开表示多个,或组合使用:

				<param name="exculdeMethods">index</param>
				<param name="includeMethods">execute,login</param>

				<param name="exculdeMethods">index*</param>
				<param name="includeMethods">execute</param>

				<param name="exculdeMethods">^index</param>
				<param name="includeMethods">execute</param>

 



抱歉!评论已关闭.