Struts自定义拦截器&拦截器工作原理
0.拦截器的调用原理:
拦截器是一个继承了序列化接口的普通接口。其工作原理是讲需要被拦截的对象作为参数传到intercept()方法内,在方法内部对此对象进行处理之后再执行原方法。intercept(ActionInvocation invocation)是拦截处理的方法。
Interceptor .java
public interface Interceptor extends Serializable { /** * Called to let an interceptor clean up any resources it has allocated. */ void destroy(); /** * Called after an interceptor is created, but before any requests are processed using * {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept} , giving * the Interceptor a chance to initialize any needed resources. */ void init(); /** * Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the * request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code. * * @param invocation the action invocation * @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself. * @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}. */ String intercept(ActionInvocation invocation) throws Exception; }
1.自定义拦截器步骤
I. 定义一个拦截器的类
> 可以实现 Interceptor 接口
> 继承 AbstractInterceptor 抽象类
1.拦截器
1 package Action; 2 3 import com.opensymphony.xwork2.ActionContext; 4 import com.opensymphony.xwork2.ActionInvocation; 5 import com.opensymphony.xwork2.interceptor.Interceptor; 6 7 public class PrivelegeInterceptor implements Interceptor { 8 9 @Override 10 public void destroy() { 11 // TODO Auto-generated method stub 12 } 13 @Override 14 public void init() { 15 // TODO Auto-generated method stub 16 //初始化方法,获得数据库信息。调用服务 17 } 18 19 @Override 20 public String intercept(ActionInvocation arg0) throws Exception { 21 22 //如果用户登录了就会有user属性(Session里面存一个session属性) 23 Object user = arg0.getInvocationContext().getSession().get("user"); 24 // 上面可能是系统权限的管理 25 String result=""; 26 System.out.println(user); 27 if(user!=null){ 28 // 当满足条件时,让其执行,相当于是放行 29 arg0.invoke(); 30 }else { 31 result = "logon"; 32 ActionContext.getContext().put("msg", "您没有权限管理"); 33 } 34 System.out.println(result); 35 return result; 36 } 37 }
2.被拦截的Action
1 package Action; 2 3 import com.opensymphony.xwork2.ActionContext; 4 5 public class UserAction { 6 7 public String addUI(){ 8 ActionContext.getContext().put("msg", "成功执行了addUI操作"); 9 System.out.println("执行addui操作"); 10 return "success"; 11 } 12 13 public String update(){ 14 ActionContext.getContext().put("msg", "成功执行了update操作"); 15 System.out.println("执行update操作"); 16 return "success"; 17 } 18 }
3.JSP页面(主页面,也就是开始时要访问Action的页面)
1 <%@ page language="java" contentType="text/html; charset=utf-8" 2 pageEncoding="utf-8"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 7 <title>Insert title here</title> 8 </head> 9 <body> 10 <%-- <% 11 session.setAttribute("user", "uuuu"); 12 %> --%> 13 Success 14 ${msg } 15 <a href="/struts2interceptor/user_addUI.action">addui</a> 16 <a href="/struts2interceptor/user_update.action">update</a> 17 </body> 18 </html>
msg.jsp 也就是被拦截到没有权限时要去的页面
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body> ${msg } </body> </html>
II. 在 struts.xml 文件配置.
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <!-- package的名字必须唯一!只能拦截.action请求 默认值:class:com.opensymphony.xwork2.ActionSupport method:execute result的name属性:success 方法中返回success即可跳转到结果对应的页面 --> <!-- 第一个package命名空间 --> <package name="intercept" namespace="/" extends="struts-default"> <!-- 拦截器 --> <interceptors> <!-- 定义刚才的拦截器 --> <interceptor name="permission" class="Action.PrivelegeInterceptor"></interceptor> <!-- 定义拦截器栈 --> <interceptor-stack name="permissionStack"> <!-- 拦截器栈里面可以引用另外一个拦截器,也可以引用另外一个拦截器栈 --> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="permission"></interceptor-ref> </interceptor-stack> </interceptors>
<action name="user_*" class="Action.UserAction" method="{1}"> <result>/index.jsp</result> <result name="logon">/msg.jsp</result> <!-- 使用拦截器栈 --> <interceptor-ref name="permissionStack"></interceptor-ref> </action> </package> </struts>
第二种使用拦截器的方式是:(在前面定义一下拦截器,然后在Action中使用新定义的拦截器与默认的拦截器)
1 <interceptors> 2 3 <interceptor name="hello" class="com.atguigu.struts2.interceptors.MyInterceptor"></interceptor> 4 5 </interceptors> 6 7 <action name="testToken" class="com.atguigu.struts2.token.app.TokenAction"> 8 <interceptor-ref name="hello"></interceptor-ref> 9 <interceptor-ref name="defaultStack"></interceptor-ref> 10 <result>/success.jsp</result> 11 <result name="invalid.token">/token-error.jsp</result> 12 </action>
III. 注意: 在自定义的拦截器中可以选择不调用 ActionInvocation 的 invoke() 方法. 那么后续的拦截器和 Action 方法将不会被调用.Struts 会渲染自定义拦截器 intercept 方法返回值对应的 result
这种经常用于权限管理,例如上面的拦截器,没有权限时,返回的是logon,自动渲染返回值为设置的值,然后根据返回值在Action配置中跳转到响应的页面。
IV.测试
1.没权限的测试,即session中不存在user
2.有权限的测试,即session中存在user
结果:
Struts2 拦截器 和 过滤器 的区别:
①、过滤器依赖于 Servlet 容器,而拦截器不依赖于 Servlet 容器。
②、Struts2 拦截器只能对 Action 请求起作用,而过滤器则可以对几乎所 有请求起作用。
③、拦截器可以访问 Action 上下文(ActionContext)、值栈里的对象 (ValueStack),而过滤器不能.
④、在 Action 的生命周期中,拦截器可以多次调用,而过滤器只能在容器 初始化时被调用一次。