控制器是mvc模式中非常重要的部分。Spring中定义了Controller接口,包含了FormController、CommandController以及各种Controller。
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;
}
这个接口非常的简单,只有一个可以返回适当Model和View的请求处理方法。除了这个接口Spring还提供了一些该接口的实现,包括了一些常用的功能方法。
AbstractController提供了一个构建Controller的基础。AbstractController继承了WebContentGenerator并实现了Controller接口。这样,在AbstractController中就具备了以下的功能。
supportedMethods,表明控制器可以接受那些方法。通常是设置GET和POST两个方法,但是你可以自己定义实现一些方法的处理。所有可以接受的方法放在一个SET中。
下面是WebContentGenerator的构造方法,这里可以看到设置了可以接受的方法。
/**
* Create a new WebContentGenerator supporting GET and POST methods.
*/
public WebContentGenerator() {
this.supportedMethods = new HashSet();
this.supportedMethods.add(METHOD_GET);
this.supportedMethods.add(METHOD_POST);
}
requiresSession,指明该Controller是否需要使用session。
synchronizeSession,是否需要同步用户session。
cacheSeconds,是否需要缓存HTTP response,可以设置一个int,默认是-1,即不启用该功能。
代码如下:
protected final void cacheForSeconds(HttpServletResponse response, int seconds, boolean mustRevalidate) {
if (this.useExpiresHeader) {
// HTTP 1.0 header
response.setDateHeader(HEADER_EXPIRES, System.currentTimeMillis() + seconds * 1000L);
}
if (this.useCacheControlHeader) {
// HTTP 1.1 header
String headerValue = "max-age=" + seconds;
if (mustRevalidate) {
headerValue += ", must-revalidate";
}
response.setHeader(HEADER_CACHE_CONTROL, headerValue);
}
}
protected final void preventCaching(HttpServletResponse response) {
response.setHeader(HEADER_PRAGMA, "No-cache");
if (this.useExpiresHeader) {
// HTTP 1.0 header
response.setDateHeader(HEADER_EXPIRES, 1L);
}
if (this.useCacheControlHeader) {
// HTTP 1.1 header
response.setHeader(HEADER_CACHE_CONTROL, "no-cache");
}
}
此外,还提供了useExpiresHeader和useCacheHeader。
如果你使用AbstractController来做为一个基类的话(不推荐),你需要override一下handleRequestInternal方法,填充你的代码,返回一个ModelAndView对象。
例如:
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>
其他的控制器
ParameterizableViewController,根据指定的View名称,返回View。
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
return new ModelAndView(this.viewName);
}
UrlFilenameViewController,从请求URL中得到FileName。
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
String uri = request.getRequestURI();
int begin = uri.lastIndexOf('/');
if (begin == -1) {
begin = 0;
}
else {
begin++;
}
int end;
if (uri.indexOf(";") != -1) {
end = uri.indexOf(";");
}
else if (uri.indexOf("?") != -1) {
end = uri.indexOf("?");
}
else {
end = uri.length();
}
String fileName = uri.substring(begin, end);
if (fileName.indexOf(".") != -1) {
fileName = fileName.substring(0, fileName.lastIndexOf("."));
}
return new ModelAndView(fileName);
}
MultiActionController
这个Controller在一个独立的包中,org.springframework.web.mvc.multiaction。
你可以把多个动作集中到这个Controller中。当你需要大量公用的功能在一个Controller中时,这个Controller是很好的选择。
你可以子类化MultiActionController,也可以使用MethodNameResolver。
MethodNameResolver,当接受请求的时候MultiActionController需要调用一个处理该请求的方法,你可以自己定义个解决方法,通过配置文件中指定的参数名称找到这个方法。
方法定义必需使用以下格式:
ModelAndView actionName(HttpServletRequest, HttpServletResponse);
此外你也可以自己定义一个异常类来处理异常,格式为:
ModelAndView anyMeaningfulName(HttpServletRequest, HttpServletResponse, ExceptionClass);
Spring提供了MethodNameResolver的三种方式:
ParameterMethodNameResolver,这个可以根据请求的参数来确定一个需要调用的方法。
例如,http://www.sf.net/index.view?testParam=testIt,这个请求会调用名称为testIt的处理方法。
InternalPathMethodNameResolver,这个可以根据请求的路径名称来调用相应的方法。
例如,http://www.sf.net/testing.view,这个请求会调用testing方法。
PropertiesMethodNameResolver,这个可以根据一个URLs 映射列表来调用相应的方法。
例如,如果定义了/index/welcome.html=doIt,那么当请求为/index/welcome.html时,会调用doIt方法。在定义URLs时可以使用通配符。/**/welcom?.html
<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()));
}
}
或者
<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>
CommandControllers
这个控制器简化了struts中的操作,可以直接和数据对象进行交互。例如把HttpServletRequest得到的参数动态绑定到dataobject上。
AbstractCommandController,通过这个可以创建你自己的Command Comtroller。它继承了BaseCommandController,可以设置commandObject来保存数据,可以指定验证类。
AbstractFormController
SimpleFormController