差不多去年这个时候写的了,最近整理到,贴出来给大家看看~
Struts
Struts的核心理念,设计初衷即是MVC设计模式。理解struts就要从理解MVC开始。这张图显示Stuts的MVC模型:
我认为,应用Struts的关键即在于此,就是对于MVC模型的实现,而且是企业级、规范化的实现,可以享受Struts框架所提供的关于表单验证、动作管理、消息处理、国际化、配置管理等等规范化的服务和管理。在此基础上,基本只要正确的理解和使用Struts,可以确保系统对于MVC模型的良好实现,这便是Struts的精髓。
Struts的工作原理
其实如果没有那么多的功能,撇开struts,自己按照MVC来实现也是不怎么复杂的,但是struts作为一个优秀的框架,会给我们提供更多的便利。而了解一下struts关于MVC的实现,会对我们更好地理解MVC也有帮助。
如上图所示,struts的工作流程大概是这样的:
所有的动作都会交给ActionServlet,这应当相当于是一种前端控制器模式,这个ActionServlet会查找相应的Action来执行,那么是怎么查找的呢?
首先,使用过Struts的都会知道,关于Action、ActionForm的注册信息都在Struts-config.xml配置文件中,该配置文件在每一个应用了Struts框架的JavaEE程序中可能有一个或者多个(对于复杂的应用),它的格式是这样的:
<struts-config>
<data-sources />
<form-beans >
<form-beanname="studentLoginForm" type="edu.nju.studentsLoginForm"/>
<form-beanname="ManagerLoginForm"type="org.apache.struts.action.DynaActionForm">
<form-propertyname="managerId" type="java.lang.String" />
<form-propertyname="password" type="java.lang.String" />
</form-bean>
</form-beans>
<global-exceptions />
<global-forwards />
<action-mappings >
<action
attribute="ManagerLoginForm"
input="/JSP/Manager/ManagerLogin.jsp"
name="ManagerLoginForm"
path="/managerlogin"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy"
validate="false">
<set-property property="cancellable"value="false" />
<forward name="failure"path="/JSP/Manager/ManagerLogin.jsp" />
<forward
name="success"
path="/JSP/Manager/ManagerIndex.jsp"
redirect="true" />
</action>
</action-mappings>
<message-resourcesparameter="edu.nju.struts.ApplicationResources" />
<plug-inclassName="org.springframework.web.struts.ContextLoaderPlugIn">
<set-propertyproperty="contextConfigLocation"
value="/WEB-INF/applicationContext.xml"/>
</plug-in>
</struts-config>
其中包括了data source、action、action form、excepetion的信息。ActionServlet将根据此xml文件中的信息来处理动作。
但是,每处理一次动作就调用读取一次配置文件显然十分没有效率,所以Struts采取了一次读取,创建了一个ModuleConfig对象来保存这些配置信息。每一个struts-config文件都对应一个ModuleConfig对象。
当有动作需要处理时,ActionServlet的处理过程是:
1) 搜寻那个正确的ModuleConfig对象;
2) 创建一个RequestProcessor,ModuleConfig将作为构造参数传给RequestProcessor;
3) 调用RequestProcessor的process方法。
在RequestProcessor的process方法中,实现了对于Action的匹配和管理等操作,如果我们分析process方法的代码可以发现其中包含了以下操作:
1) Process Multipart:检验是否在上传一个或多个文件。是则将当前HttpServletRequest打包到MultipartRequestWrapper对象里去。(这里是一种装饰者模式)
2) ProcessPath:获得被调用的Struts动作的路径。
3) ProcessLocale:在Struts动作进一步处理之前,保存当前用户的地区信息。
4) processContent:将内容类型设置为配置文件中controller的contentType属性值,默认是text/html。
5) processNoCache:确定是否禁用客户端浏览器的内容缓存功能。
6) processPreprocess:其实该方法什么都没有做。
7) processCachedMessage:移除HttpSession中缓存的ActionMessage对象。
8) processMapping:确定控制权的移交对象。
9) processRoles:调查当前用户角色,看是否能访问该动作。
10) processAcitonForm:检索当前动作需要一个动作表单,如果是就返回一个。
11) processPopulate:使用当前HttpServletRequest对象的参数填充刚刚的动作表单。
12) processValidate:调用该表单的验证方法验证该表单。
13) processForward:将控制权移交给当前action定义的forward目标。
14) processInclude:处理include属性。
15) processActionCreate:返回与当前action元素关联的Acton对象。
16) processActionPerform:调用Action的execute方法。
17) processForwardConfig:把用户转向或重定向到目标资源。
Spring
谈Spring,首先要说说EJB,正是EJB的缺点催生了Spring这种轻量级框架的诞生,Spring的优点也正与这些缺点相对应。(以下观点,主要是来自于阅读《Java EE Development without EJB》一书)
EJB,作为Java EE的官方框架,固然有其强大的一面,但是其复杂而脱离实践的特征一直饱受诟病。
EJB有哪些缺点呢,在《JavaEE Development without EJB》一书中提到有几个显著特征是:
1. 复杂
2. 生产率低下
比如为了实现一个Entity Bean,你可能需要写好几个类,而这其中很多其实并不需要那么复杂。
3. 违反了OO的设计原则
4. 难于测试
EJB为什么要把自己弄的这么复杂呢,如果查阅EJB委员会给出的文档,我们可能会被找到想要的答案,那就是是EJB很多的目标,比如可伸缩性,比如分布式。所以需要三种客户端模式,有local有remote。
但其实呢,帕累托法则告诉我们:80%的工作往往只需要20%的功能就可以完成。就比如说大部分情况下,我们的服务器同一个模块间就是在同一个JVM上,而不是那么的复杂。但是在EJB下开发,为了去照顾这些有可能的复杂情况,我们必须把代码构建的十分复杂,而且这种复杂的机制往往还不是一种比较好的实现。(本人对EJB的理解并不深刻,如果有时间,希望可以去研究一下,这些观点都是对书本中语句的理解,比较生硬,望原谅)
那么Spring做了什么来改进呢,先来看看Spring提供了哪些模块:
1. Bean工厂
2. 应用上下文
3. AOP框架
4. 自动代理
5. 事务管理
6. DAO抽象
7. JDBC支持
8. 继承OR映射工具
9. Web MVC框架
10. 远程调用支持
这其中,Spring最显著的特征我觉得3个:轻型容器、依赖注入机制、以及AOP。
下面将做一一分析:
轻型容器:
SSH开发中,Struts负责的是前段控制和动作分配,Hibernate负责数据库的操作和数据模型构建,而Spring则负责的是对这些组件的管理。通俗的说法,Spring为J2EE web应用提供了逻辑中间层得基本骨架。Spring的最典型概念就是一个容器,这个容器可以是一个简单的bean工厂,也可以是一个更为强大的应用上下文,这就是Spring用来代替EJB的地方,作为web层的容器来对其中的模块进行管理。Spring容器在工厂模式的思想下实现,它的“轻”体现在其配置简单,可以对bean组件进行组装、配置以及管理。这种管理不但体现在其相对于EJB简单,而且由于依赖注入、AOP等机制,更好的保持了组件的独立性。
此外,Spring的“轻”还体现在容器的“无侵入性”,抑或“低侵入性”,即被管理的组件其实无需实际上也确实不知道Spring容器的存在。通过反射和依赖注入方式,组件不需要调用Spring的API,也不用去上下文中进行查询,只需要执行自己的工作。这样不单单是将配置独立出来,保持组件完整性,对于单元测试等工作将非常有意义(EJB中为了测试某个类,有时必须要配置很多文件或者写很多类)。
(未完待续)