技术开发 频道

Web框架

控制器的概念是MVC设计模式的一部分。控制器定义了应用的行为,至少能使用户访问到这些行为。控制器解释用户输入,并将其转换成合理的模型数据,从而可以进一步地由视图展示给用户。Spring以一种抽象的方式实现了控制器概念,这样使得不同类型的控制器可以被创建。Spring包含表单控制器,命令控制器,执行向导逻辑的控制器等等。

Spring控制器架构的基础是org.springframework.mvc.Controller接口。

public interface Controller { /** * Process the request and return a ModelAndView object which the DispatcherServlet * will render. */ ModelAndView handleRequest( HttpServletRequest request, HttpServletResponse response) throws Exception; }


你可以发现Controller接口仅仅声明了一个方法,它能够处理请求并返回合适的模型和视图。Spring MVC实现的基础就是这三个概念:ModelAndView和Controller。 因为Controller接口是完全抽象的,Spring提供了许多已经包含一定功能的控制器。控制器接口仅仅定义了每个控制器提供的共同功能:处理请求并返回一个模型和一个视图。 

AbstractController 和 WebContentGenerator
当然,就一个控制器接口并不够。为了提供一套基础设施,所有的Spring控制器都从 AbstractController 继承,AbstractController 提供缓存和其它比如 mimetype 的设置的功能。

表 AbstractController提供的功能

功能 解释
supportedMethods 指定这个控制器应该接受什么样的请求方法。通常它被设置成GET和POST,但是你可以选择你想支持的方法。如果控制器不支持请求发送的方法,客户端会得到通知(ServletException)
requiresSession 指定这个控制器是否需要会话。这个功能提供给所有控制器。如果控制器在没有会话的情况下接收到请求,用户被通知ServletException
synchronizeSession 如果你需要使控制器同步访问用户会话,使用这个参数。具体地说,继承的控制器要重载handleRequestInternal方法,如果你指定了这个变量,控制器就被同步化。
cacheSeconds 当你需要控制器在HTTP响应中生成缓存指令,用这参数指定一个大于零的整数。缺省它被设置为-1,所以就没有生成缓存指令
useExpiresHeader 指定你的控制器使用HTTP 1.0兼容的"Expires"。缺省为true,所以你可以不用修改它
useCacheHeader 指定你的控制器使用HTTP 1.0兼容的"Cache-Control"。缺省为true,所以你也可以不用修改它

最后的两个属性是WebContentGenerator定义的,WebContentGenerator是AbstractController的超类……

当使用AbstractController作为你的控制器基类时(一般不推荐这样做,因为有许多预定义的控制器你可以选择),你只需要重载handleRequestInternal(HttpServletRequest, HttpServletResponse)这个方法,实现你自己的逻辑,并返回一个ModelAndView对象。下面这个简单例子包含一个类和在web应用上下文中的定义。

package samples; public class SampleController extends AbstractController { public ModelAndView handleRequestInternal( HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView("foo", new HashMap()); } } <bean id="sampleController" class="samples.SampleController"> <property name="cacheSeconds"><value>120</value</property> </bean>


除了这个类和在web应用上下文中的定义,还需要设置处理器映射(参考第 12.4 节 “处理器映射”),这样这个简单的控制器就可以工作了。这个控制器将生成缓存指令告诉客户端缓存数据2分钟后再检查状态。这个控制器还返回了一个硬编码的视图名(不是很好)(详情参考第 12.5 节 “视图与视图解析”)。

其它的简单控制器
除了AbstractController——虽然有许多其他控制器可以提供给你更多的功能,但是你还是可以直接继承AbstractController——有许多简单控制器,它们可以减轻开发简单MVC应用时的负担。ParameterizableViewController基本上和上面例子中的一样,但是你可以指定返回的视图名,视图名定义在web应用上下文中(不需要硬编码的视图名)

