13.3.1. AbstractController
和 WebContentGenerator
为了提供一套基础设施,所有的Spring控制器都继承了 AbstractController
,AbstractController
提供了诸如缓存支持和mimetype设置这样的功能。
表 13.3. AbstractController
提供的功能
功能 |
描述 |
supportedMethods
|
指定这个控制器应该接受什么样的请求方法。通常它被设置成同时支持GET和POST,但是你可以选择你想支持的方法。如果控制器不支持请求发送的方法,客户端会得到通知(通常是抛出一个ServletException )。 |
requiresSession
|
指定这个控制器是否需要HTTP session才能正常工作。如果控制器在没有session的情况下接收到请求,客户端会因为抛出ServletException 而得到通知。 |
synchronizeSession
|
指定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
继承以及如何在applicationContext.xml中进行配置
package samples;
public class SampleController extends AbstractController {
public ModelAndView handleRequestInternal(
HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView("hello");
mav.addObject("message", "Hello World!");
return mav;
}
}
<bean id="sampleController" class="samples.SampleController">
<property name="cacheSeconds" value="120"/>
</bean>
该controller返回的ModelAndView使用了硬编码的视图名(尽管这样做不好),并通知客户端将响应数据缓存2分钟。除了通过以上方式创建和配置controller之外,还需要配置handler mapping(请参考第 13.4 节 “处理器映射(handler mapping)”),这样该controller就可以工作了。
13.3.3. MultiActionController
MultiActionController
将多个行为(action)合并在一个控制器里,这样可以把相关功能组合在一起。MultiActionController
位于org.springframework.web.mvc.multiaction
包中,它通过将请求映射到正确的方法名来调用方法。当在一个控制器存在大量公共的行为,但是有多个调用入口时,使用MultiActionController
就特别方便。
表 13.4. MultiActionController
提供的功能
功能 |
描述 |
delegate
|
MultiActionController 有两种使用方式。第一种是你继承MultiActionController ,并在子类中指定由MethodNameResolver 解析的方法(这种情况下不需要这个delegate参数)。第二种是你定义一个代理对象,由它提供MethodNameResolver 解析出来的方法(这种情况下,你必须使用这个配置参数定义代理对象)。 |
methodNameResolver
|
MultiActionController 需要一种策略,使其可以通过解析请求信息来获得要调用的方法。这个解析策略由MethodNameResolver 这个接口定义的。这个参数允许你实现MethodNameResolver 接口,然后在控制器中使用你的策略。 |
MultiActionController
所支持的方法需要符合下列格式:
// anyMeaningfulName can be replaced by any methodname
public [ModelAndView | Map | void] anyMeaningfulName(HttpServletRequest, HttpServletResponse [, Exception | AnyObject]);
注意:在此不允许方法重载,因为MultiActionController
无法分辨出重载(overloading)了的方法。此外,你可以定义exception handler来处理方法中抛出的异常。
Exception
参数是可选的,它可以是任何异常,只要它是java.lang.Exception
或java.lang.RuntimeException
的子类。AnyObject
参数也是可选的,它可以是任何对象。HTTP Request中的参数会存在这个对象中,以便使用。
下面几个例子示范了MultiActionController
正确的方法定义。
标准格式(跟Controller
接口定义的一样)。
public ModelAndView doRequest(HttpServletRequest, HttpServletResponse)
下面这个方法支持Login
参数, 这个参数中包含从请求中抽取出来的信息。
public ModelAndView doLogin(HttpServletRequest, HttpServletResponse, Login)
下面这个方法可以处理Exception
。
public ModelAndView processException(HttpServletRequest, HttpServletResponse, IllegalArgumentException)
下面这个方法不返回任何数值。 (请参考后面的章节 第 13.11 节 “惯例优先原则(convention over configuration)”)
public void goHome(HttpServletRequest, HttpServletResponse)
This signature has a Map
return type (see the section entitled 第 13.11 节 “惯例优先原则(convention over configuration)” below).
下面这个方法返回一个Map
。 (请参考后面的章节第 13.11 节 “惯例优先原则(convention over configuration)”)
public Map doRequest(HttpServletRequest, HttpServletResponse)
MethodNameResolver
负责从请求中解析出需要调用的方法名称。下面是Spring中内置的三个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
一起工作,比如上边那个URL写成/**/welcom?.html
也是可以的。
我们来看一组例子。首先是一个使用ParameterMethodNameResolver
和代理(delegate)属性的例子,它接受包含参数名"method"的请求,调用方法retrieveIndex
:
<bean id="paramResolver" class="org....mvc.multiaction.ParameterMethodNameResolver">
<property name="paramName" value="method"/>
</bean>
<bean id="paramMultiController" class="org....mvc.multiaction.MultiActionController">
<property name="methodNameResolver" ref="paramResolver"/>
<property name="delegate" ref="sampleDelegate"/>
</bean>
<bean id="sampleDelegate" class="samples.SampleDelegate"/>
## together with
public class SampleDelegate {
public ModelAndView retrieveIndex(HttpServletRequest req, HttpServletResponse resp) {
return new ModelAndView("index", "date", new Long(System.currentTimeMillis()));
}
}
当使用上面的代理对象时,我们也可以使用PropertiesMethodNameRseolver
来匹配一组URL,将它们映射到我们定义的方法上:
<bean id="propsResolver" class="org....mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<value>
/index/welcome.html=retrieveIndex
/**/notwelcome.html=retrieveIndex
/*/user?.html=retrieveIndex
</value>
</property>
</bean>
<bean id="paramMultiController" class="org....mvc.multiaction.MultiActionController">
<property name="methodNameResolver" ref="propsResolver"/>
<property name="delegate" ref="sampleDelegate"/>
</bean>