聊聊Spring WebFlux中的HttpHandler

3,433 阅读9分钟

0、请求 -> 响应

在 Netty 中,一般会有 2 个 EventLoopGroup。 BossEventLoopGroup 用来监听请求,当收到 ACCEPT 事件时,创建 socket 连接,并将该 socket 注册到 WorkEventLoopGroup 中。WorkEventLoop 监听到 READ 事件时,读取字节流,对请求进行解码,根据请求内容查找对应的处理方法,将结果编码后发送给客户端。

在 WebFlux 中,实现根据请求内容查找对应的处理方法这个过程,是通过HttpHandler实现的,接口定义如下:

public interface HttpHandler {
	/**
	 * Handle the given request and write to the response.
	 * @param request current request
	 * @param response current response
	 * @return indicates completion of request handling
	 */
	Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response);
}

以下试着从源码角度,分析HttpHandler的实现和功能,版本:org.springframework.boot:spring-boot-starter-webflux:2.3.3.RELEASE。

1、HttpHandler

HttpHandler何时被调用?接收到请求时。

/** NettyWebServer **/
public class NettyWebServer implements WebServer {
	private final BiFunction<? super HttpServerRequest, ? super HttpServerResponse, ? extends Publisher<Void>> handler;
  
	private DisposableServer startHttpServer() {
		HttpServer server = this.httpServer;
		if (this.routeProviders.isEmpty()) {
			server = server.handle(this.handler);  //1 此时为 HttpServerHandle 类型
		}
		...
		return server.bindNow();
	}
  
    /** HttpServerHandle **/
    final BiFunction<? super HttpServerRequest, ? super HttpServerResponse, ? extends Publisher<Void>> handler;
   
    public void onStateChange(Connection connection, State newState) {
		if (newState == HttpServerState.REQUEST_RECEIVED) {  //2 接收到 Request 请求时
			try {
				HttpServerOperations ops = (HttpServerOperations) connection;
				Mono.fromDirect(handler.apply(ops, ops))  //3 执行 HttpHandler
				    .subscribe(ops.disposeSubscriber());
			}
      ...
		}
	}
}

在程序启动时,会自动创建一个HttpHandlerbean。

/** HttpHandlerAutoConfiguration **/
public class HttpHandlerAutoConfiguration {

	@Configuration(proxyBeanMethods = false)
	public static class AnnotationConfig {
		@Bean
		public HttpHandler httpHandler(ObjectProvider<WebFluxProperties> propsProvider) {
			HttpHandler httpHandler = WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();  // 1 创建 HttpHandler
			WebFluxProperties properties = propsProvider.getIfAvailable();
      		// 2 可以设置base-path,类似于springmvc的server.servlet.context-path
			if (properties != null && StringUtils.hasText(properties.getBasePath())) {
				Map<String, HttpHandler> handlersMap = Collections.singletonMap(properties.getBasePath(), httpHandler);
				return new ContextPathCompositeHandler(handlersMap);
			}
			return httpHandler;
		}
	}
}

注意步骤 2,这里可以设置 base-path,类似于 SpringMVC 的 server.servlet.context-path

继续分析HttpHandler的创建过程:

/** WebHttpHandlerBuilder **/
private final WebHandler webHandler;

private final List<WebFilter> filters = new ArrayList<>();

private final List<WebExceptionHandler> exceptionHandlers = new ArrayList<>();

public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) {
    WebHttpHandlerBuilder builder = new WebHttpHandlerBuilder(
            context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class), context);  //初始化WebHandler

    List<WebFilter> webFilters = context
            .getBeanProvider(WebFilter.class)
            .orderedStream()  //排序
            .collect(Collectors.toList());
    builder.filters(filters -> filters.addAll(webFilters));  //初始化WebFilter
    List<WebExceptionHandler> exceptionHandlers = context
            .getBeanProvider(WebExceptionHandler.class)
            .orderedStream()  //排序
            .collect(Collectors.toList());
    builder.exceptionHandlers(handlers -> handlers.addAll(exceptionHandlers));  //初始化ExceptionHandler
    ...
    return builder;
}

从以上代码分析,HttpHandler中主要分为三个部分:

  • WebFilter:过滤器,类型为 List,所以这是一个过滤器链;
  • WebHandler: 请求的业务处理;
  • WebExceptionHandler:异常处理。

继续看 build 方法:

