Struts2教程9:实现自已的拦截器

本文介绍如何在Struts2中实现自定义拦截器,包括拦截器的基本实现及如何利用拦截器调用Action类的不同方法。同时讲解了拦截器参数的使用方法。

本文为原创,如需转载,请注明作者和出处,谢谢!

在上一篇中介绍了Struts2拦截器的原理,在这一篇中我们将学习一下如何编写自己的拦截器。

一、拦截器的实现

实现一个拦截器非常简单。实际上,一个拦截器就是一个普通的类,只是这个类必须实现 com.opensymphony.xwork2.interceptor.Interceptor 接口。 Interceptor 接口有如下三个方法:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> public interface Interceptor extends Serializable
{
void destroy();
void init();
Stringintercept(ActionInvocationinvocation)
throws Exception;
}

其中init和destroy方法只在拦截器加载和释放(都由Struts2自身处理)时执行一次。而intercept方法在每次访问动作时都会被调用。Struts2在调用拦截器时,每个拦截器类只有一个对象实例,而所有引用这个拦截器的动作都共享这一个拦截器类的对象实例,因此,在实现Interceptor接口的类中如果使用类变量,要注意同步问题。

下面我们来实现一个简单的拦截器,这个拦截器通过请求参数action指定一个拦截器类中的方法,并调用这个方法(我们可以使用这个拦截器对某一特定的动作进行预处理)。如果方法不存在,或是action参数不存在,则继续执行下面的代码。如下面的URL:

http://localhost:8080/struts2/test/interceptor.action?action=test

访问上面的url后,拦截器会就会调用拦截器中的test方法,如果这个方法不存在,则调用invocation.invoke方法,invoke方法和Servlet过滤器中调用FilterChain.doFilter方法类似,如果在当前拦截器后面还有其他的拦截器,则invoke方法就是调用后面拦截器的intercept方法,否则,invoke会调用Action类的execute方法(或其他的执行方法)。

下面我们先来实现一个拦截器的父类ActionInterceptor。这个类主要实现了根据action参数值来调用方法的功能,代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> package interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import javax.servlet.http. * ;
import org.apache.struts2. * ;

public class ActionInterceptor implements Interceptor
{
protected final StringINVOKE = " ##invoke " ;

public void destroy()
{
System.out.println(
" destroy " );
}

public void init()
{
System.out.println(
" init " );
}

public Stringintercept(ActionInvocationinvocation) throws Exception
{
HttpServletRequestrequest
= ServletActionContext.getRequest();
Stringaction
= request.getParameter( " action " );
System.out.println(
this .hashCode());
if (action != null )
{
try
{
java.lang.reflect.Methodmethod
= this .getClass().getMethod(action);
Stringresult
= (String)method.invoke( this );
if (result != null )
{
if ( ! result.equals(INVOKE))
return result;
}
else
return null ;
}
catch (Exceptione)
{
}
}
return invocation.invoke();
}
}

从上面代码中的intercept方法可以看出,在调用action所指定的方法后,来判断返回值。可能发生的情况有三种:

1. 返回值为null,执行return null。

2. 返回值为INVOKE,执行return invockation.invoke()。

3. 其他情况,执行return result。result表示指定方法的返回值,如上面代码所示。

在实现完上面的拦截器父类后,任何继承于

ActionInterceptor

类的拦截器都可以自动根据 action 的参数值调用自身的相应方法。下面我们来实现一个拥有两个动作方法 testprint 的拦截器类。代码如下:


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> package interceptor;

import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;

public class MultiMethodInterceptor extends ActionInterceptor
{
public Stringtest() throws Exception
{
HttpServletResponseresponse
= ServletActionContext.getResponse();
response.getWriter().println(
" invoketest " );
return this .INVOKE;
}

public Stringprint() throws Exception
{
HttpServletResponseresponse
= ServletActionContext.getResponse();
response.getWriter().println(
" invokeprint " );

return null ;
}
}

test方法返回了INVOKE,因此,在执行完这个方法后,Struts2会接着调用其他拦截器的intercept方法或Action类的execute方法。而print方法在执行完后,只是返回了null,而不再调用其他的方法了,也就是访问如下的url时,动作的execute方法将不会执行:

http://localhost:8080/struts2/test/ddd.action?action=print

下面我们来实现一个 Action 类,代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> package action;

import org.apache.struts2. * ;
import com.opensymphony.xwork2.ActionSupport;

