SpringMVC源码系列文章
SpringMVC源码解析(一):web容器启动流程
SpringMVC源码解析(二):请求执行流程
前文中我们介绍了SpringMVC容器的启动,包括前端控制器DispatcherServlet对象的创建,过滤器添加到Tomcat容器的过滤器集合中,将所有拦截器、跨域配置、消息转换器等配置统一添加到各自集合中,解析@RequestMapping注解生成请求路径和Controller方法的映射map。本章来研究下请求的执行过程。
说到请求过程,那么得先说下入口在哪里?入口肯定是统一分发请求给处理程序的DispatcherServlet,DispatcherServlet归根结底也是Servlet。Tomcat通过请求Mapping映射和Servelt对应关系找到Servelt,调用Servelt之前会执行过滤器链,所有过滤器放行才会走到Servelt真正的执行逻辑。
// 接受User对象并返回 @PostMapping("/test") @ResponseBody public User test(@RequestBody User user) { user.setName("李四"); System.out.println(user); return user; } 
DispatcherServelt重写的doPost方法就是入口了
本文就不讲过滤器的调用了,因为从DispatcherServelt开始,过滤器链已经执行完成,之前文章Tomcat源码解析(八):一个请求的执行流程(附Tomcat整体总结)有介绍过。
DispatcherServlet的类图如下:

从doPost到doDispatch方法
doPost方法是由DispatcherServelt的父类FrameworkServlet实现的processRequest(request, response)
doService(request, response)// FrameworkServlet类方法 protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; ... try { doService(request, response); } catch (ServletException | IOException ex) { failureCause = ex; throw ex; } catch (Throwable ex) { failureCause = ex; throw new NestedServletException("Request processing failed", ex); } finally { ... } } doDispatch(request, response)// DispatcherServlet类方法 @Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { // ... 设置一堆Attribute属性 try { doDispatch(request, response); } finally { ... } } 核心方法
doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; // 异步请求相关,以后单独篇章讲 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { // 判断是否上传请求,以后有机会单独将 processedRequest = checkMultipart(request); // 如果是上传请求,这个参数置为true,最后会去清理资源 multipartRequestParsed = (processedRequest != request); // 获取HandlerExcutionChain (内部包括Handler) mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { // 请求url找不到404就会走到这里 noHandlerFound(processedRequest, response); return; } // 获取适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // get请求缓存相关,以后有机会单独将 String method = request.getMethod(); boolean isGet = HttpMethod.GET.matches(method); if (isGet || HttpMethod.HEAD.matches(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } // 调用拦截器的前置方法preHandle if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // 执行handler方法 // 需要跳转页面这里才会返回ModelAndView对象,否则@ResponseBody返回对象这里返回null mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); // 调用拦截器的后置方法postHandle mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { //从4.3开始,我们也在处理处理程序方法抛出的错误, //使它们可用于@ExceptionHandler方法和其他场景。 dispatchException = new NestedServletException("Handler dispatch failed", err); } // 处理结果 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { // 调用拦截器请求处理完成后的回调triggerAfterCompletion triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { // 调用拦截器请求处理完成后的回调triggerAfterCompletion triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // 异步处理的回调 if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // 如果是上传请求,清理相关资源 if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } } 遍历所有的HandlerMapping,只要getHandler方法能获取到HandlerExecutionChain立即返回。
// DispatcherServlet类方法 @Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; } 如下这三个HandlerMapping是web容器启动时候加载的,上篇文章SpringMVC源码解析(一):web容器启动流程有具体介绍。三个轮流调用getHandler方法,而HandlerMapping也有顺序的,RequestMappingHanderMapping排序为0优先级最高,而它也是处理@RequestMapping注解的映射关系的映射器。