/** WebHttpHandlerBuilder **/
public HttpHandler build() {

    WebHandler decorated = new FilteringWebHandler(this.webHandler, this.filters);
    decorated = new ExceptionHandlingWebHandler(decorated,  this.exceptionHandlers);

    HttpWebHandlerAdapter adapted = new HttpWebHandlerAdapter(decorated);
    ...
    if (this.applicationContext != null) {
        adapted.setApplicationContext(this.applicationContext);
    }
    adapted.afterPropertiesSet();

    return adapted;
}

最终生成的HttpHandlerHttpWebHandlerAdapter类型,并且其 delegate 为ExceptionHandlingWebHandler,其 delegate 为FilteringWebHandler,其 delegate 为this.webHandler。构成了下面的调用链:

HttpWebHandlerAdapter -> ExceptionHandlingWebHandler -> FilteringWebHandler -> this.webHandler

/** HttpWebHandlerAdapter **/
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
    ...
    return getDelegate().handle(exchange)  //调用ExceptionHandlingWebHandler的handle
            .doOnSuccess(aVoid -> logResponse(exchange))
            .onErrorResume(ex -> handleUnresolvedError(exchange, ex))
            .then(Mono.defer(response::setComplete));
}

/** ExceptionHandlingWebHandler **/
public Mono<Void> handle(ServerWebExchange exchange) {
    Mono<Void> completion;
    try {
        completion = super.handle(exchange);  //调用FilteringWebHandler的handle
    }
    catch (Throwable ex) {
        completion = Mono.error(ex);
    }

    for (WebExceptionHandler handler : this.exceptionHandlers) {  //如果报异常,处理异常
        completion = completion.onErrorResume(ex -> handler.handle(exchange, ex));
    }
    return completion;
}

/** FilteringWebHandler **/
public class FilteringWebHandler extends WebHandlerDecorator {

	private final DefaultWebFilterChain chain;

	public FilteringWebHandler(WebHandler handler, List<WebFilter> filters) {
		super(handler);
		this.chain = new DefaultWebFilterChain(handler, filters);
	}

	public List<WebFilter> getFilters() {
		return this.chain.getFilters();
	}

	@Override
	public Mono<Void> handle(ServerWebExchange exchange) {
		return this.chain.filter(exchange);  //调用DefaultWebFilterChain的filter
	}
}

/** DefaultWebFilterChain **/
private static DefaultWebFilterChain initChain(List<WebFilter> filters, WebHandler handler) {
    DefaultWebFilterChain chain = new DefaultWebFilterChain(filters, handler, null, null);
    ListIterator<? extends WebFilter> iterator = filters.listIterator(filters.size());
    // 这里实现了:当执行 chain.filter(exchange) 时,会调用下一个 webfilter
    while (iterator.hasPrevious()) {
        chain = new DefaultWebFilterChain(filters, handler, iterator.previous(), chain);
    }
    return chain;
}

public Mono<Void> filter(ServerWebExchange exchange) {
  	// 当执行完 webfilter 后,开始执行 webhandler
	return Mono.defer(() ->
        this.currentFilter != null && this.chain != null ?
                invokeFilter(this.currentFilter, this.chain, exchange) :
                this.handler.handle(exchange));
}

private Mono<Void> invokeFilter(WebFilter current, DefaultWebFilterChain chain, ServerWebExchange exchange) {
    String currentName = current.getClass().getName();
    return current.filter(exchange, chain).checkpoint(currentName + " [DefaultWebFilterChain]");
}

针对以上代码实现的功能,可以用一张图来表示:

其中,黑线表示请求的正常过程,红线表示发生异常后的处理过程。

2、WebFilter

以一个简单的 demo 来看WebFilter的使用:

/** Log1Filter **/
@Component
@Order(100)
public class Log1Filter implements WebFilter {
   private static final Logger logger = LoggerFactory.getLogger(Log1Filter.class);

   @Override
   public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
       logger.info("left: 111");
       return chain.filter(exchange)
               .doOnSuccess(aVoid -> logger.info("right: 111"))
               .doOnError(RuntimeException.class, e -> logger.error("error1: {}", e.getMessage()));
   }
}

/** Log2Filter **/
@Component
@Order(200)
public class Log2Filter implements WebFilter {
   private static final Logger logger = LoggerFactory.getLogger(Log2Filter.class);

   @Override
   public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
       logger.info("left: 222");
       return chain.filter(exchange)
               .doOnSuccess(aVoid -> logger.info("right: 222"))
               .doOnError(RuntimeException.class, e -> logger.error("error2: {}", e.getMessage()));
   }
}

