《Struts2技术内幕》学习笔记

来源:互联网 发布:手机版解压软件 编辑:程序博客网 时间:2024/05/21 22:36

第2、3章 基础

  1. 三种类模式:属性-行为模式、属性模式、行为模式。其中属性模式有:PO(持久化对象)、BO(业务对象)、VO(值对象)、DTO(数据传输对象)、FromBean(页面对象)他们是对JavaBean的扩展增强。行为模式当中的方法是“请求相应模式”的天然载体。
  2. 当我们加载一个Jar包到classpath时,实际上是获得了Jar对JDK的额外支持。框架只是一个jar包而已,其本质是对JDK功能扩展
  3. 最佳实践:实际上是无数程序员在经过了无数次的尝试后,总结出来的处理特定问题的特定方法。其是一条最短路径,能够极大的解放生产力。使用保证程序的可读性可维护性可扩展性。简单就是美,面向对象编程,减少耦合。
  4. 从宏观上来说,web开发模式中最重要的一条是分层开发模式,即将整个程序根据功能职责进行纵向划分,一个比较典型的划分方法是将程序划分为:表示层、业务层和持久层,即所谓的三层架构。
    表示层:负责处理与界面交互相关的功能。  业务层:负责复杂的业务逻辑计算和判断。例如:一些有效性验证的工作:①不允许文本框中输入指定的字符串 ②数据格式是否正确及数据类型验证 ③用户权限的合法性判断等等。  持久层:负责将业务逻辑数据进行持久化存储。持久层是为业务逻辑层服务的,业务逻辑层操作的是对象,而数据库是关系型数据库。持久层要把表和字段屏蔽掉,把它变成对象来传递给我们的业务层。  Struts2是表示层的框架  Spring是业务层的框架  Hibernate是持久层的框架
  5. Struts2的运行环境是Web容器,通过扩展实现Servlet来处理HTTP请求。两条主线:Struts2初始化:init方法驱动执行。Struts2处理HTTP请求,doFilter方法的执行。
  6. Struts2的配置元素以XML为核心,而Properties文件则是起到辅助作用。struts-default.xml\default.properties是框架级别的配置文件,struts.xml\struts.properties是应用级别的配置文件。XML文件的配置元素是Properties文件配置元素的超集。
  7. XML配置元素分为:容器配置元素:bean,constant;事件映射元素:package结点。

第4章 Struts2中的设计模式

  1. Servlet使用无状态模式实现线程安全。Servlet无状态的单例对象。
  2. ThreadLocal线程安全:实现了数据的共享
    1. 纵向隔离:线程与线程之间的数据访问隔离。
    2. 横线隔离:同一线程当中不同的ThreadLocal实例操作的对象之间是相互隔离的。
  3. ThreadLocal与Sychronized关键字:ThreadLocal是一个类,Sychronized是一个保留的关键字。ThreadLocal使用了“以时间换空间”的方式以实现线程安全,而ThreadLocal使用了“以空间换时间”的方式实现了线程安全。

第5章 XWork当中的容器

  1. 对象的声明周期的管理包括两个方面:①在程序运行期间,对象实例的创建和应用机制。②对象与其关联对象的依赖关系的处理机制。
  2. 不引入容器的三大弊端:(应该引入一个与具体业务逻辑完全无关的额外编程元素容器来帮助进行对象的生命周期管理)
    1. 对象将频繁创建,效率大大降低
    2. 对象的创建逻辑与业务逻辑代码高度耦合,是的一个对象逻辑关注度大大分散。
    3. 程序的执行效率大大降低,哟与无法区分明确的职责,很难针对对象实现的业务逻辑进行单元测试。
  3. 容器的设计必须要遵循的原则:①全局的、统一的容器元素②降低与具体业务逻辑的入侵③简单而全面的操作接口。
  4. 容器管理的对象包括所有的“容器配置元素”:xml配置文件当中的所有bean框架内部对象,自定义对象和constant结点以及properties文件当中生声明的参数
  5. 对象依赖注入的步骤:①为方法、变量、参数等声明@Inject的注解②调用容器的inject方法实现注入。
  6. 在容器内部缓存的是对象实例的构建方法,而不是对象实例本身。这就让容器看起来像一个工厂的集合,能够更加不同的要求,制造出不同种类的对象实例。在容器内部根据type和name进行对象构造工厂factory的寻址。只爱后的inject调用过程,只不过是调用factory构建对象,并使用Java当中最为普通的反射机制来完成依赖注入。

