<a href="#%E4%BA%94%E5%A4%A7%E6%A0%B8%E5%BF%83%E7%BB%84%E4%BB%B6" target="_blank">五大核心组件</a>
<a href="#controller-%E5%A4%84%E7%90%86%E5%99%A8%E6%8E%A7%E5%88%B6%E5%99%A8" target="_blank">Controller 处理器控制器</a>
<a href="#mvc%E8%A1%A5%E5%85%85" target="_blank">MVC补充</a>
<a href="#abstractcontroller-%E5%92%8C-webcontentgenerator" target="_blank">AbstractController 和 WebContentGenerator</a>
<a href="#%E5%85%B6%E5%AE%83%E7%9A%84%E7%AE%80%E5%8D%95%E6%8E%A7%E5%88%B6%E5%99%A8" target="_blank">其它的简单控制器</a>
<a href="#multiactioncontroller" target="_blank">MultiActionController</a>
<a href="#%E5%91%BD%E4%BB%A4%E6%8E%A7%E5%88%B6%E5%99%A8command-controllers%E9%87%8D%E7%82%B9" target="_blank">命令控制器command controllers重点</a>
<a href="#abstractcommandcontroller" target="_blank">AbstractCommandController</a>
<a href="#abstractformcontroller" target="_blank">AbstractFormController</a>
<a href="#simpleformcontroller" target="_blank">SimpleFormController</a>
<a href="#abstractwizardformcontroller" target="_blank">AbstractWizardFormController</a>
<a href="#viewresolver%E5%92%8Cview-%E8%A7%86%E5%9B%BE%E4%B8%8E%E8%A7%86%E5%9B%BE%E8%A7%A3%E6%9E%90%E5%99%A8" target="_blank">ViewResolver和View 视图与视图解析器</a>
<a href="#%E8%A7%86%E5%9B%BE%E8%A7%A3%E6%9E%90%E5%99%A8viewresolver" target="_blank">视图解析器ViewResolver</a>
<a href="#%E8%A7%86%E5%9B%BE%E8%A7%A3%E6%9E%90%E9%93%BE" target="_blank">视图解析链</a>
<a href="#%E9%87%8D%E5%AE%9A%E5%90%91rediret" target="_blank">重定向Rediret</a>
<a href="#%E8%A7%86%E5%9B%BE" target="_blank">视图</a>
<a href="#%E5%AF%B9%E6%A8%A1%E5%9E%8B%E7%9A%84%E6%94%AF%E6%8C%81modelmapmodelandview" target="_blank">对模型的支持ModelMapModelAndView</a>
<a href="#%E5%AF%B9%E8%A7%86%E5%9B%BE%E7%9A%84%E6%94%AF%E6%8C%81requesttoviewnametranslator" target="_blank">对视图的支持RequestToViewNameTranslator</a>
控制器的概念是MVC设计模式的一部分(确切地说,是MVC中的C)。应用程序的行为通常被定义为服务接口, 而控制器使得用户可以访问应用所提供的服务。控制器解析用户输入,并将其转换成合理的模型数据,从而可以进一步由视图展示给用户。
Spring控制器架构的基础是org.springframework.mvc.Controller接口,Controller接口仅仅声明了一个方法,它负责处理请求并返回合适的模型和视图。Controller接口仅仅定义了每个控制器都必须提供的基本功能: 处理请求并返回一个模型和一个视图。
模式一:
模式二:
MVC模式是经典的设计模式,是代码的分层思想:
1.M:Moder,即业务层,用来处理业务。
2.V:View,即视图层,用来显示数据。
3.C:Controller,即控制层,用来管理和调度程序,它是M和V的桥梁。
其目的是降低代码之间的耦合度,便于团队开发和维护。
Spring MVC实现的基础
就是这三个概念:Mdel、View(ModelAndView)以及 Controller。虽然 Controller接口是完全抽象的,但Spring也提供了许多你可能会用到的控制器。Controller接口仅仅定义了每个控制器都必须提供的基本功能: 处理请求并返回一个模型和一个视图。
所有的Spring控制器都继承了 AbstractController ,AbstractController 提供了诸如缓存支持和mimetype设置这样的功能。
功能
描述
supportedMethods
指定这个控制器应该接受什么样的请求方法。通常它被设置成同时支持GET和POST,但是可以选择你想支持的方法。如果控制器不支持请求发送的方法, 客户端会得到通知(通常是抛出一个ServletException)。
requiresSession
表明这个控制器是否需要HTTP session才能正常工作。如果控制器在没有session的情况下接收到请求,客户端会因为抛出ServletException 而得到通知。
synchronizeOnSession
指定controller是否同步用户的HTTP session。
cacheSeconds
指定controller通知客户端对数据内容缓存的秒数,一般为大于零的整数。默认值为-1,即不缓存。
useExpiresHeader
指定Controller在响应请求时是否兼容HTTP 1.0 Expires header。缺省值为true。
useCacheHeader
指定Controller在相应请求时是否兼容HTTP 1.1 Cache-Control header。默认值为true。
当从AbstractController**继承时,只需要实现handleRequestInternal**(HttpServletRequest, HttpServletResponse)抽象方法,该方法将用来实现自定义的逻辑,并返回一个ModelAndView对象。
当从AbstractController继承时,只需要实现handleRequestInternal(HttpServletRequest, HttpServletResponse)抽象方法,该方法将用来实现自定义的逻辑,并返回一个ModelAndView对象。
例子演示 了如何从AbstractController继承以及如何在applicationContext.xml中进行配置。
尽管可以继承AbstractController来实现自己的控制器,不过Spring提供的众多控制器减轻了我们开发简单MVC应用时的负担。 ParameterizableViewController基本上和上面例子中的一样,不同的是,可以在application context中指定返回的视图名称(从而 避免了在Java代码中的硬编码)。
UrlFilenameViewController会检查URL,获取文件请求的文件名,并把它作为视图名加以使用。。
例如
<a href="http://www.springframework.org/index.html" target="_blank">http://www.springframework.org/index.html</a>
对应的视图文件名是index。
MultiActionController来将多个请求处理方法合并在一个控制器里,这样可以把相关功能组合在一起。位于org.springframework.web.mvc.multiaction包中,它可以定义页面
请求到控制器方法名的映射, 然后在处理相应请求时调用该方法。 当你有很多比较小的且相关的功能时使用MultiActionController很方便,这样就不必为每个小功能创建 一个单独的Controller了。
MultiActionController有两种使用方式:
一是创建MultiActionController的子类,并指定将被 MethodNameResolver解析的方法(这种情况下不需要这个delegate参数);
二是定义一个委托对象, MethodNameResolver解析出目标方法后将调用该对象的相应方法。这种情况下需要定义MultiActionController 的实例并将委托对象作为协作者注入(可通过构造参数或者setDelegate方法)。
MultiActionController需要一种策略,使其可以通过解析请求信息来获得要调用的方法。这个解析策略由* MethodNameResolver接口*定义。MultiActionController提供了’methodNameResolver’ 属性使得你可以注入需要的MethodNameResolver。在自己的MultiActionController(或者前面说的委托对象) 上定义的请求处理方法必须符合如下签名:
说明:’anyMeaningfulName’指任意方法名
public [ModelAndView | Map | void] anyMeaningfulName(HttpServletRequest, HttpServletResponse [,HttpSession] [,AnyObject])
注意:接受一个AnyObject参数,这个参数包含从请求中抽取出来的信息,并且要求请求中已经存在一个 合法的session对象。注意参数的顺序很重要:session必须是第三个参数,而绑定参数必须是final的,并位于session之后。
命令控制器提供了一种和数据对象交互的方式,并动态地将来自HttpServletRequest的参数绑定到指定的数据对象上。 它的功能和Struts中的ActionForm有点像,不过在Spring中,不需要实现任何接口来实现数据绑定。
可以使用该抽象命令控制器来创建自己的命令控制器,它能够将请求参数绑定到指定的命令对象。
这个类并不提供任何表单功能,但是它提供验证功能,并且让你在控制器中去实现如何处理由请求参数值产生的命令对象。
一个支持表单提交的抽象控制器类。 使用这个控制器,可以定义表单,并使用从控制器获取的数据对象构建表单。
当用户输入表单内容,AbstractFormController将用户输入的内容绑定到命令对象,验证表单内容, 并将该对象交给控制器,完成相应的操作。它支持的功能有防止重复提交、表单验证以及一般的表单处理流程。
子类需要实现自己的方法来指定采用哪个视图来显示输入表单,哪个视图显示表单正确提交后的结果。 如果需要表单,但不想在应用上下文中指定显示给用户的视图,可使用该控制器。
这是一个form controller,当需要根据命令对象来创建相应的form的时候,该类可以提供更多的支持。 可以为其指定一个命令对象,显示表单的视图名,当表单提交成功后显示给用户的视图名等等。
这是一个抽象类,继承这个类需要实现validatePage()、processFinish() 和processCancel() 方法。
你有可能也需要写一个contractor,它至少需要调用setPages()和setCommandName()方法。setPages()的参数是一个String数组,这个数组包含了组成向导的视图名。 setCommandName()的参数是一个String,该参数将用来在视图中调用你的命令对象。
和AbstractFormController的实例一样, 需要使用命令对象(其实就是一个JavaBean, 这个bean中包含了表单的信息)。 这里有两个选择:在构造函数中调用setCommandClass()方法(参数是命令对象的类名),或者实现formBackingObject()方法。
AbstractWizardFormController 有多个可以覆写(override)的方法。 最有用的一个是referenceData(..)。 这个方法允许把模型数据以Map的格式传递给视图;getTargetPage() 允许动态地更改向导的页面顺序, 或者直接跳过某些页面;onBindAndValidate() 允许覆写内置的绑定和验证流程。
ViewResolver和View是Spring的视图处理方式中特别重要的两个接口。 ViewResolver提供了从视图名称到实际视图的映射。 View处理请求的准备工作,并将该请求提交给某种具体的视图技术。
SpringWeb框架的所有控制器都返回一个ModelAndView实例。 Sprnig中的视图以名字为标识,视图解析器通过名字来解析视图。
ViewResolver
AbstractCachingViewResolver
抽象视图解析器实现了对视图的缓存。在视图被使用之前,通常需要进行一些准备工作。 从它继承的视图解析器将对要解析的视图进行缓存。
XmlViewResolver
XmlViewResolver实现ViewResolver,支持XML格式的配置文件。 该配置文件必须采用与Spring XML Bean Factory相同的DTD。默认的配置文件是 /WEB-INF/views.xml。
ResourceBundleViewResolver
ResourceBundleViewResolver实现ViewResolver, 在一个ResourceBundle中寻找所需bean的定义。 这个bundle通常定义在一个位于classpath中的属性文件中。默认的属性文件是views.properties。
UrlBasedViewResolver
UrlBasedViewResolver实现ViewResolver, 将视图名直接解析成对应的URL,不需要显式的映射定义。 如果你的视图名和视图资源的名字是一致的,就可使用该解析器,而无需进行映射。
InternalResourceViewResolver
作为UrlBasedViewResolver的子类, 它支持InternalResourceView(对Servlet和JSP的包装), 以及其子类JstlView和TilesView。 通过setViewClass方法,可以指定用于该解析器生成视图使用的视图类。 更多信息请参考UrlBasedViewResolver的Javadoc。
VelocityViewResolver / FreeMarkerViewResolver
作为UrlBasedViewResolver的子类, 它能支持VelocityView(对Velocity模版的包装)和FreeMarkerView以及它们的子类。
当使用JSP作为视图层技术时,就可以使用UrlBasedViewResolver。 这个视图解析器会将视图名解析成URL,并将请求传递给RequestDispatcher来显示视图。
当返回的视图名为test时, 这个视图解析器将请求传递给RequestDispatcher,RequestDispatcher再将请求传递给/WEB-INF/jsp/test.jsp。
当在一个web应用中混合使用不同的视图技术时,可以使用ResourceBundleViewResolver:
ResourceBundleViewResolver通过basename所指定的ResourceBundle解析视图名。 对每个待解析的视图,ResourceBundle里的[视图名].class所对应的值就是实现该视图的类。 同样,[视图名].url所对应的值是该视图所对应的URL。
从上面的例子里能够发现,可以指定一个parent view,其它的视图都可以从parent view扩展。用这种方法,可以声明一个默认的视图。
Spring支持多个视图解析器一起使用。可以把它们当作一个解析链。
这样有很多好处,比如在特定情况下重新定义某些视图。 定义视图解析链很容易,只要在应用上下文中定义多个解析器就可以了。 必要时,也可以通过order属性来声明每个解析器的序列。 要记住的是,某个解析器的order越高, 它在解析链中的位置越靠后。
例子:展示了一个包含两个解析器的解析链。 一个是InternalResourceViewResolver,这个解析器总是被自动的放到链的末端。 另一个是XmlViewResolver,它支持解析Excel视图(而InternalResourceViewResolver不可以)。
如果某个解析器没有找到合适的视图,Spring会在上下文中寻找是否配置了其它的解析器。 如果有,它会继续进行解析,否则,Srping会抛出一个Exception。
当一个视图解析器找不到合适的视图时,它可能 返回null值。
RedirectView
在控制器中强制重定向的方法之一是让控制器创建并返回一个Spring的RedirectView的实例。 在这种情况下,DispatcherServlet不会使用通常的视图解析机制, 既然它已经拿到了一个(重定向)视图,它就让这个视图去完成余下的工作。
RedirectView会调用HttpServletResponse.sendRedirect()方法, 其结果是给用户的浏览器发回一个HTTP redirect。所有的模型属性都被转换成以HTTP请求的访问参数。
redirect:前缀
redirect:/my/response/controller.html这个逻辑视图名中的URL是当前servlet context中的相对路径。
redirect:http ://myhost.com/some/arbitrary/path.html中的URL是绝对路径。
如果返回的视图名包含redirect:前缀,UrlBasedViewResolver (以及它的子类) 会知道系统要生成一个HTTP redirect。 视图名其余的部分会被当作重定向URL。
forward:前缀
使用包含有forward:前缀的视图名,这些视图名会被UrlBasedViewResolver和它的子类正确解析。 解析的内部实现是生成一个InternalResourceView, 这个视图最终会调用RequestDispatcher.forward()方法,将forward视图名的其余部分作为URL。 所以,当使用InternalResourceViewResolver/InternalResourceView, 并且你所用的视图技术是JSP时,你没有必要使用这个前缀。 但是,当你主要使用其它的视图技术,但仍需要对Servlet/JSP engine处理的页面强制forward时
如果含有redirect和forward前缀的视图名和其他视图名一样被注入控制器, 控制器根本不需要知道在处理响应的过程中是否发生任何特殊情况。
ModelMap类首先是一个绚丽的Map实现, 它可以使新增的将要显示在View中(或上)的对象也遵循同一命名规范。 考虑下面的Controller实现,注意对象被加入ModelAndView, 而并没有指定任何名称。
ModelAndView类使用的ModelMap类是一个自定义的Map的实现。 当有一个新对象加入的时候,它就被用于为这个对象自动生成一个键。 决定某个加入的对象的名字的策略是,当它是一个标量对象(scalar object),比如User时, 就使用这个对象所属类的简短类名。
RequestToViewNameTranslator接口的功能是当没有显式的提供这样一个逻辑视图名称的时候, 确定一个逻辑的View名称。 这个接口只有一个实现,精明的命名为DefaultRequestToViewNameTranslator。