@RestController
@RequestMapping("/testfilter")
public class TestFilterController {
   private static final Logger logger = LoggerFactory.getLogger(TestFilterController.class);
   
   @GetMapping("/test-ok")
   public Mono<String> testOk(@RequestParam("name") String name) {
       logger.info("get name: {}", name);
       return Mono.just(name);
   }

   @GetMapping("/test-error")
   public Mono<String> testError(@RequestParam("name") String name) {
       logger.info("get name: {}", name);
       throw new RuntimeException("get name error");
   }
}

调用 test-ok 接口返回:

2020-08-23 16:51:15.749  INFO 50589 --- [ctor-http-nio-2] m.p.demos.webflux.filter.Log1Filter      : left: 111
2020-08-23 16:51:15.751  INFO 50589 --- [ctor-http-nio-2] m.p.demos.webflux.filter.Log2Filter      : left: 222
2020-08-23 16:51:15.778  INFO 50589 --- [ctor-http-nio-2] m.p.d.w.controller.TestFilterController  : invoke method: testOk
2020-08-23 16:51:15.799  INFO 50589 --- [ctor-http-nio-2] m.p.demos.webflux.filter.Log2Filter      : right: 222
2020-08-23 16:51:15.799  INFO 50589 --- [ctor-http-nio-2] m.p.demos.webflux.filter.Log1Filter      : right: 111

调用 test-error 接口返回:

2020-08-23 16:51:18.909  INFO 50589 --- [ctor-http-nio-2] m.p.demos.webflux.filter.Log1Filter      : left: 111
2020-08-23 16:51:18.910  INFO 50589 --- [ctor-http-nio-2] m.p.demos.webflux.filter.Log2Filter      : left: 222
2020-08-23 16:51:18.911  INFO 50589 --- [ctor-http-nio-2] m.p.d.w.controller.TestFilterController  : invoke method: testError
2020-08-23 16:51:18.920 ERROR 50589 --- [ctor-http-nio-2] m.p.demos.webflux.filter.Log2Filter      : error2: error
2020-08-23 16:51:18.928 ERROR 50589 --- [ctor-http-nio-2] m.p.demos.webflux.filter.Log1Filter      : error1: error
2020-08-23 16:51:18.966 ERROR 50589 --- [ctor-http-nio-2] a.w.r.e.AbstractErrorWebExceptionHandler : [5b86a385-2]  500 Server Error for HTTP GET "/testfilter/test-error"

3、WebHandlerDispatcherHandler

默认的WebHandlerDispatcherHandler

/** WebFluxConfigurationSupport **/
public class WebFluxConfigurationSupport implements ApplicationContextAware {
    @Bean
    public DispatcherHandler webHandler() {
        return new DispatcherHandler();
    }
}

看下实现:

/** DispatcherHandler **/
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
	private List<HandlerMapping> handlerMappings;

	private List<HandlerAdapter> handlerAdapters;

	private List<HandlerResultHandler> resultHandlers;

    protected void initStrategies(ApplicationContext context) {
		Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
				context, HandlerMapping.class, true, false);

		ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
		AnnotationAwareOrderComparator.sort(mappings);
		this.handlerMappings = Collections.unmodifiableList(mappings);

		Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
				context, HandlerAdapter.class, true, false);

		this.handlerAdapters = new ArrayList<>(adapterBeans.values());
		AnnotationAwareOrderComparator.sort(this.handlerAdapters);

		Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
				context, HandlerResultHandler.class, true, false);

		this.resultHandlers = new ArrayList<>(beans.values());
		AnnotationAwareOrderComparator.sort(this.resultHandlers);
	}
}

DispatcherHandler中也主要分为三部分:

  • HandlerMapping:根据 http 请求,找到对应的处理方法。比如根据 URL 和 HttpMethod,确定对应的 Controller 层的某个方法。
  • HandlerAdapter:调用具体的处理方法;
  • HandlerResultHandler:针对返回类型,进行不同的处理,并发送给客户端;
public Mono<Void> handle(ServerWebExchange exchange) {
    if (this.handlerMappings == null) {
        return createNotFoundError();
    }
    return Flux.fromIterable(this.handlerMappings)
        .concatMap(mapping -> mapping.getHandler(exchange))
        .next()  //找到第一个可用的handler
        .switchIfEmpty(createNotFoundError())
        .flatMap(handler -> invokeHandler(exchange, handler))  //处理请求
        .flatMap(result -> handleResult(exchange, result));  //处理结果
}