第6章 OGNL

  1. Struts 2中Container.getInstance()与ObjectFactory.buildBean()的区别如下,Container.getInstance()的执行过程中需要在struts.xml中声明相应的bean节点如:
    <bean name ="entity" type ="com.yang.test.Entity" class ="com.yang.test.Entity" />
    是通过IOC容器管理得到实例的,根据bean节点中class类型的不同采用不同的InternalFactory的匿名实现,当class中含有@Inject注解时,InternalFactory的create方法调用了Container.inject()方法以实现注入。ObjectFactory.buildBean()的执行过程分两步,第一步调用Class.netInstance()建立要创建对象的实例,第二部调用Container.inject()实现依赖注入。两者的不同主要体现在实例的创建上,前者是通过在struts.xml当中声明bean节点实现的,而后者无需多余的操作,只要类的构造函数合法即可。
  2. 数据模型(Model)在View层表现为字符串,在Control层表现为Java对象。这是由于Http协议所在的Web层的“弱类型”与Java的面向对象的“强类型”不同所造成的。对于“弱类型”与“强类型”之间的转换匹配在Struts2中由“表达式引擎”完成。数据访问(从Controller层流转到View层)的困境,主要还是来源于数据模型在某些层次的表现缺乏足够的表现力。例如,在View层,即没有数据类型的概念也没有数据结构的概念。
  3. 表达式引擎能够处理表达式与对象之间双向的映射关系、能够支持丰富多样的表达式语法计算、能够支持必要的数据类型转换。
  4. OGNL表达式的三要素:表达式、Root对象、上下文环境。
  5. ClassResolver:类的寻址方式(根据字符串进行Java类寻址的处理方式)。TypeConverter:指定当一个对象属性转化为字符串以及字符串转化为Java对象时的处理方式。MemberAccess:方法/属性访问策略。
  6. 为了解决数据从View层传递到Controller层时的不匹配性,Struts2采纳了XWork的OGNL方案。并且在OGNL的基础上,构建了OGNLValueStack的机制,从而比较完美的解决了数据流转中的不匹配性。 
    OGNL(Object Graph Navigation Language),是一种表达式语言。使用这种表达式语言,你可以通过某种表达式语法,存取Java对象树中的任意属性、调用Java对象树的方法、同时能够自动实现必要的类型转化。如果我们把表达式看做是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。

