@RestController和@Controller注解
咱们都晓得RestController默认都只提供Rest格调接口返回值,针对不须要返回页面的Controller都采纳RestController进行注解,上面依据源码简略剖析一下两者解决上的区别。
@RestController
源码如下。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Controller@ResponseBodypublic @interface RestController { /** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any * @since 4.0.1 */ String value() default "";}
@RestController
的编写形式依赖注解组合,@RestController
被@Controller
和@ResponseBody
标注,示意@RestController
具备两者的注解语义,因而在注解解决时@RestController
比@Controller
多具备一个@ResponseBody
语义,这就是@RestController
和@Controller
的区别,也是@RestController
的返回值为何都是通过转换的json的起因。
所以小结就是:@RestController = @Controller + @ResponseBody;
@ResponseBody注解的处理过程
既然晓得@RestController
与@Controller
的区别是多了一个@ResponseBody
语义,咱们无妨理解一下@ResponseBody
的处理过程。
首先,能够晓得,@ResponseBody
是一个针对办法返回值进行解决的注解。如果相熟Spring MVC处理过程的话,能够晓得在依据requesturl
映射获取到HandlerMethod
之后,依据HandlerMethod
调度申请办法的对象是HandlerAdapter
,办法调用完结,返回值解决的调度对象也是HandlerAdapter
。所以,@ResponseBody
注解的解决应该也是在HandlerAdapter
中实现。
在RequestMappingHandlerAdapter#invokeHandlerMethod
办法外面,有上面几句比拟重要的代码
//创立办法调用对象ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);//......//设置返回值处理器invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);//......//调用办法invocableMethod.invokeAndHandle(webRequest, mavContainer);
returnValueHandlers
这个变量听名字就像返回值解决,实际上也是对返回值解决的处理器汇合。首先创立一个调用办法的对象,而后注入处理器,最初调用办法,这就是残缺的一个流程。
咱们能够再剖析一下这外面的处理器初始化时有没有咱们的针对@ResponseBody
注解的处理器。
@ResponseBody注解处理器初始化
搜寻一下returnValueHandlers
初始化的中央,能够看到是这么个调用链:
RequestMappingHandlerAdapter#afterPropertiesSet
handlers = RequestMappingHandlerAdapter#getDefaultReturnValueHandlers
returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers)
所以是在RequestMappingHandlerAdapter
的bean初始化实现时,就会进行返回值处理器的初始化,在RequestMappingHandlerAdapter#getDefaultReturnValueHandlers
办法外部执行,代码如下。
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() { List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>(); // Single-purpose return value types handlers.add(new ModelAndViewMethodReturnValueHandler()); handlers.add(new ModelMethodProcessor()); handlers.add(new ViewMethodReturnValueHandler()); handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters())); handlers.add(new StreamingResponseBodyReturnValueHandler()); 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 handlers.add(new ModelAttributeMethodProcessor(false)); //@ResponseBody注解处理器 handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice)); // Multi-purpose return value types handlers.add(new ViewNameMethodReturnValueHandler()); handlers.add(new MapMethodProcessor()); // Custom return value types if (getCustomReturnValueHandlers() != null) { handlers.addAll(getCustomReturnValueHandlers()); } // Catch-all if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) { handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers())); } else { handlers.add(new ModelAttributeMethodProcessor(true)); } return handlers;}
能够看到十分对处理器,RequestResponseBodyMethodProcessor
就是@ResponseBody
的处理器。
@ResponseBody注解处理器调用
进入调用办法invocableMethod.invokeAndHandle(webRequest, mavContainer)/ServletInvocableHandlerMethod#invokeAndHandle
,持续进行调用,跟踪调用链如下。
ServletInvocableHandlerMethod#invokeAndHandle
this.returnValueHandlers.handleReturnValue/HandlerMethodReturnValueHandlerComposite#handleReturnValue
HandlerMethodReturnValueHandlerComposite#handleReturnValue
代码如下所示。
public void handleReturnValue(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);}
so,根本就是从所有处理器中选出指标处理器,解决返回值。进入HandlerMethodReturnValueHandlerComposite#selectHandler
private HandlerMethodReturnValueHandler selectHandler(Object value, MethodParameter returnType) { boolean isAsyncValue = isAsyncReturnValue(value, returnType); for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue; } //判断处理器是否反对 if (handler.supportsReturnType(returnType)) { return handler; } } return null;}
RequestResponseBodyMethodProcessor#supportsReturnType
,代码如下。
public boolean supportsReturnType(MethodParameter returnType) { return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) || returnType.hasMethodAnnotation(ResponseBody.class));}
显著如果类上有@ResponseBody
或者办法上有的话,就能适配处理器,@RestController
具备@ResponseBody
语义可能适配,所以进行RequestResponseBodyMethodProcessor#handleReturnValue
进行返回值解决。
发表回复