3.1 HandlerMapping

其接口定义如下:

/** HandlerMapping **/
public interface HandlerMapping {
  
	Mono<Object> getHandler(ServerWebExchange exchange);
}

/** AbstractHandlerMapping **/
public Mono<Object> getHandler(ServerWebExchange exchange) {
    return getHandlerInternal(exchange).map(handler -> {
        ...
        return handler;
    });
}

列举几种常见的HandlerMapping

RouterFunctionMapping: 处理RouterFunction接口定义的请求路由;

RequestMappingHandlerMapping: 处理@Controller以及@RequestMapping定义的请求路由;

SimpleUrlHandlerMapping: 处理基于 url 的请求路由;

这里需要注意的是,对于同一个请求,有可能会找到多个路由;因此这些路由需要有个优先级,一旦找到匹配的路由,就不会查询后续的路由了。

/** WebFluxConfigurationSupport **/
public class WebFluxConfigurationSupport implements ApplicationContextAware {
    @Bean
	public RequestMappingHandlerMapping requestMappingHandlerMapping(
			@Qualifier("webFluxContentTypeResolver") RequestedContentTypeResolver contentTypeResolver) {
		RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
		mapping.setOrder(0);
    ...
		return mapping;
	}
  
    @Bean
	public RouterFunctionMapping routerFunctionMapping(ServerCodecConfigurer serverCodecConfigurer) {
		RouterFunctionMapping mapping = createRouterFunctionMapping();
		mapping.setOrder(-1);  // go before RequestMappingHandlerMapping
		mapping.setMessageReaders(serverCodecConfigurer.getReaders());
		mapping.setCorsConfigurations(getCorsConfigurations());
		return mapping;
	}
}

从以上代码可知,RouterFunctionMapping的优先级要高于RequestMappingHandlerMapping

写段代码验证一下:

@RestController
@RequestMapping("/testrouter")
public class UrlRouterFunction implements RouterFunction {
    @GetMapping("/test")
    public Mono<String> test() {
        return Mono.just("RequestMappingHandlerMapping");
    }

    @Override
    public Mono<HandlerFunction> route(ServerRequest request) {
        HandlerFunction urlHandler = req -> ServerResponse.ok().bodyValue("RouterFunctionMapping");
        if (request.uri().getPath().equals("/testrouter/test")) {
            return Mono.defer(() -> Mono.just(urlHandler));
        } else {
            return Mono.empty();
        }
    }
}

调用请求:

➜  ~ curl -L -X GET 'http://127.0.0.1:8080/testrouter/test';
RouterFunctionMapping

3.2 HandlerAdapter

其接口定义如下:

public interface HandlerAdapter {

	/**
	 * Whether this {@code HandlerAdapter} supports the given {@code handler}.
	 * @param handler the handler object to check
	 * @return whether or not the handler is supported
	 */
	boolean supports(Object handler);

	/**
	 * Handle the request with the given handler.
	 * <p>Implementations are encouraged to handle exceptions resulting from the
	 * invocation of a handler in order and if necessary to return an alternate
	 * result that represents an error response.
	 * <p>Furthermore since an async {@code HandlerResult} may produce an error
	 * later during result handling implementations are also encouraged to
	 * {@link HandlerResult#setExceptionHandler(Function) set an exception
	 * handler} on the {@code HandlerResult} so that may also be applied later
	 * after result handling.
	 * @param exchange current server exchange
	 * @param handler the selected handler which must have been previously
	 * checked via {@link #supports(Object)}
	 * @return {@link Mono} that emits a single {@code HandlerResult} or none if
	 * the request has been fully handled and doesn't require further handling.
	 */
	Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler);
}

HandlerAdapter.supports()方法的主要作用在于判断当前的HandlerAdapter是否能够支持传过来的 handler。以RequestMappingHandlerAdapter为例,

public class RequestMappingHandlerAdapter implements HandlerAdapter, ApplicationContextAware, InitializingBean {
    public boolean supports(Object handler) {  //支持HandlerMethod类型
		return handler instanceof HandlerMethod;
	}
    
    @Override
	public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
		HandlerMethod handlerMethod = (HandlerMethod) handler;

		InitBinderBindingContext bindingContext = new InitBinderBindingContext(
				getWebBindingInitializer(), this.methodResolver.getInitBinderMethods(handlerMethod));

