`
jimgreat
  • 浏览: 132123 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring-AOP、Struts2拦截器、MyBatis Plugin实现原理比较(二)

阅读更多

Struts 2

 

Struts2是由StrutsPrepareAndExecuteFilter 的 doFilter 来处理每个HTTP请求的

 

由执行器的executeAction进入执行流程

execute.executeAction(request, response, mapping);
 

实际的执行是由dispatcher发起的

    public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException {
        dispatcher.serviceAction(request, response, servletContext, mapping);
    }

 

在serviceAction中会由ActionProxyFactory根据URL请求和struts的配置 , 生成对应Action的ActionProxy 实例 

 

            ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                    namespace, name, method, extraContext, true, false);

            request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

            // if the ActionMapping says to go straight to a result, do it!
            if (mapping.getResult() != null) {
                Result result = mapping.getResult();
                result.execute(proxy.getInvocation());
            } else {
                proxy.execute();
            }
 

 

Action的执行是由proxy.execute()触发的

在execute()   拦截器和Action执行都是由invocation调度的

 

    public String execute() throws Exception {
        ActionContext nestedContext = ActionContext.getContext();
        ActionContext.setContext(invocation.getInvocationContext());

        String retCode = null;

        String profileKey = "execute: ";
        try {
            UtilTimerStack.push(profileKey);

            retCode = invocation.invoke();
        } finally {
            if (cleanupContext) {
                ActionContext.setContext(nestedContext);
            }
            UtilTimerStack.pop(profileKey);
        }

        return retCode;
    }
 

下面我们来看一下invocation的核心函数invoke

 

 

    public String invoke() throws Exception {
        String profileKey = "invoke: ";
        try {
            UtilTimerStack.push(profileKey);

            if (executed) {
                throw new IllegalStateException("Action has already executed");
            }

            if (interceptors.hasNext()) {
                final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);
                try {
                                resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
                            }
                finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
            } else {
                resultCode = invokeActionOnly();
            }

            // this is needed because the result will be executed, then control will return to the Interceptor, which will
            // return above and flow through again
            if (!executed) {
                if (preResultListeners != null) {
                    for (Object preResultListener : preResultListeners) {
                        PreResultListener listener = (PreResultListener) preResultListener;

                        String _profileKey = "preResultListener: ";
                        try {
                            UtilTimerStack.push(_profileKey);
                            listener.beforeResult(this, resultCode);
                        }
                        finally {
                            UtilTimerStack.pop(_profileKey);
                        }
                    }
                }

                // now execute the result, if we're supposed to
                if (proxy.getExecuteResult()) {
                    executeResult();
                }

                executed = true;
            }

            return resultCode;
        }
        finally {
            UtilTimerStack.pop(profileKey);
        }
    }

 

从InterceptorMapping 链中,也就是拦截器链中取出下一个InterceptorMapping ,拦截器被封装在里面

 

【对interceptors的初始化,也就是解析配置文件,加载所有的拦截器实例,在这里就不分析了】

 

 final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();

 

 

执行拦截器的拦截方法,参数是本身这个中央调度器

 

 interceptor.getInterceptor().intercept(DefaultActionInvocation.this);

 

 

再看一个拦截器的例子 LoggingInterceptor

 

 

        logMessage(invocation, START_MESSAGE);    //记录开始

        String result = invocation.invoke();       //调度器 推进拦截器链

        logMessage(invocation, FINISH_MESSAGE);   //记录结束

 

 

public class LoggingInterceptor extends AbstractInterceptor {
    private static final Logger LOG = LoggerFactory.getLogger(LoggingInterceptor.class);
    private static final String FINISH_MESSAGE = "Finishing execution stack for action ";
    private static final String START_MESSAGE = "Starting execution stack for action ";

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        logMessage(invocation, START_MESSAGE);
        String result = invocation.invoke();
        logMessage(invocation, FINISH_MESSAGE);
        return result;
    }

  ......

}
  

在invocation.invoke()推进拦截器链时,又会从InterceptorMapping 链中,也就是拦截器链中取出下一个InterceptorMapping ,下一个拦截器被封装在里面。接着执行拦截器的拦截方法,参数是本身这个中央调度器。下一个拦截器中也会调用 invocation.invoke();推进拦截器链前进。

 

如果拦截器已经执行完了, invoke() 会执行  resultCode = invokeActionOnly(); 执行对应的Action,并得到返回值。

 

前面的多次invoke()其实是形成了一个递归,当LoggingInterceptor中的 invocation.invoke();返回后,后面的记录结束语句会才会执行。这样这个LoggingInterceptor就形式了一个环绕的拦截器。

 

这个递归的调用,自然就是形成了层层包裹的结构,但在包裹的前后是否要执行相应的逻辑,就要看具体需求了。

 


 

从这里可以看出,对目标的拦截细节和责任链的推进要在拦截器中显式实现。

 

总结:

和MyBatis相比,虽然都是责任链的层层调用,链的推进和包裹的前后的执行逻辑,也要在实现中直接体现。

但这里的调度器封装了拦截器链,向下推进也都是在一个统一的逻辑中执行,并将这个中央调度器传递到每个拦截器中,以便拦截器控制推进逻辑。

而MyBatis是层层proxy,第次传给拦截器的调度器都是封闭了下一个目标,可能是一个proxy,也可能是target,责任链的推进,就是执行下一个对象的对应方法。拦截器没有被统一组织。

 

 

 

  • 大小: 15.7 KB
分享到:
评论

相关推荐

    Spring-Struts2-mybatis jar包整合

    - **配置Struts2**:在项目中添加`struts2-core.jar`等必需库,创建`struts.xml`配置文件,定义Action、结果类型、拦截器栈等。Struts2通过Action类处理请求,并转发到相应的视图或执行业务逻辑。 - **Struts2与...

    整合struts2-spring-MyBatis

    5. **整合Struts2和Spring**:使用Spring插件`struts2-spring-plugin`,配置Struts2的拦截器链,使Struts2能够从Spring容器中自动注入Action。 6. **整合Spring和MyBatis**:通过Spring的`SqlSessionFactoryBean`...

    ssm jar spring struts mybatis 所需jar

    其核心JAR文件如`struts2-core`提供了Action、拦截器、结果类型等关键组件。此外,可能还需要其他相关库,如`struts2-convention-plugin`、`struts2-json-plugin`等,用于不同类型的请求处理和数据格式化。 **...

    struts2+spring+mybatis框架JAR包

    Struts2的核心特性包括动作映射、拦截器、结果类型、国际化和主题支持等。它的优点在于提供了丰富的插件和强大的表单验证机制,使得视图层与业务逻辑层解耦,便于维护和扩展。 Spring框架则是一个全面的企业级应用...

    全注解,演示Struts2 + Spring + MyBatis整合

    **Struts2** 是一个强大的MVC框架,它提供了丰富的拦截器、结果类型和插件,使得Action控制更加简洁。在Struts2中,我们可以使用注解来定义Action类和方法,比如`@Action` 和 `@Result`,这使得配置文件大大简化。 ...

    struts2,spring3,mybatis整合图书

    Struts2通过拦截器机制实现了灵活的扩展性,同时支持多种结果类型,如JSP、FreeMarker等。在图书管理系统中,Struts2可以作为用户交互的入口,处理借书、还书、查询等操作的请求。 2. **Spring3**:Spring是一个...

    struts2 spring3 mybatis3整合简单例子

    在实际的项目中,还需要考虑异常处理、国际化、权限控制等方面,Struts2提供了拦截器(Interceptor)机制,可以方便地实现这些功能。Spring的AOP则可以在不修改原有代码的情况下,对代码进行扩展或增强。 总的来说...

    Struts2+Spring3+MyBatis框架整合源码+pdf整合文档

    Struts2的核心是Action和Interceptor(拦截器),通过配置Action和Interceptor,我们可以实现灵活的控制流程和业务处理。 Spring则是一个全面的企业级应用框架,它提供依赖注入(DI)和面向切面编程(AOP)等功能,...

    mybatis+spring+struts必须的jar包

    这些jar包包括但不限于:mybatis、mybatis-spring、spring-core、spring-context、spring-web、spring-tx、struts2-core、struts2-spring-plugin等。此外,还需要配置相应的XML配置文件,如Spring的...

    ssi(struts+spring+maven+mybatis)整合

    通过Action类和配置文件,Struts能够协调用户的输入和系统的响应,提供了丰富的拦截器和插件机制,便于扩展和定制。 **2. Spring:**Spring是一个全面的后端开发框架,包括IOC(Inversion of Control)容器、AOP...

    struts2+spring+mybatis整合

    Struts2、Spring和MyBatis是Java Web开发中三个非常重要的开源框架,它们的整合为开发者提供了强大的功能,能够实现MVC(Model-View-Controller)架构模式,提高开发效率,同时也便于项目的维护和扩展。以下是关于...

    mybatis拦截器的完整实现

    MyBatis使用了Java的动态代理和AOP(面向切面编程)思想,拦截器实际上是一个实现了`org.apache.ibatis.plugin.Interceptor`接口的类。当MyBatis执行Mapper的方法时,会通过拦截器链对方法进行处理。每个拦截器都有`...

    mybatis使用拦截器实现分页操作

    在MyBatis中,我们可以通过实现`org.apache.ibatis.plugin.Interceptor`接口并重写`intercept`方法来创建一个自定义拦截器。 分页是数据库操作中常见的需求,传统的做法是在每个查询方法中添加分页逻辑,但这会导致...

    spring3.0整合mybatis3.0、struts2

    它提供了强大的拦截器机制,可以方便地实现AOP、权限控制等功能。Struts2与Spring的整合使得模型层(由Spring管理)和视图层(由Struts2处理)可以无缝对接,提供了更好的业务逻辑处理和用户界面展示。 **整合的...

    SSH整合的包 Struts2包 spring的jar包 Mybatis包

    Struts2-Spring-plugin是一个关键的jar包(如struts2-spring-plugin-2.5.13.jar),它实现了Struts2和Spring之间的无缝集成。这个插件使得Action类可以直接从Spring容器中获取依赖,简化了配置,并且提供了更好的...

    spring_struts2_mybatis配置文件架包

    例如,Spring会通过AOP代理来调用Struts2的Action,而Struts2的Action可以通过Spring的Service层来访问MyBatis的数据访问对象(DAO)。这些交互的配置通常在`struts-plugin.xml`、`spring-struts.xml`等文件中设定。...

    Spring与Struts 2整合.zip

    5. **拦截器集成**:可以使用Spring的AOP拦截器与Struts 2的拦截器相结合,增强应用的功能。 6. **测试与调试**:整合完成后,进行单元测试和集成测试,确保所有组件协同工作。 整合Spring和Struts 2可以使开发...

    mybatis-3.5.9 源码(mybatis-3-mybatis-3.5.9.tar.gz)

    7. **插件支持**:MyBatis 提供了插件机制,允许用户自定义拦截器来修改 SQL 执行过程。在源码中,你可以看到 Plugin 类的实现,它是如何实现 AOP 功能的。 8. **事务管理**:MyBatis 支持手动和自动的事务管理。...

    Spring+struts2

    7. **拦截器(Interceptor)**:Struts2 的拦截器可以实现登录检查、权限控制等功能。 8. **过滤器(Filter)**:可能包括字符编码过滤器、Spring Security 过滤器等,用于处理请求和响应。 在实际开发中,还需要...

    struts2+spring3+mybatis整合

    Struts2、Spring3和MyBatis是Java Web开发中常用的三大框架,它们各自负责不同的职责,协同工作可以构建出高效、松耦合的应用。在Java企业级开发中,这三者的整合是常见的实践,通常被称为SSM框架。下面将详细介绍这...

Global site tag (gtag.js) - Google Analytics