`
- 浏览:
40500 次
- 性别:
- 来自:
太原
-
在当今的MVC framework里,似乎Webwork2逐渐成为主流, Webwork2+SpringFramework的组合变得越来越流行。这似乎意味着Spring自带的MVC framework远比Webwork2差,所以大家纷纷用Webwork2来代替。确实,Spring的MVC framework不算是整个Spring的核心部件,但它的威力却超过了很多人的想象。很多人包括xiecc认为Spring的MVC framework是非常优秀的,甚至比Webwork2更优秀。
下面列举一下Spring的MVC framework在设计时做出的一些重要的决定,并将之和相关的MVC framework如Webwork2或struts进行对比:
一、Spring的整个MVC配置是基于IOC容器的
与struts 或webwork2相比,这是一个ms有点奇怪的决定,看一下Spring MVC的配置文件,最先看到的不是action或者form,而是一些有着特定名字的bean,Bean下面的配置是一些简单或有点复杂的属性。我们看到 的是机器更容易的数据结构,而不是人更容易理解的元素。
但是这恰恰是Spring的MVC强大的根源!因为它的配置就是Spring的核心 IOC容器的配置,这意味着所有IOC容器的威力都可以在这 里展现,我们可以为所欲为地对Spring MVC进行扩展和增强,我们可以完成在其它MVC framwork中很多难以想象的任务。想扩展新的URL映射方式吗?要换一个themeResolver或LocalReolver的实现吗?想在页面 中显示新类型的View(比如说RDF,呵呵,一个小秘密:xiecc是研究语义网的,虽然成天不务正业,不写论文,只写八卦)?甚至想直接在 Controller里定义AOP吗?这些对Spring的MVC来说都是小菜一碟。 字串2
我 没有仔细研究过Webwork2的扩展机制,我知道通过Webwork2的interceptor机制,可以进行很多的扩展,甚至有一个简单简 单的IOC容器。但不管它有多强大,提供了多少扩展点。它的威力都很难和真正的IOC容器相比。而struts的plugin功能则是出名的滥,虽然它也 提供了plugin机制。
Spring采用IOC配置的另一个原因是使Spring的MVC与Spring的IOC容器的整合变得非 常的容易。Spring提供了与 struts与webwork2的整合,但是这样整合都需要在进行间接的包装,感觉总不是很自然。而且还会导致一个概念多个配置,webwork2就需要 在Spring里配置bean,再配置自己的xwork文件。想象一下吧,我们的bean直接就是一个controller,直接可以完成MVC的所有任 务,这是多少爽的感觉。
Rod Johnson采用IOC容器来实现的另一个原因是这会减少好多开发工作量。看一下urlMapping吧,它提供的property本身就是一个 HashMap,只有配置完成,我们的bean里的数据就自然存在了,哈哈,好爽吧。不用象struts那样解析XML,再把它的内容一项一项地读到 HashMap里。
虽然这样的配置会有点怪异,但假如我们对Spring的IOC容器非常熟悉的话,会发现它非常的亲切,也非常的简单。
最 后是一个简单的小秘密,Spring怎么知道某个bean的配置就是urlMapping?另一个bean的配置就是 viewResolver?其实很简单,把所有的bean全部读到内存里,然后通过bean的名字或类型去找就行了。通过名字去找就是简单的 getBean方法,通过类型去找则使用了BeanFactoryUtils.beansOfTypeIncludingAncestors的静态方法。
字串5
二、Spring提供了明确的Model, View概念和相应的数据结构
在Spring里有一个有趣的数据类型叫做ModelAndView,它只是简单地把要显示的数据和显示的结果封装在一个类里。但是它却提供了明确的MVC概念,尤其是model概念的强化,使程序的逻辑变得更清晰了。
记 得以前在Struts里写程序里的时候,为了显示数据经常自己把东西放到HttpSession或HttpServletRequest里(或set到 form里,虽然不太有用),这造成了model概念的模糊,而且也导致了struts与JSP页面的紧耦合。假如我们要替换成Veloctiy,就得另 外加一个plugin,因为在velocity里数据是不需要不放到request里的。
Webwork2里强调的是与Web framework解耦和它的command模式的简单性,因此在它的action里只有简单的get或set方法,假如返回数据,也只是简单地返回一个 String。当然这样的实现有它的好处,但是它淡化了model和view的概念。Rod Johnson认为Webwork2里的Action同时包含了Action和Model的职责,这样一个类的职责太多,不是一个很好的设计。当然 Jason Carreira不太认同这种观点,因为Action里的model对象完成可以delege给其它对象。但不管怎样,这种争论的根源在于 Webwork2里淡化了model, view甚至web的概念。仁者见仁,智者见智,最后的结果还是看个人喜欢好吧。
字串5
三、Spring的Controller是Singleton的,或者是线程不安全的
和Struts 一样,Spring的Controller是Singleton的,这意味着每个request过来,系统都会用原有的 instance去处理,这样导致了两个结果:我们不用每次创建Controller,减少了对象创建和垃圾收集的时间;由于只有一个 Controller的instance,当多个线程调用它的时候,它里面的instance变量不是线程安全的。
这也是Webwork2吹 嘘的地方,它的每个Action都是线程安全的。因为每过来一个request,它就创建一个Action对象。由于 现代JDK垃圾收集功能的效率已经不成问题,所以这种创建完一个对象就扔掉的模式也得到了好多人的认可。Rod Johnson甚至以此为例证明J2EE提供的object pool功能是没多大价值的。
但是当人们在吹嘘线程安全怎么怎么重要的 时候,我想请问有多少人在多少情况下需要考虑线程安全?Rod Johnson在分析EJB的时候也提出过其它问题,并不是没有了EJB的线程安全魔法,世界就会灭亡的,大多数情况下,我们根本不需要考虑线程安全的问 题,也不考虑object pool。因为我们大多数情况下不需要保持instance状态。
至少我写了那么多的struts Action,写了那么多的Spring Controller,几乎没有碰到需要在instance变量保持状态的问题。当然也许是我写的代码不够多,Struts的设计者Craig R. McClanahan曾经说当时他设计struts时有两个条件不成熟:当时没有测试驱动开发的概念;当时JVM的垃圾收集性能太次。假如现在重新设计的 话,他也会采用每个request生成一个新对象的设计方法,这样可以解决掉线程安全的问题了。
字串7
四、Spring不象Webwork2或tapestry那样去隐藏Servlet相关的元素如HttpServletRequest或HttpServletResponse
这 又是一个重要的设计决定。在Webwork2里我们没有HttpServletRequest或者HttpServletResponse,只 有getter, setter或ActionContext里数据,这样的结果导致一个干净的Action,一个与Web完全无关的Action,一个可以在任何环境下独 立运行的bean。那么Webwork2的这样一个基于Command模式的Action究竟给我们带来了什么?我想主要有两点:
1、它使我们的Action可以非常容易地被测试。
2、用户可以在Action里添加业务逻辑,并被其它类重用。
然 而仔细跟Spring比较一下,我们就会发现这两点功能所带来的好处其实并不象我们想象的那么显著。Spring的Controller类也可 以非常轻松被测试,看一下spring-mock下面的包吧,它提供的MockHttpServletRequest, MockHttpServletResponse还有其它一些类让测试Controller变得异常轻松。再看一下Action里的业务逻辑吧, Jason Carreira曾经说我们可以尽情地在Webwork2的Action里加业务逻辑,因为Action是不依赖于Web的。但是有多少人真正往 Action里加业务逻辑的?大多数人都会业务逻辑delegate给另一个Service类或Manager类。因为我们很清楚,往Action里加业 务逻辑会使整个体系的分层架构变得不清晰,不管怎样,Web层就是Web层,业务层就是业务层,两者的逻辑混在一起总会带来问题的。而且往Action里 加业务逻辑会使用这个Action类变得庞大,Webwork2的Action是每个request都创建实例的,尽管带来的性能影响不太大,但并不表示 每次都要把业务逻辑再new出来,业务逻辑在大多数的情况下应该是单例的。 字串4
不 把request和response展现给用户当然还会带来功能上的损失,也许一般的场合,用用webwork2提供的接口已经足够了,但有时 我们必须要知道request和response才能发挥出更大的威力。比如我以前的一个项目里有一个通过递归动态生成的树状结构的页面,在jsp页面上 显示递归是痛苦或不可能的,因此我用response直接write出页面,这在spring里很easy,但在webwork里可能比较难了(偶不敢肯 定,偶研究得不够深,也许高手是有办法的)。
五、Spring提供了不错但不够充分的interceptor机制
回头看一下struts,它在架构里甚至没有给我们提供hook point的机会,我们没有任何机会加入自己的interceptor。我们只能通过重载struts的RequestProcessor类来进行一点有限的扩展。
到 了Webwork2,似乎interceptor一下子成了整个Framework的核心,除了Action的核心部件,其它所有的东西都是 interceptor。它的超强的interceptor功能使们扩展整个架构变得非常方便。有人称这种interceptor为AOP,Jason Carreira则自豪地宣称这个叫做pragamtic AOP。我不认同这是AOP,它只是简单的interceptor机制。但不管如何,它的interceptor确实有强大的功能。
字串5
Spring 也提供了它的interceptor机制,它的HandlerInterceptor三个interceptor方法: peHandle, postHandle, afterCompletion。分别对应Controller执行前,Controller执行后和page render之后。虽然大多数情况下已经够用,但是从功能上来说显然它没有Webwork2强大。从AOP的角度来看,它没有提供around interceptor,而只有before与after interceptor。这意味着我们无法在interceptor前后保持状态,最简单的情况假如我们要计算一个Controller的执行时间,我们 必须在执行完before后把begintime这个状态保持住,再在after里把它调出来,但是显然这个状态保持会是个问题,我们不能把它放到 instance变量里,因为interceptor不是线程安全的。也许通过ThreadLocal可以解决这个问题,但是如此简单的功能要用到这样的 方法来处理,显然这个Interceptor本身设计上还是有点问题的。
六、Spring提供了MultiActionController,使它可以在一个类里包含多个Action
这 个设计和struts的DispatchAction有点类似,只不过提供了更灵活的机制。当我们的项目变大的时候,把功能类似的方法放到同一 个Action里完全值得的!Webwork2缺少这样的机制。假如看一下Spring的源代码,会发现其实实现 MultiActionController的工作量相当的少,只不过是用反射机制把解析出来的方法名执行一下就完事了。其实Webwork2也完全可以 提供这样的机制。虽然从设计上来说确实不是很优雅,但是它确实很有用。 字串5
七、Spring提供了更多的选择方式
看 看Spring里提供的Controller吧,它提供了好多不同的Controller类。要生成Wizard吗?要专门用于提交form的 Controller吗?要执多个方法的类吗?Spring提供了丰富的子类来扩展这些选择。当然我们还可以很轻松地自己扩展这些功能。
再 看看Spring的ViewResolver吧, 它提供了无数不同类型的ViewResolver。更重要的是我们自定义我们的页面映射方式。看看strtus,看看webwork2,都会存在页面与 forward name的一层间接转换,我们必须在配置文件里配置好某个字符串(典型的是success)对应的是那个页面。但是Spring里我们有了更大的自由度, 我们可以采用webwork2的策略,也可以采用更简单的策略,如将JSP文件名去掉扩展名的映射方法。也许有人认为这种映射方式很幼稚,但是我觉得它是 非常有用的方式,即使在大项目里。
还有新的扩展吗?看看Spring Web Flow吧,它是SpringFramework的子项目。它为一长串的基于页面流的Wizard页面提供了可配置的实现方式。在Spring 1.3里,它将是SpringFramework的一部分。
八、Spring的tag 字串3
尽 管Spring的tag数量上少得可怜,但它却是精心设计的。它的目标很简单:让美工可以轻松地编辑页面。因为在Spring的页面里Text 仍然是Text,checkbox仍然是CheckBox,而不象在struts或webwork2中的Tag。它只是用Springbind对输入内容 进行了一下包装。所以尽管页面显示代码上会比Webwork2多,但这绝对是有价值的。
在接下来的几章里,我会分析一下Spring是如何让我们的Web应用不需要知道ApplicationContext就能够访问IOC容器的,然后会对Spring的设计和执行过程进行简单的源码分析,然后给出几个扩展Spring MVC的方法。
分享到:
Global site tag (gtag.js) - Google Analytics
相关推荐
在当今的MVC framework里,似乎Webwork2逐渐成为主流, Webwork2+SpringFramework的组合变得越来越流行。这似乎意味着Spring自带的MVC framework远比Webwork2差,所以大家纷纷用Webwork2来代替。确实,Spring的MVC ...
### Spring MVC 快速入门深入分析 #### 一、Spring MVC 概述 Spring MVC 是 Spring Framework 的一个重要模块,主要用于构建 Web 应用程序。它遵循 MVC(Model-View-Controller)设计模式,将应用程序的不同关注点...
这个"Spring MVC使用Demo"提供了实践操作,帮助开发者深入理解Spring MVC的开发环境配置、注解的使用以及工作原理。 首先,Spring MVC的设计模式基于Model-View-Controller(MVC),它将应用程序的业务逻辑、数据和...
Spring MVC深入解析 Spring MVC是一个基于模型-视图-控制器(MVC)模式的Web应用程序框架,是Spring Framework的一部分。它提供了一个灵活的方式来构建Web应用程序,使得开发者可以轻松地创建复杂的Web应用程序。 ...
通过阅读和分析"spring-framework-master",开发者可以深入理解Spring的工作机制,提升自己的编程技巧,同时也可以根据需求自定义扩展,使Spring更好地服务于项目需求。这不仅对于Java开发者,对于所有希望深入学习...
***.mvcframework.servlet.LgDispatcherServlet <param-name>contextConfigLocation <param-value>springmvc.properties <servlet-name>lgoumvc <url-pattern>/* ``` 以上配置显示了如何在web.xml...
《Spring Framework 5.2.3源码深度解析》 Spring Framework是Java开发中的核心框架,它为构建高质量的应用提供了全面的基础设施。5.2.3版本是Spring的一个稳定版本,包含了众多改进和新特性。这个官方原版源码包为...
通过对Spring Framework 5.3.4源码的深入学习,开发者不仅可以提升自己的技术能力,还能了解到更多设计原则和最佳实践。这将有助于在实际项目中编写出更高效、可维护的代码,同时也能更好地参与到Spring社区的发展中...
8. **源码分析**:深入理解Spring和Spring MVC的源码,有助于优化配置和解决问题。例如,了解DispatcherServlet如何调度请求,以及HandlerMapping如何找到合适的处理器。 9. **工具**:IDEA、Eclipse等集成开发环境...
深入阅读并理解Spring Framework BOM的源码,可以提升开发者对Spring生态系统的整体理解和应用能力,从而更好地利用Spring进行高效、可靠的软件开发。同时,这也是一次学习设计模式、编程原则和最佳实践的好机会。
首先,源码分析从`spring-framework-5.1.4.RELEASE-dist.zip`开始,这是Spring框架的基础组件包,包含了所有核心模块的类库和配置文件。主要模块有Core Container(核心容器)、Data Access/Integration(数据访问与...
对于毕业设计或者深入学习软件工具的开发者来说,这份源码提供了深入理解Spring框架工作原理的机会。通过阅读源码,可以学习到设计模式、最佳实践以及如何编写高质量的Java代码。同时,对于想要自定义或扩展Spring...
《Spring框架5.2.25.RELEASE源码解析》 Spring Framework是Java开发领域中最受...因此,对于任何致力于提升自身技术水平的Java开发者来说,Spring Framework 5.2.25.RELEASE的源码分析都是一个不容错过的学习资源。
提供的定时器功能可能使用了`java.util.Timer`或Spring的`org.springframework.scheduling.timer`包,用于定期执行某些任务,如数据清理、统计分析等。在Spring中,也可以使用`@Scheduled`注解配合`TaskScheduler`...
【Spring5MVC源码分析】 Spring MVC 是一个基于Java的、用于构建Web应用程序的、高度可插拔的MVC框架,它是Spring Framework的重要组成部分。Spring MVC的核心目标是简化前端控制器的开发,使得开发者可以专注于...
本文将围绕Spring Framework的核心特性,通过源码分析,帮助开发者深化对Spring的理解,提升开发技能。 1. **核心模块**:Spring Framework由多个模块组成,如Core Container(核心容器)、Data Access/Integration...
下面我们将深入探讨 Spring MVC 的关键概念和相关知识点。 1. **DispatcherServlet**:Spring MVC 的入口点,它是一个前端控制器,负责接收请求,分发到相应的处理器。在项目中,通常在 web.xml 配置文件中定义 ...
3. 分析关键组件的源码,如IoC容器、AOP、MVC等。 4. 创建小型示例应用,利用源码中的功能,以便于实际操作和理解。 5. 使用断点、日志等方式进行调试,观察Spring框架内部工作流程。 通过以上步骤,开发者不仅可以...