		InvocableHandlerMethod invocableMethod = this.methodResolver.getRequestMappingMethod(handlerMethod);

		Function<Throwable, Mono<HandlerResult>> exceptionHandler =
				ex -> handleException(ex, handlerMethod, bindingContext, exchange);

		return this.modelInitializer
				.initModel(handlerMethod, bindingContext, exchange)
				.then(Mono.defer(() -> invocableMethod.invoke(exchange, bindingContext)))  //通过反射调用具体的方法
				.doOnNext(result -> result.setExceptionHandler(exceptionHandler))
				.doOnNext(result -> bindingContext.saveModel())
				.onErrorResume(exceptionHandler);  //处理`@ExceptionHandler`指定的异常
	}
}

3.3 HandlerResultHandler

其接口定义如下:

public interface HandlerResultHandler {
	/**
	 * Whether this handler supports the given {@link HandlerResult}.
	 * @param result the result object to check
	 * @return whether or not this object can use the given result
	 */
	boolean supports(HandlerResult result);

	/**
	 * Process the given result modifying response headers and/or writing data
	 * to the response.
	 * @param exchange current server exchange
	 * @param result the result from the handling
	 * @return {@code Mono<Void>} to indicate when request handling is complete.
	 */
	Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result);
}

ResponseBodyResultHandler为例,可以处理通过@ResponseBody标识的方法:

public class ResponseBodyResultHandler extends AbstractMessageWriterResultHandler implements HandlerResultHandler {
    @Override
	public boolean supports(HandlerResult result) {
		MethodParameter returnType = result.getReturnTypeSource();
		Class<?> containingClass = returnType.getContainingClass();
        // 支持@ResponseBody注解
		return (AnnotatedElementUtils.hasAnnotation(containingClass, ResponseBody.class) ||
				returnType.hasMethodAnnotation(ResponseBody.class));
	}

	@Override
	public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
		Object body = result.getReturnValue();
		MethodParameter bodyTypeParameter = result.getReturnTypeSource();
		return writeBody(body, bodyTypeParameter, exchange);
	}
}

继续分析对结果进行了哪些处理:

public abstract class AbstractMessageWriterResultHandler extends HandlerResultHandlerSupport {
    protected Mono<Void> writeBody(@Nullable Object body, MethodParameter bodyParameter,
			@Nullable MethodParameter actualParam, ServerWebExchange exchange) {

		ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParameter);  //返回类型,比如MonoJust
		ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType);
		ReactiveAdapter adapter = getAdapterRegistry().getAdapter(bodyType.resolve(), body);  //适配器

		Publisher<?> publisher;
		ResolvableType elementType;
		ResolvableType actualElementType;  //实际类型,如果通过适配器封装过,获取封装前的类型
		if (adapter != null) {
			publisher = adapter.toPublisher(body);
			boolean isUnwrapped = KotlinDetector.isKotlinReflectPresent() &&
					KotlinDetector.isKotlinType(bodyParameter.getContainingClass()) &&
					KotlinDelegate.isSuspend(bodyParameter.getMethod()) &&
					!COROUTINES_FLOW_CLASS_NAME.equals(bodyType.toClass().getName());
			ResolvableType genericType = isUnwrapped ? bodyType : bodyType.getGeneric();
			elementType = getElementType(adapter, genericType);
			actualElementType = elementType;
		}
		else {
			publisher = Mono.justOrEmpty(body);
			actualElementType = body != null ? ResolvableType.forInstance(body) : bodyType;
			elementType = (bodyType.toClass() == Object.class && body != null ? actualElementType : bodyType);
		}

		if (elementType.resolve() == void.class || elementType.resolve() == Void.class) {
			return Mono.from((Publisher<Void>) publisher);
		}

        //选择最佳的MediaType
		MediaType bestMediaType = selectMediaType(exchange, () -> getMediaTypesFor(elementType));
		if (bestMediaType != null) {
			String logPrefix = exchange.getLogPrefix();
            ...
            //遍历HttpMessageWriter,找到第一个可以处理该对象类型的writer,编码后响应给客户端
			for (HttpMessageWriter<?> writer : getMessageWriters()) {
				if (writer.canWrite(actualElementType, bestMediaType)) {
					return writer.write((Publisher) publisher, actualType, elementType,
							bestMediaType, exchange.getRequest(), exchange.getResponse(),
							Hints.from(Hints.LOG_PREFIX_HINT, logPrefix));
				}
			}
		}
		...
	}
}

