《Struts2技术内幕》学习笔记

第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与Sychronizedkeyword:ThreadLocal是一个类,Sychronized是一个保留的keyword。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载入和对weblogicserver的特殊设置。
      
      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代码作为构建的主要问题。
    • 攻克了与server端进行数据沟通的问题,以Java语法作为沟通基础。
  2. 全部的JSP在执行期都被编译成Servlet在Web容器中执行。浏览器是视图层的表现载体,全部视图层的交互职责都是通过浏览器进行的操作。视图的本质是Web容器对象HttpServletRequest和HttpServletResponse对浏览器行为的控制。

  3. 视图的两大职责:(最大的职责就是驾起Controller层到View层的桥梁)
    • 视图内容呈现——以HTML为基础进行的构建
    • 数据和逻辑呈现——以Java语法为基础的构建
  4. Result不同的视角。XWork视角——事件处理结点(我们对事件处理流程步骤的划分结果),Struts2视角——视图的操作窗体(相当于完毕了Servlet对象中HttpServletResponse的职责)
  5. 标签库产生的初衷:消除在HTML代码其中的Java代码,以一种自己定义的扩展标签来取代原本须要Java代码表达的业务逻辑。
  6. 标签的分类:
    • 逻辑控制类——控制页面输出逻辑
    • 数据输出类——与server端进行数据沟通并以一定格式进行输出
    • 页面组件类——将页面元素的功能进行组件化编程
  7. 与传统的Servlet其中使用HttpServletRequest方式作为数据输出的方式不同。Struts2使用了使用ValueStack方式进行数据訪问。

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

  1. 可维护性,可扩展性。

    核心程序:①抽取各个功能模块的公共逻辑成为一个独立的核心功能模块。②为核心功能模块加入对其它功能模块的运行调度功能。不同功能模块之间没有依赖关系,插件模块与主模块之间存在调用关系。这是一种星形依赖关系。

    客户功能模块对插件模块进行调度,不同插件模块之间没有依赖关系,功能模块之间保持独立。不会互相影响。如Chrome的插件,和Eclipse的插件OSGi。

  2. 插件式开发的利弊。(软件环境:基础构建,俗称程序骨架。功能模块:插件)
    • 软件模块的管理变得更加easy
    • 软件功能的可塑性和可扩展性更强
    • 页软件的产品化和定制化成为可能
    • 软件执行环境的优劣,将直接印象整个软件的质量
    • 软件环境的版本号升级将导致依赖于该环境的全部插件失效
  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的载入顺序是不确定的。
时间: 2024-10-12 14:48:34

《Struts2技术内幕》学习笔记的相关文章

疯狂Android讲义 - 学习笔记(二)

Android应用的用户界面编程 Android推荐使用XML布局文件来定义用户界面 ViewGroup是一个抽象类,通常使用它的子类作为容器,ViewGroup控制其子组件的分布依赖于两个内部类: ViewGroup.LayoutParams 和 ViewGroup.MarginLayoutParams 疯狂Android讲义 - 学习笔记(二),布布扣,bubuko.com

疯狂Android讲义 - 学习笔记(六)

第7章 7.1 使用简单图片 7.1.1 使用Drawable对象 7.1.2 Bitmap和BitmapFactory 7.2 绘图 7.2.1 Android绘图基础:Canvas.Paint等 Android的绘图应该继承View组件,并重写onDraw(Canvas canvas) 方法即可,Canvas代表了“依附”于指定View的画布.表7.1 Canvas的绘制方法 Paint代表了Canvas上的画笔,Paint类主要用于设置绘制风格,包括画笔颜色.画笔粗细.填充风格等. 7.2

疯狂Android讲义 - 学习笔记(八)

第10章 Service与BroadcastReceiver 10.1 Service简介 Service组件也是可执行的程序,有自己的生命周期,创建.配置Service与创建.配置Activity的过程基本相似.Service一直在后台运行,没有用户界面. 10.1.1 创建.配置Service 需要2个步骤:1 定义基础Service的子类,2 在AndroidManifest.xml文件中配置Service. Service与Activity都是从Context派生出来的,因此都可以调用C

