XWork是Struts2运行机制的核心。

按照官方定义:XWork是一个灵活而可靠的基于命令模式的开发框架。所谓命令模式,本质上就是请求-响应模式。

请求响应的实现模式

  • 参数-返回值模式

    在这里,方法在语法上天然的能够与请求-响应模式相对应:

    方法签名-请求-响应模式的处理载体

    方法参数-请求内容映射

    方法返回值-处理结果响应

SpringMVC就是基于这种模式来定义和实现 Http 请求的处理与响应的。

  • 参数-参数模式

    Servlet标准就是基于这种模式来进行设计的,因此这种模式也叫Servlet模式。

    参数列表——Http请求被封装在一个HttpServletRequest对象,而响应被封装在HttpServletResponse对象中。

    返回值——方法不存在返回值。

    这种将请求和响应同时置于参数位置的模式,就是参数-参数模式。

    为什么采用这种模式呢?

    Servlet作为一个开发标准,它所设计的接口已经无法再将任何处理职责继续往上层推送了,因为它是Web开发最底层的标准。

  • POJO模式

    在这种模式中,我们看到虽然实际进行请求的处理和响应的载体依然是POJO中的一个具体方法,但是我们并没有看到这个方法中存在任何参数。所有的请求参数,将以POJO内部属性变量的形式存在并被调用。所有的执行结果对象也同样以POJO内部属性变量的形式存在。这样一来,POJO相对应某一次的响应是一个有状态响应。因为响应处理流程、处理机制和处理结果,与当前POJO实例的内部属性的状态有关。

    public class UserController {

        private String username;

        private String password;

        public String login() {

            return "success";

        }

    }

上面是一个普通POJO的例子。
可以看到,POJO模式与Servlet模式有很大不同,传统的Servlet对象是一个无状态的对象,即并非一个线程安全的对象,而POJO模式从概念上突破了Servlet对象的限制,将每一个请求的处理映射到一个线程安全的响应对象中去执行。

数据流和控制流

数据流和控制流是两股隐藏于程序内部的神秘力量,是程序运行的核心驱动力。

在整个请求-响应过程中,数据流实际上表现为数据内容,其核心包括数据请求和数据响应;而控制流实际上表现为方法进行逻辑处理的过程,包含程序的执行方向。

数据载体

在MVC中的Model层,我们对于数据的关注点主要有两个:数据存储和数据传输。Model所扮演的是一个载体角色。

载体必须有一定的数据结构,什么样的数据结构和数据形式最适合最为Web层的传输介质呢?

Map

基于键值对的数据结构。Servlet标准在设计HttpServletRequest规范时就是用了类似Map结构来进行数据交互。

在源码中这样定义方法:

public Map getParameterMap();//返回一个Map实例,以参数名称为键值,以参数实际值为Value的键值对。

public String[] getParameterValues(String name);

public String getParameter(String name);

这种方式的局限性:

1.Map的本质是一个容器结构,使用Map中的键值作为数据存取的依据,使得程序的可读性大大降低。

Map中的数据可以在任意情况下进行增删。当这些增删的逻辑散落在程序的各个角落时,我们很难在某一个特定时刻知道当前Map中到底有哪些Key值可以进行存取。

2.使用Map结构进行数据交互,无法实现必要的类型转化。

从上面的源码中可以看到,根据name可以取到页面上提交上来的值,但是那些值全部都是String或者String[]类型。Map无法提供Java所具备的强类型语言的基本功能。

FormBean

Struts1.X为代表的许多Web框架提出的数据交互载体的解决方案。

具体实现此处略去。大致问题是:某些方法实现需要框架和容器的支持,与框架耦合性太强。

POJO

1.作为JavaBean,POJO是一个具备语义的强类型。

2.POJO不依赖于任何框架,可以在程序的任何一个层次(如业务逻辑层或者持久层)复用。

3.POJO突破了FormBean对于页面元素唯一对应的限制,我们可以将一个页面的元素自由映射到多个POJO中去。

控制流的细节

控制层的核心职责是处理业务逻辑。

所以,控制层应该更加关注其核心的职责,而其他的辅助逻辑则由框架帮忙来完成。

XWork

XWork宏观视图

核心分发器

Dispatcher,本身不属于XWork的框架部分,但是它运行于Web容器中,是XWork框架的调用者和驱动执行者。

XWork 控制流体系

XWork进行请求响应的一系列执行元素:ActionProxy,ActionInvocation, Interceptor, Action, Result。

XWork 数据流体系

XWork在进行请求响应时所依赖的一个数据环境,包括两大元素:ActionContext 和 ValueStack。

XWork 微观视图

数据流元素

ActionContext: 是一个独立的数据结构,其主要作用是XWork的执行提供数据环境。无论是请求参数还是处理的返回值,甚至一些原生的Web容器对象都封装在ActionContext内部。

ValueStack:本身是一个数据结构,主要作用是对ognl 计算进行扩展。

XWork 构成数据流元素的两大基础性功能:数据存储和数据传输。由ActionContext负责数据存储,而ValueStack负责数据传输。

将数据流元素设计成为独立的数据结构,是XWork的一大亮点。传统的参数-返回值模式和参数-参数模式,无论是请求内容还是响应内容,在表现形式上都是方法的一个重要组成部分,作为控制流主要载体的方法本身对于数据流元素形成了语法依赖。造成了数据流和控制流天然耦合,参数和返回值在语法层面被紧密联系在一起。

控制流元素

从图中可以看到,构成控制流的元素有五个。从功能逻辑上划分可以分成两类:Interceptor/Action/Result被用于定义事件处理的基本流程,称之为事件处理节点;ActionProxy和ActionInvocation在事件处理的过程中起到作用的是对于事件处理节点进行调度执行,成为事件驱动元素

下一篇博客将详细深入地介绍这七大元素。