SpringMVC请求处理流程

看了很多介绍源码的文章,上来就是代码段劝退,别怕,虽然我也有代码段,但是肯定比他们少!

一些想法

我们一直在SpringMVC这种框架里面写各种Controller,标注各种@RequestMapping,然后请求就能到指定的处理方法上了。这背后的逻辑,如果让我们实现应该怎么去弄?

他会不会像下面这样

  1. 根据请求地址找到处理方法
  2. 在调用处理方法前执行一些拦截逻辑
  3. 调用处理方法
    1. 根据处理方法所需要的各种参数,从请求中获取
    2. 根据处理方法的参数类型做转换
    3. 实际调用
  4. 在处理完成之后再执行一些拦截逻辑
  5. 处理返回值并返回

当然上面是最简单最基本的一个流程,SpringMVC肯定也是这样做的,只是中间肯定多了非常多的一些其他逻辑,例如异常处理,静态资源处理,视图渲染等等

SpringMVC是怎么做的?

跟我们想象的差不多,上面说的那些东西,在SpringMVC里面都有对应的实现,我们用最朴素最简单的方式来介绍这些组件。当然,会非常不严谨,但不妨碍我们了解它的大概原理。

1、DispatcherServlet 前端控制器

这些事情的入口都发生在一个叫做DispatcherServlet的地方;并且按照我们一开始的设想,那些执行步骤都在这里体现到了。

下面的代码是精简版,删了很多其他的逻辑,我们只关注我们需要关注的

doDispatch(HttpServletRequest processedRequest, HttpServletResponse response) throws Exception {
    // 根据请求,拿到对应的handleChain(就是拦截器+Handle),里面就有我们写的Controller中的方法
    HandlerExecutionChain mappedHandler = getHandler(processedRequest);
    if (mappedHandler == null) {
        noHandlerFound(processedRequest, response);
        return;
    }
    // 根据handle获取处理器适配器(为什么需要处理器适配器??后面会讲)
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    // 执行前置拦截器,根据返回值true/false决定能不能继续
    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
        return;
    }
    // 使用处理器适配器来实际调用handle
    ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    // 执行后置拦截器
    mappedHandler.applyPostHandle(processedRequest, response, mv);
    // 处理结果
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

2、HandlerMapping根据请求找到对应的处理方式

没错,可以简单的将它理解成一个Map<请求地址,handle>的映射。只不过handle有很多种,所以HandlerMapping也有很多实现

public interface HandlerMapping {
	HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

3、HandlerExecutionChain处理器执行链

Spring里面可以看见各种各样的Chain,这样做的好处就是在执行目标方法前后可以添加各种逻辑。而这里不直接调用目标handle的原因也是这样,可以应用我们写的各种HandlerInterceptor;

所以一个HandlerExecutionChain= handle + List<HandlerInterceptor>的组合。

public class HandlerExecutionChain {
	private HandlerInterceptor[] interceptors;
  // 遍历调用这些interceptors,执行他们的preHandle
	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response){
		// ....
	}
 // 也是遍历,调用postHandle
 void applyPostHandle(HttpServletRequest request, HttpServletResponse response,  ModelAndView mv){
		// ...
	}
}

4、HandlerAdapter 处理器适配器

因为我们实际的handle可能是一个我们最经常使用的@Controller+@RequestMapping+Method的方式,也可能是一个org.springframework.web.servlet.mvc.Controller的实现类,也可能是一个org.springframework.web.HttpRequestHandler的实现类等,这两种我们平时很少接触到,虽然我们可以不用,但是框架不可能不支持啊。所以就会有各种各样的HandlerAdapter `的子类来处理。

public interface HandlerAdapter {
	// 资不资磁啊?
	boolean supports(Object handler);
  // 去实际调用handle并适配返回结果吧
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
  // 无关紧要
	long getLastModified(HttpServletRequest request, Object handler);
}

总结

很明显,这只是个大体的处理逻辑,其中的细节,每一个都能说很多,例如一个请求参数的封装逻辑都很复杂。

看到这里只要脑子里有个大体的印象,每个东西都是干嘛的,大体流程是怎么样的就行。后面细节我在一个一个的补充。说了这么多废话好像有人看一样

Q.E.D.