getDefaultArgumentResolvers()
这个步骤作用是初始化HandlerMethodArgumentResolver
,提供对方法参数的支持。也就是@RequestMapping
的handler上能写哪些注解自动封装参数,是由这里决定的。
RequestMappingHandlerAdapter: // Return the list of argument resolvers to use including built-in resolvers and custom resolvers provided via {@link #setCustomArgumentResolvers}. // 返回内建的参数处理器们,以及用户自定义的一些参数处理器(注意顺序) private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() { List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(); // Annotation-based argument resolution // 基于注解的 resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); resolvers.add(new RequestParamMapMethodArgumentResolver()); resolvers.add(new PathVariableMethodArgumentResolver()); resolvers.add(new PathVariableMapMethodArgumentResolver()); resolvers.add(new MatrixVariableMethodArgumentResolver()); resolvers.add(new MatrixVariableMapMethodArgumentResolver()); resolvers.add(new ServletModelAttributeMethodProcessor(false)); resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory())); resolvers.add(new RequestHeaderMapMethodArgumentResolver()); resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver()); resolvers.add(new RequestAttributeMethodArgumentResolver()); // Type-based argument resolution // 基于type类型的 resolvers.add(new ServletRequestMethodArgumentResolver()); resolvers.add(new ServletResponseMethodArgumentResolver()); resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RedirectAttributesMethodArgumentResolver()); resolvers.add(new ModelMethodProcessor()); resolvers.add(new MapMethodProcessor()); resolvers.add(new ErrorsMethodArgumentResolver()); resolvers.add(new SessionStatusMethodArgumentResolver()); resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); // Custom arguments // 用户自定义的 if (getCustomArgumentResolvers() != null) { resolvers.addAll(getCustomArgumentResolvers()); } // Catch-all // 兜底方案:这就是为何很多时候不写注解参数也能够被自动封装的原因 resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true)); resolvers.add(new ServletModelAttributeMethodProcessor(true)); return resolvers; }
这里使用的是ArrayList保存的,所以处理器都是有序的。最终会放进HandlerMethodArgumentResolverComposite使用Composite模式统一管理和使用~
关于参数解析器HandlerMethodArgumentResolver的系列文章,你可以从这里开始
getDefaultInitBinderArgumentResolvers()
这一步和上面非常相似,也是对方法参数的处理,不过它针对的是@InitBinder这个注解标注的方法。可简单理解为它是@RequestMapping的阉割版:支持的参数类型、注解都没那么多,支持内容如下:
RequestMappingHandlerAdapter: private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() { List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(); // Annotation-based argument resolution resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); resolvers.add(new RequestParamMapMethodArgumentResolver()); resolvers.add(new PathVariableMethodArgumentResolver()); resolvers.add(new PathVariableMapMethodArgumentResolver()); resolvers.add(new MatrixVariableMethodArgumentResolver()); resolvers.add(new MatrixVariableMapMethodArgumentResolver()); resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver()); resolvers.add(new RequestAttributeMethodArgumentResolver()); // Type-based argument resolution resolvers.add(new ServletRequestMethodArgumentResolver()); resolvers.add(new ServletResponseMethodArgumentResolver()); // Custom arguments if (getCustomArgumentResolvers() != null) { resolvers.addAll(getCustomArgumentResolvers()); } // Catch-all resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true)); return resolvers; }
从此处可以看到它具体支持哪些参数,像什么@RequestParam/@PathVariable/ServletRequest...等等都是支持的,但像什么@ModelAttribute/@RequestBody/@RequestPart等等这些它就不支持了(没这必要嘛)。
关于参数解析器@InitBinder的系列文章,你可以从这里开始
getDefaultReturnValueHandlers()
顾名思义,它是提供对HandlerMethod返回值的支持(比如@ResponseBody、DeferredResult等返回值类型)。多个返回值处理器最终使用的是HandlerMethodReturnValueHandlerComposite模式管理和使用。
RequestMappingHandlerAdapter: private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() { List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(); // Single-purpose return value types handlers.add(new ModelAndViewMethodReturnValueHandler()); handlers.add(new ModelMethodProcessor()); handlers.add(new ViewMethodReturnValueHandler()); // 返回值是ResponseBodyEmitter时候,得用reactiveAdapterRegistry看看是Reactive模式还是普通模式 // taskExecutor:异步时使用的线程池,使用当前类的 contentNegotiationManager:内容协商管理器 handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(), this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager)); handlers.add(new StreamingResponseBodyReturnValueHandler()); // 此处重要的是getMessageConverters()消息转换器,一般情况下Spring MVC默认会有8个,包括`MappingJackson2HttpMessageConverter` // 参见:WebMvcConfigurationSupport定的@Bean --> RequestMappingHandlerAdapter部分 // 若不@EnableWebMvc默认是只有4个消息转换器的哦~(不支持json) // 此处的requestResponseBodyAdvice会介入到请求和响应的body里(消息转换期间) handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice)); handlers.add(new HttpHeadersReturnValueHandler()); handlers.add(new CallableMethodReturnValueHandler()); handlers.add(new DeferredResultMethodReturnValueHandler()); handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory)); // Annotation-based return value types // 当标注有@ModelAttribute或者@ResponseBody的时候 这里来处理。显然也用到了消息转换器~ handlers.add(new ModelAttributeMethodProcessor(false)); handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice)); // Multi-purpose return value types // 当返回的是个字符串/Map时候,这时候就可能有多个目的了(Multi-purpose) // 比如字符串:可能重定向redirect、或者直接到某个view handlers.add(new ViewNameMethodReturnValueHandler()); handlers.add(new MapMethodProcessor()); // Custom return value types // 自定义的返回值处理器 if (getCustomReturnValueHandlers() != null) { handlers.addAll(getCustomReturnValueHandlers()); } // Catch-all // 兜底:ModelAndViewResolver是需要你自己实现然后set进来的(一般我们不会自定定义) // 所以绝大部分情况兜底使用的是ModelAttributeMethodProcessor表示,即使你的返回值里木有标注@ModelAttribute // 但你是非简单类型(比如对象类型)的话,返回值都会放进Model里 if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) { handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers())); } else { handlers.add(new ModelAttributeMethodProcessor(true)); } return handlers; }
关于参数解析器HandlerMethodReturnValueHandler的系列文章,你可以从这里开始
这个步骤完成后,整个RequestMappingHandlerAdapter的初始化就全部完成了。当然它还有一些属性、方法等都没有讲述到,下面做出集中式的统一说明:
其它重要属性、方法
属性:
RequestMappingHandlerAdapter: // ModelAndViewResolver木有内置实现,可自定义实现来参与到返回值到ModelAndView的过程(自定义返回值处理) // 一般不怎么使用,我个人也不太推荐使用 @Nullable private List<ModelAndViewResolver> modelAndViewResolvers; // 内容协商管理器 默认就是它喽(使用的协商策略是HeaderContentNegotiationStrategy) private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager(); // 消息转换器。使用@Bean定义的时候,记得set进来,否则默认只会有4个(不支持json) // 若@EnableWebMvc后默认是有8个的,一般都够用了 private List<HttpMessageConverter<?>> messageConverters; // 它在数据绑定初始化的时候会被使用到,调用其initBinder()方法 // 只不过,现在一般都使用@InitBinder注解来处理了,所以使用较少 // 说明:它作用域是全局的,对所有的HandlerMethod都生效~~~~~ @Nullable private WebBindingInitializer webBindingInitializer; // 默认使用的SimpleAsyncTaskExecutor:每次执行客户提交给它的任务时,它会启动新的线程 // 并允许开发者控制并发线程的上限(concurrencyLimit),从而起到一定的资源节流作用(默认值是-1,表示不限流) // @EnableWebMvc时可通过复写接口的WebMvcConfigurer.getTaskExecutor()自定义提供一个线程池 private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync"); // invokeHandlerMethod()执行目标方法时若需要异步执行,超时时间可自定义(默认不超时) // 使用上面的taskExecutor以及下面的callableInterceptors/deferredResultInterceptors参与异步的执行 @Nullable private Long asyncRequestTimeout; private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0]; private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0]; // @Since 5.0 private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); // 对应ModelAndViewContainer.setIgnoreDefaultModelOnRedirect()属性 // redirect时,是否忽略defaultModel 默认值是false:不忽略 private boolean ignoreDefaultModelOnRedirect = false; // 返回内容缓存多久(默认不缓存) 参考类:WebContentGenerator private int cacheSecondsForSessionAttributeHandlers = 0; // 执行目标方法HandlerMethod时是否要在同一个Session内同步执行??? // 也就是同一个会话时,控制器方法全部同步执行(加互斥锁) // 使用场景:对同一用户同一Session的所有访问,必须串行化~~~~~~ private boolean synchronizeOnSession = false; private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); @Nullable private ConfigurableBeanFactory beanFactory; // ====================下面是各种缓存们==================== private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64); private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64); private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>(); private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64); private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>();