一个 HTTP 请求进到 Spring MVC 之后到底经过哪些环节?Filter、Interceptor、参数解析、返回值处理各在什么时候?抛异常和 404、405 又是怎么走的?这篇用 Spring Boot 4.0.8 的 Spring MVC 7.0.9,把每个扩展点的调用顺序逐个记下来。
DispatcherServlet 是容器里的一个 Bean:DispatcherServlet;参数 detectAllHandlerMappings 默认由 Spring 决定
HandlerMapping(按顺序):[RouterFunctionMapping, RequestMappingHandlerMapping, WelcomePageHandlerMapping, BeanNameUrlHandlerMapping, WelcomePageNotAcceptableHandlerMapping, SimpleUrlHandlerMapping]
HandlerAdapter(按顺序):[RequestMappingHandlerAdapter, HandlerFunctionAdapter, HttpRequestHandlerAdapter, SimpleControllerHandlerAdapter]
HandlerExceptionResolver(按顺序):[DefaultErrorAttributes, HandlerExceptionResolverComposite]
RequestMappingHandlerAdapter 的参数解析器 29 个,返回值处理器 15 个,消息转换器 6 个:[ByteArray, String, Resource, ResourceRegion, AllEncompassingForm, JacksonJson]
RequestMappingHandlerMapping 登记的处理方法 5 个(含 Boot 自带的 /error):[{ [/error], produces [text/html]}, { [/error]}, {GET [/boom]}, {GET [/hello/{name}]}, {POST [/only-post]}]DispatcherServlet 背后有 6 个 HandlerMapping、4 个 HandlerAdapter 和一长串解析器。
响应:200 {"hi":"spring"}
① Filter 进入 GET /hello/spring
③ Interceptor.preHandle,handler 类型 = HandlerMethod(hello)
④ 自定义 HandlerMethodArgumentResolver 解析 Trace 参数
Controller 方法 hello(spring,Trace[id=t-1])
⑥ ResponseBodyAdvice.beforeBodyWrite,将用 JacksonJsonHttpMessageConverter 写出
⑧ Interceptor.postHandle
⑨ Interceptor.afterCompletion,异常 = 无
⑩ Filter 返回,状态码 200Filter 包住拦截器,拦截器包住控制器方法,返回值经过 ResponseBodyAdvice 和消息转换器写出。
响应:500 handled ① Filter 进入 GET /boom ③ Interceptor.preHandle,handler 类型 = HandlerMethod(boom) ⑦′ @ExceptionHandler 处理 IllegalStateException ⑥ ResponseBodyAdvice.beforeBodyWrite,将用 StringHttpMessageConverter 写出 ⑨ Interceptor.afterCompletion,异常 = 无 ⑩ Filter 返回,状态码 500
异常由 @ExceptionHandler 处理,没有 postHandle,afterCompletion 照常调用。
GET /nope → 404:① Filter 进入 GET /nope | ③ Interceptor.preHandle,handler 类型 = ResourceHttpRequestHandler | ⑨ Interceptor.afterCompletion,异常 = 无 | ⑩ Filter 返回,状态码 404 | ③ Interceptor.preHandle,handler 类型 = HandlerMethod(error) | ⑥ ResponseBodyAdvice.beforeBodyWrite,将用 JacksonJsonHttpMessageConverter 写出 | ⑧ Interceptor.postHandle | ⑨ Interceptor.afterCompletion,异常 = 无 GET /only-post → 405:① Filter 进入 GET /only-post | ⑩ Filter 返回,状态码 405 | ③ Interceptor.preHandle,handler 类型 = HandlerMethod(error) | ⑥ ResponseBodyAdvice.beforeBodyWrite,将用 JacksonJsonHttpMessageConverter 写出 | ⑧ Interceptor.postHandle | ⑨ Interceptor.afterCompletion,异常 = 无
404 由静态资源处理器兜底再转 /error,405 没有处理器,拦截器在错误派发里再走一遍。