版权声明: https://blog.csdn.net/hu18315778112/article/details/84855024
-
拦截器(interceptor)是struts2框架的又一主要功能,他是基于过滤器(Filter)来开发的,主要功能就是对用户的请求进行包装,处理等等。
-
例如,前面学习的Action中获取参数的几种方式,都是在请求到达Action之前,在拦截器中进行获取并封装的,我们在Action类中创建属性,只不过是给获取的参数创建一个容器,好让前面的拦截器可以将参数封装进去。
-
Struts2框架自带了一堆拦截器(20个左右)
- 这是Struts2默认的拦截器栈,也就是请求到达action默认要经过这些拦截器。可以看到其中有一个叫做
- <interceptor-ref name="modelDriven"/>
- 的拦截器,他的功能就是实现模型驱动封装参数。
<interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="i18n"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="datetime"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="debugging"/> </interceptor-stack>
我们知道有的系统(网站)、会要求用户必须登录,否则就无法使用网站中的各种功能,这就可以使用拦截器来实现,想要使用拦截器实现,当然要回创建并配置拦截器,接下来就学习了拦截器的基本用法:
-
1. 如何创建拦截器interceptor
创建拦截器又有三种方式:
- 方式一:实现Interceptor接口(最原始的方式)
// 接口中有三个方法需要实现,分别是创建时执行的方式、销毁时执行的方法,和拦截器具体行为 // 这里介绍一下拦截器的生命周期:随项目工程部署而创建(开启服务器)、随项目关闭而销毁 public class MyInterceptor1 implements Interceptor{ @Override public void destroy() { } @Override public void init() { } @Override // intercept方法,参数顾名思义:Action调用,用于执行action类的对象 public String intercept(ActionInvocation invocation) throws Exception { /* * 放行之前书写在action执行之前的操作 */ // 放行 String str =i nvocation.invoke(); /* * 放行之后书写在action执行之后的操作 */ return str; // 如果不想放行(不执行后续拦截器及Action类),可以直接返回一个结果字符创,如error // return "error"; // 当然前面的放行代码可以删掉,这样他会直接去到配置的中 // 查找name为error的result元素,并执行相应的跳转操作 } }
- 方式二:继承AbstractInterceptor 类
// AbstractInterceptor类也是实现的Interceptor接口,他只是方便开发者书写代码, // 因为init方法与destroy方法基本用不到,所以他就简化了需要实现的方法。 public class MyInterceptor1 extends AbstractInterceptor{ @Override public String intercept(ActionInvocation arg0) throws Exception { return null; } }
- 方式三:继承MethodFilterInterceptor 类
// MethodFilterInterceptor类可以说是方法过滤拦截器。 // 他的功能就是:定制拦截器拦截的方法——拦截哪些方法、不拦截哪些方法 // 具体代码与其他几种方式相同 public class MyInterceptor1 extends MethodFilterInterceptor{ @Override protected String doIntercept(ActionInvocation arg0) throws Exception { return null; } }
-
2. 如何使用(配置)拦截器
- 写好了拦截器后,当然要使其生效,所以需要对拦截器进行具体配置,有优秀基础的人,拦截器配置的步骤可以参照struts-default.xml中的配置来写。
拦截器配置步骤:
- 1. 注册拦截器
<!-- 拦截器主元素:位置:package元素里面,action元素前面 --> <interceptors> <!-- interceptor元素:用于注册拦截器 name属性:为该拦截器起个名称; class属性:填写该拦截器类的全包名 --> <interceptor name="login" class="com.huhu.web.interceptor.MyInterceptor"></interceptor> </interceptors>
- 2. 创建拦截器栈
<!-- 该元素创建拦截器栈,放在interceptors元素里面,interceptor元素后面。name属性,为栈起个名称--> <interceptor-stack name="loginStack"> <!-- 将自己书写的拦截器栈引入进来,并引入struts2默认的拦截器 --> <interceptor-ref name="login"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack>
- 3. 指定拦截器工作范围
<!-- 直接在package元素里配置此元素,意思是该package下的所有action都要走name为loginStack的拦截 器栈 --> <default-interceptor-ref name="loginStack"></default-interceptor-ref> <!-- 也可以指定某个action元素适用的拦截器栈(不常用) 将interceptor-ref元素配置在action里面,即指定该action适用的拦截器栈 --> <action> <interceptor-ref name="loginStack"></interceptor-ref> </action>
-
到这里,技术点都学完了,之后就是适用这些知识实现效果:
-
访问功能时,未登录,则跳转到登录页面。
详细实现:这里就简单的将代码贴出来。
- 拦截器具体代码:
public class LoginInterceptor extends MethodFilterInterceptor{ @Override protected String doIntercept(ActionInvocation invocation) throws Exception { // 获取session域,获取user Object user = ActionContext.getContext().getSession().get("user"); // 判断用户是否登录(user是否存在) if (user == null) { // 未登录,跳转到登录页面 return "toLogin"; } // 登录放行 return invocation.invoke(); } }
- 配置文件详细代码:
<package name="sh" namespace="/" extends="struts-default"> <!-- 配置程序员自定义拦截器,放在package元素的最前面 --> <interceptors> <!-- 注册拦截器 --> <interceptor name="login" class="com.huhu.web.interceptor.LoginInterceptor"></interceptor> <interceptor-stack name="loginStack"> <!-- 将注册的拦截器添加到自定义拦截器栈 --> <interceptor-ref name="login"> <!-- 配置不执行此拦截器栈的方法 --> <param name="excludeMethods">login</param> </interceptor-ref> <!-- 引入struts2默认拦截器栈 --> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> <!-- 设置package默认拦截器栈 --> <default-interceptor-ref name="loginStack"></default-interceptor-ref> <!-- 配置全局结果集,整个工程都可以使用的结果集 ,放在全局异常处理之前--> <global-results> <result name="toLogin" type="redirect">/login.jsp</result> </global-results> <action name="custAction_*" class="com.huhu.web.action.CustomerAction" method="{1}"> <result name="custlist" >/jsp/customer/list.jsp</result> <result name="success" type="redirectAction"> <param name="actionName">custAction_findCust</param> <param name="namespace">/customer</param> </result> <!-- 配置可以动态调用的方法名,多个方法用,逗号隔开 --> <allowed-methods>findCust,add</allowed-methods> </action> <action name="userAction_*" class="com.huhu.web.action.UserAction" method="{1}"> <interceptor-ref name="loginStack"></interceptor-ref> <result name="login" type="redirect">/index.jsp</result> <result name="error" type="dispatcher">/login.jsp</result> <!-- 不知道为啥,以转发的方式到页面,页面加载不到资源,原因:资源路径前没加工程名 --> <!-- <result name="error" >/login.jsp</result> --> <allowed-methods>login</allowed-methods> </action> </package>
这也可以说是已经实现了登录校验的功能(校验用户是否登录)
拓展:
-
1. 拦截器无法拦截页面的显示,只能拦截action中的元素,所以想要实现拦截页面的功能需要使用其他的技术。或者,每个页面的显示都是使用action的某个方法跳转到的,则可以用拦截器拦截这些方法,来起到拦截页面显示的作用,不过这种方式可能不太常用。
-
2. 如果页面使用的是frame框架布局的页面,未登录时,跳转到登录页面可能只是框架中的某一部分跳转,如:
-
如果想让跳转到的登录页只显示登录页信息,可以使用js的一段简单代码解决:
- 注意:此段代码实在想要显示的页面的文件中书写的,如:我的登录页面文件名为login.jsp,则在该文件中书写
<script type="text/javascript">
window.onload=function(){
if(window.parent != window){
window.parent.location.href="${pageContext.request.contextPath}/login.jsp";
}
};
</script>
-
书写一个页面加载完毕事件,作用是,页面加载完毕后,判断当前页面的父窗口是不是浏览器的主窗口,如果不是,则将父窗口重新跳转到当前页面。