6、拦截器

拦截器(Interceptor):拦截器是struts2的核心,struts2的众多功能都是通过拦截器来实现的。

拦截器的实现与Filter非常类似。

1、拦截器的配置:

1)编写实现Interceptor接口的类。
2)在struts.xml文件中定义拦截器
3)在action中使用

一旦定义了自己的拦截器,将其配置到action上后,我们需要在action的最后加上默认的拦截器栈:defaultStack。

定义一个拦截器:

package com.cdtax.interceptor;

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



public class TheInterceptor1 implements Interceptor
{
	private String test;
	
	public String getTest()
	{
		return test;
	}
	public void setTest(String test)
	{
		this.test = test;
	}
	@Override
	public void destroy()
	{
		
	}
	@Override
	public void init()
	{
		System.out.println("init invoke");
	}
	@Override
	public String intercept(ActionInvocation invocation) throws Exception
	{
		System.out.println("brfore");
		String result = invocation.invoke();
		System.out.println("after");
		return result;
	}
}


在struts.xml进行配置:

<interceptors>
    <interceptor name="theInterceptor1" class="com.cdtax.interceptor.TheInterceptor1">
	<param name="test">cdtax</param>
    </interceptor>
</interceptors>


<action name="action11" class="com.cdtax.struts2.Action1">
	<result name="success" type="redirectAction">
		<param name="actionName">action22</param>
			
		<param name="password">${password}</param>
		<param name="usernameAndpassword">${usernameAndpassword}</param>
		<param name="eee">${ceshi}</param>
	</result>
	<interceptor-ref name="theInterceptor1"></interceptor-ref>			
</action>


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

AbstractInterceptor,是一个对Interceptor接口的默认实现类,就是空实现。

在定义一个拦截器TheInterceptor2:

package com.cdtax.interceptor;

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

public class TheInterceptor2 extends AbstractInterceptor
{

	@Override
	public String intercept(ActionInvocation invocation) throws Exception
	{
		System.out.println("before....");
		System.out.println("interceptor2:" + invocation.getAction().getClass());
		String result = invocation.invoke();
		System.out.println("after.....");
		return result;
	}

}

配置struts.xml

<action name="action11" class="com.cdtax.struts2.Action1">
			<result name="success" type="redirectAction">
				<param name="actionName">action22</param>
				
				<param name="password">${password}</param>
				<param name="usernameAndpassword">${usernameAndpassword}</param>
				<param name="eee">${ceshi}</param>
			</result>
			<interceptor-ref name="theInterceptor1"></interceptor-ref>
			<interceptor-ref name="theInterceptor2"></interceptor-ref>
			<interceptor-ref name="defaultStack"></interceptor-ref>			
		</action>



定义拦截器时可以直接继承AbstractInterceptor抽象类(该类实现了Interceptor接口,并且对init和destroy方法进行了空实现),然后实现其抽象方法intercept。

对于intercept的参数ActionInvocation,它的getAction方法获得与该拦截器相关的Action,如上面的例子,拦截器1和2的System.out.println("interceptor:" + invocation.getAction().getClass());打印的是相同的信息,都是com.cdtax.struts2.Action1

方法拦截器(可以对指定方法进行拦截的拦截器),需要继承抽象类MethodFilterInterceptor,方法拦截器的配置有两个参数,includeMethods和excludeMethods,表示包含哪些方法和排除某些方法。

MethodFilterInterceptor类中有doIntercept()方法和intercept()方法,看一下源代码

public abstract class MethodFilterInterceptor extends AbstractInterceptor {
    protected transient Logger log = LoggerFactory.getLogger(getClass());
    
    protected Set<String> excludeMethods = Collections.emptySet();
    protected Set<String> includeMethods = Collections.emptySet();

    public void setExcludeMethods(String excludeMethods) {
        this.excludeMethods = TextParseUtil.commaDelimitedStringToSet(excludeMethods);
    }
    
    public Set<String> getExcludeMethodsSet() {
    	return excludeMethods;
    }

    public void setIncludeMethods(String includeMethods) {
        this.includeMethods = TextParseUtil.commaDelimitedStringToSet(includeMethods);
    }
    
    public Set<String> getIncludeMethodsSet() {
    	return includeMethods;
    }

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

