springmvc

原文:https://my.oschina.net/lichhao/blog/99039

一、web请求框架

  • URL到框架的映射。
  • http请求参数绑定
  • http响应的生成和输出

二、处理过程

1.用户在浏览器中,输入了http://www.xxxx.com/aaa/bbb.ccc的地址,回车后,浏览器发起一个http请求。请求到达你的服务器后,首先会被SpringMVC注册在web.xml中的前端转发器DispatcherServlet接收,DispatcherServlet是一个标准的Servlet,它的作用是接受和转发web请求到内部框架处理单元。

2.回到DispatcherServlet的处理流程,当DispatcherServlet接收到web请求后,由标准Servlet类处理方法doGet或者doPost,经过几次转发后,最终注册在DispatcherServlet类中的HandlerMapping实现类组成的一个List(有点拗口)会在一个循环中被遍历。以该web请求的HttpServletRequest对象为参数,依次调用其getHandler方法,第一个不为null的调用结果,将被返回。

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }

HandlerMapping接口的getHandler方法参数是HttpServletRequest,这意味着,HandlerMapping的实现类可以利用HttpServletRequest中的 所有信息来做出这个HandlerExecutionChain对象的生成”决策“。这包括,请求头、url路径、cookie、session、参数等等一切你从一个web请求中可以得到的任何东西(最常用的是url路径)。

SpirngMVC的第一个扩展点,就出现在这里。我们可以编写任意的HandlerMapping实现类,依据任何策略来决定一个web请求到HandlerExecutionChain对象的生成。

public class HandlerExecutionChain {

    private final Object handler;

    private HandlerInterceptor[] interceptors;
...
public interface HandlerInterceptor {

    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception;

    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

}

至此,HandlerExecutionChain整个执行脉络也就清楚了:在真正调用其handler对象前,HandlerInterceptor接口实现类组成的数组将会被遍历,其preHandle方法会被依次调用,然后真正的handler对象将被调用。

handler对象被调用后,就生成了需要的响应数据,在将处理结果写到HttpServletResponse对象之前(SpringMVC称为渲染视图),其postHandle方法会被依次调用。视图渲染完成后,最后afterCompletion方法会被依次调用,整个web请求的处理过程就结束了.

SpringMVC中的又一个核心接口,HandlerAdapter

public interface HandlerAdapter {

    boolean supports(Object handler); 

    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    long getLastModified(HttpServletRequest request, Object handler);

}

在DispatcherServlet中,除了HandlerMapping实现类的列表,同样也注册了一个HandlerAdapter实现类组成的列表

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        for (HandlerAdapter ha : this.handlerAdapters) {
            if (logger.isTraceEnabled()) {
                logger.trace("Testing handler adapter [" + ha + "]");
            }
            if (ha.supports(handler)) {
                return ha;
            }
        }
        throw new ServletException("No adapter for handler [" + handler +
                "]: Does your handler implement a supported interface like Controller?");
    }

HandlerExecutionChain中的handler对象会被作为参数传递进去,在DispatcherServlet类中注册的HandlerAdapter实现类列表会被遍历,然后返回第一个supports方法返回true的HandlerAdapter对象,用这个HandlerAdapter实现类中的handle方法处理handler对象,并返回ModelAndView这个包含了视图和数据的对象。HandlerAdapter就是SpringMVC提供的第三个扩展点,你可以提供自己的实现类来处理handler对象。

public interface View {

    String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";

    String PATH_VARIABLES = View.class.getName() + ".pathVariables";

    String getContentType();

    void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

}

所有的数据,最后会作为一个Map对象传递到View实现类中的render方法,调用这个render方法,就完成了视图到响应的渲染。这个View实现类,就是来自HandlerAdapter中的handle方法的返回结果。当然从ModelAndView到真正的View实现类有一个解析的过程,ModelAndView中可以有真正的视图对象,也可以只是有一个视图的名字,SpringMVC会负责将视图名称解析为真正的视图对象。

在一个典型的SpringMVC调用中,HandlerExecutionChain中封装handler对象就是用@Controller注解标识的类的一个实例,根据类级别和方法级别的@RequestMapping注解,由默认注册的DefaultAnnotationHandlerMapping生成HandlerExecutionChain对象,再由AnnotationMethodHandlerAdapter来执行这个HandlerExecutionChain对象,生成最终的ModelAndView对象后,再由具体的View对象的render方法渲染视图。

posted @ 2017-07-18 15:43  jerrice  阅读(215)  评论(0编辑  收藏  举报