表示层的一些困惑:
---------------------------------------------------------------------------------------------------
问题一:Web应用是典型的“请求——响应”模式,数据是如何顺利流转于浏览器和Java世界之间的?
在浏览器中,数据总是以字符串形式展现出来的,表现出“弱类型”的特征,而在Java世界,数据则体现为一个个结构化的Java对象,表现出强类型的特征。
struts2为解决数据流转的问题,提供了表达式引擎——OGNL,将表达式插入到程序执行之前,我们就能从复杂的对象转换中解放出来。
------------------------------------------------------------------------------------------------------------------
问题二:Web容器是一个多线程的环境,针对每个Http请求,Web容器的线程池都会分配一个特定的线程进行处理,如何保证数据的流转和访问都是线程安全的?
Servlet对象是一个非线程安全的对象,传统的保证线程安全的方式是规避,即禁止在Servlet对象的方法中访问Servlet对象的内部变量(非语法检查级别的禁止)。
struts2在整个请求周期中引入ThreadLocal模式,将整个对象额访问都线程安全化。
Struts2概述
struts2是一个运行于Web容器表示层的框架,其核心作用是帮助我们处理Http请求(通过扩展实现Servlet标准)。
一、struts2的核心技术
1.struts2与表示层技术
struts2运行于Web容器中,其核心依赖就是Web容器对于Servlet标准和JSP标准的实现。
作为一个服务于表示层的解决方案,Struts2需要与其他表示层技术进行整合。例如模板技术、Flex技术、Ajax技术等等。struts2要做的只是通过扩展实现一些Servlet标准与这些技术进行底层沟通从而完成与这些技术的整合。一般通过“插件”模式。
2.struts2与设计模式
命令(command)模式、ThreadLocal模式、装饰(Decorator)模式、策略( Strategy )模式、构造(Builder)模式、责任链(Chain Of Responsibility)模式、代理(Proxy)模式等等。
3.表达式引擎——OGNL
OGNL是Struts2运行所依赖的基本核心技术之一。解决了Web应用与Java世界之间的沟通问题。
4.Xwork
二、struts2的宏观视图
1.struts2的核心程序入口
struts2的核心入口程序,从功能上讲必须能够处理Http请求,这是表示层框架的基本要求。因此Struts2遵循了Servlet标准,通过实现标准的Filter接口来进行Http请求的处理。通过在web.xml中指定这个实现类,就可以将Struts2框架引入到应用中来:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
其中StrutsPrepareAndExecuteFilter是Filter接口的一个实现类。由于Filter中所定义的方法具有完全不同的执行时间和生命周期,它们的执行互不影响。将Filter的生命周期作为对整个Struts2进行运行逻辑主线划分的主要依据:
第一条主线——Struts2的初始化:init方法驱动执行
第二条主线——Struts2处理Http请求:doFilter方法驱动执行
示意图:
2.Struts2的初始化主线
发生在应用程序启动之初,由入口程序的init方法驱动执行完成。特点:
1)仅在Web应用启动时执行一次,执行完毕,则该主线结束,不参与后面任何Http请求的处理过程。
2)init方法执行失败将导致整个Web应用启动失败。
初始化主线做了什么?
1)框架元素的初始化工作:对框架内部的许多内置对象的创建和缓存。
2)控制框架运行的必要条件:Struts2框架级的运行时检查。
3.Struts2的Http请求处理主线(核心主线)
包含Struts2处理Http请求、进行必要的数据处理和处理数据返回的全部过程。这条主线将在满足web.xml中所指定的URL Pattern的Http请求发生时进行响应,由doFilter方法负责驱动执行。
两个阶段:
第一阶段——Http请求预处理
该阶段,程序的控制权在Struts2手中,主要针对每个Http请求进行预处理,为真正的业务逻辑执行做必要的数据环境和运行环境的准备。阶段特点:依赖于Web容器,与Web容器打交道。
第二阶段——XWork执行业务逻辑
该阶段,程序控制权被移交给了XWork。Struts2在完成Http请求预处理后,将Http请求中的数据封装成普通的Java对象,并由XWork负责执行具体的业务逻辑。阶段特点:不依赖于Web容器,由Xwork框架驱动整个执行过程。
由此可见,Struts2的核心设计理念在于消除核心程序对运行环境(Web容器)的依赖,实现解耦。
三、Struts2的微观元素
1.Struts2的初始化主线
为了管理Struts2的内置对象,Struts2引入了一个“容器”的概念。Struts2的初始化过程也是围绕这个“容器”展开。除了“容器”,PackageConfig也是Struts2初始化的主要内容之一。以下给出部分数据结构和基础操作接口:
2.第二条主线:第一阶段——Http请求预处理
该阶段做了大量对象创建和对象转化的工作。
Dispatcher是整个Struts2框架的核心,称为核心分发器,是进行Http请求处理的实际场所。它不仅是Http请求预处理的实际执行者,更是将Http请求与Web容器进行解耦并进行逻辑处理转发的执行驱动核心。
3.第二条主线:第二阶段——XWork执行业务逻辑
XWork元素调用关系图:
主要分为三个部分:
(1),核心分发器 Dispatcher : Dispatcher 不属于XWork框架的组成,但是是XWork框架的调用者和驱动执行者,在运行过程中起着重要的作用。
(2),控制流体系 (ActionProxy, ActionInvocation, Inteceptor, Action, Result), 其中,Interceptor和Action以及Result作为事件处理节点,是处理事件逻辑的主要地方,而ActionProxy和ActionInvocation负责对这些事件处理节点进行调用。
这里,ActionProxy主要是XWork框架和外部环境,为框架内部元素提供一个环境的同时也提供外部调用XWork内部元素的接口,即负责提供一个执行环境。而ActionInvocation作为核心调度器,主要负责的就是对事件处理节点进行调用。
(3),数据流体系 (ActionContext, ValueStack),其中ActionContext负责数据的储存和数据的共享,而ValueStack负责数据的操作。
四、Struts2配置
1.配置元素
1)include节点
配置文件第一层根节点,主要作用是帮助管理Struts2配置文件,实现配置文件的模块化。
2)bean节点
一个用于描述接口及其实现类映射关系的结点。从逻辑关系上,bean节点的寻址是通过name属性和type属性共同构成一个逻辑主键来共同决定一个class属性。即可以通过name属性和type属性的值来控制一个接口的不同实现方式。
bean节点在 Struts2内部的存在形式:Struts2实现了一个对象容器,并将配置文件中所有bean节点所定义的对象纳入容器之中进行管理。Struts2通过这个容器在框架级别负责这些对象的创建、销毁以及依赖关系的处理 。并且在该容器的基础上实现了依赖注入(IoC)。
3)constant节点
主要用于定义Struts2运行时的参数,作用与Properties文件是完全重合的。
该节点与bean一样,会在系统初始化时被加载到Struts2容器中进行统一管理。
4)package节点
一个package节点实际上可以被看做一条简单的XWork生产线,其中包含了XWork框架如何对某些请求并选择相应的执行序列进行处理的具体方式。
package节点的作用是一种映射关系,更多的反映框架如何与外部程序进行交互的过程。其中name属性是唯一标识符,namespace从命名空间的角度为整个事件请求机制划分不同的种类。二者都用于对请求进行逻辑划分。
extends属性允许package之间形成相应的继承关系。通过继承,子package自动获得父package的所有配置定义。