- 这是学习过程的一些记录,可能会有些地方出错,仅供参考
拦截器的介绍
在Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者在定义的action执行的前后加入执行的代码,也可以在一个action执行前阻止其执行。也就是说它提供了一种可以提取action中可重代码,统一管理和执行的方式。
- 拦截器与Fliter过滤器的区别
- 过滤器是所有web开发都能够使用的技术,也就是说filter是web开发中的一种规范,但是拦截器Interceptor是Struts2的一门技术,只有在Struts2中可以使用。
- 在过滤器中,filter能够过滤所有的资源,包括servlet、jsp、html等资源,但是因为拦截器是属于Struts2的技术,所以也就只能拦截Struts2所特有的资源,也就是Action,拦截器只对后缀为action的进行拦截。
- 拦截器的作用
在Struts2中,拦截器可以说是Struts2的核心技术,我们之所以不用关心编码问题,参数封装问题,这都是因为拦截器都帮我们做好了,因此我们可以只专注于业务逻辑的处理,拦截器在内部还帮我们做了许多的事情。
- 拦截器的定义与使用
- 创建拦截器类的两种方式
package com.wzm.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
/*
* 拦截器的第一种创建方式,通过实现接口Interceptor,接口是属于拦截器的最底层,需要实现其中的所有方法
*/
public class MyInterceptor implements Interceptor{
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("Interceptor在action之前执行了");
//invocation.invoke()方法类似于过滤器Filter的放行chain
//在处理完本拦截器的相应逻辑后,将请求交于下一个拦截器,如果没有就直接交于Action执行
//其返回值为Action执行完后的返回值,这个返回值最终要到struts.xml中与result标签对比
String str = invocation.invoke();
System.out.println(str);
//在Action执行完之后,其返回值还会经过拦截器,可以再进行相应逻辑处理
System.out.println("Interceptor在action之后执行了");
//最终将action的返回值送到struts.xml的result中对比
return str;
}
public void destroy() {
// TODO Auto-generated method stub
}
public void init() {
// TODO Auto-generated method stub
}
}
package com.wzm.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.Interceptor;
/*
* 拦截器的第一种创建方式,通过继承AbstractInterceptor,该类实现了Interceptor接口
* 该类只需要我们实现intercept方法
*/
public class MyInterceptor1 extends AbstractInterceptor{
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("Interceptor1在action之前执行了");
//invocation.invoke()方法类似于过滤器Filter的放行chain
//在处理完本拦截器的相应逻辑后,将请求交于下一个拦截器,如果没有就直接交于Action执行
//其返回值为Action执行完后的返回值,这个返回值最终要到struts.xml中与result标签对比
String str = invocation.invoke();
System.out.println(str);
//在Action执行完之后,其返回值还会经过拦截器,可以再进行相应逻辑处理
System.out.println("Interceptor1在action之后执行了");
//最终将action的返回值送到struts.xml的result中对比
return str;
}
}
- 拦截器的定义与使用
<package name="test7" extends="struts-default" namespace="/">
<!-- interceptors用来定义拦截器的 -->
<interceptors>
<!-- interceptor定义一个拦截器,name可以自己定,class为拦截器的全限定名
可以有多个 interceptor
-->
<interceptor name="myInterceptor" class="com.wzm.interceptor.MyInterceptor"></interceptor>
<interceptor name="myInterceptor1" class="com.wzm.interceptor.MyInterceptor1"></interceptor>
<!-- interceptor-stack定义一组拦截器,即将interceptor定义的拦截器包含进来
interceptor-stack可以在里边包含另一组拦截器
-->
<interceptor-stack name="myInterceptorStack">
<!-- 这里需要包含进Struts2中默认的一组拦截器
因为struts2默认的拦截器会帮我们做很多事,例如模型驱动封装就是默认拦截器帮我们做的
如果不包含进来,当我们使用这组拦截器时就只会执行我们自己定义的拦截器
-->
<interceptor-ref name="defaultStack"></interceptor-ref>
<!-- 自己定义的拦截器 -->
<interceptor-ref name="myInterceptor"></interceptor-ref>
<interceptor-ref name="myInterceptor1"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定义好拦截器要使用,这里是在全局使用拦截器,即对整个包下的action有效 -->
<default-interceptor-ref name="myInterceptorStack"></default-interceptor-ref>
<action name="demo8" class="com.wzm.action.ActionDemo8">
<!-- 在action中使用拦截器,即该拦截器只在该action中生效
同时如果全局也有使用拦截器的话,全局的会失效,以action的优先
-->
<interceptor-ref name="myInterceptor"></interceptor-ref>
<result>/ognl.jsp</result>
</action>
</package>
- 对特定方法的拦截
在之前的拦截器都是对action的所有方法进行拦截,这里实现对action的特定的方法进行拦截。
- 创建拦截器
package com.wzm.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
/*
* 在创建拦截器时,不管是实现接口Interceptor还是继承父类AbstractInterceptor,
* 这两种方式都是对action中的所有方法都拦截,也就是说不过请求过来到action的哪个方法都会先执行拦截器
* 而这里的继承MethodFilterInterceptor类。
* 可以实现只对访问某些方法的请求进行拦截,这个底层同样是实现了Interceptor
*/
public class MyInterceptor2 extends MethodFilterInterceptor{
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
System.out.println("MyInterceptor2在action之前执行了");
String string = invocation.invoke();
System.out.println("MyInterceptor2在action只会执行了");
return string;
}
}
- 拦截器的使用
<package name="test8" extends="struts-default" namespace="/">
<interceptors>
<interceptor name="MyInterceptor2" class="com.wzm.interceptor.MyInterceptor2">
<!--
在定义拦截器的时候,在内部添加标签param
includeMethods代表要拦截访问哪些方法的请求
excludeMethods代表不拦截访问哪些方法的请求
方法可以写多个,用逗号隔开
<param name="includeMethods">find</param> -->
<param name="excludeMethods">find</param>
</interceptor>
</interceptors>
<action name="demo9" class="com.wzm.action.ActionDemo8" method="find">
<interceptor-ref name="MyInterceptor2"></interceptor-ref>
</action>
</package>
- Action类
package com.wzm.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.wzm.entity.User;
public class ActionDemo8 extends ActionSupport implements ModelDriven<User>{
//注意,当action实现ModelDriven来封装一个对象时,ModelDriven会把被封装的对象也放在Root区的栈顶
private User user = new User();
public User getModel() {
return user;
}
@Override
public String execute() throws Exception {
System.out.println("execute执行");
return null;
}
public String find() throws Exception {
System.out.println("find执行");
return null;
}
}
Struts2注解的使用
在Struts2中同样有注解,通过使用注解可以代替struts.xml中的部分配置,要使用注解有两个条件。
- 要导入一个struts2解压缩包lib下的包struts2-convention-plugin-2.3.24.jar
- 注解只能在特定的包下使用,只有包名中包含action,actions,struts,struts2下的类才能使用注解。
- 注解的使用
package com.wzm.action;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import com.opensymphony.xwork2.ActionSupport;
/*
* 注解的使用
*/
/*
* @ParentPackage要继承的包,@Namespace命名空间
* 相当于
* <package name="test8" extends="struts-default" namespace="/">
</package>
*/
@ParentPackage("struts-default")
@Namespace("/")
public class ActionDemo9 extends ActionSupport{
/*
* value:访问路径
* results:返回的逻辑页面
* 相当于
* <action name="demo10" class="com.wzm.action.ActionDemo9" method="execute">
* <result name="success" type="dispatcher">/ognl.jsp</result>
* <result name="login" type="redirect">/ognl.jsp</result>
</action>
*/
@Action(value="demo10",results= {
@Result(name="success",type="dispatcher",location="/ognl.jsp"),
@Result(name="login",type="redirect",location="/ognl.jsp")
})
@Override
public String execute() throws Exception {
System.out.println("execute执行");
return null;
}
}
Struts2的工作流程
当tomcat服务器启动,Struts2先加载好各种配置文件,当一个请求过来时,会被前端控制器所拦截,然后就进入到StrutsPrepareAndExecuteFilter中,在其中创建了ActionContext还有ValueStack和Action等对象,然后还创建了ActionMapper对象,通过ActionMapper判断请求资源是否为Action,如果不是就直接正常放行,如果是则会进入到核心程序进行拦截过滤,在核心程序内部会创建一个代理Action,ActionProxy内部会调用ActionInvocation的一个方法invoke,这个方法按顺序会调用拦截器,一个拦截器执行完毕又会调用invoke方法,如果还有拦截器就继续执行,如果没有就执行action,然后action执行完毕就返回一个字符串,这个字符串又会经过之前的所有拦截器到达struts.xml中,在其中与result的name匹配,最终跳转到一个逻辑页面。