拦截器是现在开发之中最为重要的特色,是基于AOP的设计思想(AOP是基于代理设计模式思想),面向切面设计思想实现的.
1.清楚拦截器的基本作用;
2.开发自己的拦截器
3.实现登录检查拦截器
4.实现服务器端数据验证拦截器(工具类);
5.拦截器栈的定义及使用
在Strut2.x里面为了方便用户进行数据的验证,专门提供有validate()方法以及验证框架,但是这两个验证操作都有一个最致命的问题--永远都要在其赋值完成之后才能够验证,赋值之前无法验证,所以后台会一直出现错误,为了解决这样的问题,或者说为了解决所有辅助性的检测的功能.那么可以利用拦截器完成
认识拦截器
在Struts2.x里面所有的客户端发送过来的请求都交给Filter进行处理,而后由Filter再去决定执行哪个Action.而拦截器是在某一个Action之前做的数据拦截操作
实际上在之前也有拦截器出现,表单参数类型自动变为vo类型对象,这个就是拦截器的功能,
范例:定义一个Action,手工配置一个拦截器
package cn.mldn.action; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class MessageAction extends ActionSupport{ public void insert(){ System.out.println("插入信息~~~~~~~~"); } }范例:配置一个计算处理事件的拦截器
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="root" namespace="/" extends="struts-default"> <action name="MessageAction" class="cn.mldn.action.MessageAction"> <interceptor-ref name="timer"></interceptor-ref> </action> </package> </struts>
此时会计算出当前操作的执行时间,而后台的输出效果如下
Executed action [//MessageAction!insert] took 1 ms.
此时拦截器自动执行了,但是timer这个拦截器默认是在Action之后执行,
开发自定义拦截器
如果要想开发自定义拦截器,那么在Struts2.x里面是由要求的这个拦截器的类必须继承自"com.opensymphony.xwork2.interceptor.AbstractInterceptor"父类,这个类是一个抽象类;
public abstract class AbstractInterceptor extends Object implements Interceptor
在这个类之中存在有三个方法, 但是有一个抽象方法
○拦截:
public abstract class AbstractInterceptor extends Object implements Interceptor
这个方法参数里面接受了一个ActionInvocation的对象,这个类对象可以取得一切的发送及执行信息.
范例:实现一个最基础的拦截器
package cn.mldn.interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; @SuppressWarnings("serial") public class MyInterceptor extends AbstractInterceptor{ @Override public void init() { System.out.println("-------拦截器初始化------"); } @Override public String intercept(ActionInvocation arg0) throws Exception { System.out.println("---------拦截器执行----------"); return arg0.invoke(); //将请求向下传递 } @Override public void destroy() { System.out.println("----------拦截器销毁---------"); } }
拦截器定义完成固然是一件好事,但是拦截器必须在strtus.xml文件中进行配置.
范例:配置strtus.xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="root" namespace="/" extends="struts-default"> <interceptors> <interceptor name="mldn" class="cn.mldn.interceptor.MyInterceptor"></interceptor> </interceptors> <action name="MessageAction" class="cn.mldn.action.MessageAction"> <interceptor-ref name="timer"></interceptor-ref> <interceptor-ref name="mldn"></interceptor-ref> </action> </package> </struts>
此时在MessageAction执行的时候挂了两个拦截器执行结果如下:
---------拦截器执行----------
插入信息~~~~~~~~
六月 05, 2018 10:19:06 下午 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
信息: Executed action [//MessageAction!insert] took 0 ms.
此时的拦截器是在Action执行之前进行了处理,等于是说当前已经拦截下来了
范例:现在在Message中定义News类型进行数据接收
package cn.mldn.action; import com.opensymphony.xwork2.ActionSupport; import cn.mldn.vo.News; @SuppressWarnings("serial") public class MessageAction extends ActionSupport{ private News news=new News(); public News getNews() { return news; } public void insert(){ System.out.println(this.news); System.out.println("插入信息~~~~~~~~"); } }
发现一旦编写了自定义拦截器之后,非常遗憾的问题出现了,自动赋值操作不会出现了,因为在Struts2.x里面你没有使用拦截器,会自动使用赋值的拦截器,而一旦使用了拦截器,那么就需要手工来配置拦截器.
范例:修改配置
<action name="MessageAction" class="cn.mldn.action.MessageAction"> <interceptor-ref name="timer"/> <interceptor-ref name="mldn"/> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
如果开始编写自定义拦截器,所有的操作必须采用手工的模式进行.
利用拦截器检测登录
如果要进行登录检测,那么肯定是用过滤器是最合适的,不过遗憾的是Struts2.x为了Struts1.x区别所以使用了过滤器进行整个的分发处理.那么自己写的过滤器自然无法进行session的登录检查.如果要想实现登录检查,那么只能够依靠拦截器完成,也就是说现在必须要对ActionInvocation做进一步研究
这是一个接口com.opensymphony.xwork2.interceptor.AliasInterceptor
请求继续向下传递给Action:
String invoke() throws Exception
取得上下文对象内容:
ActionContext getInvocationContext()
使用此方法返回的是一个“com.opensymphony.xwork2.ActionContext”类的对象,这个类包含有如下方法:
取得全部的参数:public HttpParameters getParameters()
取得全部Session保存的数据
public Map<String,Object> getSession()
取得全部Application保存的属性数据
public Map<String,Object> getSession()
范例:假设登陆的session属性名称为“mid”,所以本次验证如下
package cn.mldn.interceptor; import java.util.Map; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; @SuppressWarnings("serial") public class Logininterceptor extends AbstractInterceptor{ @Override public String intercept(ActionInvocation arg0) throws Exception { Map<String, Object> map = arg0.getInvocationContext().getSession(); if(map.get("mid")!=null){ return arg0.invoke(); }else{ ServletActionContext.getRequest().setAttribute("msg", "您还未登录请先登录!"); ServletActionContext.getRequest().setAttribute("url", "login.jsp"); } return "forward.page"; //全局跳转提示页面 } }
但是使用了一个“forward.page”的页面面对于这个页面需要提醒注意,几乎所有的开发之中都需要统一的信息提示页,那么可以定义为全局跳转资源.
范例:修改strtus.xml文件,配置拦截器使用
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="root" namespace="/" extends="struts-default"> <interceptors> <interceptor name="mldn" class="cn.mldn.interceptor.MyInterceptor"></interceptor> <interceptor name="login" class="cn.mldn.interceptor.Logininterceptor"></interceptor> </interceptors> <global-results > <result name="forward.page">forward.jsp</result> </global-results> <action name="MessageAction" class="cn.mldn.action.MessageAction"> <interceptor-ref name="timer"/> <interceptor-ref name="mldn"/> <interceptor-ref name="login"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action> </package> </struts>
此时已经彻底实现了拦截器的实际使用.
所有的拦截器都会按照既定的顺序依次向下执行,这一点的控制是非常方便的,因为很多时候是先进行登录验证后再进行其他操作.