话不多说,上来就干
在阅读soul源码的过程中,我发现了一个请求处理接口 WebHandler,之所以发现这个接口,是因为网关中,对于请求的处理,都是通过 SoulWebHandler接口的具体方法处理的,而这个接口就是直接继承了spring的 WebHandler接口
/**
* Contract to handle a web request.
*
* <p>Use {@link HttpWebHandlerAdapter} to adapt a {@code WebHandler} to an
* {@link org.springframework.http.server.reactive.HttpHandler HttpHandler}.
* The {@link WebHttpHandlerBuilder} provides a convenient way to do that while
* also optionally configuring one or more filters and/or exception handlers.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
public interface WebHandler {
/**
* Handle the web server exchange.
* @param exchange the current server exchange
* @return {@code Mono<Void>} to indicate when request handling is complete
*/
Mono<Void> handle(ServerWebExchange exchange);
}
这接口是spring5新增的接口,用于使用reative编程处理web强求,webhandler接口的唯一方法会被一个http请求的适配器 HttpWebHandlerAdapter处理
@Override
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
if (this.forwardedHeaderTransformer != null) {
request = this.forwardedHeaderTransformer.apply(request);
}
ServerWebExchange exchange = createExchange(request, response);
LogFormatUtils.traceDebug(logger, traceOn ->
exchange.getLogPrefix() + formatRequest(exchange.getRequest()) +
(traceOn ? ", headers=" + formatHeaders(exchange.getRequest().getHeaders()) : ""));
// webhandler 被调用
return getDelegate().handle(exchange)
.doOnSuccess(aVoid -> logResponse(exchange))
.onErrorResume(ex -> handleUnresolvedError(exchange, ex))
.then(Mono.defer(response::setComplete));
}
protected ServerWebExchange createExchange(ServerHttpRequest request, ServerHttpResponse response) {
return new DefaultServerWebExchange(request, response, this.sessionManager,
getCodecConfigurer(), getLocaleContextResolver(), this.applicationContext);
}
适配器最终会被 ServletHttpHandlerAdapter的service方法调用,而这个service方式很熟悉,就是我们最初学习java的serlvet容器中必须要实现那个service,用来处理http请求,这个适配器最终就是java的 Servlet接口的具体实现
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
// Check for existing error attribute first
if (DispatcherType.ASYNC.equals(request.getDispatcherType())) {
Throwable ex = (Throwable) request.getAttribute(WRITE_ERROR_ATTRIBUTE_NAME);
throw new ServletException("Failed to create response content", ex);
}
// Start async before Read/WriteListener registration
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(-1);
ServletServerHttpRequest httpRequest;
try {
httpRequest = createRequest(((HttpServletRequest) request), asyncContext);
}
catch (URISyntaxException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to get request URL: " + ex.getMessage());
}
((HttpServletResponse) response).setStatus(400);
asyncContext.complete();
return;
}
ServerHttpResponse httpResponse = createResponse(((HttpServletResponse) response), asyncContext, httpRequest);
if (httpRequest.getMethod() == HttpMethod.HEAD) {
httpResponse = new HttpHeadResponseDecorator(httpResponse);
}
AtomicBoolean isCompleted = new AtomicBoolean();
HandlerResultAsyncListener listener = new HandlerResultAsyncListener(isCompleted, httpRequest);
asyncContext.addListener(listener);
HandlerResultSubscriber subscriber = new HandlerResultSubscriber(asyncContext, isCompleted, httpRequest);
this.httpHandler.handle(httpRequest, httpResponse).subscribe(subscriber);
}
继承了这个service方法的接口就有大名鼎鼎的 GenericServlet 通用servlet接口,他也是springmvc的核心调度器 DispatcherServlet的间接父类
可见spring新增的响应式编程在同一的servlet框架下,很好的兼容了之前的springmvc框架