假如这个世界上只剩下你一个人,当你正坐在屋子里的时候,这时突然响起了敲门声...

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

上一篇 / 下一篇  2008-05-09 20:57:58

查看( 46 ) / 评论( 0 )
本文为原创,如需转载,请注明作者和出处,谢谢!ITPUB个人空间2`)B8Rg:g

f;aIP/~iv0    在上一篇中介绍了Struts2拦截器的原理,在这一篇中我们将学习一下如何编写自己的拦截器。ITPUB个人空间6Na)E J'G
ITPUB个人空间"Z/GF] R1`
一、拦截器的实现
+}Qe Bfd0     实现一个拦截器非常简单。实际上,一个拦截器就是一个普通的类,只是这个类必须实现com.opensymphony.xwork2.interceptor.Interceptor接口。Interceptor接口有如下三个方法:ITPUB个人空间1D)m$G&~P"i
ITPUB个人空间#M?B@+W)g6[
ITPUB个人空间E$r:I;Q"["D6k:h0u6eok
public interface Interceptor extends Serializable
M+R y6Og9SC0{
,`7Z#Usl u @0    void destroy();ITPUB个人空间Vr|+O+r+[_,He
    void init();ITPUB个人空间5S4kFC;Q-Fj$@A&e1I
    String intercept(ActionInvocation invocation) throws Exception;
?;o(I.T3a(T]a0}
?#y+}JG_ Y0ITPUB个人空间OH\2M#|C|
其中init和destroy方法只在拦截器加载和释放(都由Struts2自身处理)时执行一次。而intercept方法在每次访问动作时都会被调用。Struts2在调用拦截器时,每个拦截器类只有一个对象实例,而所有引用这个拦截器的动作都共享这一个拦截器类的对象实例,因此,在实现Interceptor接口的类中如果使用类变量,要注意同步问题。ITPUB个人空间-D.a^3I!I

#MMUGP_-t8I}/Jf0下面我们来实现一个简单的拦截器,这个拦截器通过请求参数action指定一个拦截器类中的方法,并调用这个方法(我们可以使用这个拦截器对某一特定的动作进行预处理)。如果方法不存在,或是action参数不存在,则继续执行下面的代码。如下面的URL:ITPUB个人空间6R6~-o9?!c{9k
ITPUB个人空间'j&[i1}4~y
http://localhost:8080/struts2/test/interceptor.action?action=test
B ~ J DF.J |G M0
`*d2gJn6svX:}0访问上面的url后,拦截器会就会调用拦截器中的test方法,如果这个方法不存在,则调用invocation.invoke方法,invoke方法和Servlet过滤器中调用FilterChain.doFilter方法类似,如果在当前拦截器后面还有其他的拦截器,则invoke方法就是调用后面拦截器的intercept方法,否则,invoke会调用Action类的execute方法(或其他的执行方法)。ITPUB个人空间(_!k r-Wd&t

E4Y&ePR'w}0下面我们先来实现一个拦截器的父类ActionInterceptor。这个类主要实现了根据action参数值来调用方法的功能,代码如下:ITPUB个人空间VIu)k1y

9hf1oaR X qoS0
`K8\&`7]:E'M-Q[!im0package interceptor;ITPUB个人空间#jh%Sh-^-o!JV
ITPUB个人空间{8r/X4|5Gp/w ]@\
import com.opensymphony.xwork2.ActionInvocation;ITPUB个人空间W QTe0c ?
import com.opensymphony.xwork2.interceptor.Interceptor;ITPUB个人空间e5`o/Q,iv-Y
import javax.servlet.http.*;
B{5Q,a8x#}0import org.apache.struts2.*;
J4y2d(w-I ~)m+b{6P0ITPUB个人空间F ?F;}0u"O5@
public class ActionInterceptor implements Interceptor
f;n9I(@ D:KLm0{ITPUB个人空间 s-c2L/K&^t;ss x8M
    protected final String INVOKE = "##invoke";ITPUB个人空间 |h0h4V9e$R,_ D*c;qm
   
;[&bL8vk2_%B/X-X0    public void destroy()
9B/RCV*Q0    {ITPUB个人空间 w$f @2?0w&W$Z(A#i
        System.out.println("destroy");
3j5]*m n0jA#U0    }
8i0}#g,Z4Gy0ITPUB个人空间N~g3a0^.SR:_)k:E
    public void init()
P3r/m1l X+kU0    {ITPUB个人空间!|$|{$V)P#}F"C
        System.out.println("init");ITPUB个人空间8U&J~b(yr.v
    }ITPUB个人空间*dAYu H T N!_
ITPUB个人空间u8s i&E6g6}9k
    public String intercept(ActionInvocation invocation) throws Exception
;C J&a} I#FIqKL!?K0    {   
vw/}/cAG hX0        HttpServletRequest request = ServletActionContext.getRequest();
@'@,N\d7l/pY0        String action = request.getParameter("action");
%N]i/}]-m0        System.out.println(this.hashCode());ITPUB个人空间7^fi#m8kV:e
        if (action != null)
im2YpR'R.cOf0        {ITPUB个人空间:`Djt?
            tryITPUB个人空间*]J(cct9s r
            {
O2Um yr0                java.lang.reflect.Method method = this.getClass().getMethod(action);
Y/w1qd`N!W0                String result = (String)method.invoke(this);
cEJ2J e%@0                if(result != null)ITPUB个人空间| MGs$c'z \N"N
                {ITPUB个人空间*kdE;E6d D
                    if(!result.equals(INVOKE))ITPUB个人空间.P8~Bu"y5Sw
                        return result;ITPUB个人空间x}cm?q4IQ
                }
B2rSGBL(_lT9|d0                elseITPUB个人空间#Eu3xM"O}x'f1e
                    return null;ITPUB个人空间:MV a L*L Y z O
            }ITPUB个人空间E'mp [\| Y
            catch (Exception e)ITPUB个人空间u \K(fw
            {ITPUB个人空间&B YM-p1ed,Mj$H4BK;w
            }
-m,r(D2?4e"^5\ H0        }ITPUB个人空间r+o2VG4VTvvf3s
        return invocation.invoke();ITPUB个人空间/o dD vp2]G
    }ITPUB个人空间F H4k*{(?
}
t5RD]d5|SVy^0
pR)x Ip Y Z9~0从上面代码中的intercept方法可以看出,在调用action所指定的方法后,来判断返回值。可能发生的情况有三种:ITPUB个人空间 P)Qa o K.C9N:k

:w*|z_BZ)](BY!b2fy01.        返回值为null,执行return null。ITPUB个人空间%tVb/u'N5W
ITPUB个人空间1zX U)A$}R
2.        返回值为INVOKE,执行return invockation.invoke()。
.S#EL6R i%p0
Rg d(G,}03.        其他情况,执行return result。 result表示指定方法的返回值,如上面代码所示。ITPUB个人空间ym.nsK/Ti\)?.[
    在实现完上面的拦截器父类后,任何继承于ActionInterceptor类的拦截器都可以自动根据action的参数值调用自身的相应方法。下面我们来实现一个拥有两个动作方法test和print的拦截器类。代码如下:ITPUB个人空间al7{;b*x
ITPUB个人空间3oZ6z/A1P5y6~

5?Y]0F4y0package interceptor;
&Gp K ^Z)Kk0ITPUB个人空间qD8@uw {,sc
import javax.servlet.http.HttpServletResponse;
JV/]Z#E;oz;Y0import org.apache.struts2.ServletActionContext;
7B[wk\ u0f-RJU0
z U5~|)K| _H m0public class MultiMethodInterceptor extends ActionInterceptor
p'A!t_"~0{
y"JPA-W0    public String test() throws ExceptionITPUB个人空间X;J} h Vf)}%u
    {
m8yO'H)F4H0        HttpServletResponse response = ServletActionContext.getResponse();
$s_y y`K X0        response.getWriter().println("invoke test");
8I;Z uy6a]U_F0        return this.INVOKE;ITPUB个人空间4q,R3I9` `
    }ITPUB个人空间'h9E/ny#H0h\si0n