public class InterceptorAction extends ActionSupport
{
public Stringabcd() throws Exception
{
ServletActionContext.getResponse().getWriter()
.println(
" invokeabcd " );
return null ;
}
}

在这个Action类中,只有一个abcd方法,实际上,这个方法相当于execute方法,在下面会设置动作的method属性为abcd。下面我们来在struts.xml中定义拦截器类和动作,代码如下:


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> <? xmlversion="1.0"encoding="UTF-8" ?>
<! DOCTYPEstrutsPUBLIC
"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"
>
< struts >
< package name ="demo" extends ="struts-default" namespace ="/test" >
< interceptors >
< interceptor name ="method" class ="interceptor.MultiMethodInterceptor" />
< interceptor-stack name ="methodStack" >
< interceptor-ref name ="method" />
< interceptor-ref name ="defaultStack" />
</ interceptor-stack >
</ interceptors >

< action name ="interceptor" class ="action.InterceptorAction" method ="abcd" >
< interceptor-ref name ="methodStack" />
</ action >
</ package >
</ struts >

在配置上面的methodStack拦截器时要注意,最好在后面引用defaultStack,否则很多通过拦截器提供的功能将失去。

OK,现在访问如下的URL:

http://localhost:8080/struts2/test/ddd.action?action=test

在浏览器中将会出现如下的字符串:

invoke test

invoke abcd

而如果访问http://localhost:8080/struts2/test/ddd.action?action=print,将会只出现如下的字符串:

invoke print

大家可以看出,访问这个url时并没有调用abcd方法。如果随便指定的action值的话,则只调用abcd方法,如访问http://localhost:8080/struts2/test/ddd.action?action=aaa,就只会输出invoke abcd。


二、拦截器的参数

我们在使用很多Struts2内置的拦截器时会发现有很多拦截器都带参数,当然。我们自己做的拦截器也可以加上同样的参数。有两个参数比较常用,这两个参数是includeMethods和excludeMethods,其中includeMethods指定了拦截器要调用的Action类的执行方法(默认是execute),也就是说,只有在includeMethods中指定的方法才会被Struts2调用,而excludeMethods恰恰相反,在这个参数中指定的执行方法不会被Struts2调用。如果有多个方法,中间用逗号(,)分隔。在Struts2中提供了一个抽象类来处理这两个参数。这个类如下:

com.opensymphony.xwork2.interceptor.MethodFilterInterceptor

如有继承于这个类的拦截器类都会自动处理 includeMethodsexcludeMethods 参数,如下面的拦截器类所示:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> package interceptor;

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

public class MyFilterInterceptor extends MethodFilterInterceptor
{
private Stringname;
public StringgetName()
{
return name;
}
public void setName(Stringname)
{
this .name = name;
}
@Override
protected StringdoIntercept(ActionInvocationinvocation) throws Exception
{
System.out.println(
" doIntercept " );
System.out.println(name);
return invocation.invoke();
}
}

MethodFilterInterceptor 的子类需要实现 doIntercept 方法(相当于 Interceptorintercept 方法),如上面代码所示。在上面的代码中还有一个 name 属性,是为了读取拦截器的 name 属性而设置的,如下面的配置代码所示:


<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> <? xmlversion="1.0"encoding="UTF-8" ?>
<! DOCTYPEstrutsPUBLIC
"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"
>
< struts >
< package name ="demo" extends ="struts-default" namespace ="/test" >
< interceptors >
< interceptor name ="method" class ="interceptor.MultiMethodInterceptor" />
< interceptor name ="filter"
class
="interceptor.MyFilterInterceptor" >
< param name ="includeMethods" > abcd </ param >
< param name ="name" > 中国 </ param >
</ interceptor >
< interceptor-stack name ="methodStack" >
< interceptor-ref name ="method" />
< interceptor-ref name ="filter" />
< interceptor-ref name ="defaultStack" />
</ interceptor-stack >
</ interceptors >

< action name ="interceptor" class ="action.InterceptorAction" method ="abcd" >
< interceptor-ref name ="methodStack" />
</ action >
</ package >
</ struts >

再次访问 http://localhost:8080/struts2/test/ddd.action?action=test, Struts2 就会调用

MyFilterInterceptor

doIntercept

方法来输出

name

属性值。如果将上面的

includeMethods

参数值中的

abcd

去掉,则

Action

类的

abcd

方法不会被执行。

《银河系列原创教程》发布

《Java Web开发速学宝典》出版,欢迎定购
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值