拦截器
1. 拦截器:拦截器和过滤器很相似,在action执行的前后执行。Struts2的核心功能都是通过拦截器来实现的。
2. 拦截器栈:由多个拦截器组成。
3. 作用:对action的一些公共处理代码可以放到拦截器中实现,如:权限控制,日志等等。
4. 多个拦截器之间的执行是采用责任链来实现的。
5. 拦截器的执行流程
6. 拦截器的实现步骤:
a. 编写拦截器,实现interceptor接口或者继承AbstractInterceptor类
b. 在struts.xml中配置拦截器
c. 在action中引用拦截器
7. 案例
拦截器类
publicclass HelloAction extends AbstractInterceptor{ public String intercept(ActionInvocation invocation) throws Exception { longstart=System.currentTimeMillis(); //执行下一个拦截器,当所有拦截器执行完后执行action String result=invocation.invoke(); longend=System.currentTimeMillis(); System.out.println("time is:"+(end-start)+"ms"); returnresult; } } |
struts.xml(配置拦截器以及引用拦截器)
<!-- 配置拦截器 --> <interceptors> <interceptor name="timer" class="com.zys.interceptor.HelloAction" /> </interceptors>
<action name="test" class="com.zys.action.LoginAction" method="register"> <result name="success">/success.jsp</result> <result name="input">/login.jsp</result> <!—应用拦截器 --> <interceptor-ref name="timer"></interceptor-ref> </action> |
当请求test.action时将会执行该拦截器
8. 拦截器的配置详解
a) 当引用了自定义的拦截器时,默认的拦截器不起作用
b) 默认拦截器在struts-default.xml中,配置了默认拦截器,当配置了默认拦截器以后,如果不引用拦截器,那么默认的拦截器将起作用。
<default-interceptor-ref name="defaultStack"/> |
之前之所以有默认拦截器,在于在sturts.xmlh中继承了struts-default
<package name="default" extends="struts-default"> |
c) 当引用自定义拦截器后,又想使用struts2提供的拦截器功能,那么需要手动引用
<action name="test" class="com.zys.action.LoginAction" method="register"> <result name="success">/success.jsp</result> <result name="input">/login.jsp</result> <!-- 引用拦截器 --> <interceptor-ref name="timer" /> <!-- 引用默认的拦截器栈, --> <interceptor-ref name="defaultStack" /> </action> |
d) 当action引用的拦截器个数比较多的时候,可以将多个拦截器放入一个拦截器栈中。
<!--配置拦截器 --> <interceptors> <interceptor name="timer" class="com.zys.interceptor.HelloAction" /> <!-- 一个拦截器栈中,可以包含多个拦截器的引用,拦截器栈的引用和拦截器一致 --> <interceptor-stack name="myStack"> <!-- 引用拦截器 --> <interceptor-ref name="timer"></interceptor-ref> <!-- 引用默认的拦截器栈 --> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors>
<action name="test" class="com.zys.action.LoginAction" method="register"> <result name="success">/success.jsp</result> <result name="input">/login.jsp</result> <!-- 引用自定义拦截器栈 --> <interceptor-ref name="myStack"></interceptor-ref> </action> |
e) 当自定义的拦截器栈在这个包下的所有的action都使用的时候,可以定义为默认的的拦截器,或默认的拦截器。
<!-- 定义默认的拦截器/栈 --> <default-interceptor-ref name="myStack" /> <action name="test" class="com.zys.action.LoginAction" method="register"> <result name="success">/success.jsp</result> <result name="input">/login.jsp</result> </action> |
9. 拦截器的运用案例 (对于登录权限的运用):
拦截器的实现
publicclass LoginInterceptor extends AbstractInterceptor{
public String intercept(ActionInvocation invocation) throws Exception { //判断是否是login.action,如果是则直接执行下一个拦截器 //如果不是则判断是否登录,如果登录就执行下一个拦截器 //如果不是登录则返回登录界面 String actionName=invocation.getProxy().getActionName(); if("login".equals(actionName)){ returninvocation.invoke(); }
//通过获得session的name来判断是否登录,session在LoginAction中设置了值 Object obj=invocation.getInvocationContext().getSession().get("name"); if(obj!=null){ //不为空表示登录 returninvocation.invoke(); } return Action.LOGIN; //直接返回结果集 } } |
JSP页面(success.jsp 登录后点击该链接可以成功跳转,未登录在浏览器输入该action无法跳转)
<body> <a href="hello.action">hello</a> </body> |
JSP页面(login.jsp)
<form action="login.action" method="post"> 用户名:<input type="text" name="name"/><br> 密 码:<input type="password" name="pwd"/><br> 年 龄:<input type="text" name="age" /><br> 邮 箱:<input type="text" name="email" /><br> <input type="submit" value="提交"/> <s:actionerror /> </form> |
struts.xml
<!--配置拦截器 --> <interceptors> <interceptor name="loginInterceptor" class="com.zys.interceptor.LoginInterceptor" /> <interceptor-stack name="myStack"> <interceptor-ref name="loginInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> |
LoginAction
publicclass LoginAction extends ActionSupport{ HttpServletRequest request; public String register(){ request=ServletActionContext.getRequest(); ActionContext.getContext().getSession().put("name",request.getParameter("name")); return"success"; } } |
10. 方法拦截器:方法拦截器是比Action拦截器具有更加细粒度的控制,主体实现和Action拦截器一致,但是方法拦截器继承MethodFilterInterceptor类,重写doIntercept方法,配置会发生改变。
struts.xml
<!--配置拦截器 --> <interceptors> <interceptor name="loginInterceptor" class="com.zys.interceptor.LoginInterceptor" /> <interceptor name="methodInteceptor" class="com.zys.interceptor.ListInterceptor" /> <interceptor-stack name="myStack"> <interceptor-ref name="methodInteceptor"> <!-- 配置被拦截的方法,多个方法用逗号分隔--> <param name="includeMethods">list,add</param> <!--配置不被拦截的方法 --> <param name="excludeMothods">login</param> </interceptor-ref> <interceptor-ref name="loginInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors>
<!-- 定义默认的拦截器/栈 --> <default-interceptor-ref name="myStack" />
<!-- 因为有多个界面需要跳转到登录界面,所以定义为全局结果集 --> <global-results> <result name="login">/login.jsp</result> </global-results>
<action name="login" class="com.zys.action.LoginAction" method="register"> <result name="success">/success.jsp</result> </action> <action name="hello" class="com.zys.interceptor.HelloAction"> <result name="show">/show.jsp</result> </action> <action name="list" class="com.zys.interceptor.HelloAction" method="list"> <result name="show">/show.jsp</result> </action> <action name="add" class="com.zys.interceptor.HelloAction" method="add"> <result name="show">/show.jsp</result> </action> |
注意:struts2拦截器的执行顺序是按照拦截器栈中引用的顺序来进行的。
MethodFilterInterceptor类
publicclass ListInterceptor extends MethodFilterInterceptor{ protected String doIntercept(ActionInvocation invocation) throws Exception { System.out.println("方法拦截器被执行!"); returninvocation.invoke(); } } |
HelloAction类
publicclass HelloAction{ public String execute(){ return"show"; } public String list(){ System.out.println("list方法!"); return"show"; } public String add(){ System.out.println("add方法"); return"show"; } } |