关于java:深入分析-RestController-与-Controller-的区别你真的了解吗

3次阅读

共计 5638 个字符,预计需要花费 15 分钟才能阅读完成。

@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 进行返回值解决。

正文完
 0