调用抽象类的方法,那么上面看到的三个HandlerMapping应该都会调用此方法,而这里肯定有一些核心的不同的方法实现在不同的HandlerMapping具体实现类中,典型的模板方法设计模式。
// AbstractHandlerMapping类方法 @Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 获取Handler Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // handler为bean的名称 // 这种Controller应该是实现Controler、HttpRequestHandler接口的方式 // 以前的老实现方式,暂不研究 if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } ... // 获取执行链(包括Handler和拦截器) HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); // ...打印日志 // 添加跨域设置(本身也是拦截器)到拦截器链中第一个位置 if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) { CorsConfiguration config = getCorsConfiguration(handler, request); if (getCorsConfigurationSource() != null) { CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request); config = (globalConfig != null ? globalConfig.combine(config) : config); } if (config != null) { config.validateAllowCredentials(); } executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; } // RequestMappingInfoHandlerMapping类方法 @Override @Nullable protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); try { // 核心方法调用父类的getHandlerInternal方法 return super.getHandlerInternal(request); } finally { ProducesRequestCondition.clearMediaTypesAttribute(request); } } 查找路径HandlerMethod// AbstractHandlerMethodMapping类方法 @Override @Nullable protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { // 通过request获取查找路径 String lookupPath = initLookupPath(request); this.mappingRegistry.acquireReadLock(); try { // 通过查找路径获取HandlerMethod HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } } uri,如图/springmvc/test,/springmvc为项目路径,/test为我们需要的查找路径
这个方法的核心内容就是从之前讲的SpringMVC源码解析(一):web容器启动流程注册的两个map获取数据。

