拦截器针对的是action请求,struts2提供了众多拦截器,用户也可根据需要自定义拦截器。struts2的拦截器是通过代理(AOP)来实现的。struts2的拦截器是单例的,所有action共享,在定义常量时应注意线程安全问题。
一、struts2的默认拦截器
struts2的默认拦截器在struts-default.xml中的struts-default包下,所以要使用默认提供的拦截器,应该使package直接或者间接继承struts-default。
日常pojo、action以及xml如下
public class User {
private String name;
private String psw;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
}
public class LoginAction implements ModelDriven<User> {
private User user;
@Override
public User getModel() {
return user = new User();
}
public String login(){
if(user != null){
System.out.println(user.getName()+"/"+user.getPsw());
}else {
System.out.println("user is null");
}
return Action.SUCCESS;
}
}
<%@taglib prefix="s" uri="/struts-tags" %> <!-- A -->
<form action="login.action" method="post">
<s:token></s:token> <!-- B -->
name:<input type="text" name="name"/><br/>
password:<input type="text" name="psw"/><br/>
<input type="submit" />
</form>
<package name="default" namespace="/" extends="struts-default">
<action name="login" class="com.action.LoginAction" method="login">
<result>/index.jsp</result>
<!-- 在要用拦截器的action中引用拦截器 -->
<!-- 拦截器是类似于重定向吗?会清除请求数据 -->
<interceptor-ref name="timer"></interceptor-ref>
<interceptor-ref name="token"></interceptor-ref> <!-- C -->
</action>
</package>
如上所示,使用默认提供的拦截器timer,只需在struts.xml配置文件中的对应action中配置即可,形如
<interceptor-ref name="the default interceptor name"></interceptor-ref>
而使用 token ,用于防止表单重复提交,这需要进行 A、B和C操作,重复提交对应结果集 <result name="invalid.token"></result> 。
timer拦截器会计算业务方法的执行时间,如果log4j配置完毕,会在console输出时间
此处本人存在疑问,如果使用拦截器,执行action处理类的login方法时,user是为null的,难道拦截器对请求数据进行了清除?
原来是因为显示使用拦截器后,导致框架默认使用的拦截器不默认使用了,其中包括传递请求参数等,解决办法就是,在显示使用拦截器后,使用 defaultStack 拦截器。
<interceptor-ref name="defaultStack"></interceptor-ref>
二、自定义拦截器
自定义拦截器 有两种方式
- 实现Interceptor接口
- 继承AbstractInterceptor类
下面以第一种方式为例,继续使用上面的action类、pojo类以及login.jsp
1.编写自定义拦截器类
public class MyInterceptor implements Interceptor {
@Override
public void destroy() {
System.out.println("this is destroy");
}
@Override
public void init() {
System.out.println("this is init");
}
/**
* 拦截器执行后,通过 actionInvocation.invoke 调用下一个拦截器
* 如果没有后继拦截器,就会执行action中的业务方法
*/
@Override
public String intercept(ActionInvocation actionInvocation) throws Exception {
System.out.println("this is myInterceptor");
return actionInvocation.invoke();
}
}
2.在struts.xml中注册拦截器
<!-- 配置自定义拦截器 -->
<interceptors>
<interceptor name="myInterceptor" class="com.interceptor.MyInterceptor"></interceptor>
</interceptors>
3.在相关action中使用拦截器
<interceptor-ref name="myInterceptor"></interceptor-ref>
所以,使用方法和使用默认拦截器一样基本一样。