版本说明
jdk
:1.8.0_131
springboot
:2.1.6.RELEAS
maven
:3.6.1
database
:mysql-5.7.14
lombok插件
源码分析
仅仅针对被@ControllerAdvice
注解的且实现接口ResponseBodyAdvice
的类,进行源码分析,了解一下当controller
中被@ResponseBody
注解的方法的返回值,是如何被解析成前端需要的值的。 至于RequestBodyAdvice
和@ExceptionHandler
等实现原理是差不多的。
根据Spring自定义ReturnValueHandlers中的分析,我们了解了实际调用controller
类中的被@ResponseBody
注解方法时,实际使用RequestResponseBodyMethodProcessor
处理器去处理。
我们查看下RequestResponseBodyMethodProcessor
的handleReturnValue
1 |
|
writeWithMessageConverters
节选片段
1 | if (selectedMediaType != null) { |
this.messageConverters
的循环调用,其实就是用合适的HttpMessageConverter
来解析返回报文,默认情况下我们用的就是SpringBoot
内容的MappingJackson2HttpMessageConverter
处理器
MappingJackson2HttpMessageConverter
的canWrite
就是查看MediaType
是否满足
1 | protected boolean canWrite(@Nullable MediaType mediaType) { |
重点的是getAdvice()
的加载
1 | RequestResponseBodyAdviceChain getAdvice() { |
用Debug
模式一步步回溯最终发现RequestMappingHandlerAdapter
中
1 | public void afterPropertiesSet() { |
节选initControllerAdviceCache
1 | List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); |
节选方法getDefaultArgumentResolvers
细节
1 | resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); |
RequestResponseBodyMethodProcessor
构造方法最终指向父类AbstractMessageConverterMethodArgumentResolver
,那么我们看到@ControllerAdvice
注解的且实现接口ResponseBodyAdvice
的类被加载到this.advice
中
1 | public AbstractMessageConverterMethodArgumentResolver(List<HttpMessageConverter<?>> converters, |
那么我们看下this.advice
的类RequestResponseBodyAdviceChain
方法beforeBodyWrite
细节
1 |
|
最后贴下@ControllerAdvice
实现类
1 | package com.li.springboot.controller; |