Interceptor(拦截器) |
拦截器:Interceptor
------------------------------
拦截器:Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.
AOP:面向切面编程.其实现原理:动态代理模式--->留给Spring
WebWork中文文档解释:拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个Action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也提供了一种可以提取Action中可重用的代码的方式。
拦截器栈(InterceptorStack):Struts2拦截器栈就是将拦截器按一定的顺序连接成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
-------------------------------------------------------------------------
拦截器的"美":
---------------------------------------------------
DRY原则:Dont'tRepeat Yourself.
拦截器在设计和程序结构上的优点:
拦截器能把很多功能从Action中独立出来,分散到不同的拦截器里面,减少了Action的代码。如此,拦截器和Action本身的功能都更单一了。当通用的功能代码被封装在拦截器里面(代码模块化),就可以对不同的Action,根据功能需要,来配置相应功能的拦截器了。提高了拦截器所实现的功能的重用性,也变相实现了装配式和可插拔式的体系结构,使得整个系统结构变得更灵活。
1.简化Action的实现
2.功能更单一
3.通用代码模块化
4.提高重用性
----------------------------------------------------
Struts2内置的拦截器 |
Struts2中内置的拦截器:
在struts-core-2.5.x.jar--->struts-default.xml中 (里面这个是默认的struts2配置文件)
------------------------------------------
常见的拦截器:
1:params拦截器
这个拦截器偷偷的把请求参数设置到相应的Action的属性去的,并自动进行类型转换。
2.modelDriven拦截器
如果Action实现ModelDriven接口,它将getModel()取得的模型对象存入OgnlValueStack中。
3.execption拦截器
顾名思义,在抛出异常的时候,这个拦截器起作用。最好把它放在第一位,让它能捕获所有的异常。
4.validation拦截器
调用验证框架读取 *-validation.xml文件,并且应用在这些文件中声明的校验。
5.token拦截器
核对当前Action请求(request)的有效标识,防止重复提交Action请求。
6.fileUpload拦截器
用来处理文件上传
7.workflow拦截器
调用Action的validate方法,一旦有错误返回,重新定位到INPUT结果视图
8.servletConfig
通过感知接口,获取感应对象
自定义拦截器 |
package clu.mochunrong.interceptor_action;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class InterceptorAction extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
HttpSession session = ServletActionContext.getRequest().getSession();
String username = (String) session.getAttribute("USERNAME_IN_SESSION");
if (username != null) {
System.out.println("放行");
return invocation.invoke();
}else {
System.out.println("拦截了");
return "abc";
}
}
}
struts2配置文件:
<package name="loginpkg" extends="struts-default" namespace="/a">
<interceptors>
<interceptor name="myinterceptor" class="clu.mochunrong.interceptor_action.InterceptorAction"/>
<interceptor-stack name="mystack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="myinterceptor" />
</interceptor-stack>
</interceptors>
<global-results>
<result name="abc" type="dispatcher">
<param name="location">/views/jsp/login.jsp</param>
</result>
</global-results>
<action name="b" class="clu.mochunrong.login_action.LoginAction">
<interceptor-ref name="mystack"/>
<result name="SUCCESS" type="redirectAction">
<param name="actionName">main</param>
</result>
</action>
<action name="main">
<result>/views/jsp/login_success.jsp</result>
</action>
</package>
LoginAction.java:
package clu.mochunrong.login_action;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String username;
private String password;
@Override
public String execute() throws Exception {
System.out.println("--------execute---------------");
System.out.println("--------username----------"+username);
System.out.println("--------password----------"+password);
ActionContext.getContext().getSession().put("USERNAME_IN_SESSION", username);
return "SUCCESS";
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
User.java:
package clu.mochunrong.login_action;
public class User {
private String name;
private int age;
public User() {
System.out.println("----User--------");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
拦截器的使用细节 |
上述拦截器的定义和使用都是没问题的.
但是,如果有多个<action>元素都需要改拦截器,那么每一个<action>元素中都得去引用该拦截器,很烦.
解决方案:在<package>中设置全局的拦截器引用,针对于该<package>中所有的<action>元素都有效.
---------------------------------------------------------------
问题1:此时在LoginAction中再也获取不了请求参数.
原因是:当我们在<package>设置了默认的拦截器引用,那么<package>之前的默认的拦截器栈(defaultStack)就不引用了,那么defaultStack中的获取请求参数的拦截器也不再引用.
问题2:登陆失败,永远进步了login的这个Action.
原因是:进入login之前,需要判断session中是否有USER_IN_SESSION.
而USER_IN_SESSION只有在login中才能设置.
结论:login这个action不需要做登陆检查.