第7章 别具匠心——XWork设计原理

  1. 人机沟通的三大元素:沟通协议、请求内容、相应内容。放到Web开发层面分别表现为:HTTP协议、HTTP请求、HTTP响应。
  2. 请求——相应模式在Web开发当中的实现模式:参数-返回值模式(Spring MVC)、参数-参数模式(原生Servlet)、POJO模式(Struts2)。前两者中,数据流展现在方法参数上,而最后一个反应在类的属性上,将数据流和控制流进行了有效的分离。其中“参数-参数模式(Servlet)”是其他两者的基础,其他两者都是在其基础之上发展而来的,“参数-参数模式”不仅仅考虑到了返回值的问题(数据层面的返回值),还考虑到了程序跳转的问题(控制层面的返回值)。
    它们之间的主要分歧在于:不同的实现模式使用了不同的编程元素(方法参数、方法返回值、类的属性)来表达请求-响应模式中不同的逻辑语义。
  3. 数据流 —— 描述程序运行过程中数据的流转方式及其行为状态
    控制流 —— 控制程序逻辑执行的先后顺序
    数据流和控制流是两股隐藏于程序内部的神秘力量,是程序的运行的核心驱动力。
  4. 三种数据载体:使用Map作为数据载体、使用FormBean作为数据载体、使用POJO作为数据载体。
    其中使用Map作为数据载体的缺点如下
    1. Map作为一个原始的容器数据结构,弱化了Java作为一个强类型语言的功能。
    2. 使用Map中的键值作为数据存取的依据,使得程序的可读性大大降低。
    3. 使用Map结构进行数据交互,无法实现必要的类型转化。
    使用FormBean作为数据载体的缺点如下:
    1. ForeBean被强制继承ActionForm。
    2. FormBean被强制与框架的功能耦合在一起。
    3. FormBean在参数传递非常复杂的情况下,几乎无法工作。
    其中使用POJO作为数据载体的优点如下:
    1. 作为JavaBean,POJO是一个具备语义的强类型,不仅能够享受编译器的类型检查,还能够自由定义我们所需要表达的语义。
    2. POJO不依赖于任何框架,可以再程序的任何一个层次(如业务逻辑层,甚至是持久层)被复用。
    3. POJO突破了FormBean对于页面元素唯一对应的限制,我们可以将页面中的元素自由映射到多个POJO中去。
  5. 控制层的四大职责:请求数据的接受、业务逻辑的处理、相应数据的收集、响应流程的控制。控制层的核心职责是处理业务逻辑。
  6. XWork中的三大体系包括:核心分发器(Dispatcher)、XWork控制流体系(ActionProxy、ActionInvocation、Interceptor、Action和Result)、XWork数据流体系(ActionContext和ValueStack)。这三大体有一下关系:调用关系、映衬关系。
  7. XWork数据流体系(ActionContext和ValueStack):ActionContext是一个数据环境,主要用于数据存储,ValueStack是一个数据访问环境,主要用于数据传输。
  8. XWork控制流被划分为五大元素:Action(核心处理类)、Interceptor(拦截器)、Result(处理结果)、ActionProxy(执行环境)、ActionInvocation(核心调度器)。我们可以使用一个战斗序列,来对这五大元素之间的关系进行诠释。 
    每当一个战役打响的时候,总指挥部总是需要分派一个具体番号的部队(ActionProxy)来执行战斗。任何一支部队,都有主力军(Action)策应部队(Interceptor)。主力军(Action)负责核心战斗,而策应部队(Interceptor)则负责对主力部队进行策应和援助。然而,所有的战斗指令都是由部队的指挥官(ActionInvocation)决定的。指挥官(ActionInvocation)是一个部队(ActionProxy)的核心,他将负责主力部队(Action)和策应部队(Interceptor)的调度。当一个战斗结束以后,指挥官(ActionInvocation)还要负责指挥部队下一步的动向(Result),是乘胜追击敌人,还是继续待命。

