拦截器和过滤器很相似,在action的前后执行,对于action的一些公共处理代码可以放到拦截器中实现,如日志,权限控制等等。
拦截器和过滤器的区别:
- 过滤器属于web容器,可以过滤一切请求
- 拦截器属于struts2框架,只能拦截action
- 过滤器内部采用函数回调(doFilter就是回调函数)来实现,拦截器使用动态代理实现
拦截器的执行流程
拦截器的实现步骤:
- 编写拦截器(实现Interceptor接口或者继承AbstractInterceptor类)
- 在struts.xml中配置拦截器
- 在action引用拦截器
案例:
编写拦截器
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
//计算Action的执行时间
public class TimeInterceptor implements Interceptor{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init() {
// TODO Auto-generated method stub
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
long start=System.currentTimeMillis();
String result=invocation.invoke();
long end=System.currentTimeMillis();
System.out.println("执行action所用时间"+(end-start)+"ms");
return result;
}
}
在struts.xml中配置拦截器和引用拦截器
<struts>
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="time" class="cn.sxt.interceptor.TimeInterceptor"></interceptor>
</interceptors>
<action name="hello" class="cn.sxt.action.HelloAction" >
<result>/index.jsp</result>
<interceptor-ref name="time"/>
</action>
</package>
</struts>
拦截器配置详解
(1)当引用了拦截器,默认拦截器将不起作用。那么一些功能不能实现,如赋值属性
(2 )默认拦截器在struts-default.xml中,配置了默认拦截器。当配置了默认拦截器,没有引用拦截器的时候,那么默认的拦截器会起作用
Struts-default.xml中有这么一行代码
<default-interceptor-ref name="defaultStack"/>
defaultStack是拦截器栈,里面有很多个拦截器
(3)所以当引用了拦截器,又想使用struts2提供的拦截器功能,那么需要手动引用
<action name="hello" class="cn.sxt.action.HelloAction" >
<result>/index.jsp</result>
<interceptor-ref name="time"/>
<interceptor-ref name="defaultStack"/>
</action>
(4)当action的拦截器个数较多时,可以将多个拦截器放入一个拦截器栈中
<interceptors>
<interceptor name="time" class="cn.sxt.interceptor.TimeInterceptor"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="time"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<action name="hello" class="cn.sxt.action.HelloAction" >
<result>/index.jsp</result>
<interceptor-ref name="myStack"/>
</action>
(5)当自定义拦截器栈在这个包下的所有action都使用的时候,可以定义为默认的拦截器栈或者拦截器(位置可以看dtd)
<default-interceptor-ref name="myStack"></default-interceptor-ref>
<action name="hello" class="cn.sxt.action.HelloAction" >
<result>/index.jsp</result>
</action>
登录拦截器的应用、
拦截器实现
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
//计算Action的执行时间
public class LoginInterceptor implements Interceptor{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init() {
// TODO Auto-generated method stub
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//判断是否是Login.action 如果是,则直接执行下一个拦截器
//如果不是则判断是否登录,如果登录执行下一个拦截器
//如果没有返回登录页面
//actionName没有扩展名
String actionName=invocation.getProxy().getActionName();
System.out.println("actionName="+actionName);
if("login".equals(actionName)){
return invocation.invoke();
}
Object object=invocation.getInvocationContext().getSession().get("user");
if(object==null){
return Action.LOGIN;
}
return invocation.invoke();
}
}
struts.xml配置
<struts>
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="time" class="cn.sxt.interceptor.TimeInterceptor"></interceptor>
<interceptor name="LoginInterceptor" class="cn.sxt.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="LoginInterceptor"/>
<interceptor-ref name="time"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"/>
<global-results>
<result name="login">/login.jsp</result>
</global-results>
<action name="hello" class="cn.sxt.action.HelloAction" >
<result>/WEB-INF/index.jsp</result>
</action>
<action name="login" class="cn.sxt.action.LoginAction" >
<result>/success.jsp</result>
</action>
</package>
</struts>
Action
import com.opensymphony.xwork2.ActionContext;
public class LoginAction {
private String name;
private String pwd;
public String execute(){
System.out.println(name);
if("siggy".equals(name)&&"111".equals(pwd)){
ActionContext.getContext().getSession().put("user", name);
return "success";
}
else {
return "login";
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
index.jsp
<body>
${name}
需要登录才能访问的页面 <br>
</body>
login.jsp
<body>
<form action="login.action" method="post" >
用户名:<input type="text" name="name"/><br>
密码:<input type="password" name="pwd"/><br>
<input type="submit" value="登录"/>
</form>
</body>
success.jsp
<body>
success
<a href="hello.action?name=zhangsan">hello</a><br>
</body>
方法拦截器
方法拦截器是比Action拦截器更加细粒度的控制,主体实现和Action拦截器一致,但是方法拦截器是继承MethodFilterInterceptor类,重写doIntercept()方法
Action
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
//方法拦截器
public class ListInterceptor extends MethodFilterInterceptor{
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
System.out.println("方法拦截器执行");
return invocation.invoke();
}
}
struts.xml配置
<interceptor name="methodInterceptor" class="cn.sxt.interceptor.ListInterceptor"></interceptor>
<interceptor-ref name="methodInterceptor">
<!--配置被拦截的方法 -->
<param name="includeMethods">list,add</param>
<!--配置不被拦截的方法 -->
<param name="excludeMethods">login</param>
</interceptor-ref>