AsyncHandlerMethodReturnValueHandler
它是一个子接口,增加了一个方法。这个接口是Spring4.2提供的,挺有意思的一个接口,Spring内部并没有提供任何实现。
// @since 4.2 // 支持异步类型的返回值处理程序。此类返回值类型需要优先处理,以便异步值可以“展开”。 // 异步实现此接口并不是必须的,但是若你需要在处理程序之前执行,就需要实现这个接口了~~~ // 因为默认情况下:我们自定义的Handler它都是在内置的Handler后面去执行的~~~~ public interface AsyncHandlerMethodReturnValueHandler extends HandlerMethodReturnValueHandler { // 给定的返回值是否表示异步计算 boolean isAsyncReturnValue(@Nullable Object returnValue, MethodParameter returnType); }
需要注意的是,这个接口和异步好像并没有任何关系,只是体现出了它的优先级。
因为默认情况下我们定义custom自己的处理器,排名都是靠后的。但是如果你定义了一个实现类,实现的是AsyncHandlerMethodReturnValueHandler这个子接口,你的排名就会靠前执行了~~~
由于上面已有类似的例子了,此处就不花篇幅举例了。
关于Spring MVC异步处理的几个返回值处理器
因为Spring MVC支持多种异步返回的方式,因此放在此处一起讲。推荐先参考博文:
【小家Spring】高性能关键技术之—体验Spring MVC的异步模式(Callable、WebAsyncTask、DeferredResult) 基础使用篇
StreamingResponseBodyReturnValueHandler
Spring4.2才出来。(因为StreamingResponseBody是Spring4.2才出来的~~~它很方便做文件下载)
public class StreamingResponseBodyReturnValueHandler implements HandlerMethodReturnValueHandler { // 显然这里支持返回值直接是StreamingResponseBody类型,也支持你用`ResponseEntity`在包一层 // ResponseEntity的泛型类型必须是StreamingResponseBody类型~~~ @Override public boolean supportsReturnType(MethodParameter returnType) { if (StreamingResponseBody.class.isAssignableFrom(returnType.getParameterType())) { return true; } else if (ResponseEntity.class.isAssignableFrom(returnType.getParameterType())) { Class<?> bodyType = ResolvableType.forMethodParameter(returnType).getGeneric().resolve(); return (bodyType != null && StreamingResponseBody.class.isAssignableFrom(bodyType)); } return false; } @Override @SuppressWarnings("resource") public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // 从这句代码也可以看出,只有返回值为null了,它才关闭,否则可以持续不断的向response里面写东西 if (returnValue == null) { mavContainer.setRequestHandled(true); return; } HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); Assert.state(response != null, "No HttpServletResponse"); ServerHttpResponse outputMessage = new ServletServerHttpResponse(response); // 从ResponseEntity里body提取出来~~~~~ if (returnValue instanceof ResponseEntity) { ResponseEntity<?> responseEntity = (ResponseEntity<?>) returnValue; response.setStatus(responseEntity.getStatusCodeValue()); outputMessage.getHeaders().putAll(responseEntity.getHeaders()); returnValue = responseEntity.getBody(); if (returnValue == null) { mavContainer.setRequestHandled(true); outputMessage.flush(); return; } } ServletRequest request = webRequest.getNativeRequest(ServletRequest.class); Assert.state(request != null, "No ServletRequest"); ShallowEtagHeaderFilter.disableContentCaching(request); // 禁用内容缓存 Assert.isInstanceOf(StreamingResponseBody.class, returnValue, "StreamingResponseBody expected"); StreamingResponseBody streamingBody = (StreamingResponseBody) returnValue; // 最终也是开启了一个Callable 任务,最后交给WebAsyncUtils去执行的~~~~ Callable<Void> callable = new StreamingResponseBodyTask(outputMessage.getBody(), streamingBody); // WebAsyncUtils.getAsyncManager得到的是一个`WebAsyncManager`对象 // startCallableProcessing会把callable任务都包装成一个`WebAsyncTask`,最终交给`AsyncTaskExecutor`执行 // 至于异步的详细执行原理,请参考上面的相关博文,此处只点一下~~~~ WebAsyncUtils.getAsyncManager(webRequest).startCallableProcessing(callable, mavContainer); } // 这个任务很简单,实现了Callable的call方法,它就是相当于启一个线程,把本次body里面的内容写进response输出流里面~~~ // 但是此时输出流并不会关闭~~~~ private static class StreamingResponseBodyTask implements Callable<Void> { private final OutputStream outputStream; private final StreamingResponseBody streamingBody; public StreamingResponseBodyTask(OutputStream outputStream, StreamingResponseBody streamingBody) { this.outputStream = outputStream; this.streamingBody = streamingBody; } @Override public Void call() throws Exception { this.streamingBody.writeTo(this.outputStream); return null; } } }
可以看出它的原理是自己构建出一个内部的异步线程,交给reponse的异步上下文去处理。
由上面代码课件,它不仅仅支持json内容,也是支持一直返回页面渲染的内容的。(只是大多数情况下我们把它和@ResponseBody联合使用)
DeferredResultMethodReturnValueHandler
这个也许是我们最为常用的一种异步处理方式。它不仅仅处理返回值类型为DeferredResult,也会处理返回值类型为ListenableFuture和CompletionStage(Java8新增的接口)类型的
public class DeferredResultMethodReturnValueHandler implements HandlerMethodReturnValueHandler { // 它支持处理丰富的数据类型 @Override public boolean supportsReturnType(MethodParameter returnType) { Class<?> type = returnType.getParameterType(); return (DeferredResult.class.isAssignableFrom(type) || ListenableFuture.class.isAssignableFrom(type) || CompletionStage.class.isAssignableFrom(type)); } @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // 一样的 只有返回null了才代表此请求处理完成了 if (returnValue == null) { mavContainer.setRequestHandled(true); return; } DeferredResult<?> result; // 此处是适配器模式的使用,最终都适配成了一个DeferredResult(使用的内部类实现的~~~) if (returnValue instanceof DeferredResult) { result = (DeferredResult<?>) returnValue; } else if (returnValue instanceof ListenableFuture) { result = adaptListenableFuture((ListenableFuture<?>) returnValue); } else if (returnValue instanceof CompletionStage) { result = adaptCompletionStage((CompletionStage<?>) returnValue); } else { // Should not happen... throw new IllegalStateException("Unexpected return value type: " + returnValue); } // 此处调用的异步方法是:startDeferredResultProcessing WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(result, mavContainer); } // 下为两匿名内部实现类做的兼容适配、兼容处理~~~~~非常的简单~~~~ private DeferredResult<Object> adaptListenableFuture(ListenableFuture<?> future) { DeferredResult<Object> result = new DeferredResult<>(); future.addCallback(new ListenableFutureCallback<Object>() { @Override public void onSuccess(@Nullable Object value) { result.setResult(value); } @Override public void onFailure(Throwable ex) { result.setErrorResult(ex); } }); return result; } private DeferredResult<Object> adaptCompletionStage(CompletionStage<?> future) { DeferredResult<Object> result = new DeferredResult<>(); future.handle((BiFunction<Object, Throwable, Object>) (value, ex) -> { if (ex != null) { result.setErrorResult(ex); } else { result.setResult(value); } return null; }); return result; } }
CallableMethodReturnValueHandler
因为已经解释了StreamingResponseBodyReturnValueHandler,它最终也是转换为一个Callable去处理了的。因此此处返回值直接是callable,简直就不要太简单了~~~
ResponseBodyEmitterReturnValueHandler
XXXEmitter它相当于加强版的DeferredResult,它可以返回多个值给客户端。其实它的底层原理还是DeferredResult,此处不再做过多的介绍~~~~
AsyncTaskMethodReturnValueHandler
顾名思义,它是专门处理返回值类型为WebAsyncTask的异步请求形式。
// @since 3.2 因为WebAsyncTask这个时候才出来~~~ public class AsyncTaskMethodReturnValueHandler implements HandlerMethodReturnValueHandler { @Nullable private final BeanFactory beanFactory; public AsyncTaskMethodReturnValueHandler(@Nullable BeanFactory beanFactory) { this.beanFactory = beanFactory; } @Override public boolean supportsReturnType(MethodParameter returnType) { return WebAsyncTask.class.isAssignableFrom(returnType.getParameterType()); } @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { if (returnValue == null) { mavContainer.setRequestHandled(true); return; } WebAsyncTask<?> webAsyncTask = (WebAsyncTask<?>) returnValue; if (this.beanFactory != null) { webAsyncTask.setBeanFactory(this.beanFactory); } // 我们发现它使用的也是startCallableProcessing... WebAsyncUtils.getAsyncManager(webRequest).startCallableProcessing(webAsyncTask, mavContainer); } }
代码逻辑非常简单
HandlerMethodReturnValueHandlerComposite:处理器合成
这是个厉害角色。其实它就是提供的所有的HandlerMethodReturnValueHandler集合,它定义了一个链表用于存储所有实现的HandlerMethodReturnValueHandler。
它用在RequestMappingHandlerAdapter和ExceptionHandlerExceptionResolver里,此处以RequestMappingHandlerAdapter为例:
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean { // 这里保存在用户自定义的一些处理器,大部分情况下无需自定义~~~ @Nullable private List<HandlerMethodReturnValueHandler> customReturnValueHandlers; // 保存着所有的处理器~~~~上面custom自定义的最终也会放进来,放在尾部 // 从它的命名似乎可议看出,它就是汇总~~~ @Nullable private HandlerMethodReturnValueHandlerComposite returnValueHandlers; // 可以看到即使你调用了set方法,最终也是会给你生成一个HandlerMethodReturnValueHandlerComposite public void setReturnValueHandlers(@Nullable List<HandlerMethodReturnValueHandler> returnValueHandlers) { if (returnValueHandlers == null) { this.returnValueHandlers = null; } else { this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite(); this.returnValueHandlers.addHandlers(returnValueHandlers); } } @Nullable public List<HandlerMethodReturnValueHandler> getReturnValueHandlers() { return (this.returnValueHandlers != null ? this.returnValueHandlers.getHandlers() : null); } // 它的初始化发生在这: @Override public void afterPropertiesSet() { ... // 相当于你自己没有set,那就交给Spring自己去处理吧~~~~ if (this.returnValueHandlers == null) { // 这个getDefaultReturnValueHandlers()会装载15个左右的返回值处理器,可以说覆盖我们日常开发的所有 // 若你自己自定义了custom的,放进了customReturnValueHandlers里,最终也会被加进来放进去~~~~ 放在末尾~~~~ List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } } }
Co
mposite:混合成的,由此可见它就是和汇总的作用。
那么接下来,就看看它本尊自身,提供了哪些能力?其实它的代码量不大:
// 首先发现,它也实现了接口HandlerMethodReturnValueHandler // 它会缓存以前解析的返回类型以加快查找速度 public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler { private final List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<>(); // 返回的是一个只读视图 public List<HandlerMethodReturnValueHandler> getHandlers() { return Collections.unmodifiableList(this.returnValueHandlers); } public HandlerMethodReturnValueHandlerComposite addHandler(HandlerMethodReturnValueHandler handler) { this.returnValueHandlers.add(handler); return this; } public HandlerMethodReturnValueHandlerComposite addHandlers( @Nullable List<? extends HandlerMethodReturnValueHandler> handlers) { if (handlers != null) { this.returnValueHandlers.addAll(handlers); } return this; } // 由这两个可议看出,但凡有一个Handler支持处理这个返回值,就是支持的~~~ @Override public boolean supportsReturnType(MethodParameter returnType) { return getReturnValueHandler(returnType) != null; } @Nullable private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) { for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (handler.supportsReturnType(returnType)) { return handler; } } return null; } // 这里就是处理返回值的核心内容~~~~~ @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // selectHandler选择收个匹配的Handler来处理这个返回值~~~~ 若一个都木有找到 抛出异常吧~~~~ // 所有很重要的一个方法是它:selectHandler() 它来匹配,以及确定优先级 HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType); if (handler == null) { throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName()); } handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); } // 根据返回值,以及返回类型 来找到一个最为合适的HandlerMethodReturnValueHandler @Nullable private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) { // 这个和我们上面的就对应上了 第一步去判断这个返回值是不是一个异步的value(AsyncHandlerMethodReturnValueHandler实现类只能我们自己来写~) boolean isAsyncValue = isAsyncReturnValue(value, returnType); for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { // 如果判断发现这个值是异步的value,那它显然就只能交给你自己定义的异步处理器处理了,别的处理器肯定就靠边站~~~~~ if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue; } if (handler.supportsReturnType(returnType)) { return handler; } } return null; } private boolean isAsyncReturnValue(@Nullable Object value, MethodParameter returnType) { for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (handler instanceof AsyncHandlerMethodReturnValueHandler && ((AsyncHandlerMethodReturnValueHandler) handler).isAsyncReturnValue(value, returnType)) { return true; } } return false; } }
我们可以看到,它内的逻辑其实非常的简单。重点在于我们需要关心下调用栈:
请求的入口处在这:doDispatcher里会找到一个HandlerAdapter会调用@handle方法来真正执行Spring MVC的Handler。扔给ServletInvocableHandlerMethod#invokeAndHandle去执行处理器,从而拿到方法返回值:returnValue。
最终交给HandlerMethodReturnValueHandlerComposite#handleReturnValue它去处理~~~上面看了源码处理过程,这就简单了,其实最终做事的是我们的具体的找到唯一的一个HandlerMethodReturnValueHandler~
Spring MVC默认配置返回值处理器们
不管开启@EnableWebMvc还是未开启,都是15个
备注:如果是Spring5一下的版本,若未开启@EnableWebMvc,处理的类是过时的AnnotationMethodHandlerAdapter,而它里面还并没有HandlerMethodReturnValueHandler这个接口,所以此处就不介绍了,知道就行。注意版本必须是Spring5以内的,因为Spring5以后那两个过时的类就直接都干掉了~~~
请注意,上面原理已经讲过,这里面处理器的先后顺序还是比较重要的~~~从下面源码处也能看出,Spring MVC大致上做了分类
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()); handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(), this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager)); 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 // 基于注解的返回值处理器:@ModelAttribute和@ResponseBody handlers.add(new ModelAttributeMethodProcessor(false)); 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:处理所有 // Spring MVC相当于它定位成自己是能够处理所有的请求的~~~~ // 特别是ModelAndViewResolverMethodReturnValueHandler,我们上面也有举例了 if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) { handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers())); } else { handlers.add(new ModelAttributeMethodProcessor(true)); } return handlers; }
备注:若遇上多个处理器都能处理器的情况下,是按照添加顺序执行的。比如Jackson和FastJson都能处理,那就根据添加顺序了,最终生效的肯定只有一个
总结
Spring MVC支持各种返回值类型,是因为默认给我们注册了足够锁的返回值处理器。它面向接口编程以及对责任链模式很好的使用,实现了非常高的扩展性和解耦性。
一个成熟的框架,体现在它对很多细节上的处理,这才行程了一个产品,而Spring Framework就是这么样一个很优秀的产品,值得参考、学习