疯狂Android讲义 - 学习笔记(五)

第五章 Android使用统一的Intent对象来封装“启动意图”,不管是启动Activity.Service组件.或者BroadcastReceiver等,提供了一致的编程模型.Intent设计有点类似于Struts2框架中的逻辑视图设计. Intent还是应用程序组件之间通信的重要媒介:数据封装成Bundle对象,Intent携带Bundle对象. 5.1 Intent对象详解 5.2 Intent的属性及intent-filter配置 5.2.1 Component属性 5.2.2 Act

疯狂Android讲义 - 学习笔记(四)

Android应用通常有多个Activity,多个Activity组成Activity栈,当前活动的Activity位于栈顶.Activity相当于Java Web开发的Servlet.当Activity处于Android应用运行时,同样受系统控制.有生命周期. 4.1 建立.配置和使用Activity 4.1.1 Activity 建立自己的Activity需要集成Activity基类,在不同的应用场景,有时也能集成Activity的子类. Activity间接或直接继承了Context.Co

疯狂Android讲义 - 学习笔记(七)

第8章 Android数据存储与IO  Java IO的数据存储可以移植到Android应用开发上来,Android系统还提供了一些专门的IO API. Android系统内置了SQLite数据库,SQLite是轻量级的,没有后台进程,整个数据库对应一个文件,这样可以非常方便的在不同设备之间移植.Android为访问SQLite提供了大量便捷的API. 8.1 使用SharedPreferences 适用于保存简单格式的数据. 8.1.1 SharedPreferences 与 Editor S

【疯狂Java讲义学习笔记】【数据类型与运算符】

[学习笔记]1.8bit = 1byte,4byte = 1word.Java中的整型数据有byte(1字节),short(2字节),int(4字节),long(8字节).Java中的浮点数据有float(4字节),double(8字节)Java中还有一个字符型char(2字节),本质也是整型Java中的布尔型boolean(1位) 2.类型转换分为自动类型转换和强制类型转换.自动类型转换,比如:范围小的数赋值给了范围大的数:空字符串和基本类型数值连接. 3.表达式类型的自动提升:当一个算术表达

【疯狂Java讲义学习笔记】【流程控制与数组】

[学习笔记]1.switch语句后的expression表达式的数据类型只能是byte.short.char.int四个整数类型.String(Java 7后才支持)和枚举类型. 2.数组的长度不可变,定义数组时候不能指定数组的长度.为数组分配空间的时候一定要进行初始化,数组初始化的方法有两种,第一种是静态初始化,在数组中直接为每个数组元素赋上初值,另一种是动态初始化,在初始化的时候指定数组的长度,由系统来为每个元素指定初值.注意的是两种初始化不能够同时使用,即既指定数组的长度,同时又为每个元素

疯狂Android讲义 - 学习笔记(三)

Android的事件处理 3.1 Android提供了两套事件处理机制:基于监听的事件处理.基于回调的事件处理. 3.2 基于监听的事件处理 3.2.1 监听的处理模型  主要涉及三类对象:EventSource.Event.EventListener. Android的事件处理机制是一种委派式(Delegation)事件处理方式:普通组件将整个事件处理委托给特定的对象(事件监听器),可以把所有可能的事件授权给不同的事件监听器来处理,也可以让一类事件都使用同一个事件监听器来处理. 事件监听类是一

《疯狂XML讲义》学习笔记

<疯狂XML讲义>主要分为五个部分.第一部分介绍了XML.DTD.XML Schema等基础知识,这些知识主要教读者如何定义有效的XML文档,这部分 内容是深入学习后面知识的基础,也是每个使用XML的开发者都应该掌握的 基础.第二部分介绍了CSS.XSLT和XPath等知识,通过使用CSS或XSLT,可 直接将XML文档当成视图技术.第三部分介绍了DOM.SAX.JAXP.dom4j. JDOM.XQuery和XQJ等,其中的DOM.SAX.JAXP.dom4j和JDOM都以结构化的 方式来创