N%Ej@ gt @Tq-d9o0    public String print() throws Exception
%K,}4Hm~9ty2u#n0    {
'}u[^8d.o7l7k)@0        HttpServletResponse response = ServletActionContext.getResponse();
9Y.K8eJ2@|D0        response.getWriter().println("invoke print");
gjd U;\0BY+K;~ g0ITPUB个人空间\ zb6D+k`L\6I W
        return null;
H1Y/B$b`~0    }
'Bm~Q?hu0}ITPUB个人空间Y.E^ur:LS

jb2b m,|3\#n,AP2@0test方法返回了INVOKE,因此,在执行完这个方法后,Struts2会接着调用其他拦截器的intercept方法或Action类的execute方法。而print方法在执行完后,只是返回了null,而不再调用其他的方法了,也就是访问如下的url时,动作的execute方法将不会执行:ITPUB个人空间d8j;D%{U9I3k"v
ITPUB个人空间7npa o!FB
    http://localhost:8080/struts2/test/ddd.action?action=print
BQ Rzi0    下面我们来实现一个Action类,代码如下:
%Js c@c+iNNQ0
BAG6\weAa0package action;
4Q P \Q6?7G$V%gQ Bf0
R R#kPgW#f0import org.apache.struts2.*;
[q:Z'X#vR)q9MZ f0import com.opensymphony.xwork2.ActionSupport;ITPUB个人空间CkOHEa#y:t0e5h
ITPUB个人空间p\!X:y jM
public class InterceptorAction extends ActionSupport
S Nj&w'E&K@8\j'j0{ITPUB个人空间 Z d]z/_p
    public String abcd() throws Exception
z5A$C2@Pr0O0    {
Y`!LY[D"N0        ServletActionContext.getResponse().getWriter()ITPUB个人空间l tc(? Rg9\^,^J-F.V
                .println("invoke abcd");ITPUB个人空间 Q%tM;P/h2o:t
        return null;ITPUB个人空间]GDf:H3w"fA,b5Q
    }
9t4F2l%MN!Z0}
J|j1pE0
Ki)NN^8CgRaZ&n0在这个Action类中,只有一个abcd方法,实际上,这个方法相当于execute方法,在下面会设置动作的method属性为abcd。下面我们来在struts.xml中定义拦截器类和动作,代码如下:ITPUB个人空间X$_g#H4St
ITPUB个人空间!bCI\3S
<?xml version="1.0" encoding="UTF-8" ?>
"gNE/h+P'xY2y0<!DOCTYPE struts PUBLICITPUB个人空间"K(t0U1vf&t AH
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
(?1C"lcA,u3AQIN|sL0    "http://struts.apache.org/dtds/struts-2.0.dtd">ITPUB个人空间_-Xpy"oA k+?*}
<struts>ITPUB个人空间2~dC1O#J!i
    <package name="demo" extends="struts-default" namespace="/test">ITPUB个人空间v Kfhxvu*T
        <interceptors>
8q^!S zl0            <interceptor name="method" class="interceptor.MultiMethodInterceptor" />
3in7_s'nI0F0                <interceptor-stack name="methodStack">
&Vn} { \Y0                    <interceptor-ref name="method" />
0p|Qa^4]MN"\&se0                    <interceptor-ref name="defaultStack" />
hU ob)~o.q0                </interceptor-stack>ITPUB个人空间v p A&] L
        </interceptors>
b3lh:d\)s5y0ITPUB个人空间,C+|L-C\7j.G DiZ
        <action name="interceptor" class="action.InterceptorAction" method="abcd">ITPUB个人空间A`;eg'JB5Q^W
            <interceptor-ref name="methodStack" />ITPUB个人空间.mnL@,V?i n
        </action>ITPUB个人空间c$Q:~y`go
    </package>
C'P u s4m#p9q0</struts>
(|'w#?,rd3S U!~0ITPUB个人空间pGzy:V
在配置上面的methodStack拦截器时要注意,最好在后面引用defaultStack,否则很多通过拦截器提供的功能将失去。ITPUB个人空间|"f c|zH7r

rX4r#p,hs/C0OK,现在访问如下的URL:ITPUB个人空间Ry&^^[:ak/bT

"TcXC7~0    http://localhost:8080/struts2/test/ddd.action?action=test
O)Z H+dfx'c6gm0
V;DcrJ0在浏览器中将会出现如下的字符串:ITPUB个人空间${GSzao&],@
ITPUB个人空间;R2[ g} F$fx
    invoke testITPUB个人空间Z*]`8N e/F'A
ITPUB个人空间[W0I,X*kZ"}1Zr G
invoke abcdITPUB个人空间*eV.B S?

1UK#u'BMw/H:Q&I0而如果访问http://localhost:8080/struts2/test/ddd.action?action=print,将会只出现如下的字符串:
p'K T,uG7C7eb0ITPUB个人空间3DP[/|5t zrNT
    invoke print
Z_%Z4{G,n*p0ITPUB个人空间7kN"L|D+V z
大家可以看出,访问这个url时并没有调用abcd方法。如果随便指定的action值的话,则只调用abcd方法,如访问http://localhost:8080/struts2/test/ddd.action?action=aaa,就只会输出invoke abcd。
H3X/}|/zQ0
cY@;x"H0ITPUB个人空间q0K'_0e8|+|
二、拦截器的参数
2B/SqJr3A5J0
D7xqLZ @e'h0    我们在使用很多Struts2内置的拦截器时会发现有很多拦截器都带参数,当然。我们自己做的拦截器也可以加上同样的参数。有两个参数比较常用,这两个参数是includeMethods和excludeMethods,其中includeMethods指定了拦截器要调用的Action类的执行方法(默认是execute),也就是说,只有在includeMethods中指定的方法才会被Struts2调用,而excludeMethods恰恰相反,在这个参数中指定的执行方法不会被Struts2调用。如果有多个方法,中间用逗号(,)分隔。在Struts2中提供了一个抽象类来处理这两个参数。这个类如下:ITPUB个人空间-Xd;~O2@YfG {u
ITPUB个人空间I3mgPP/vh6gD
com.opensymphony.xwork2.interceptor.MethodFilterInterceptorITPUB个人空间3H&yd"mR k

ri#N;?"SSRa0    如有继承于这个类的拦截器类都会自动处理includeMethods和excludeMethods参数,如下面的拦截器类所示:
_c}:G%Ma'~0ITPUB个人空间(_*Q7`0f~a0GS4^,Vi
package interceptor;
i:gp8YM7FN.m0ITPUB个人空间$E*N`O3eK @+m
import com.opensymphony.xwork2.ActionInvocation;
_+hL.q*P0import com.opensymphony.xwork2.interceptor.*;ITPUB个人空间4wv9FV6g:E

#@@`R Yf!tgU9W8_3A"H0public class MyFilterInterceptor extends MethodFilterInterceptorITPUB个人空间0|8u5w:vj`1U&P1hc
{ITPUB个人空间6[2t*h,w6~7P(Xt"Ti
    private String name;ITPUB个人空间hj1b+s1Q^sM
    public String getName()ITPUB个人空间)F#k.Ha0k
    {
;X n7]1dIs F8W0        return name;
f ~/O7ueF"K%^0    }
8^ Tb;Ud$pS*a0    public void setName(String name)ITPUB个人空间1?(Xb/yYCQ J3M
    {ITPUB个人空间F*f;az f]u
        this.name = name;
~ `1lkTK^Z0    }
9]#s`F0yb6H0    @OverrideITPUB个人空间*i)cr6~@0{6nO"C
    protected String doIntercept(ActionInvocation invocation) throws Exception
k$v*` qHz&H{P0    {ITPUB个人空间$Wty JU7q
        System.out.println("doIntercept");ITPUB个人空间9j0P']2B%u-o n
        System.out.println(name);ITPUB个人空间 } XC:WAW
        return invocation.invoke();
q0YD4~;u,n0    }ITPUB个人空间 I7K2q;Q#L*p
}ITPUB个人空间KPz:b8j

rY?-] bU;W)Q r0    MethodFilterInterceptor的子类需要实现doIntercept方法(相当于Interceptor的intercept方法),如上面代码所示。在上面的代码中还有一个name属性,是为了读取拦截器的name属性而设置的,如下面的配置代码所示:
*}JxO y+N4V _0ITPUB个人空间~6B*ovT"AO_ V

L a$v2Ou3h@CZ:R]5N0<?xml version="1.0" encoding="UTF-8" ?>
F-[ L\e6|0<!DOCTYPE struts PUBLIC
"P4ozHbkT0    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"ITPUB个人空间4W2h x x'Ng
    "http://struts.apache.org/dtds/struts-2.0.dtd">ITPUB个人空间,ot#^ c(d{d2f
<struts>ITPUB个人空间2O'|oJH v
    <package name="demo" extends="struts-default" namespace="/test">
7i2PpA8f%r%o$d0        <interceptors>ITPUB个人空间it2Q.sN'W;g
            <interceptor name="method" class="interceptor.MultiMethodInterceptor" />
}%L7w?Bm0                <interceptor name="filter"ITPUB个人空间mQ1H%w ql'v:zZ'c
                    class="interceptor.MyFilterInterceptor">ITPUB个人空间y(r M-?&AN ~n
                    <param name="includeMethods">abcd</param>
Y F4_fYB0                    <param name="name">中国</param>ITPUB个人空间;k!M,n w1J0p0{$O j
                </interceptor>ITPUB个人空间-E'Kp8{WhN w
                <interceptor-stack name="methodStack">
8P+m&j"DE)G u.O0                    <interceptor-ref name="method" />
bAt5Pe yYC0                    <interceptor-ref name="filter" />
q ~"` C(JX0                    <interceptor-ref name="defaultStack" />
H#k\:ZEkM-d0                </interceptor-stack>
F-aTG8s C0        </interceptors>ITPUB个人空间!G\6[bo!p r2w+D
ITPUB个人空间/R1f'_3w/P A{$K%B
        <action name="interceptor" class="action.InterceptorAction" method="abcd">ITPUB个人空间!u'f ^)F^*P
            <interceptor-ref name="methodStack" />ITPUB个人空间2A~\p3J.ws-p4I{ T
        </action>
pO+E5P |7X0    </package>
e ?)\;V~0</struts>ITPUB个人空间;\ KH8XAp_`c-s4i

f7yw{PX_2g^h0    再次访问http://localhost:8080/struts2/test/ddd.action?action=test, Struts2就会调用MyFilterInterceptor的doIntercept方法来输出name属性值。如果将上面的includeMethods参数值中的abcd去掉,则Action类的abcd方法不会被执行。

TAG:

我来说两句

(可选)

日历

« 2008-05-17  
    123
45678910
11121314151617
18192021222324
25262728293031

数据统计

  • 访问量: 3739
  • 日志数: 83
  • 建立时间: 2008-02-08
  • 更新时间: 2008-04-25

RSS订阅

Open Toolbar