一、框架的本质
在说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 ...
随机推荐
- Android内存控制小技巧-使用矢量图来节省你的内存并简化你的开发。
先上一个 位图和矢量图的 说明.http://zhidao.baidu.com/link?url=xwvs5CBzWeh15O3Ee4bICwCqg4PCQWwg5oZ0a6CVydbVZzufqrI ...
- Linux下的Memcache安装
Linux下Memcache服务器端的安装服务器端主要是安装memcache服务器端,目前的最新版本是 memcached-1.3.0 .下载:http://www.danga.com/memcach ...
- Linux 安装JDK7 遇到的问题
Error occurred during initialization of VMjava/lang/NoClassDefFoundError: java/lang/Object 如出现 unpac ...
- [转] DateTime.Now.ToString()的较为全面的使用介绍
原文地址 DateTime.Now.ToString() 用法 具体的操作如下面的两段代码 //2008年4月24日 System.DateTime.Now.ToString("D" ...
- 多数据源问题--Spring+Ibatis 访问多个数据源(非分布式事务)
有的时候,我在一个工程中需要访问两个以上的数据源,尤其是在系统集成的时候,以下是我在系统集成的时候遇到的情况,我的工程的架构是:spring2.0+ibatis2.0+struts1.2. 数据库是o ...
- Modernizr.js入门指南(HTML5&CSS3浏览器兼容插件)
HTML5 和 CSS3 的快速发展,给我们带来了极大的便利,比如从此再也不用花费大量的时间只是为了设计一个圆角的效果. 但是!我们不能像控制机器一样来控制所有的人都一夜之间升级到现代浏览器,因为那些 ...
- 第一个UI脚本--python+selenium
之前一直是用java+selenium做自动化测试的,最近因为工作需要,需要用pyhton+selenium去实现,于是就赶驴上架,熟悉了一下python的语法和脚本的编写过程,下面是一个简单的脚本, ...
- Android无限级树状结构
通过对ListView简单的扩展.再封装,即可实现无限层级的树控件TreeView. package cn.asiontang.nleveltreelistview; import android.a ...
- C# 类和结构
类和结构实际上都是创建对象的模板,每个对象都包含数据,并提供了处理和访问数据的方法 . 类定义了类的每个对象(称为实例)可以包含什么数据和功能. 例如,如 果一个类表示一个顾客,就可以定义字段 Cus ...
- C字符串和C++中string的区别 &&&&C++中int型与string型互相转换
在C++中则把字符串封装成了一种数据类型string,可以直接声明变量并进行赋值等字符串操作.以下是C字符串和C++中string的区别: C字符串 string对象(C++) 所需的头文件名称 ...