第 13 章 Web MVC framework Web框架

目录

13.1. 概述
13.1.1. 与其他MVC实现框架的集成
13.1.2. Spring Web MVC框架的特点
13.2. DispatcherServlet
13.3. 控制器
13.3.1. AbstractControllerWebContentGenerator
13.3.2. 其它的简单控制器
13.3.3. MultiActionController
13.3.4. 命令控制器
13.4. 处理器映射(handler mapping)
13.4.1. BeanNameUrlHandlerMapping
13.4.2. SimpleUrlHandlerMapping
13.4.3. 拦截器(HandlerInterceptor
13.5. 视图与视图解析
13.5.1. 视图解析器(ViewResolver
13.5.2. 视图解析链
13.5.3. 重定向(Rediret)到另一个视图
13.6. 本地化解析器
13.6.1. AcceptHeaderLocaleResolver
13.6.2. CookieLocaleResolver
13.6.3. SessionLocaleResolver
13.6.4. LocaleChangeInterceptor
13.7. 使用主题
13.7.1. 简介
13.7.2. 如何定义主题
13.7.3. 主题解析器
13.8. Spring对分段文件上传(multipart file upload)的支持
13.8.1. 介绍
13.8.2. 使用MultipartResolver
13.8.3. 在表单中处理分段文件上传
13.9. 使用Spring的表单标签库
13.9.1. 配置
13.9.2. form标签
13.9.3. input标签
13.9.4. checkbox标签
13.9.5. checkboxes标签
13.9.6. radiobutton标签
13.9.7. radiobuttons标签
13.9.8. password标签
13.9.9. select标签
13.9.10. option标签
13.9.11. options标签
13.9.12. textarea标签
13.9.13. hidden标签
13.9.14. errors标签
13.10. 处理异常
13.11. 惯例优先原则(convention over configuration)
13.11.1. 对控制器的支持:ControllerClassNameHandlerMapping
13.11.2. 对模型的支持:ModelMapModelAndView
13.11.3. 对视图的支持:RequestToViewNameTranslator
13.12. 基于注解的控制器配置
13.12.1. 建立dispatcher实现注解支持
13.12.2. 使用@Controller定义一个控制器
13.12.3. 使用@RequestMapping映射请求
13.12.4. 使用@RequestParam绑定请求参数到方法参数
13.12.5. 使用@ModelAttribute提供一个从模型到数据的链接
13.12.6. 使用@SessionAttributes指定存储在会话中的属性
13.12.7. 自定义WebDataBinder初始化
13.13. 更多资源

13.1. 概述

Spring的web框架围绕DispatcherServlet设计。 DispatcherServlet的作用是将请求分发到不同的处理器。 Spring的web框架包括可配置的处理器(handler)映射、视图(view)解析、本地化(local)解析、 主题(theme)解析以及对文件上传的支持。Spring的Web框架中缺省的处理器是Controller 接口,这是一个非常简单的接口,仅包含ModelAndView handleRequest(request, response) 方法。可以通过实现这个接口来创建自己的控制器(也可以称之为处理器),但是更推荐继承Spring提供的一系列控制器, 比如AbstractControllerAbstractCommandControllerSimpleFormController。注意,需要选择正确的基类:如果没有表单,就不需要一个FormController。 这是和Struts的一个主要区别。

提示

从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller方式。 在实现传统的Controller及其子类时这是一种更好的替换方案, 其中提供了更为灵活的处理multi-action的能力。更多信息请参考第 13.12 节 “基于注解的控制器配置”

Spring Web MVC允许使用任何对象作为命令对象(或表单对象)- 不必实现某个特定于框架的接口或从某个基类继承。 Spring的数据绑定相当灵活,例如,它认为类型不匹配这样的错误应该是应用级的验证错误,而不是系统错误。 所以你不需要为了保证表单内容的正确提交,而重复定义一个和业务对象有相同属性的表单对象来处理简单的无 类型字符串或者对字符串进行转换。这也是和Struts相比的另一个重要区别,Struts是围绕 ActionActionForm等基类构建的。

和WebWork相比,Spring将对象细分成更多不同的角色:控制器( Controller)、可选的命令对象(Command Object)或表单对象(Form Object), 以及传递到视图的模型(Model)。模型不仅包含命令对象或表单对象,而且也可以包含任何引用数据。 相比之下,WebWork的Action将所有的这些角色都合并在一个单独的对象里。 虽然WebWork的确允许在表单中使用现有的业务对象,但是必须把它们定义成相应的Action 类的bean属性。更重要的是,在进行视图层(View)运算和表单赋值时,WebWork使用的是同一个处理请求的 Action实例。因此,引用数据也需要被定义成Action 的bean属性。这样一个对象就承担了太多的角色(当然,对于这个观点仍有争议)。

Spring的视图解析相当灵活。一个控制器甚至可以直接向response输出一个视图 (此时控制器返回ModelAndView的值必须是null)。在一般的情况下,一个ModelAndView 实例包含一个视图名字和一个类型为Map的model, 一个model是一些以bean的名字为key,以bean对象(可以是命令或form,也可以是其他的JavaBean) 为value的键值对。对视图名称的解析处理也是高度可配置的,可以通过bean的名字、属性文件或者自定义的 ViewResolver实现来进行解析。实际上基于 Map的model(也就是MVC中的M)是高度抽象的,适用于各种表现层技术。 也就是说,任何表现层都可以直接和Spring集成,无论是JSP、Velocity还是其它表现层技术。 Map model可以被转换成合适的格式,比如JSP request attribute或者Velocity template model。

13.1.1. 与其他MVC实现框架的集成

由于种种原因,许多团队倾向于使用其他的web框架。比如,某些团队已经在其他的技术和工具方面进行了 投入,他们希望充分利用已有的经验。另外,Struts不仅有大量的书籍和工具,而且有许多开发人员都熟悉它。 因此,如果能忍受Struts的架构性缺陷,它仍然是web层一个不错的选择。WebWork和其它的web框架也是这样。

如果不打算使用Spring的web MVC框架,但仍希望使用Spring提供的其它功能, 可以很容易地将所选择的web框架和Spring结合起来。只需通过Spring的 ContextLoadListener启动一个root application context,就可以在 Struts或WebWork的Action中,通过ServletContext属性 (或者Spring提供的相应辅助方法)进行访问。请注意我们没有提到任何具体的“plugins”,因此也你不 需要任何专门的集成工具。从web层的角度看,可以以root application context实例为入口,把Spring作为一个library使用。

即便不使用Spring的web MVC,仍可以使用Spring提供的服务以及所有注册的bean。 在这里,Spring不会和Struts或WebWork竞争,它只是提供这些纯粹的web MVC框架所没有的功能, 例如:bean的配置、数据访问和事务处理。因此可以使用Spring的中间层或者数据访问层来增强你的应用, 比如你可能只需要JDBC或Hibernate事务抽象。

13.1.2. Spring Web MVC框架的特点

Spring的web模块提供了大量独特的功能,包括:

  • 清晰的角色划分:控制器(controller)、验证器(validator)、 命令对象(command object)、表单对象(form object)、模型对象(model object)、 Servlet分发器(DispatcherServlet)、 处理器映射(handler mapping)、视图解析器(view resolver)等等。 每一个角色都可以由一个专门的对象来实现。

  • 强大而直接的配置方式:将框架类和应用程序类都能作为JavaBean配置,支持跨多个context的引用,例如,在web控制器中对业务对象和验证器(validator)的引用。

  • 可适配、非侵入:可以根据不同的应用场景,选择合适的控制器子类 (simple型、command型、form型、wizard型、multi-action型或者自定义),而不是从单一控制器 (比如Action/ActionForm)继承。

  • 可重用的业务代码:可以使用现有的业务对象作为命令或表单对象,而不需要去扩展某个特定框架的基类。

  • 可定制的绑定(binding) 和验证(validation):比如将类型不匹配作为应用级的验证错误, 这可以保存错误的值。再比如本地化的日期和数字绑定等等。在其他某些框架中,你只能使用字符串表单对象, 需要手动解析它并转换到业务对象。

  • 可定制的handler mapping和view resolution:Spring提供从最简单的URL映射, 到复杂的、专用的定制策略。与某些web MVC框架强制开发人员使用单一特定技术相比,Spring显得更加灵活。

  • 灵活的model转换:在Springweb框架中,使用基于Map的 键/值对来达到轻易地与各种视图技术的集成。

  • 可定制的本地化和主题(theme)解析:支持在JSP中可选择地使用Spring标签库、支持JSTL、支持Velocity(不需要额外的中间层)等等。

  • 简单而强大的JSP标签库(Spring Tag Library):支持包括诸如数据绑定和主题(theme) 之类的许多功能。它提供在标记方面的最大灵活性。如欲了解详情,请参阅附录附录 D, spring.tld

  • JSP表单标签库:在Spring2.0中引入的表单标签库,使得在JSP中编写 表单更加容易。如欲了解标签库详情,请参阅附录附录 E, spring-form.tld

  • Spring Bean的生命周期可以被限制在当前的HTTP Request或者HTTP Session。 准确的说,这并非Spring MVC框架本身特性,而应归属于Sping MVC使用的WebApplicationContext容器。 该功能在第 3.4.4 节 “其他作用域”有详细描述。