前话 在编写SpringBoot Web
程序完后,运行这个web
程序,然后用http
请求工具发送请求,然后程序对应的请求处理器就会执行相应的操作;那么,这个http
请求是如何被web
程序所接受的,又是如何路由到我们对应的http handler
上的?
Web容器 在使用SpringBoot
有一大好处——再也不用外部的web
容器了,它自身整合了目前流行的几大web
容器,当然你也可以实现自己的web
容器
SpringBoot
关于Web
容器相关的代码在org.springframework.boot.web.embedded
包中,该包下目前有四种web
容器——jetty
、netty
、tomcat
以及undertow
;在这里我使用的是netty
的web
容器
ReactiveWebServerApplicationContext 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Override protected void onRefresh () { super .onRefresh(); try { createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start reactive web server" , ex); } } private void createWebServer () { ServerManager serverManager = this .serverManager; if (serverManager == null ) { this .serverManager = ServerManager.get(getWebServerFactory()); } initPropertySources(); }
这个createWebServer
方法的执行表示正式开始对WebServer
进行相应的前期初始化,因为该方法调用的时期位于ApplicationContext
的onRefresh
时期,因此ServerManager == null
,所以前去执行ServerManager.get(getWebServerFactory())
进行创建一个ServerManager
1 2 3 4 5 6 7 8 9 10 private ServerManager (ReactiveWebServerFactory factory) { this .handler = this ::handleUninitialized; this .server = factory.getWebServer(this ); } private Mono<Void> handleUninitialized (ServerHttpRequest request, ServerHttpResponse response) { throw new IllegalStateException( "The HttpHandler has not yet been initialized" ); }
因此此时整个程序处于onRefresh
状态,Handler
尚未被Spring
加载,此处便用handleUninitialized
进行代替(ServerManager的handler此时是一个lambda表达式),在这里又可以看到,需要获取一个WebServer
NettyReactiveWebServerFactory 这是一个创建netty web
容器的工厂,通过调用getWebServer
方法即可获得一个web
容器
1 2 3 4 5 6 7 @Override public WebServer getWebServer (HttpHandler httpHandler) { HttpServer httpServer = createHttpServer(); ReactorHttpHandlerAdapter handlerAdapter = new ReactorHttpHandlerAdapter( httpHandler); return new NettyWebServer(httpServer, handlerAdapter, this .lifecycleTimeout); }
这里需要获取两个对象,一个是HttpServer
,另一个是获取http
请求的处理器handler
;然后创建一个NettyWebServer
,这个就是最终的Web
容器
现在再次回到ReactiveWebServerApplicationContext
这个对象中,此时onRefresh
中相应的操作均已完成,接着就是finishRefresh
,此步骤,将会正式启动我们的WebServer
ReactiveWebServerApplicationContext 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Override protected void finishRefresh () { super .finishRefresh(); WebServer webServer = startReactiveWebServer(); if (webServer != null ) { publishEvent(new ReactiveWebServerInitializedEvent(webServer, this )); } } private WebServer startReactiveWebServer () { ServerManager serverManager = this .serverManager; ServerManager.start(serverManager, this ::getHttpHandler); return ServerManager.getWebServer(serverManager); }
经过此前的onRefresh
阶段,this.serverManager
已经不为null了,因此执行start
方法启动WebServer
;并且进行Http Handler
的加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 protected HttpHandler getHttpHandler () { String[] beanNames = getBeanFactory().getBeanNamesForType(HttpHandler.class); if (beanNames.length == 0 ) { throw new ApplicationContextException( "Unable to start ReactiveWebApplicationContext due to missing HttpHandler bean." ); } if (beanNames.length > 1 ) { throw new ApplicationContextException( "Unable to start ReactiveWebApplicationContext due to multiple HttpHandler beans : " + StringUtils.arrayToCommaDelimitedString(beanNames)); } return getBeanFactory().getBean(beanNames[0 ], HttpHandler.class); }
加载完所有的Handler
之后,正式启动WebServer
,并且重新为handler
赋值(此时的Handler
为HttpWebHandlerAdapter
对象)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public static void start (ServerManager manager, Supplier<HttpHandler> handlerSupplier) { if (manager != null && manager.server != null ) { manager.handler = handlerSupplier.get(); manager.server.start(); } } @Override public void start () throws WebServerException { if (this .disposableServer == null ) { try { this .disposableServer = startHttpServer(); } catch (Exception ex) { ChannelBindException bindException = findBindException(ex); if (bindException != null ) { throw new PortInUseException(bindException.localPort()); } throw new WebServerException("Unable to start Netty" , ex); } logger.info("Netty started on port(s): " + getPort()); startDaemonAwaitThread(this .disposableServer); } } private DisposableServer startHttpServer () { if (this .lifecycleTimeout != null ) { return this .httpServer.handle(this .handlerAdapter) .bindNow(this .lifecycleTimeout); } return this .httpServer.handle(this .handlerAdapter).bindNow(); }
至此整个WebServer
容器算是启动完成
请求处理 涉及Http
请求处理那就要来看ReactorHttpHandlerAdapter
、HttpWebHandlerAdapter
以及DispatcherHandler
了,先来看ReactorHttpHandlerAdapter
ReactorHttpHandlerAdapter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public class ReactorHttpHandlerAdapter implements BiFunction <HttpServerRequest , HttpServerResponse , Mono <Void >> { private static final Log logger = HttpLogging.forLogName(ReactorHttpHandlerAdapter.class); private final HttpHandler httpHandler; public ReactorHttpHandlerAdapter (HttpHandler httpHandler) { Assert.notNull(httpHandler, "HttpHandler must not be null" ); this .httpHandler = httpHandler; } @Override public Mono<Void> apply (HttpServerRequest reactorRequest, HttpServerResponse reactorResponse) { NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(reactorResponse.alloc()); try { ReactorServerHttpRequest request = new ReactorServerHttpRequest(reactorRequest, bufferFactory); ServerHttpResponse response = new ReactorServerHttpResponse(reactorResponse, bufferFactory); if (request.getMethod() == HttpMethod.HEAD) { response = new HttpHeadResponseDecorator(response); } return this .httpHandler.handle(request, response) .doOnError(ex -> logger.trace(request.getLogPrefix() + "Failed to complete: " + ex.getMessage())) .doOnSuccess(aVoid -> logger.trace(request.getLogPrefix() + "Handling completed" )); } catch (URISyntaxException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to get request URI: " + ex.getMessage()); } reactorResponse.status(HttpResponseStatus.BAD_REQUEST); return Mono.empty(); } } }
可以看出,ReactorHttpHandlerAdapter
是最先接收到请求的(具体如何调用到这里的需要结合reactor.netty
,这里不细说)然后调用HttpHandler
,将请求下发至对应的HttpHandler
(即HttpWebHandlerAdapter
)
HttpWebHandlerAdapter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @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()) : "" )); 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); }
在这里会对ServerHttpRequest request, ServerHttpResponse response
进行包装成为ServerWebExchange
,然后下发到WebHabdler
(此处为ExceptionHandlingWebHandler
),这里就是Spring
能够拦截到我们程序中出现的异常的原因。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Override public Mono<Void> handle (ServerWebExchange exchange) { Mono<Void> completion; try { completion = super .handle(exchange); } catch (Throwable ex) { completion = Mono.error(ex); } for (WebExceptionHandler handler : this .exceptionHandlers) { completion = completion.onErrorResume(ex -> handler.handle(exchange, ex)); } return completion; }
这时,super.handler
跳转到了FilteringWebHandler
(此时就是责任链模式了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private final DefaultWebFilterChain chain;@Override public Mono<Void> handle (ServerWebExchange exchange) { return this .chain.filter(exchange); } @Override public Mono<Void> filter (ServerWebExchange exchange) { return Mono.defer(() -> this .currentFilter != null && this .next != null ? this .currentFilter.filter(exchange, this .next) : this .handler.handle(exchange)); }
Spring对于
Http请求采用的是责任链模式,会判断当前的
filter以及下一个
filter,只要有一个为
null直接结束责任链,进入
handler;而进入责任链模式后,第一个遇到的就是
DispatcherHandler`!
DispatcherHandler 它的内部有三个
List`
{@link HandlerMapping} – map requests to handler objects
{@link HandlerAdapter} – for using any handler interface
{@link HandlerResultHandler} – process handler return values
1 2 3 4 5 6 7 8 9 10 11 12 @Override public Mono<Void> handle (ServerWebExchange exchange) { if (this .handlerMappings == null ) { return createNotFoundError(); } return Flux.fromIterable(this .handlerMappings) .concatMap(mapping -> mapping.getHandler(exchange)) .next() .switchIfEmpty(createNotFoundError()) .flatMap(handler -> invokeHandler(exchange, handler)) .flatMap(result -> handleResult(exchange, result)); }
由注解可知,这里就是进行Http
请求分发至相应的请求处理器了,这里截了图以便更为清晰的了解
接着重要的就是如何将请求路由到对应的处理器了,这里是由HandlerMapping.getHandler
实现的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Override public Mono<Object> getHandler (ServerWebExchange exchange) { return getHandlerInternal(exchange).map(handler -> { if (logger.isDebugEnabled()) { logger.debug(exchange.getLogPrefix() + "Mapped to " + handler); } if (CorsUtils.isCorsRequest(exchange.getRequest())) { CorsConfiguration configA = this .corsConfigurationSource.getCorsConfiguration(exchange); CorsConfiguration configB = getCorsConfiguration(handler, exchange); CorsConfiguration config = (configA != null ? configA.combine(configB) : configB); if (!getCorsProcessor().process(config, exchange) || CorsUtils.isPreFlightRequest(exchange.getRequest())) { return REQUEST_HANDLED_HANDLER; } } return handler; }); }
根据代码可以看出,在执行函数getHandlerInternal(exchange)
时已经找出了对应的handler
了,此操作的执行者为RouterFunctionMapping
1 2 3 4 5 6 7 8 9 10 11 @Override protected Mono<?> getHandlerInternal(ServerWebExchange exchange) { if (this .routerFunction != null ) { ServerRequest request = ServerRequest.create(exchange, this .messageReaders); return this .routerFunction.route(request) .doOnNext(handler -> setAttributes(exchange.getAttributes(), request, handler)); } else { return Mono.empty(); } }
此处route
函数的执行者会采用DefaultRouterFunction
作为执行者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private final RequestPredicate predicate;private final HandlerFunction<T> handlerFunction;@Override public Mono<HandlerFunction<T>> route(ServerRequest request) { if (this .predicate.test(request)) { if (logger.isTraceEnabled()) { String logPrefix = request.exchange().getLogPrefix(); logger.trace(logPrefix + String.format("Matched %s" , this .predicate)); } return Mono.just(this .handlerFunction); } else { return Mono.empty(); } }
可以看到这里有一个this.predicate.test(request)
,而这个就是最核心的了,通过RequestPredicate
对请求进行判断,是否符合要求,符合要求将HandlerFunction
向外发布出去。
RequestPredicate
有多个实现子类,所有的子类都在org.springframework.web.reactive.function.server.RequestPredicates
下,有关于Http
请求类型(get、post、put等等)的验证HttpMethodPredicate
;有关于请求URL的验证PathPatternPredicate
主要说一下PathPatternPredicate
PathPatternPredicate 我的代码
1 2 3 4 5 6 7 8 9 10 @Bean (value = "NacosRouter" )public RouterFunction NacosRouter () { return route( POST(StringConst.API).and(accept(MediaType.APPLICATION_JSON_UTF8)) .and(contentType(MediaType.APPLICATION_JSON_UTF8)), nacosHandler::post) .andRoute(PUT(StringConst.API).and(accept(MediaType.APPLICATION_JSON_UTF8)) .and(contentType(MediaType.APPLICATION_JSON_UTF8)), nacosHandler::put) .andRoute(GET(StringConst.API).and(accept(MediaType.APPLICATION_JSON_UTF8)) , nacosHandler::get); }
这段代码是我的web
程序关于路由设定的
1 2 3 4 5 6 7 8 9 10 11 12 13 @Override public boolean test (ServerRequest request) { PathContainer pathContainer = request.pathContainer(); PathPattern.PathMatchInfo info = this .pattern.matchAndExtract(pathContainer); traceMatch("Pattern" , this .pattern.getPatternString(), request.path(), info != null ); if (info != null ) { mergeAttributes(request, info.getUriVariables(), this .pattern); return true ; } else { return false ; } }
根据你设定的请求URL创建一个PathContainer
对象,该对象是对URL进行结构化的表示,然后调用
1 PathPattern.PathMatchInfo info = this .pattern.matchAndExtract(pathContainer);
进行实际请求URL与设定的URL信息进行比对
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Nullable public PathMatchInfo matchAndExtract (PathContainer pathContainer) { if (this .head == null ) { return hasLength(pathContainer) && !(this .matchOptionalTrailingSeparator && pathContainerIsJustSeparator(pathContainer)) ? null : PathMatchInfo.EMPTY; } else if (!hasLength(pathContainer)) { if (this .head instanceof WildcardTheRestPathElement || this .head instanceof CaptureTheRestPathElement) { pathContainer = EMPTY_PATH; } else { return null ; } } MatchingContext matchingContext = new MatchingContext(pathContainer, true ); return this .head.matches(0 , matchingContext) ? matchingContext.getPathMatchResult() : null ; }
通过对返回的PathMatchInfo
是否为null来对本次请求匹配做判断,具体的匹配模式有很多种,具体的实现看PathElement
的子类即可。
经过以上步骤之后,再次回到DispatcherHandler
的handler
方法
1 2 3 4 5 6 7 8 9 10 11 12 @Override public Mono<Void> handle (ServerWebExchange exchange) { if (this .handlerMappings == null ) { return createNotFoundError(); } return Flux.fromIterable(this .handlerMappings) .concatMap(mapping -> mapping.getHandler(exchange)) .next() .switchIfEmpty(createNotFoundError()) .flatMap(handler -> invokeHandler(exchange, handler)) .flatMap(result -> handleResult(exchange, result)); }
这时执行完了mapping.getHandler(exchange)
方法了,然后根据返回的handler
是否为空决定是否创建Http Not Found
错误;如果handler
不为空,就是将请求信息送入对应的handler
去处理了以及获取handler
处理后的返回信息进行拦截返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 private Mono<HandlerResult> invokeHandler (ServerWebExchange exchange, Object handler) { if (this .handlerAdapters != null ) { for (HandlerAdapter handlerAdapter : this .handlerAdapters) { if (handlerAdapter.supports(handler)) { return handlerAdapter.handle(exchange, handler); } } } return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler)); } private Mono<Void> handleResult (ServerWebExchange exchange, HandlerResult result) { return getResultHandler(result).handleResult(exchange, result) .onErrorResume(ex -> result.applyExceptionHandler(ex).flatMap(exceptionResult -> getResultHandler(exceptionResult).handleResult(exchange, exceptionResult))); } private HandlerResultHandler getResultHandler (HandlerResult handlerResult) { if (this .resultHandlers != null ) { for (HandlerResultHandler resultHandler : this .resultHandlers) { if (resultHandler.supports(handlerResult)) { return resultHandler; } } } throw new IllegalStateException("No HandlerResultHandler for " + handlerResult.getReturnValue()); }