今天我们来看一下Spring WebMvc是怎么工作的
入口Servlet
DispatcherServlet作为Servlet的实现,我们先从它父类FrameworkServlet的processRequest方法开始,因为doGet doPost doPut doDelete 等方法都是调用这个方法的
先构建RequestAttributes
pre不存在才需要构建,然后设置attr到RequestContextHolder,以便后续可以从RequestContextHolder获取request/response等对象
Multipart处理
接下来开始进入doService –> doDispatch
如果请求时multipart类型,则将request转换为StandardMultipartHttpServletRequest并准备好需要的信息
在StandardMultipartHttpServletRequest的构造过程中准备信息
Controller和拦截器
继续mappedHandler = getHandler(processedRequest); 获取到HandlerExecutionChain,这个chain包含1个handler和HandlerInterceptor list
可以看到其中的handler是我们Controller的Mapping方法,而interceptorList是HandlerInterceptor类型的拦截器,上面的拦截器则是默认的,我们自定义的也会加入进去
继续mappedHandler.applyPreHandle
将处理HandlerInterceptor的preHandle方法
继续mv = ha.handle(processedRequest, response, mappedHandler.getHandler());开始进行Controller方法的调用
这里所创建的invocableMethod与原handlerMethod进行了一些字段引用赋值,基本可以视为不变
继续invocableMethod.invokeAndHandle
这里getMethodArgumentValues会把Controller方法需要的参数提取与验证
参数验证使用不同参数类型对应的HandlerMethodArgumentResolver
例如AbstractNamedValueMethodArgumentResolver验证必须的参数不通过将抛出MissingServletRequestParameterException等异常
之后就执行Controller方法
执行后回到doDispatch方法,接下来开始执行mappedHandler.applyPostHandle
最后执行mappedHandler.triggerAfterCompletion
结束主要流程
异常处理器
下面再看下当发生异常时(参数验证异常、Controller方法异常等)是如何处理的,我们回到doDispatch方法,来看其中的processDispatchResult方法
上面的handlerExceptionResolvers默认有2个,DefaultErrorAttribute、HandlerExceptionResolverComposite
来看HandlerExceptionResolverComposite
这里的resolvers默认有3个ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolver
第一个是ExceptionHandlerExceptionResolver,如果我们自定义了ExceptionHandler且支持处理对应的异常,则会调用对应的方法进行异常处理
第二个是ResponseStatusExceptionResolver,如果异常类型是ResponseStatusException或异常上有@ResponseStatus注解,则将被它处理,通过response写入对应的http状态码
第三个是DefaultHandlerExceptionResolver,属于兜底的处理方式,响应错误信息