拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个Action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也提供了一种可以提取Action中可重用的代码的方式。
1、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
通过感知接口,获取感应对象
2、自定义拦截器
(1)步骤:
①自定义一个类,继承AbstractInterceptor抽象类,或实现Interceptor接口
②在struts.xml配置文件中注册拦截器
③在struts.xml配置文件中,设置默认拦截器或配置Action类的局部拦截器来使用。
(2)eg:该示例自定义拦截器拦截主页面,防止未登录用户强行登陆主页面。
①CheckLoginInterceptors.java(拦截器)
public class CheckLoginInterceptors extends AbstractInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//获取Session对象中的用户信息
String username = (String) ActionContext.getContext().getSession().get("USER_IN_SESSION");
if(username!=null){
return invocation.invoke();//如果username不为空,放行
}
return "input";//否则返回登录页面
}
}
②LoginAction.java
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(username+","+password);
//将用户名存入Session对象中
ActionContext.getContext().getSession().put("USER_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;
}
}
③struts.xml
<package name="interPkg" extends="struts-default" namespace="/">
<!-- 注册拦截器 -->
<interceptors>
<interceptor name="checkLogin" class="interceptors.CheckLoginInterceptors"/>
</interceptors>
<!-- 指定默认拦截器 -->
<default-interceptor-ref name="checkLogin"/>
<!-- 全局视图 -->
<global-results>
<result name="input">
/views/login/login.jsp
</result>
</global-results>
<action name="login" class="action.interceptors.LoginAction">
<result name="success" type="redirectAction">
<param name="namespace">/</param>
<param name="actionName">main</param>
</result>
</action>
<action name="main">
<result name="success" type="dispatcher">
/views/login/welcome.jsp
</result>
</action>
</package>
上述代码
存在问题:
a.登陆失败,永远进不了LoginAction
原因:进入LoginAction之前,需要判断session中是否有USER_IN_SESSION,而USER_IN_SESSION只有在LoginAction中才能设置。
结论:LoginAction不需要做登陆检查。
b.在LoginAction中再也获取不了请求参数
原因:当我们在<package>设置了默认的拦截器引用,那么<package>之前的默认的拦截器栈(defaultStack)就不引用了,那么defaultStack中的获取请求参数的拦截器也不再引用。
应改为如下:
<package name="interPkg" extends="struts-default" namespace="/">
<!-- 注册拦截器 -->
<interceptors>
<interceptor name="checkLogin" class="interceptors.CheckLoginInterceptors"/>
<!-- 自定义拦截器栈,可放置多个拦截器 -->
<interceptor-stack name="myStack">
<interceptor-ref name="checkLogin"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<!-- 指定默认拦截器 -->
<default-interceptor-ref name="myStack"/>
<!-- 全局视图 -->
<global-results>
<result name="input">
/views/login/login.jsp
</result>
</global-results>
<action name="login" class="action.interceptors.LoginAction">
<!-- 配置局部拦截器 -->
<interceptor-ref name="defaultStack"/>
<result name="success" type="redirectAction">
<param name="namespace">/</param>
<param name="actionName">main</param>
</result>
</action>
<action name="main">
<result name="success" type="dispatcher">
/views/login/welcome.jsp
</result>
</action>
</package>
④测试
使用隐身窗口重新登陆,试图登陆主页