Struts2的拦截器只能拦截Action,拦截器是AOP的一种实现方式,可以使我们的系统架构更松散(耦合度低),可以插拔,容易互换,代码不改变的情况下很容易满足客户需求。
项目的权限管理模块就使用到了Struts2的拦截器,原理是这样的,我们来自定义一个拦截器,拦截所有的Action请求,对用户的登录状态和权限信息进行判断。如果用户为登录状态且有足够的权限,则继续访问;若未登录,则为其跳转到登录页面,若无足够权限,则跳转到无权访问页面。
下面来看看具体实现:
自定义拦截器CheckPrivilegeInterceptor
package cn.itcast.oa.util;
import cn.itcast.oa.domain.User;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class CheckPrivilegeInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
// 获取信息
User user = (User) ActionContext.getContext().getSession().get("user"); // 当前登录用户
String namespace = invocation.getProxy().getNamespace();
String actionName = invocation.getProxy().getActionName();
String privUrl = namespace + actionName; // 对应的权限URL,用户要访问的URL
// 如果未登录
if (user == null) {
if (privUrl.startsWith("/user_login")) { // "/user_loginUI", "/user_login"
// 如果是去登录,就放行
return invocation.invoke();
} else {
// 如果不是去登录,就转到登录页面
return "loginUI";
}
}
// 如果已登 录,就判断权限
else {
if (user.hasPrivilegeByUrl(privUrl)) {
// 如果有权限,就放行
return invocation.invoke();
} else {
// 如果没有权限,就转到提示页面
return "noPrivilegeError";
}
}
}
}
在拦截器中会通过session信息判断用户是否登录,通过自己写的hasPrivilegeByUrl()方法判断是否有相应的访问权限。
配置拦截器
<struts>
<!-- 当struts.xml配置文件发生修改,会立刻加载,在生产环境下最好不要配置 -->
<constant name="struts.configuration.xml.reload" value="true"/>
<!-- 会提供更加友好的提示信息 -->
<constant name="struts.devMode" value="true"/>
<!-- 需要继承struts-default包,这样就拥有的最基本的功能 -->
<package name="struts2" extends="struts-default">
<interceptors>
<!-- 声明拦截器 -->
<interceptor name="checkPrivilege" class="cn.itcast.oa.util.CheckPrivilegeInterceptor"></interceptor>
<!-- 定义自己的拦截器栈 -->
<interceptor-stack name="myInterceptorStack">
<interceptor-ref name="checkPrivilege"></interceptor-ref>
<!-- defaultStack:Struts2的默认拦截器栈 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定义为缺省拦截器,所有的Action都会得到使用 -->
<default-interceptor-ref name="myInterceptorStack"/>
<!-- 全局的Result配置 -->
<global-results>
<result name="loginUI">/WEB-INF/jsp/userAction/loginUI.jsp</result>
<result name="noPrivilegeError">/noPrivilegeError.jsp</result>
</global-results>
<!--其他Action -->
.
.
.
</package>
</struts>
首先将自定义的拦截器配置好,另外因为咱们自定了拦截器,会导致缺省拦截器会失效,必须显示引用Struts2默认的拦截器即defaultStack。
然后重新定义缺省拦截器<default-interceptor-ref>
,对所有的Action都有效,替换defaultStack。
经过这两步配置后,自定义的拦截器就能使用了。
小结
整个拦截器体现了责任链模式,Filter也体现了责任链模式,后面会讲到Shiro的过滤器链,也是这个意思。
拦截器的执行原理就是,在ActionInvocation中有一个成员变量Iterator,这个Iterator中保存了所有的拦截器,每次都会取得Iterator进行next,执行invocation.invoke()方法,如果找到了拦截器就会执行拦截器内容,找不到的话就继续往下走,执行自定义的Action方法,都执行完拦截器出栈。
本篇主要讲解的是如何使用Struts2拦截器,关于权限管理的具体流程,后面会详细讲到。