详解Spring Web MVC中的Controller(上)

来源:互联网 发布:矩阵式组织结构 编辑:程序博客网 时间:2024/05/17 06:17

MVC模型中的控制器负责解析用户的输入信息,并将之变换处理后传入一个model,而这个model则可能被呈现给发起请求的用户。Spring以非常抽象的方式体现了控制器的理念,从而开发人员在创建controller时将有多种选择。Spring包含了3类controller:处理HTML表单的controller,基于command的controller,和向导风格的controller。

    Spring中Controller的基本类是org.springframework.web.servlet.mvc.Controller,这是一个相当简洁的接口,源代码如下:

package org.springframework.web.servlet.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;

public interface Controller {
    ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

   Controller接口仅仅定义了一个方法用于负责处理客户请求,并返回适当的模型和视图,这也是所有控制器都需要完成的职责。ModelAndView与Controller,这便是SpringMVC框架实现的基础。尽管Controller相当抽象,但Spring提供了多种Controller接口实现类。

1. AbstractController 类
   AbstractController是WebContentGenerator的子类,并实现了Controller接口。AbstractController是最重要的Controller接口实现之一,它提供了一些很基本的功能特征,例如生成HTTP协议的缓存头标数据,设定GET/POST动作等等。
    考察一下AbstratorController所在的类层次:

java.lang.Object
|_ org.springframework.context.support.ApplicationObjectSupport
  |_ org.springframework.web.context.support.WebApplicationObjectSupport
    |_   org.springframework.web.servlet.support.WebContentGenerator
        |_ org.springframework.web.servlet.mvc.AbstractController


    AbstratorController从其超类中继承许多属性,这些属性可以通过配置文件注入:
* supportedMethods :指明本Controller应该接受的方法,缺省值“GET,POST”,开发人员也可以自己修改本属性以反应欲支持的方法。若一个请求带有该方法设定,但Controller并不支持,那么这个信息将被通知客户。
* requiresSession:指明本Controller是否需要一个HTTP会话以完成它的工作,若Contrller在接收一个请求时并没有HTTP会话存在,那么将抛出一个ServletException。本属性的缺省值是false。
* synchronizeSession:若在客户的HTTP会话中,需要以同步方式处理Controller,则使用本属性。
* cacheSeconds:当需要Controller为客户的HTTP响应生成一个缓存指令时,可以为cacheSeconds指定一个正整数。本属性缺省值为-1,即不设定缓存。
* useExpiresHeader:指示Controller为客户的HTTP响应指定一个兼容HTTP 1.0版本中的"Expires"头标数据。本属性缺省值是true。
* useCacheHeader:指示Controller为客户的HTTP响应指定一个兼容HTTP 1.1版本中的"Cache-Control"头标数据。本属性缺省值是true。

    我们阅读一下Spring src目录中的AbstractController的源代码:

package org.springframework.web.servlet.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.WebContentGenerator;
import org.springframework.web.util.WebUtils;

public abstract class AbstractController extends WebContentGenerator implements Controller {

    private boolean synchronizeOnSession = false;

    public final void setSynchronizeOnSession(boolean synchronizeOnSession) {
        this.synchronizeOnSession = synchronizeOnSession;
    }

    public final boolean isSynchronizeOnSession() {
        return synchronizeOnSession;
    }


    public final ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
              throws Exception {
        checkAndPrepare(request, response, this instanceof LastModified);

        if (this.synchronizeOnSession) {
              HttpSession session = request.getSession(false);
              if (session != null) {
                  Object mutex = WebUtils.getSessionMutex(session);
                  synchronized (mutex) {
                      return handleRequestInternal(request, response);
                  }
              }
        }
       
        return handleRequestInternal(request, response);
    }

    protected abstract ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
      throws Exception;

}
   

从上述代码可以看出,AbstractorController的工作流程如下:
1.DispatcherServlet调用handleRequest方法;
2.检查被支持的方法(GET/POST/PUT之一),若不支持则抛出ServletException;
3.若需要发起一个session,则尝试获取一个session,若获取不到,则抛出ServletException;
4.根据cacheSeconds属性,设定缓存头标的数据;
5.调用受保护的抽象方法handleRequestInternal,这个方法应由AbstractController的子类提供实际的功能实现,并返回ModelAndView对象。
   
   当开发人员使用AbstractController作为自己所设计的控制器的基类时,只需覆盖handleRequestInternal(HttpServletRequest,HttpServletResponse)方法即可,并返回一个ModelAndView对象,示例如下:

package samples;
public class SampleController extends AbstractController {

public ModelAndView handleRequestInternal(
HttpServletRequest request,
HttpServletResponse response) throws Exception {
    ModelAndView modelAndView = new ModelAndView("hello");
    modelAndView.addObject("message", "Hello World!");
    return modelAndView;
}

}

    而配置文件中定义示例如下:
<bean id="sampleController" class="samples.SampleController">
    <property name="cacheSeconds" value="120"/>
</bean>
   
    在本例中,若使这个SampleController将在给客户的HTTP响应中指定120秒的缓存。SampleController返回了一个一个编码的视图(通常不建议这样设计)。

2. 其他简单的Controller
    尽管开发人员可以自己扩展AbstractController,不过Spring提供了许多具体的实现,可以用于简单的MVC应用。
    ParameterizableViewController类与上面的示例基本相同,除了开发人员可以自己指定所返回视图的名字,这样便不需要在Java类中写视图的名字。
UrlFilenameViewController检查URL,查找文件请求的文件名,并以之作为视图的名字。例如“http://www.springframework.org/index.html”的文件名是“index”。