Struts2 拦截器配置以及达成
发布时间:2021-11-15 13:37:12 所属栏目:PHP教程 来源:互联网
导读:@(Java ThirdParty)[Struts|Interceptor] Struts2 拦截器配置以及实现 Struts2的拦截器应用于Action,可以在执行Action的方法之前,之后或者两者。用于处理一些公共的方法,而不影响原有的代码,并且使得可以关注功能的实现,分离关注点。比如防止重复提交等
@(Java ThirdParty)[Struts|Interceptor] Struts2 拦截器配置以及实现 Struts2的拦截器应用于Action,可以在执行Action的方法之前,之后或者两者。用于处理一些公共的方法,而不影响原有的代码,并且使得可以关注功能的实现,分离关注点。比如防止重复提交等。 如下图(图片来自Struts2文档Interceptor章节): 拦截器配置 注:以下配置均来自于Struts2官方的例子 Struts2内置了一些拦截器,也可以通过实现Interceptor接口来自定义拦截器。 如下,在struts.xml中配置自定义拦截器以及引用定义的拦截器: <package name="default" extends="struts-default"> <interceptors> <interceptor name="timer" class=".."/> </interceptors> <action name="login" class="tutorial.Login"> <interceptor-ref name="timer"/> <result name="input">login.jsp</result> </action> </package> 如果定义多个拦截器,像上面那样一个个引用显然是很费劲的,这里可以将多个打包为一个拦截器栈,直接引用该拦截器栈即可: <package name="default" extends="struts-default"> <interceptors> <interceptor name="timer" class=".."/> <interceptor name="logger" class=".."/> <interceptor-stack name="myStack"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> </interceptor-stack> </interceptors> <action name="login" class="tutuorial.Login"> <interceptor-ref name="myStack"/> <result name="input">login.jsp</result> </action> </package> Struts2 拦截器实现 在先介绍Struts2拦截器实现时,需要先介绍一个设计模式,拦截过滤器,Struts2采用了该设计模式来实现,文档中注解了说明是使用Command设计模式,但是我觉得用Intercepting filter来理解比较好理解。 Intercepting filter pattern 在wiki中Intercepting Filter定义为:JavaEE设计模式,用于创建可插拔式过滤器,用于处理通用的服务,而不需要改变和兴请求的处理代码。这涉及了四个组件:Filter Manager,Filter chain,Filters,Target。如下: 在下图,可以看成FilterManager维护着一系列的Filter,并且知道Target,这里可以实现为:FilterManager内部维护一个List<Filter>,该List作为Filter Chain。 注:图片来自Wiki 处理流程如下: 注:图片来自Wiki Struts2 拦截器实现 Struts2中DefaultActionInvocation可以看做一个FilterManager,其中有Iterator<InterceptorMapping>,可以看做FilterChain,即包含了所有需要拦截该Action的Interceptor,其中Object action为真正的Target。如下图: Interceptor接口: public interface Interceptor extends Serializable { void destroy(); void init(); String intercept(ActionInvocation invocation) throws Exception; } 主要执行流程在DefaultActionInvocation.invoke方法中,该方法用递归来实现链式调用(和Tomcat中实现FIlter一样): public String invoke() throws Exception { // 省略了部分代码... // 如果还有Interceptor,则继续(递归条件) if (interceptors.hasNext()) { try { // 获取拦截器,并将当前对象传递给拦截器,由拦截器决定是要需要继续执行,例如:invocation.invoke(),如果执行了,则继续递归,直到执行完所有的拦截器,如果没有调用该方法,即拦截了,则这里就终止递归了。 resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); } finally { UtilTimerStack.pop(interceptorMsg); } } else { // 只有执行完所有拦截器,才执行Action的方法 resultCode = invokeActionOnly(); } } Tomcat Filter实现 Tomcat中Filter的实现和上面差不多,不过其中的类名和概念的名称比较匹配。如下: ApplicationDispatcher通过使用FilterChain来实现Filter链式调用。 其中ApplicationFIlterChain.internalDoFilter为核心的代码: private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // 通过pos来记录当前执行的Filter,只有到所有Filter执行完(递归终止条件之一) if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = null; try { filter = filterConfig.getFilter(); if (request.isAsyncSupported() && "false".equalsIgnoreCase( filterConfig.getFilterDef().getAsyncSupported())) { // ... } else { // Filter.doFilter,通过传入当前对象,来实现递归调用,将控制权传递给Filter,由Filter来决定是否需要继续执行下去 filter.doFilter(request, response, this); } return; } try { if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) { if( Globals.IS_SECURITY_ENABLED ) { // ... } else { // 执行Target真正的方法 servlet.service(request, response); } } else { servlet.service(request, response); } } // ... } (编辑:云计算网_泰州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |