一、框架的本质
在说Struts2,Spring和Hibernate核心原理之前,我觉得应该先搞明白以下三个问题,简短概括如下:
1、什么框架?
框架并不是什么神圣的东西,它只是一组jar包而已,其本质是对jdk功能的扩展,包含了一系列最佳实践,作用是解决某个领域的问题。
从广义上说,jdk也可以看做一个复合框架,它提供的api同样是为了解决各个领域的问题,例如java io解决文件操作的问题,java socket解决网络通讯的问题等等。
2、框架从何而来?
从框架的本质看,框架的产生就是为了解决一个又一个在开发中所遇到的问题。不同的框架是为了解决不同领域的问题。
3、为什么要使用框架?
框架是因解决问题而来,而且它带来了解决某一领域问题的最佳实践,实际是无数程序员在经过了无数次尝试后,总结出来处理特定问题的特定方法,如果我们把每个程序员的自由发挥看做是一条通往成功的路径,最佳实践就是其中的最短路径,它能够极大地解放生产力。
二、框架的适用范围
Web开发模式中最普遍的一种是“分层开发模式”,分层开发模式是指,在开发J2ee程序时,将整个程序根据功能职责进行纵向划分,比较常见的划分方法是:表示层,业务层,持久层。具体不再赘述,做java web开发,这是基本常识了。根据业务需求作用域的不同,这种分层会产生不同程度的变化,可能会细化更多层,也可能会合并,不能为了分层而分层,一切脱离业务架构的设计都是虚幻的。
我们最为熟悉得Struts,Spring,Hibernate正是为了应对各个层次的编程问题的最佳实践。即Struts对应表示层,Hibernate对应持久层,而Spring比较特殊,我们暂时简单地认为它对应业务层,后面我们再详细讨论。
三、Struts2
说了这么多,终于进入文章的重心了。
从宏观看,Struts2是一个运行于Web容器的表示层框架,其核心作用是帮助我们处理http请求。
Struts2遵循Servlet标准,通过实现标准的Filter接口进行Http请求的处理,通过在web.xml指定这个实现类StrutsPrepareAndExecuteFilter,就可以将Struts2引入到应用中来。
而Filter的生命周期也成为我们对整个Struts2进行逻辑主线划分的主要依据。
主线1:Struts2初始化-----Filter的init方法驱动执行。
主线2:Struts2处理Http请求------Filter的doFilter方法驱动
示意图:
1、Struts2初始化
Struts2初始化只在web容器启动时执行一次,启动的成败关系整个web应用的启动成败。初始化主线贯穿Struts2对其内置对象的创建和缓存过程,将Struts2的运行环境完整地创建起来。
我们从“数据”和“行为”两个角度来分析,构成Struts2整个初始化过程的主要元素,就可以分为“数据结构的定义”和“初始化行为的操作接口”两部分。
(1)从数据结构定义的角度,Struts2围绕管理Struts2内置对象的容器展开,该容器成为初始化主线中的核心构成元素。而另一类配置元素PackageConfig作为事件请求映射的配置元素也可作为构成元素。接口定义和实现类分别为:Container,ContainerImp,PackageConfig。
(2)从初始化行为的操作接口的角度,则由另外两个元素完成,加载接口和构造器。接口为:ConfigurationProvider(使用多重继承将Container和PackageConfig两类配置加载接口进行统一),ContainerProvider(Container的配置加载接口,其实现类需要负责初始化容器中的所有对象),PackageProvider(PackageProvider接口,其实现类负责初始化用于处理事件请求的配置对象),ContainerBuilder(Container构造器,用于初始化时构造容器),PackageConfigBulider(PackageProvider构造器,用于初始化时构造PackageProvider)
还有两个辅助元素承载上述接口,驱动整个初始化流程:ConfigurationManager(配置行为操作代理类,包含所有ContainerProvider和PackageProvider的实现以及配置的结构化数据Configuration),Configuration(配置数据的管理类,运行时获取配置的基本接口,承载所有配置的结构化数据和操作方法)
初始化步骤详细示意图
2、Struts2处理Http请求
Struts2处理Http请求又分两个阶段:Http请求预处理阶段(以后统称阶段1),XWork执行业务逻辑(以后统称阶段2)
严格意义上说,Struts2是由两个不同的框架组成,一个是执行在阶段1的Struts2,负责将Web容器与MVC分离,,一个是执行在阶段2的XWork,真正的MVC实现。
(1)阶段1的主要元素
Dispatcher,整个Struts2的核心,被称为核心分发器,是Struts2进行http请求预处理的核心场所,更是将Http请求与web容器解耦并进行逻辑处理转发的执行驱动中心。
PrepareOperations,HTTP预处理类,进行Http请求预处理的操作集合
ExecuteOperations,HTTP处理执行类,进行Http请求逻辑处理的操作集合
(2)阶段2的主要元素
这一阶段,程序控制权交给了XWork框架,涉及XWork框架的七大元素,这七大元素构成一条生产线,完成对http请求的处理。
ActionProxy,整个生产线的入口,封装了所有执行细节。
ActionInvocation,生产线的调度者,负责调度整个生产线中各个元素的执行次序。
Interceptor,生产线上的工序,丰富生产线的功能。
Action,生产线上的核心工序,负责核心业务逻辑的调用或实现。
ActionContext,提供整个生产线需要的数据环境。
ValueStack,提供表达式计算的工具类,Xwork数据访问的基础。(后面细说)
Result,生产线末端设备,输出生产线的生产结果。
结合阶段1的核心分发器,根据七大元素的调用关系,我们可以得到如下示意图:
从图中,我们可以看出以下几点:
(1)Dispatcher是Xwork框架的调用者和驱动者
(2)XWork生产线依赖两个数据流:ActionContext和ValueStack
ActionContext是一个独立的数据结构,无论是请求参数,处理返回值,甚至一些远程的Web容器对象,都被封装在ActionContext内部,成为XWork执行所依赖的数据基础。值得注意的是,ActionContext采用ThreadLocal保证线程安全。
ValueStack本身也是一个数据结构,从属于ActionContext,主要是对OGNL计算进行扩展,因此,位于ActionContext之中的ValueStack则赋予了ActionContext进行数据计算的功能,从而使得ValueStack自身成为一个可以进行数据访问的环境。
插入一点OGNL相关的东西。
如果我们要数据在View层和java世界中互相流转,就回在“字符串”和“对象树”之间存在不匹配性,这个不匹配性源于Web是一个“弱类型”的平台,而java却是一个具有丰富数据类型的“强类型”的平台。同一个对象在两个平台之间交互,就必须要一个“翻译”,也就是我们说的“表达式引擎”,它充当着“翻译桥梁”的作用,保证数据能够顺利地在MVC的各个层次进行流转。而OGNL就是Struts2选择的表达式引擎。
(3)XWork生产线所依赖的控制流:事件处理驱动元素-----ActionProxy,ActionInvocation,事件处理节点-----Interceptor,Action, Result
有关这五大元素的作用和关系,我们用下面这个比喻来诠释。
四、本篇总结
至此,我们围绕初始化和处理Http请求两大主线说明Struts作为表示层框架的基本原理,用一张图概括本篇脉络
随着知识的积累,理解自然深入,下篇,我们将继续探究Hibernate的核心原理……
- SSH深度历险(七) 剖析SSH核心原理(一)
接触SSH有一段时间了,但是对于其原理,之前说不出来莫模模糊糊(不能使用自己的语言描述出来的就是没有掌握),在视频和GXPT学习,主要是实现了代码,一些原理性的内容还是欠缺的,这几天我自己也一直在反问 ...
- SSH深度历险(八) 剖析SSH核心原理+Spring依赖注入的三种方式
在java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依 ...
- 周爱民带你深入剖析JavaScript核心原理
作为前端工程师必备技能,JavaScript 的重要性不言而喻.虽然易上手,但却有着诸多复杂微妙的机制,想要真正掌握绝非易事. 专栏面向JavaScript语言的实际应用者与深度爱好者,以讲述Java ...
- 浅析SSH核心原理(二)
Hibernate是一个开放源代码的ORM(对象-关系映射)框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hibernate可以应用在任 ...
- 老李推荐:第5章5节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 获取系统服务引用
老李推荐:第5章5节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 获取系统服务引用 上一节我们描述了monkey的命令处理入口函数run是如何调用optionP ...
- 《大型网站技术架构:核心原理与案例分析》【PDF】下载
<大型网站技术架构:核心原理与案例分析>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062557 内容简介 本书通过梳理大型网站 ...
- 全面剖析Redis Cluster原理和应用
全面剖析Redis Cluster原理和应用 1.Redis Cluster总览 1.1 设计原则和初衷 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最 ...
- SSH加密原理、RSA非对称加密算法学习与理解
首先声明一下,这里所说的SSH,并不是Java传统的三大框架,而是一种建立在应用层和传输层基础上的安全外壳协议,熟悉Linux的朋友经常使 用到一 个SSH Secure Shell Cilent的工 ...
- 深入剖析Linux IO原理和几种零拷贝机制的实现
深入剖析Linux IO原理和几种零拷贝机制的实现 来源 https://zhuanlan.zhihu.com/p/83398714 零壹技术栈 公众号[零壹技术栈] 前言 零拷贝(Zero ...
随机推荐
- Oracle 性能相关常用脚本(SQL)
在缺乏的可视化工具来监控数据库性能的情形下,常用的脚本就派上用场了,下面提供几个关于Oracle性能相关的脚本供大家参考.以下脚本均在Oracle 10g测试通过,Oracle 11g可能要做相应调整 ...
- cocos2dc-x解决中文乱码
中文乱码: 方法一: 选中有中文的那个cpp,点文件另存为,在保存这里竟然有个小箭头 点之,再点编码保存 再选这个编码 这个cpp就UTF-8化了,然后中文就正常了. 但是发现:但字符串字符数为奇数时 ...
- git 创建一个新分支,并将一个分支内容复制给创建的新分支
git checkout -b newBranchName
- 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:2.搭建环境-2.4. 安装JDK
2.4.安装JDK 2.4.1.准备JDK 在百度搜索:JDK下载 2.4.2.上传JDK put E:\软件安装文件\jdk-8u11-linux-x64.rpm /home/linuxrac1/D ...
- 清除Xcode缓存和存档文件
XCode4.2 finder中找到 /Users/Library/Developer/Xcode (注:Library资源库是隐藏的文件夹) 里面有DerivedData和Snaps ...
- 【初识——最大流】 hdu 1532 Drainage Ditches(最大流) USACO 93
最大流首次体验感受—— 什么是最大流呢? 从一个出发点(源点),走到一个目标点(汇点),途中可以经过若干条路,每条路有一个权值,表示这条路可以通过的最大流量. 最大流就是从源点到汇点,可以通过的最大流 ...
- C++重要知识点小结---2
C++重要知识点小结--1 :http://www.cnblogs.com/heyonggang/p/3246631.html 1.C++允许程序员声明一个不能有实例对象的类,这样的类惟一的用途是被继 ...
- 获取当前的 viewController
- (UIViewController *)currentController { UIViewController *result = nil; UIWindow *window = [ ...
- LoadRunner界面分析(二)
1.Controller 2.创建运行场景 3.方案设计 4.Resuls settting 5.监视方案
- OSX学习02之更新输入法
OSX下最好的输入法是什么?话说在使用Windows的时候就知道了——它叫鼠须管. 想必大家用Windows的时候,进入系统第一步就是先装输入法吧~ OSX也是一样,自带输入法虽然凑合,但是我们作为A ...