com.asm.LoginAction为了简单,com.asm.LoginAction总是返回SUCCESS;这样请求这个Action总会返回到.../success.jsp页面。
编写拦截器:MyInterceptor类,内容如下:
package com.asm;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor; public class MyInterceptor implements Interceptor { }
public void destroy() { }
public void init() { }
public String intercept(ActionInvocation invocation) throws Exception { }
System.out.println(\开始拦截\);
String result = invocation.invoke(); System.out.println(\结束拦截\); return result;
为了使用此拦截器,我们必须将此拦截器进行注册,随后再在要使用此拦截器的Action中引用。即首先在
注册完成后,如果我们要在login.action中使用此拦截器,只需要在中增加如下内容:
这样便成功为LoginAction配置了我们自定义的拦截器MyInterceptor,下面只需发布测试。
实例流程分析:当我们为LoginAction配置了拦截器时,并且有客户端请求此Action时,会首先被此拦截器拦住,然后执行System.out.println(\开始拦截\),随后我们调用invocation.invoke()方法,它会把请求继续传递给下一个拦截器,下一个拦截器也会继续执行相应代码后再调用invoke方法继续传递,直到请求到达最后一个拦截器,它会把请求传递给Action,比如,我们这里只用到了一个拦截器,当它执行完成后,会把请求直接转交到LoginAction处理,LoginAction处理完成后,它会返回结果给MyInterceptor拦截器。
方式二、继承AbstractInterceptor抽象类
创建拦截器类MyAbstractInterceptor:主要代码如下:
package com.asm;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class MyAbstractInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception { }
26
System.out.println(\开始拦截\);
String result = invocation.invoke(); System.out.println(\结束拦截\); return result;
}
然后注册此拦截器,在
随后再在LoginAction中引用此拦截器,即在配置如下内容:
方式三、继承MethodFilterInteceptor类
创建拦截器类MyMethodFilterInterceptor,主要代码如下:
package com.asm;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; public class MyMethodFilterInterceptor extends MethodFilterInterceptor{ }
protected String doIntercept(ActionInvocation invocation) throws Exception { }
System.out.println(\开始拦截\); String result=invocation.invoke(); System.out.println(\结束拦截\); return result;
然后注册此拦截器,在
随后再在LoginAction中引用此拦截器,即在配置如下内容:
最后发布测试。
分析:当配置到此,实质便为LoginAction配置了三个拦截器,当我们点击登录时会在控制台打印出如下语句:
开始拦截 Abs开始拦截 method开始拦截
--先执行拦截器,再执行此Action method结束拦截 Abs结束拦截 结束拦截
其实当我们点击登录时,本来是要访问LoginAction,最后会把LoginAction的执行结果传递给访问者。但是当我们配置了拦截器时,当我们去访问Action时,会首先被拦截,随后拦截器执行一些操作后才会继续把请求传递下去。下面作图说明拦截流程:
27
客户端 执行后续操作,返回处理结果给客当我们访问Login.action时,会首先被第一个拦截器拦截 首先会执行打印语句,随后继续把请求传递给一下个拦截器 MyInterceptor拦截器 接受返回的结果并执行一此后续操作(这里都为打印本拦截器拦截结束),最后再把此结果返回给上一级拦截器 结合现实理解:比如我们要去某楼层找某人(LoginAction)取一个资源(LoginAction处理后返回的结果,这里表现为success.jsp),(1)进楼层时会被大门保安拦截检查(第一个拦截器:MyInterceptor拦截器),(2)检查通过后再进电梯时会被电梯保安员检查(第二个拦截器:MyAbstractInterceptor拦截器),(3)检查通过后再上到某楼层会被楼层保安员检查(第三个拦截器:MethodAction拦截器 ),(4)检查通过后会找到某个(LoginAction),并与某个交谈(LoginAction处理),随后某个人和我们会带着请求的资源出去,(5)出去时,会依次被楼层,电梯,大门保安员检查,最终检查通过。某个人把资源给我们(实质就是返回请求资源给客户端)。 其实拦截器的执行流程和过滤器差不多,所以我们不防用过滤器的眼光来看这些拦截器。
注意:我们在为LoginAction配置拦截器时,都没使用默认的拦截器,是原因这里的测试可以不用,但是以后在我们使用自定义的拦截器是,一定要加上默认的拦截器,否则会导致许多不可预知的结果。 补充:从上面的图并结合代码,我们可以看出拦截器的核心过程应该是ActionInvocation对这些拦截器回调处理,下面我们建立com.asm.interceptor.simulation来模拟这一过程,具体的代码参源文件,在此略去。在此我们作图分析ActionInvocation的实现过程:
由于它是最后一个拦截器,它会把请求转交到LoginAction处理。 MyAbstractInterceptor拦截器 LoginAction处理完成后会返回一个结果(多为jsp页面)给上一个拦截器 MethodAction拦截器 LoginAction 28
ActionInvocatio拦截器一 拦截器二 拦截器N Inteceptor方法 invoke方法 Inteceptor方法 Inteceptor方法 Action 补充2:上面分别使用了三种方式来创建自定义的拦截器,第一种方式是最原始的实现方式,第二种方式的好处是我们可以不必重写所有的方法,较常用。第三种方式进行了扩展,下面将会展示它的扩展性能。
3.使用来MethodFilterInterceptor灵活拦截 步骤一、建立MethodAction,代码如下:
package com.asm;
import com.opensymphony.xwork2.ActionSupport; public class MethodAction extends ActionSupport{ }
public String m1(){ }
public String m2(){ }
public String m3(){ }
return SUCCESS; return SUCCESS; return SUCCESS;
步骤二、注册此Action,并为此Action配置拦截器。配置内容如下:
我们为此Action配置了前面写的MyMethodFilterInterceptor拦截器,并在link.jsp中增加如下链接:
/Method_m1.action\>m1
/Method_m2.action\>m2
/Method_m3.action\>m3
当点m1时会访问到m1Suc.jsp页面, 点m2、m3会分别访问到m2Suc.jsp、m3Suc.jsp页面。现在假如我们想访问m2、m3时不被拦截,我们只需修改MyMethodFilterInterceptor注册:修改内容为:
m2,m3
29
它的作用和增加m1等价。上面是指定m2,m3方法调用时不被拦截,这里是指定只拦截m1。除了这种在注册拦截器时指定拦截外,还可以在引用拦截器时指定,即如下形式:
m2,m3 m1
上面的两处配置是等价的,但是如果〈param〉配置冲突,谁起作用?即如果我们对m1配置了excludeMethods同时又配置了includeMethods时,谁起作用,我们可以进行这些冲突的验证。以下是验证结果:
引用配置(在Action引用拦截器时配置)时,以includeMethods的配置为准。一旦我们为拦截器使用了配置,而对m1这样的方法不配置任何,就不会被拦截。但是如果不使用,它们全部都要被拦截。
注册配置时(在注册拦截器时配置),情况和“引用配置”完全一样。 引用配置和注册配置冲突时,以引用配置为准。 4.使用默认的execAndWait拦截器
当我们进行数据库查询等相关的操作时,如果服务器负荷过重可能不能及时把数据查询出来,进而会在状态拦显示“正在打开...”,但却一直转不到相关的页面,这将给客户端带来不便,甚于很多人会因此不愿使用网站的所有服务。对此我们可以在客户提交时,马上转到一个页面,并在该页面显示“您的请求已提交,服务器正在查询,请等待...”的内容,这样客户将不会陷于无赖的等待中。 对于此要求,struts2可以轻松帮我们完成。下面新建struts2wait项目演示此实例。 建立LoginAction,代码如下:
package com.asm;
public class LoginAction extends ActionSupport { }
public String execute() throws Exception { }
Thread.sleep(5000); return SUCCESS;
说明:为了模拟服务器负荷过重,查询时间要很长。我们在使用了线程休眠的方式。 随后配置此Action,配置的主要内容如下:
注意:在配置前我们先是使用了默认的拦截器,再此强调在我们为Action配置拦截器时,应该总是配上默认的拦截器。随后我们使用了execAndWait拦截器,如需要配置此拦截器,此拦截器一定要配置在最后,否则会出现一些难预知的结果。如果使用此拦截器,我们通常还会配置wait的result结果集,因为“On the initial request or any subsequent requests (before the action has completed), the wait result will be returned. The wait result is responsible for issuing a subsequent request back to the action, giving the effect of a self-updating progress meter”,大概意思就是当我们请求的Action在未执行完,就是未返回结果时,会首先把wait result返回,而在wait result所指定的页面中通常会再次发送请求给原始的Action。所以wait.jsp的主要内容如下:
30