第8章 庖丁解牛——XWork元素详解

  1. 数据流:XWork数据流体系中的两大元素ActionContext和ValueStack之间的关系是从属关系。ValueStack是ActionContext的一个组成部分。ActionContext是XWork的数据流实现元素,作为一个数据载体,它既负责数据存储,又负责数据共享。ValueStack是一个具备表达式引擎计算能力的数据结构。XWork将ValueStack置于ActionContext中的目的在于为静态的数据添加动态计算的功能。
  2. 控制流:事件处理结点元素(Action、Intercepter和Result构成);事件处理驱动元素(ActionProxy和ActionInvocation构成)。在XWork的控制流中,时间处理驱动元素对时间处理结点元素形成调用关系。
  3. 事件处理结点元素中的主力部队(Action)和策应部队(Interceptor)构成一个先进先出的“栈”结构。其中,Action位于栈底,整个栈中除了Action之外就是Interceptor。
    1. 对于事件处理,能够进行进一步的规范化的流程细化
    2. 对于细化的流程,能够具备高度的可扩展性
    3. 流程细化后的事件处理结点之间表现出明显的执行层次
  4. ActionContext是数据存储和数据共享空间。其中ActionContext中的数据存储采用的是获得Request、Session、Application等容器的引用,其存储的对象具有与Web容器无关的特点。其中数据共享,采用的是ThreadLocal的方式实现,这种实现方式,使得程序能够在线程级别上达到数据的共享。
  5. ValueStack对OGNL的扩展实际上是对OGNL三要素当中Root对象所进行的扩展。其采用CompoundRoot栈的形式作为root对象,将原生OGNL中单个对象作为root的情况改变为一组多个对象作为Root的形式。其中CompoundRoot是一个继承了ArrayList的栈结构,其内部采用ArrayList的操作模拟入栈出栈操作。ValueStack是Struts2中使用表达式引擎的基础,是XWork进行OGNL计算的场所。
  6. OGNL在XWork中进行表达式计算时的基本逻辑是:从栈的顶端开始对栈内元素进行表达式匹配计算,并返回第一个匹配陈宫的表达式计算结果。其中CompoundRootAccessor是这种操作进行的执行者,就是说,CompoundRootAccessor定义了这种操作进行的方式,其提供操作(单对象root变为对象栈后对栈进行访问的操作)的具体实现。
  7. ActionContext与ValueStack是相互依存,形影不离的。ActionContext的创建总是伴随着ValueStack的创建,ValueStack的上下文环境与ActionContext的数据存储空间是等同的。
  8. 对于请求数据,参数比属性变量更为直观,也更符合Java元素语法的含义(但是其数据环境绑定到了控制流当中)。对于相应数据,最合适的表达方式是方法的返回值。但是Web框架在响应处理上必须包含响应数据和响应流程控制着两个不同的方面。单一元素的返回值很难同时表达数据和控制着两个不同的层面。相对于SpringMVC当中使用ModelAndView的方式,Struts2中使用有状态的POJO对象进行请求的相应,在数据访问上有天然的优势。Struts2中的Action具有属性特征和行为特征,是一个状态和动作的合体。Servlet与Struts2的核心区别在于处理请求的核心处理类是不是一个有状态的对象。Servlet模式,采用的是参数-参数模式,而Struts2采用的是POJO模式,后者是有状态的,前者是无状态的。
  9. ActionInvocation所进行的逻辑调度,针对的是整个栈结构,也就是执行栈。在调度执行时按照栈操作中的”先进后出“的原则,Interceptor按照顺序依次执行,最后才轮到Aciton的执行。Spring是用IoC来实现AOP,而Struts2采用的是AOP来实现IoC。
  10. ActionProxy的首要职责是维护XWork的执行元素请求对象之间的配置映射关系
  11. ActionContext的生命周期在执行拦截器之前,详细代码如下:
     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {        HttpServletRequest request = (HttpServletRequest) req;        HttpServletResponse response = (HttpServletResponse) res;        try {            prepare.setEncodingAndLocale(request, response);            prepare.createActionContext(request, response);//创建ActionContext            prepare.assignDispatcherToThread();if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {chain.doFilter(request, response);} else {request = prepare.wrapRequest(request);ActionMapping mapping = prepare.findActionMapping(request, response, true);if (mapping == null) {boolean handled = execute.executeStaticResourceRequest(request, response);if (!handled) {chain.doFilter(request, response);}} else {execute.executeAction(request, response, mapping);//执行拦截器-Action}}        } finally {            prepare.cleanupRequest(request);//清理ActionContext        }    }
     /**     * Cleans up a request of thread locals     */    public void cleanupRequest(HttpServletRequest request) {        Integer counterVal = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);        if (counterVal != null) {            counterVal -= 1;            request.setAttribute(CLEANUP_RECURSION_COUNTER, counterVal);            if (counterVal > 0 ) {                if (log.isDebugEnabled()) {                    log.debug("skipping cleanup counter="+counterVal);                }                return;            }        }        // always clean up the thread request, even if an action hasn't been executed        ActionContext.setContext(null);        Dispatcher.setInstance(null);    }
  12. ActionContext的生命周期横跨整个XWork控制流执行周期的元素,ActionContext对所有的数据共享,不仅对XWork控制流执行周期元素有效,对整个当前线程都是有效的。ActionContext是控制流元素与数据流元的够沟桥梁。
  13. ValueStack当中包含了action的引用此处将Action放到ValueStack当中。设置引用的过程在DefaultActionInvocation的init方法当中,这个方法的引用序列为DefaultActionInvocation.init()→DefaultActionProxy.prepare()→DefaultActionProxyFactory.createActionProxy()
    Dispatcher.serviceAction()→ExecuteOperations.executeAction()→StrutsPrepareAndExecuteFilter.doFilter()
      if (pushAction) {            stack.push(action);            contextMap.put("action", action);        }
  14. OgnlValueStack的构造函数调用了setRoot方法,其中的context.put(VALUE_STACK, this);此处将ActionContext与ValueStack关联到了一起
  15. Action交互体系分为以下三个方面:
    1. 外部环境交互体系——构成Action与外部环境的交互接口(HttpServletRequest、HttpServletResponse等)
    2. 数据交互体系——构成Action的请求数据和响应数据(ParametersInterceptor提供了一个数据环境映射到|Action对象的途径和方法,是外部环境与Action的属性变量进行融合的骨架。)
    3. 协作交互体系——构成Action与业务逻辑处理对象之间的协作关系

第9章 包罗万象——Struts2初始化主线

  1. 数据结构——框架的核心配置元素。算法——围绕着核心配置元素的初始化过程。Struts2初始化主线的核心驱动力,正是对各种配置形式所进行的一次统一的对象化处理。Struts2在初始化的时候,将各种各样的配置元素,无论是XML形式还是Properties文件形式(设置有可能是其他自定义的配置形式)转化为Struts2多定义的Java对象或者Struts2运行时的参数的处理过程。Struts2在初始化过程当中的额外辅助对象有三类:①配置元素加载器(将配置文件——>框架元素)②配置元素构造器(框架元素的初始化)③配置元素管理类(对配置元素的数据存储和配置元素的初始化行为进行控制)。Struts2的初始化对象分为两类,一类是容器对象,另外一类是事件映射对象
  2. 核心分发器——Dispatcher。在Struts2的初始化过程当中起到了“起承转合”的作用。
    • :负责系统的初始化工作
      /**     * Load configurations, including both XML and zero-configuration strategies,     * and update optional settings, including whether to reload configurations and resource files.     */    public void init() {//初始化configurationManager    if (configurationManager == null) {    configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);    }        try {            init_DefaultProperties(); // [1] DefaultPropertiesProvider继承至LegacyPropertiesConfigurationProvider /org/apache/struts2/default.properties 文件加载器            init_TraditionalXmlConfigurations(); // [2] StrutsXmlConfigurationProvider struts-default.xml,struts-plugin.xml XmlConfigurationProvider struts.xml             init_LegacyStrutsProperties(); // [3] LegacyPropertiesConfigurationProvider 加载除default.properties之外的strutus相关的properties文件//[4]init_PreloadConfiguration()            init_CustomConfigurationProviders(); // [5] 用户自定义配置加载类 初始化用户自定义的配置加载器(这个加载器通过Filter的初始化参数配置)            init_FilterInitParameters() ; // [6] ConfigurationProvider匿名内部类实现 加载Filter的初始化配置信息将定义的initParams从web.xml中读入,放入props             init_AliasStandardObjects() ; // [7]  BeanSelectionProvider 根据struts常量配置 初始化与其他框架整合用到的类,例如xml中配置struts.objectFactory为spring就需要StrutsSpringObjectFactory             //init_PreloadConfiguration会调用ConfigurationManager.getConfiguration()会调用 DefaultConfiguration.reloadContainer()在这里面会循环调用上面七个ConfigurationProvider的register方法             Container container = init_PreloadConfiguration(); //[4] 创建容器,对容器进行依赖注入 平对package进行注入            container.inject(this);//额外的初始化操作,检查是否支持reloading加载和对weblogic服务器的特殊设置。            init_CheckConfigurationReloading(container);            init_CheckWebLogicWorkaround(container);            if (!dispatcherListeners.isEmpty()) {                for (DispatcherListener l : dispatcherListeners) {                    l.dispatcherInitialized(this);                }            }        } catch (Exception ex) {            if (LOG.isErrorEnabled())                LOG.error("Dispatcher initialization failed", ex);            throw new StrutsException(ex);        }    }
    • :接受并预处理HTTP请求。把Web容器相关的数据对象封转成普通的Java对象,进行了“去容器化”处理,是的后续依赖于Web请求的操作不再受限于任何的Web容器对象,从而做到了解耦和。
      createContextMap(Map, Map, Map, Map, HttpServletRequest, HttpServletResponse, ServletContext)createContextMap(HttpServletRequest, HttpServletResponse, ActionMapping, ServletContext)wrapRequest(HttpServletRequest, ServletContext)prepare(HttpServletRequest request, HttpServletResponse response)
    • :将Struts2转入XWork,Dispatcher是Struts2与XWork的临界点。serviceAction与Servlet当中的service有异曲同工之妙
      serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,                              ActionMapping mapping)
    • :清理垃圾
      void cleanup()
  3. Dispatcher使用了ThreadLocal模式,是一个线程安全的对象,Dispatcher涵盖了Struts2的整个生命周期。无论是Struts2的初始化,还是处理HTTP请求,实际都在Dispatcher中完成。Dispatcher是Struts2与Xwork的分界点,也是将MVC实现与Web容器相隔离的分界点
  4. 配置元素加载器(Provider):是各种配置的表现形式到Java世界的桥梁。对于配置元素加载器有一个统一的接口:
    public interface ConfigurationProvider extends ContainerProvider, PackageProvider {}
    • ContainerProvider是容器加载器,中的方法
      public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException;
      表示在Container容器中注册bean和properties(注册工作由ContainerBuilder完成?)。不同的ContainerProvider之间没有依赖关系,因此这是框架提供的隐含扩展点,只要新类型实现了ContainerProvider接口,就能实现实现自定义配置表现形式,并将其加载到容器当中。
    • PackageProvider 事件映射类型加载器,中的方法
      public void loadPackages() throws ConfigurationException;
      加载所有的Package定义,并创建PackageConfig对象。其中XmlConfigurationProvider及其子类StrutsXmlConfigurationProvider实现了这个方法,创建了PackageConfig对象。PackageConfig对象与xml配置文件当中package结点相对应
  5. 配置元素构造器(Builder):使用了构造模式。主要进行参数搜索创建对象操作。
    • ContainerBuilder,参数收集:factory方法、alias方法、constant方法。构造对象:create方法。其中BeanSelectionProvider和XmlConfigurationProvider及其子类StrutsXmlConfigurationProvider在register方法中使用了改构造器。本构造器主要用于将配置表中的结点注册到Container当中。
    • 事件映射构造器:PackageConfig.Builder。其中也包含了收集元素和创建对象的过程。其中XmlConfigurationProvider使用了该类。
  6. 配置元素的管理类(ConfigurationManager和Configuration):ConfigurationManager和Configuration两者的关系就如同XWork当中ActionProxy与ActionInvocation之间的关系类似。初始化驱动元素。ConfigurationManager是整个配置元素进行操作的代理接口类,而真正对所有配置元素的初始化进行调度的是Configuration对象。
    • Configuration,提供框架级别对所有配置元素的访问操作接口对所有的配置元素进行初始化调度。从Configuration接口的定义可以看出Struts2配置的主要两种对象:容器,事件映射对象。
    • ConfigurationManager,在XWork当中所起到的作用就如同ActionProxy在XWork当中起到的作用类似。是配置元素的操作接口。
  7. DispatcherListener用于扩展使用,比如你要定制Dispatcher,或者修改Dispatcher的某些东西;可以继承FilterDispatcher 然后获取Dispatcher然后添加DispatcherListener。其在Dispatcher初始化和结束时会被调用。还可以通过继承StrutsPrepareAndExecuteFilter并重写protected voidpostInit(Dispatcher dispatcher, FilterConfig filterConfig) { } 完成初始化时的扩展工作。
  8. 注意容器的创建过程。

第10章 井然有序——与HTTP请求的战斗

  1. Struts2对HTTP请求的处理包括两个阶段:HTTP请求的预处理阶段XWork事件处理阶段。Struts2对这两个阶段进行了划分,代码上的物理解耦(两个阶段分属于不同的框架主导执行Struts2和XWork),逻辑职责上的解耦(两个阶段主要的职责不同)。
    • HTTP预处理阶段主要由Struts2完成,主要是与Web容器打交道,将HTTP请求转化为普通的Java代码。
    • XWork事件处理阶段主要XWork完成,对请求完成核心逻辑处理。
  2. doFilter主要类是
    • Dispatcher核心分发器,执行Struts2处理逻辑的实际场所。是真正将HTTP请求与MVC实现(XWork框架)分离的核心分发器。
    • PrepareOperationsHTTP预处理类,对所有的HTTP请求进行预处理,实际上在其中的预处理操作,基本上调用了Dispatcher类中的方法。
    • ExecuteOperationsHTTP处理执行类,执行HTTP请求的场所。
  3. ActionMapper是Struts2进行URL Mapping关系查找的核心类,他的主要作用是根据请求的Request创建一个对应的ActionMapping。
  4. ActionProxy两大数据源:配置关系映射:namespace、actionName、methodName。运行上下文环境:Map<String, Object> extraContext。因为extraContext的创建过程使用了函数Dispatcher.createContextMap(),与ActionContext和ValueStack创建的过程是一样的(调用了同一个函数),也就是说,extraContext的与ActionContext和ValueStack的上下文环境是等同的
  5. DefaultActionInvocation的初始化过程init()中包含了将Action实例push到ValueStack当中的动作,是XWork当中的数据流与控制流融合的关键一步。同时还有关键的一步就是将拦截器栈的迭代器指针重置到了栈顶位置。
  6. DefaultActionInvocation的invoke()调度使用了递归调用的方式,形成了一个栈调用的方式,同时将Action放到了栈底执行。

第11章 展翅高飞——让视图放开手脚

  1. HTML语言是一种静态语言,缺乏数据沟通能力。JSP,Java Server Page允许在构成Page的HTML语言之上嵌入Java的语法片段,从而加强其余Server的交互能力。JSP的引入解决了两个方面的问题。
    • 解决了页面视图的构建问题,以HTML代码作为构建的主要问题。
    • 解决了与服务器端进行数据沟通的问题,以Java语法作为沟通基础。
  2. 所有的JSP在运行期都被编译成Servlet在Web容器中运行。浏览器是视图层的表现载体,所有视图层的交互职责都是通过浏览器进行的操作。视图的本质是Web容器对象HttpServletRequest和HttpServletResponse对浏览器行为的控制。
  3. 视图的两大职责:(最大的职责就是驾起Controller层到View层的桥梁)
    • 视图内容呈现——以HTML为基础进行的构建
    • 数据和逻辑呈现——以Java语法为基础的构建
  4. Result不同的视角,XWork视角——事件处理结点(我们对事件处理流程步骤的划分结果),Struts2视角——视图的操作窗口(相当于完成了Servlet对象中HttpServletResponse的职责)
  5. 标签库产生的初衷:消除在HTML代码当中的Java代码,以一种自定义的扩展标签来代替原本需要Java代码表达的业务逻辑。
  6. 标签的分类:
    • 逻辑控制类——控制页面输出逻辑
    • 数据输出类——与服务器端进行数据沟通并以一定格式进行输出
    • 页面组件类——将页面元素的功能进行组件化编程
  7. 与传统的Servlet当中使用HttpServletRequest方式作为数据输出的方式不同,Struts2使用了使用ValueStack方式进行数据访问。

第12章 三头六臂——Struts2的扩展机制

  1. 可维护性,可扩展性。核心程序:①抽取各个功能模块的公共逻辑成为一个独立的核心功能模块。②为核心功能模块添加对其他功能模块的执行调度功能。不同功能模块之间没有依赖关系,插件模块与主模块之间存在调用关系。这是一种星形依赖关系。客户功能模块对插件模块进行调度,不同插件模块之间没有依赖关系,功能模块之间保持独立,不会互相影响。如Chrome的插件,和Eclipse的插件OSGi。
  2. 插件式开发的利弊。(软件环境:基础构建,俗称程序骨架。功能模块:插件)
    • 软件模块的管理变得更加容易
    • 软件功能的可塑性和可扩展性更强
    • 页软件的产品化和定制化成为可能
    • 软件运行环境的优劣,将直接印象整个软件的质量
    • 软件环境的版本升级将导致依赖于该环境的所有插件失效
  3. Struts2的插件以Jar包形式存在。在Jar包的根目录下有struts-plugin.xml的文件,该文件的配置与struts.xml文件的配置格式相同。Struts2的插件仅仅对Struts2的核心Jar构成依赖关系,不同插件之间原则上不存在依赖关系。因为没有依赖关系,因此插件的加载顺序是随机的
  4. Struts2的三类扩展方式:
    • 定义新的时间映射关系对象(Action、Interceptor、Result等)
    • 进入新的接口定义实现或者运行参数,将其纳入Struts2容器进行管理。
    • 覆盖Struts2/XWork的模式接口实现
  5. Struts2的插件的分类:
    • 框架整合类插件(Spring Plugin、Guice Plugin、JRuby Plugin等)
    • 简化配置类插件(Codebehind Plugin、SmartURLs Plugin、Convention Plugin等)
    • 页面装饰类插件(Sitemesh Plugin、Tiles Plugin等)
    • 功能扩展类插件(JFreeChart Plugin、JasperReports Plugin、Potlet Plugin等)
  6. Struts2中XML文件加载顺序:struts-default.xml(最先加载)——》struts-plugin.xml(第二加载)——》sturts.xml(最后加载)
  7. struts-plugin.xml的加载顺序是不确定的。
0 0
原创粉丝点击