    protected boolean applyInterceptor(ActionInvocation invocation) {
        String method = invocation.getProxy().getMethod();
        // ValidationInterceptor
        boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, method);
        if (log.isDebugEnabled()) {
        	if (!applyMethod) {
        		log.debug("Skipping Interceptor... Method [" + method + "] found in exclude list.");
        	}
        }
        return applyMethod;
    }
    
    /**
     * Subclasses must override to implement the interceptor logic.
     * 
     * @param invocation the action invocation
     * @return the result of invocation
     * @throws Exception
     */
    protected abstract String doIntercept(ActionInvocation invocation) throws Exception;
    
}


通过set方法,有用逗号分隔的字符串方法:commaDelimitedStringToSet,所以配置中的多个方法用逗号分隔

intercept方法最终也是调用doIntercept()方法,所以我们要重写doIntercept方法。

一个action配置方法拦截器的配置:

<action name="action11" class="com.cdtax.struts2.Action1" method="myExecute">
			<result name="success" type="redirectAction">
				<param name="actionName">action22</param>
				
				<param name="password">${password}</param>
				<param name="usernameAndpassword">${usernameAndpassword}</param>
				<param name="eee">${ceshi}</param>
			</result>
			<interceptor-ref name="theInterceptor1"></interceptor-ref>
			<interceptor-ref name="theInterceptor2"></interceptor-ref>
			<interceptor-ref name="theInterceptor3">
				<param name="includeMethods">execute</param>
				<param name="excludeMethods">myExecute</param>
			</interceptor-ref>
			<interceptor-ref name="defaultStack"></interceptor-ref>			
		</action>


方法过滤拦截器(可以对指定的方法进行拦截的拦截器),在方法过滤拦截器中,如果既没有指定includeMethods参数,也没有指定execludeMethods参数,那么所有的方法都会被拦截,也就是说所有的方法都被认为是includeMethods的,如果仅指定了includeMethods参数,则仅仅拦截指定的方法。

关于intercept的参数ActionInvocation invocation:这个类有一个addPreResultListener方法addPreResultListener(PreResultListener listener),PreResultListener是一个接口,我们要提供实现这个接口的实现类。使用了观察者模式。

一个监听者:

package com.cdtax.listener;

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

public class TheListener implements PreResultListener
{

	@Override
	public void beforeResult(ActionInvocation invocation, String resultCode)
	{
		System.out.println("resultcode: "+resultCode);
	}

}


在拦截器中注册监听器:

package com.cdtax.interceptor;

import com.cdtax.listener.TheListener;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

public class TheInterceptor3 extends MethodFilterInterceptor
{

	@Override
	protected String doIntercept(ActionInvocation invocation) throws Exception
	{
		invocation.addPreResultListener(new TheListener()); 
		System.out.println("befor interceptor3...");
		 String  result = invocation.invoke();
		 System.out.println("after interceptor3...");
		 return result;
	}

}

监听器的执行时机:是在action执行后:String result = invocation.invoke();,但是还没有渲染前System.out.println("after interceptor3...");

配置默认的拦截器

定义一个拦截器栈:

在<interceptors></interceptors>标签内

<interceptor-stack name="myDefaultInterceptorStack">
			<interceptor-ref name="loginInterceptor"></interceptor-ref>
			<interceptor-ref name="defaultStack"></interceptor-ref>
		</interceptor-stack>


然后在<interceptors></interceptors>标签外定义:

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


这样我们自己定义的拦截器栈就应用到每一个action上了,为了将某些action排除在外,只能在拦截器中进行处理,如在LoginInterceptor中:

package com.cdtax.interceptor;

import java.util.Map;

import com.cdtax.struts2.LoginAction;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class LoginInterceptor extends AbstractInterceptor
{

	@Override
	public String intercept(ActionInvocation invocation) throws Exception
	{
		if(LoginAction.class == invocation.getAction().getClass())
		{
			return invocation.invoke();
		}
		
		Map map = invocation.getInvocationContext().getSession();
		
		if(null == map.get("userInfo"))
		{
			return Action.LOGIN;
		}
		
		return invocation.invoke();
	}

}

 

将配置文件拆分开来,一个主xml文件:struts.xml,而相应的配置放在其他xml文件中,主xml包含相应的分xml就行,如有分xml:struts_1.xml,struts_2.xml,都放在src目录下,则struts.xml中通过如下语句包含:

<include file="struts_1.xml" />
<include file="struts_2.xml" />


 

 

 

你可能感兴趣的:(6、拦截器)