FileNameViewController检查URL并获取文件请求的文件名(http://www.springframework.org/index.html的文件名是index),把它作为视图名。仅此而已。 

MultiActionController
Spring提供一个多动作控制器,使用它你可以将几个动作合并在一个控制器里,这样可以把功能组合在一起。多动作控制器存在在一个单独的包中——org.springframework.web.mvc.multiaction——它能够将请求映射到方法名,然后调用正确的方法。比如当你在一个控制器中有很多公共的功能,但是想多个入口到控制器使用不同的行为,使用多动作控制器就特别方便。

MultiActionController提供的功能

功能 解释
delegate MultiActionController有两种使用方式。第一种是继承MultiActionController,并在子类中指定由MethodNameResolver解析的方法(这种情况下不需要这个配置参数),第二种是你定义了一个代理对象,由它调用Resolver解析的方法。如果你是这种情况,你必须使用这个配置参数定义代理对象
methodNameResolver 由于某种原因,MultiActionController需要基于收到的请求解析它必须调用的方法。你可以使用这个配置参数定义一个解析器

一个多动作控制器的方法需要符合下列格式:

// actionName can be replaced by any methodname
ModelAndView actionName(HttpServletRequest, HttpServletResponse);
由于MultiActionController不能判断方法重载(overloading),所以方法重载是不允许的。此外,你可以定义exception handlers,它能够处理从你指定的方法中抛出的异常。包含异常处理的动作方法需要返回一个ModelAndView对象,就象其它动作方法一样,并符合下面的格式:

// anyMeaningfulName can be replaced by any methodname
ModelAndView anyMeaningfulName(HttpServletRequest, HttpServletResponse, ExceptionClass);
ExceptionClass可以是任何异常,只要它是java.lang.Exception或java.lang.RuntimeException的子类。

MethodNameResolver根据收到的请求解析方法名。有三种解析器可以供你选择,当然你可以自己实现解析器。

ParameterMethodNameResolver - 解析请求参数,并将它作为方法名(http://www.sf.net/index.view?testParam=testIt的请求就会调用testIt(HttpServletRequest,HttpServletResponse))。使用paramName配置参数可以调整所检查的参数

InternalPathMethodNameResolver - 从路径中获取文件名作为方法名(http://www.sf.net/testing.view的请求会调用testing(HttpServletRequest, HttpServletResponse)方法)

PropertiesMethodNameResolver - 使用用户定义的属性对象将请求的URL映射到方法名。当属性定义/index/welcome.html=doIt,并且收到/index/welcome.html的请求,就调用doIt(HttpServletRequest, HttpServletResponse)方法。这个方法名解析器需要使用PathMatcher(参考 第 12.10.1 节 “关于pathmatcher的小故事”)所以如果属性包含/**/welcom?.html,该方法也会被调用!

我们来看一组例子。首先是一个使用ParameterMethodNameResolver和代理属性的例子,它接受包含参数名的请求,调用方法retrieveIndex:

<bean id="paramResolver" class="org....mvc.multiaction.ParameterMethodNameResolver"> <property name="paramName"><value>method</value></property> </bean> <bean id="paramMultiController" class="org....mvc.multiaction.MultiActionController"> <property name="methodNameResolver"><ref bean="paramResolver"/></property> <property name="delegate"><ref bean="sampleDelegate"/> </bean> <bean id="sampleDelegate" class="samples.SampleDelegate"/> ## together with public class SampleDelegate { public ModelAndView retrieveIndex( HttpServletRequest req, HttpServletResponse resp) { rerurn new ModelAndView("index", "date", new Long(System.currentTimeMillis())); } } 当使用上面的代理对象时,我们也可以使用PropertiesMethodNameRseolver来匹配一组URL,将它们映射到我们定义的方法上: <bean id="propsResolver" class="org....mvc.multiaction.PropertiesMethodNameResolver"> <property name="mappings"> <props> <prop key="/index/welcome.html">retrieveIndex</prop> <prop key="/**/notwelcome.html">retrieveIndex</prop> <prop key="/*/user?.html">retrieveIndex</prop> </props> </property> </bean> <bean id="paramMultiController" class="org....mvc.multiaction.MultiActionController"> <property name="methodNameResolver"><ref bean="propsResolver"/></property> <property name="delegate"><ref bean="sampleDelegate"/> </bean>

 命令控制器
Spring的CommandControllers是Spring MVC包的重要部分。命令控制器提供了一种和数据对象交互的方式,并动态将来自HttpServletRequest的参数绑定到你指定的数据对象上。和Struts的actonform相比,在Spring中,你不需要实现任何接口来实现数据绑定。首先,让我们看一下有哪些可以使用的命令控制器,以便有一个清晰的了解:

AbstractCommandController - 你可以使用这个命令控制器来创建你自己的命令控制器,它能够将请求参数绑定到你指定的数据对象。这个类并不提供任何表单功能,但是它提供验证功能,并且让你在控制器中定义如何处理包含请求参数的数据对象。

AbstractFormController - 一个提供表单提交支持的控制器。使用这个控制器,你可以定义表单,并使用你从控制器获取的数据对象构建表单。当用户输入表单内容,AbstractFormController将用户输入的内容绑定到数据对象,验证这些内容,并将对象交给控制器,完成适当的动作。它所支持的功能有无效表单提交(再次提交),验证,和正确的表单工作流。你可以控制将什么视图绑定到你的AbstractFormController。如果你需要表单,但不想在应用上下文中指定显示给用户的视图,就使用这个控制器。

SimpleFormController - 这是一个更具体的FormCotnroller,它能用相应的数据对象帮助你创建表单。SimpleFormController让你指定一个命令对象,表单视图名,当表单提交成功后显示给用户的视图名等等。

WizardFormController - 最后一个也是功能最强的控制器。WizardFormController 允许你以向导风格处理数据对象,当使用大的数据对象时,这样的方式相当方便。

0
相关文章