版本说明
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; |