分析以上代码,发现前面的大部分代码是用于确定返回的对象类型、计算MediaType等,关键的部分是选择第一个可以处理返回对象类型的HttpMessageWriter,然后发送响应。

看下HttpMessageWriter定义:

public interface HttpMessageWriter<T> {
	/**
	 * Return the {@link MediaType}'s that this writer supports.
	 * 支持哪些MediaType
	 */
	List<MediaType> getWritableMediaTypes();

	/**
	 * Whether the given object type is supported by this writer.
	 * @param elementType the type of object to check
	 * @param mediaType the media type for the write (possibly {@code null})
	 * @return {@code true} if writable, {@code false} otherwise
	 * 是否支持给定的对象类型
	 */
	boolean canWrite(ResolvableType elementType, @Nullable MediaType mediaType);

	/**
	 * Write an given stream of object to the output message.
	 * @param inputStream the objects to write
	 * @param elementType the type of objects in the stream which must have been
	 * previously checked via {@link #canWrite(ResolvableType, MediaType)}
	 * @param mediaType the content type for the write (possibly {@code null} to
	 * indicate that the default content type of the writer must be used)
	 * @param message the message to write to
	 * @param hints additional information about how to encode and write
	 * @return indicates completion or error
	 * 发送响应
	 */
	Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType elementType,
			@Nullable MediaType mediaType, ReactiveHttpOutputMessage message, Map<String, Object> hints);

    /**
	 * Server-side only alternative to
	 * {@link #write(Publisher, ResolvableType, MediaType, ReactiveHttpOutputMessage, Map)}
	 * with additional context available.
	 * @param actualType the actual return type of the method that returned the
	 * value; for annotated controllers, the {@link MethodParameter} can be
	 * accessed via {@link ResolvableType#getSource()}.
	 * @param elementType the type of Objects in the input stream
	 * @param mediaType the content type to use (possibly {@code null} indicating
	 * the default content type of the writer should be used)
	 * @param request the current request
	 * @param response the current response
	 * @return a {@link Mono} that indicates completion of writing or error
	 */
	default Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType actualType,
			ResolvableType elementType, @Nullable MediaType mediaType, ServerHttpRequest request,
			ServerHttpResponse response, Map<String, Object> hints) {
		return write(inputStream, elementType, mediaType, response, hints);
	}
}

debug 看下getMessageWriters()返回了哪些 MessageWriter:

如果返回 byte[] 类型,会选择ByteArrayEncoder编码;如果返回 String 类型并且 MediaType 为 text/plain,会选择CharSequenceEncoder编码;JSON 会选择Jackson2JsonEncoder编码等。

4、WebExceptionHandler

WebExceptionHandler主要用来处理异常。但是如果对异常指定了@ExceptionHandler注解的话,实际处理过程在RequestMappingHandlerAdapter中,具体见RequestMappingHandlerAdapterhandleException方法。

先看下接口定义:

public interface WebExceptionHandler {
	/**
	 * Handle the given exception. A completion signal through the return value
	 * indicates error handling is complete while an error signal indicates the
	 * exception is still not handled.
	 * @param exchange the current exchange
	 * @param ex the exception to handle
	 * @return {@code Mono<Void>} to indicate when exception handling is complete
	 */
	Mono<Void> handle(ServerWebExchange exchange, Throwable ex);
}

实现该接口的默认 bean 有两个:DefaultErrorWebExceptionHandler以及WebFluxResponseStatusExceptionHandler,前者的 order 更小,并且处理完异常后会发送给请求方,所以主要看下前者。

public class ErrorWebFluxAutoConfiguration {
    @Bean
	@ConditionalOnMissingBean(value = ErrorWebExceptionHandler.class, search = SearchStrategy.CURRENT)
	@Order(-1)
	public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes,
			ResourceProperties resourceProperties, ObjectProvider<ViewResolver> viewResolvers,
			ServerCodecConfigurer serverCodecConfigurer, ApplicationContext applicationContext) {
		DefaultErrorWebExceptionHandler exceptionHandler = new DefaultErrorWebExceptionHandler(errorAttributes,
				resourceProperties, this.serverProperties.getError(), applicationContext);
		exceptionHandler.setViewResolvers(viewResolvers.orderedStream().collect(Collectors.toList()));
		exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());
		exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());
		return exceptionHandler;
	}
}

如果需要自定义全局异常,可以自定义一个ErrorWebExceptionHandlerbean。这部分内容网上比较多,就不重复了。