// AbstractHandlerMethodMapping类方法 @Nullable protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List matches = new ArrayList<>(); // 通过查找路径获取RequestMappingInfo List directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath); if (directPathMatches != null) { // 通过RequestMappingInfo获取HandlerMethod addMatchingMappings(directPathMatches, matches, request); } ... if (!matches.isEmpty()) { Match bestMatch = matches.get(0); if (matches.size() > 1) { //...匹配多个,抛错异常 } request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod()); handleMatch(bestMatch.mapping, lookupPath, request); // 获取HandlerMethod并返回 return bestMatch.getHandlerMethod(); } else { return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request); } } 
我们自定义的拦截器统一用MappedInterceptor这个拦截器包装了一层,为了统一调用matcher方法,匹配此拦截器请求是否拦截本次请求,如果是则会添加到拦截器链中。
// AbstractHandlerMapping类方法 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { // 创建HandlerExecutionChain对象 HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); // 遍历所有的拦截器,这拦截器是web容器启动时候解析加载的的 for (HandlerInterceptor interceptor : this.adaptedInterceptors) { // 我们自定义的拦截器统一用MappedInterceptor这个拦截器包装了一层 // 为了统一的匹配方法,下面调用maches if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; // matcher匹配当前请求路径是否符合拦截器的拦截请求 if (mappedInterceptor.matches(request)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; } // 执行器链对象,主要就是两个属性handler:Handler对象,interceptorList:拦截器集合 public class HandlerExecutionChain { private final Object handler; private final List interceptorList = new ArrayList<>(); // 构造方法 public HandlerExecutionChain(Object handler) { this(handler, (HandlerInterceptor[]) null); } ... } 
看下HandlerAdapter接口
public interface HandlerAdapter { /** * 因为有多个HandlerMapping和HandlerAdapter * 对于HandlerAdapter是否支持对应的HandlerMapping,通过此方法判断 */ boolean supports(Object handler); /** * 具体调用Hangder的方法 */ @Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; } 因为不同的Hander(@RequestMapping、实现Controller接口、实现HttpRequestHandler接口)对应的HandlerAdapter(适配器)不一样,通过HandlerAdapter的supports方法判断当前HandlerAdapter是否支持此次请求的Hander。
// DispatcherServlet类方法 protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); } RequestMappingHandlerAdapter重写的supportsInternal返回true,表示其支持// AbstractHandlerMethodAdapter类方法 @Override public final boolean supports(Object handler) { return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); } // RequestMappingHandlerAdapter类方法 @Override protected boolean supportsInternal(HandlerMethod handlerMethod) { return true; } 由上面HandlerAdapter接口可以猜到,RequestMappingHandlerAdapter适配器就是我们需要的,之后会通过handle方法去执行Hangder方法即调用Controller#Method。
AbstractHandlerMethodAdapter类的handle方法即重写HandlerAdapter的handle方法,所有的HandlerAdapter执行Hangdler都会进入此方法,而具体的方法实现又要调用HandlerAdapter的实现类,如下,实现类就在RequestMappingHandlerAdapter类的handleInternal方法。
// AbstractHandlerMethodAdapter类方法 @Override @Nullable public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); } 解析请求,执行真正逻辑,解析响应
// ServletInvocableHandlerMethod类方法 public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 执行Handler并获取返回值 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); setResponseStatus(webRequest); if (returnValue == null) { if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) { disableContentCachingIfNecessary(webRequest); mavContainer.setRequestHandled(true); return; } } else if (StringUtils.hasText(getResponseStatusReason())) { mavContainer.setRequestHandled(true); return; } mavContainer.setRequestHandled(false); Assert.state(this.returnValueHandlers != null, "No return value handlers"); try { // 处理响应,返回对象转换响应信息,如对象转化为json this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { // 异常向上抛 throw ex; } } // InvocableHandlerMethod类方法,实现HandlerMethod接口 @Nullable public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 获取请求参数 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } // 执行真正逻辑 return doInvoke(args); } 拿到具体Controller的Method方法参数,遍历所有参数寻找支持每个参数类型的参数解析器,解析参数并返回。
// InvocableHandlerMethod类方法,实现HandlerMethod接口 protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 从HandlerMethod中获取参数信息 // 之前项目启动就加载了Handler,里面包含了具体要执行的Controller的Method MethodParameter[] parameters = getMethodParameters(); if (ObjectUtils.isEmpty(parameters)) { return EMPTY_ARGS; } // 遍历所有的参数 Object[] args = new Object[parameters.length]; for (int i = 0; i < parameters.length; i++) { MethodParameter parameter = parameters[i]; parameter.initParameterNameDiscovery(this.parameterNameDiscoverer); args[i] = findProvidedArgument(parameter, providedArgs); if (args[i] != null) { continue; } // 寻找支持当前参数类型的参数解析器 if (!this.resolvers.supportsParameter(parameter)) { throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")); } try { // 根据上一步获取的参数解析器解析参数并返回具体参数 args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory); } catch (Exception ex) { throw ex; } } return args; } 遍历所有的参数解析器,调用参数解析器的supportsParameter方法,返回true,表示此解析器可以解析当前参数类型,而且将方法的参数与解析器放入缓存argumentResolverCache,以后同一个接口调用第二次,参数解析器直接从缓存中获取就可以,不再需要遍历调用supportsParameter方法去筛选获取。
// HandlerMethodArgumentResolverComposite类方法 @Override public boolean supportsParameter(MethodParameter parameter) { return getArgumentResolver(parameter) != null; } @Nullable private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); if (result == null) { for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) { if (resolver.supportsParameter(parameter)) { result = resolver; this.argumentResolverCache.put(parameter, result); break; } } } return result; } HandlerMethodArgumentResolver argumentResolvers中一共有27个@RequestParam、@PathVariable等等@RequestBody注解参数解析器
@RequestBody即可// RequestResponseBodyMethodProcessor类方法 @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(RequestBody.class); } // HandlerMethodArgumentResolverComposite类方法 @Override @Nullable public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { // 获取参数解析器,此时上面已经筛查出来,放到argumentResolverCache缓存中 HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first."); } // 解析方法 return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); } RequestResponseBodyMethodProcessor的resolveArgument方法消息转换器获取请求参数@Validated注解的校验,以后单独将// RequestResponseBodyMethodProcessor类方法 @Override public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { parameter = parameter.nestedIfOptional(); // 获取参数对象 Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType()); String name = Conventions.getVariableNameForParameter(parameter); if (binderFactory != null) { WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name); if (arg != null) { // @Validated注解的校验 validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { throw new MethodArgumentNotValidException(parameter, binder.getBindingResult()); } } if (mavContainer != null) { mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); } } return adaptArgumentIfNecessary(arg, parameter); } @RequstBody的required属性是否为trueRequired request body is missing// RequestResponseBodyMethodProcessor类方法 @Override protected Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter, Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException { HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); Assert.state(servletRequest != null, "No HttpServletRequest"); ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest); // 进一步调用方法,通过消息转换器获取请求参数 Object arg = readWithMessageConverters(inputMessage, parameter, paramType); // 如果请求为空,检查@RequstBody是否为请求必须参数 if (arg == null && checkRequired(parameter)) { throw new HttpMessageNotReadableException("Required request body is missing: " + parameter.getExecutable().toGenericString(), inputMessage); } return arg; } // @requestBody注解required属性是否为true protected boolean checkRequired(MethodParameter parameter) { RequestBody requestBody = parameter.getParameterAnnotation(RequestBody.class); return (requestBody != null && requestBody.required() && !parameter.isOptional()); } 消息转换器接口
MediaType类:表示互联网中多媒体数据类型的格式;例如:text/html,text/plain,application/json…canRead方法:检查能否将请求信息转换为mediaType表示的数据类型,这个mediaType是前端页面请求时设定的contentType格式read方法:如果canRead方法返回值为true,则调用read方法将请求信息转换为T类型对象canWrite方法:检查clazz对象是否能转换为mediaType类型,此时的mediaType表示后端想要响应给前端的数据格式write方法:如果canWrite返回值为true,则将T类型的对象写到响应流中,同时指定mediaType类型
回到上面的readWithMessageConverters方法
ContentType媒体内容类型,肯定是application/json,默认application/octet-stream消息转换器,调用canRead方法筛选可以将请求信息转为指定的媒体类型contentType的转换器扩展点RequestBodyAdvice,可以对请求做一些修改,如加密拦截请求等等// AbstractMessageConverterMethodArgumentResolver类方法 @Nullable protected Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException { MediaType contentType; boolean noContentType = false; try { // 获取请求头ContentType contentType = inputMessage.getHeaders().getContentType(); } catch (InvalidMediaTypeException ex) { throw new HttpMediaTypeNotSupportedException(ex.getMessage()); } if (contentType == null) { noContentType = true; // 默认媒体类型 "application/octet-stream" contentType = MediaType.APPLICATION_OCTET_STREAM; } // 获取Controller的Class对象 Class> contextClass = parameter.getContainingClass(); // 获取方法参数的Class对象 Class targetClass = (targetType instanceof Class ? (Class) targetType : null); if (targetClass == null) { ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter); targetClass = (Class) resolvableType.resolve(); } HttpMethod httpMethod = (inputMessage instanceof HttpRequest ? ((HttpRequest) inputMessage).getMethod() : null); Object body = NO_VALUE; EmptyBodyCheckingHttpInputMessage message = null; try { message = new EmptyBodyCheckingHttpInputMessage(inputMessage); // 遍历所有的消息转换器 for (HttpMessageConverter> converter : this.messageConverters) { Class> converterType = (Class>) converter.getClass(); GenericHttpMessageConverter> genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter>) converter : null); // 调用canRead方法,筛选每个消息过滤器是否能将请求信息转为指定的媒体类型contentType if (genericConverter != null ? genericConverter.canRead(targetType, contextClass, contentType) : (targetClass != null && converter.canRead(targetClass, contentType))) { if (message.hasBody()) { // 获取请求增强器并调用beforeBodyRead方法 HttpInputMessage msgToUse = getAdvice().beforeBodyRead(message, parameter, targetType, converterType); // 消息转换器真正将请求信息转为参数对象的方法 body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) : ((HttpMessageConverter) converter).read(targetClass, msgToUse)); // 获取请求增强器并调用afterBodyRead方法 body = getAdvice().afterBodyRead(body, msgToUse, parameter, targetType, converterType); } else { body = getAdvice().handleEmptyBody(null, message, parameter, targetType, converterType); } break; } } } catch (IOException ex) { throw new HttpMessageNotReadableException("I/O error while reading input message", ex, inputMessage); } ... return body; } MappingJackson2HttpMessageConverter
genericConverter.canRead
筛选方法
// AbstractJackson2HttpMessageConverter类方法 @Override public boolean canRead(Type type, @Nullable Class> contextClass, @Nullable MediaType mediaType) { // 判断是否支持传入的mediaType if (!canRead(mediaType)) { return false; } JavaType javaType = getJavaType(type, contextClass); ObjectMapper objectMapper = selectObjectMapper(javaType.getRawClass(), mediaType); if (objectMapper == null) { return false; } AtomicReference causeRef = new AtomicReference<>(); // 判断类能否反序列化,并将错误记录到causeRef中,下面会打印 if (objectMapper.canDeserialize(javaType, causeRef)) { return true; } // 打印causeRef,不能反序列化的错误 logWarningIfNecessary(javaType, causeRef.get()); return false; } genericConverter.read
json反序列化为对象方法
// AbstractJackson2HttpMessageConverter类方法 @Override public Object read(Type type, @Nullable Class> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { JavaType javaType = getJavaType(type, contextClass); return readJavaType(javaType, inputMessage); } 
上篇文章SpringMVC源码解析(一):web容器启动流程介绍过,类上有@ControllerAdvice注解且实现RequestBodyAdvice接口的即为RequestBodyAdvice增强器,主要就是在请求信息转换为参数对象的前后做一些扩展处理。
RequestBodyAdvice请求增强器
public interface RequestBodyAdvice { // 是否支持,自定义判断条件,如包含某个自定义注解等等 // 该方法返回true时,才会进去下面的beforeBodyRead方法 boolean supports(MethodParameter methodParameter, Type targetType, Class extends HttpMessageConverter>> converterType); // 请求体解析前处理,一般在此方法中对body数据进行修改 HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType) throws IOException; // 请求体解析后处理,一般直接返回原实例 Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType); // 当body为empty时操作(body什么都不传才算,即使{}也不算空) @Nullable Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType); } 回到上面的getAdvice().beforeBodyRead方法
beforeBodyRead方法`对请求信息做处理// RequestResponseBodyAdviceChain类方法 @Override public HttpInputMessage beforeBodyRead(HttpInputMessage request, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType) throws IOException { // 获取所有请求增强器 for (RequestBodyAdvice advice : getMatchingAdvice(parameter, RequestBodyAdvice.class)) { if (advice.supports(parameter, targetType, converterType)) { request = advice.beforeBodyRead(request, parameter, targetType, converterType); } } return request; } getAdvice().afterBodyRead方法
参数对象做一些扩展处理了afterBodyRead处理// RequestResponseBodyAdviceChain类方法 @Override public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType) { for (RequestBodyAdvice advice : getMatchingAdvice(parameter, RequestBodyAdvice.class)) { if (advice.supports(parameter, targetType, converterType)) { body = advice.afterBodyRead(body, inputMessage, parameter, targetType, converterType); } } return body; } getAdvice().handleEmptyBody方法
// RequestResponseBodyAdviceChain类方法 @Override @Nullable public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType) { for (RequestBodyAdvice advice : getMatchingAdvice(parameter, RequestBodyAdvice.class)) { if (advice.supports(parameter, targetType, converterType)) { body = advice.handleEmptyBody(body, inputMessage, parameter, targetType, converterType); } } return body; } method.invoke(obj,args)标准反射调用方法// InvocableHandlerMethod类方法 @Nullable protected Object doInvoke(Object... args) throws Exception { Method method = getBridgedMethod(); try { if (KotlinDetector.isSuspendingFunction(method)) { return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args); } // 反射调用方法 return method.invoke(getBean(), args); } catch (IllegalArgumentException ex) { ... } } handleReturnValue处理方法// HandlerMethodReturnValueHandlerComposite类方法 @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // 获取方法返回值处理器 HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType); if (handler == null) { throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName()); } // 处理方法 handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); } supportsReturnType方法筛选// HandlerMethodReturnValueHandlerComposite类方法 @Nullable private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) { boolean isAsyncValue = isAsyncReturnValue(value, returnType); // 遍历所有的返回值处理器 for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { // 排除异步处理器,不用管 if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue; } // 通过调用处理器的supportsReturnType方法筛选 if (handler.supportsReturnType(returnType)) { return handler; } } return null; } 
查看
RequestResponseBodyMethodProcessor的筛选方法handleReturnValue
方法或类上包含注解@ResponseBody即可@Override public boolean supportsReturnType(MethodParameter returnType) { return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) || returnType.hasMethodAnnotation(ResponseBody.class)); } // RequestResponseBodyMethodProcessor类方法 @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true); ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); // 即使返回值为空,也要尝试。ResponseBodyAdvice可能会参与其中。 writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); } 
这里用的消息转换器与获取请求参数里的转换器一样,都是MappingJackson2HttpMessageConverter。之前转化器是需要将请求信息body里的json字符串转换(反序列化)为对象;这里的转换器是将对象转换(序列化)对json字符串。
genericConverter.canWrite
筛选方法
// AbstractGenericHttpMessageConverter类方法 @Override public boolean canWrite(@Nullable Type type, Class> clazz, @Nullable MediaType mediaType) { return canWrite(clazz, mediaType); } // AbstractJackson2HttpMessageConverter类方法 @Override public boolean canWrite(Class> clazz, @Nullable MediaType mediaType) { // 判断是否支持传入的mediaType if (!canWrite(mediaType)) { return false; } if (mediaType != null && mediaType.getCharset() != null) { Charset charset = mediaType.getCharset(); if (!ENCODINGS.containsKey(charset.name())) { return false; } } ObjectMapper objectMapper = selectObjectMapper(clazz, mediaType); if (objectMapper == null) { return false; } AtomicReference causeRef = new AtomicReference<>(); // 判断对象是否能序列化为json字符串,并将错误记录到causeRef中,下面会打印 if (objectMapper.canSerialize(clazz, causeRef)) { return true; } // 打印causeRef,不能序列化的错误 logWarningIfNecessary(clazz, causeRef.get()); return false; } genericConverter.write
对象序列化为json方法
// AbstractGenericHttpMessageConverter类方法 @Override public final void write(final T t, @Nullable final Type type, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { // 设置默认请求头 final HttpHeaders headers = outputMessage.getHeaders(); addDefaultHeaders(headers, t, contentType); if (outputMessage instanceof StreamingHttpOutputMessage) { StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage; streamingOutputMessage.setBody(outputStream -> writeInternal(t, type, new HttpOutputMessage() { @Override public OutputStream getBody() { return outputStream; } @Override public HttpHeaders getHeaders() { return headers; } })); } else { // jackson序列化方法 writeInternal(t, type, outputMessage); outputMessage.getBody().flush(); } } 输出流中
上篇文章SpringMVC源码解析(一):web容器启动流程介绍过,类上有@ControllerAdvice注解且实现ResponseBodyAdvice接口的即为ResponseBodyAdvice增强器,主要就是在返回对象转换响应信息前做一些扩展处理。
ResponseBodyAdvice响应增强器
public interface ResponseBodyAdvice { // 是否支持,自定义判断条件 // 该方法返回true时,才会进去下面的 beforeBodyWrite方法 boolean supports(MethodParameter returnType, Class extends HttpMessageConverter>> converterType); // 响应写入之前调用 @Nullable T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType, Class extends HttpMessageConverter>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response); } 回到上面的getAdvice().beforeBodyWrite方法
supports方法筛选支持的增强,然后调用增强方法beforeBodyWritebody即为方法返回值,还没有序列化,我们可以对返回值做扩展处理了// RequestResponseBodyAdviceChain类方法 @Override @Nullable public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType contentType, Class extends HttpMessageConverter>> converterType, ServerHttpRequest request, ServerHttpResponse response) { return processBody(body, returnType, contentType, converterType, request, response); } @Nullable private Object processBody(@Nullable Object body, MethodParameter returnType, MediaType contentType, Class extends HttpMessageConverter>> converterType, ServerHttpRequest request, ServerHttpResponse response) { // 遍历所有的响应增强器,调用supports方法,筛选支持的增强器 for (ResponseBodyAdvice> advice : getMatchingAdvice(returnType, ResponseBodyAdvice.class)) { if (advice.supports(returnType, converterType)) { body = ((ResponseBodyAdvice) advice).beforeBodyWrite((T) body, returnType, contentType, converterType, request, response); } } return body; } 执行器链HandlerExecutionChain里面就包含了拦截器集合,如下// 执行器链对象,主要就是两个属性handler:Handler对象,interceptorList:拦截器集合 public class HandlerExecutionChain { private final Object handler; private final List interceptorList = new ArrayList<>(); // 构造方法 public HandlerExecutionChain(Object handler) { this(handler, (HandlerInterceptor[]) null); } ... } 拦截器接口
public interface HandlerInterceptor { /** * 执行处理程序之前的拦截点 */ default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } /** * 成功执行处理程序后的拦截点 */ default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { } /** * 请求处理完成后的回调,即渲染视图后 */ default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { } } 前后最后必执行
preHandle方法afterCompletion,并且Handler都不再执行,直接返回// HandlerExecutionChain类方法 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { for (int i = 0; i < this.interceptorList.size(); i++) { // 遍历所有的拦截器,调用preHandle方法 HandlerInterceptor interceptor = this.interceptorList.get(i); if (!interceptor.preHandle(request, response, this.handler)) { triggerAfterCompletion(request, response, null); return false; } // 拦截器集合索引下标记录 this.interceptorIndex = i; } return true; } 倒序遍历执行postHandle方法// HandlerExecutionChain类方法 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { for (int i = this.interceptorList.size() - 1; i >= 0; i--) { HandlerInterceptor interceptor = this.interceptorList.get(i); interceptor.postHandle(request, response, this.handler, mv); } } 倒序调用afterCompletion方法void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) { for (int i = this.interceptorIndex; i >= 0; i--) { HandlerInterceptor interceptor = this.interceptorList.get(i); try { interceptor.afterCompletion(request, response, this.handler, ex); } catch (Throwable ex2) { logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); } } } 一般来说拦截器preHandle的方法会返回true(表示放行),那么对于拦截器三个方法执行顺序即为:123 321 321
之前文章SpringMVC源码解析(一):web容器启动流程有介绍,筛选异常处理器即类上@ControllerAdvice,方法上@ExceptionHandler。
@ControllerAdvice public class ExceptionController { @ExceptionHandler(value = {Exception.class}) @ResponseBody public ResponseEntity exceptionHandler(Exception e) { return ResponseEntity.status(500).body("系统异常"); } } 
// DispatcherServlet类方法 private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { boolean errorView = false; if (exception != null) { if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); } else { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); // 执行异常处理器 mv = processHandlerException(request, response, handler, exception); errorView = (mv != null); } } ... // 执行拦截器的最终处理 if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } } resolveException方法,返回结果不为null,即跳出循环直接返回@Nullable protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) throws Exception { ... // 遍历异常处理器 ModelAndView exMv = null; if (this.handlerExceptionResolvers != null) { for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) { exMv = resolver.resolveException(request, response, handler, ex); if (exMv != null) { break; } } } // 最后抛出异常 throw ex; } JavaWeb是每一个业务逻辑就需要构建一个Servelt,Tomcat解析请求也是通过请求路径映射找到对于的Servelt程序。而SpringMVC只构建一个Servelt,那就是DispatcherServlet,这里Servelt接收所有的请求,然后再根据请求路径分发出去找到对于的Controller方法。
uri获取@RequestMapping注解映射的路径@Controller#Method @RequestMapping对应关系添加到map集合中 定义Handler的方式有很多,早期有实现Controller、HttpRequestHandler接口,现在常用的@Controller方式,不同的Handler方式生成请求和Handler的映射的方法就不同,这时候抽象出来HandlerMapping(根据request请求匹配/映射上能够处理当前request的Handler),上面说的获取执行器链获取Handler就是专门处理@Controller的HandlerMapping,这样就出现了不同实现的HandlerMapping。
不同Handler调用具体实现逻辑的方法也不同,@Controller方式直接调用记录的类的Method即可,而其他实现接口的方式这是调用此接口实现类的重写handleRequest方法,这时候抽象出来HandlerAdapter,不同HandlerAdapter处理不同Handler。
@RequestBody、@RequestParam、@PathVariable注解SpringMVC都内置的参数解析器jackson和fastjson转换器json字符串反序列化为java对象请求增强器RequestponseBodyAdvice,可以对转换前的body和转换后的对象做扩展处理@ResponseBody的,使用消息转换器将java对象序列化为json字符串(以后会传给前端)响应增强器ResponseBodyAdvice,可以对方法返回值做扩展处理再序列化前后及最后无论是否抛异常都会执行的三个位置,都可以做扩展处理