www.iocoder.cn/Spring-Clou… “Taro source” welcome to reprint, keep the summary, thank you!
This article is based on Spring-Cloud-Gateway 2.0.x M4
- 1. An overview of the
- 2. DispatcherHandler
- 2.1 SimpleHandlerAdapter
- 3. RoutePredicateHandlerMapping
- 666. The eggs
πππ follow wechat public number:
- RocketMQ/MyCAT/Sharding-JDBC all source code analysis article list
- RocketMQ/MyCAT/Sharding-JDBC δΈζ 解 ε³ source GitHub address
- Any questions you may have about the source code will be answered carefully. Even do not know how to read the source can also ask oh.
- New source code parsing articles are notified in real time. It’s updated about once a week.
- Serious source communication wechat group.
1. An overview of the
This article mainly share RoutePredicateHandlerMapping routing matching.
Let’s take a look at how a request is handled by the Spring Cloud Gateway, as shown below:
org.springframework.web.reactive.DispatcherHandler
: receives the request, matching HandlerMapping, here will match to the RoutePredicateHandlerMapping.org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping
: Received the request and matched the Route.org.springframework.cloud.gateway.handler.FilteringWebHandler
: Obtains the GatewayFilter array of the Route and creates a GatewayFilterChain to process the request.
The first and second steps are shared in this article. The third step is shared in “Spring-Cloud-Gateway source Code Parsing — Processor (3.3) : Creating filter Chains by FilteringWebHandler”.
Recommended Spring Cloud books:
- Please support the legal version. Download piracy, is equal to the initiative to write low-level bugs.
- DD — Spring Cloud Micro Services
- Zhou Li — “Spring Cloud and Docker Micro-service Architecture Combat”
- Buy two books together, jingdong free delivery.
Spring Cloud
- Java Microservices Practices – Spring Boot
- Java Microservices Practices – Spring Cloud
- Java Microservices Practices – Spring Boot/Spring Cloud
2. DispatcherHandler
Org. Springframework. Web. Reactive. DispatcherHandler, request distribution processor, Spring WebFlux access. While this class may be unfamiliar to most of you, let’s see if its Spring MVC sibling, DispatcherServlet, feels a bit familiar.
Here is the DispatcherHandler#handle(ServerWebExchange) method:
1: public class DispatcherHandler implements WebHandler, ApplicationContextAware { 2: 3: @Nullable 4: private List<HandlerMapping> handlerMappings; 5: 6: @Nullable 7: private List<HandlerAdapter> handlerAdapters; 8: 9: @Override 10: public Mono<Void> handle(ServerWebExchange exchange) { 11: if (logger.isDebugEnabled()) { 12: ServerHttpRequest request = exchange.getRequest(); 13: logger.debug("Processing " + request.getMethodValue() + " request for [" + request.getURI() + "]"); 14: } 15: if (this.handlerMappings == null) { 16: return Mono.error(HANDLER_NOT_FOUND_EXCEPTION); 17: } 18: return Flux.fromIterable(this.handlerMappings) 19: .concatMap(mapping -> mapping.getHandler(exchange)) 20: .next() 21: .switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION)) 22: .flatMap(handler -> invokeHandler(exchange, handler)) 23: .flatMap(result -> handleResult(exchange, result)); 24:25:}}Copy the code
-
Lines 18 to 20: Obtain the corresponding WebHandler using handlerMappings in sequence.
- use
#concatMap(Function)
The reason for the operator is to considerhandlerMappings
For details, seeRxJava (4) concatMap operator instructions γ - Using official
spring-cloud-gateway-sample
Project, the point of interruption here,handlerMappings
Variable values are shown as follows: - In the γRow 19γ, call
HandlerMapping#getHandler(ServerWebExchange)
Get the Handler. In sorting, RoutePredicateHandlerMapping matching request corresponding Route, and returns FilteringWebHandler. At this point,FilteringWebHandler has not yet obtained the GatewayFilter of the Route, creating a GatewayFilterChain to process the request. This is a bit different from the first figure in this article, which mainly describes the process through which the request goes. - Line 21: If no WebHandler is matched, return
HANDLER_NOT_FOUND_EXCEPTION
γ -
Line 22: Call the #handle() method to execute the Handler. The code is as follows:
1: private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) { 2: if (this.handlerAdapters != null) { 3: for (HandlerAdapter handlerAdapter : this.handlerAdapters) { 4: if (handlerAdapter.supports(handler)) { 5: return handlerAdapter.handle(exchange, handler); 6: } 7: } 8: } 9: return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler)); 10: }Copy the code
- Using official
spring-cloud-gateway-sample
Project, the point of interruption here,handlerMappings
Variable values are shown as follows: - Lines 2 to 8:The orderMatches the HandlerAdapter by calling
HandlerAdapter#handle(ServerWebExchange, Object)
Method to execute the Handler. At this point, we will match the SimpleHandlerAdapter. - Line 9: No HandlerAdapter is matched, return IllegalStateException.
- Using official
-
Line 23: Call the #handleResult() method to process the result. SimpleHandlerAdapter returns mono.empty (), so this method is not fired. #handleResult() looks like this:
1: private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) { 2: return getResultHandler(result).handleResult(exchange, result) 3: .onErrorResume(ex -> result.applyExceptionHandler(ex).flatMap(exceptionResult -> 4: getResultHandler(exceptionResult).handleResult(exchange, exceptionResult))); 5:}Copy the code
- use
2.1 SimpleHandlerAdapter
Org. Springframework. Web. Reactive. Result. SimpleHandlerAdapter, execute WebHandler processor adapter.
The supports(Object) method looks like this:
@Override
public boolean supports(Object handler) {
return WebHandler.class.isAssignableFrom(handler.getClass());
}Copy the code
- Support WebHandler.
# Handle (ServerWebExchange, Object)
1: @Override 2: public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) { 3: WebHandler webHandler = (WebHandler) handler; 4: Mono<Void> mono = webHandler.handle(exchange); 5: return mono.then(Mono.empty()); 6:}Copy the code
- Lines 3 through 4: call
WebHandler#handle(ServerWebExchange)
Method, the execution handler. For example,If WebHandler is a FilteringWebHandler, the Route obtains the GatewayFilter array and creates a GatewayFilterChain to process the request. - Line 5: In WebHandlerAfter the execution (
#then(Mongo)
) and returnMono.empty()
γ
3. RoutePredicateHandlerMapping
Org. Springframework. Cloud. Gateway. Handler. RoutePredicateHandlerMapping, match the Route, and returns the FilteringWebHandler processing Route.
RoutePredicateHandlerMapping construction method, the code is as follows:
public class RoutePredicateHandlerMapping extends AbstractHandlerMapping { private final FilteringWebHandler webHandler; private final RouteLocator routeLocator; public RoutePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator) { this.webHandler = webHandler; this.routeLocator = routeLocator; setOrder(1); / / after the RequestMappingHandlerMapping}}Copy the code
- call
#setOrder(1)
Reason, Spring Cloud Gateway GatewayWebfluxEndpoint provide HTTP API, do not need through the Gateway, it through the RequestMappingHandlerMapping request matching process. The RequestMappingHandlerMappingorder = 0
, need ahead of RoutePredicateHandlerMapping. All, RoutePredicateHandlerMapping Settingsorder = 1
γ
The #getHandlerInternal() method, called at line 19 of the DispatcherHandler#handle(ServerWebExchange) method, matches the Route, And returns the FilteringWebHandler that handles the Route. The code is as follows:
1: @Override 2: protected Mono<? > getHandlerInternal(ServerWebExchange exchange) { 3: / / set the GATEWAY_HANDLER_MAPPER_ATTR to RoutePredicateHandlerMapping 4: exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName()); 5:6: return lookupRoute(exchange) // match Route 7: // .log("route-predicate-handler-mapping", Level.FINER) //name this 8: .flatMap((Function<Route, Mono<? >>) r -> {// Return FilteringWebHandler 9: if (logger.isDebugenabled ()) {10: logger.debug("Mapping [" + getExchangeDesc(exchange) + "] to " + r); 14: exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r); 15: // Return 16: return mono.just (webHandler); 17:}).switchIfEmpty(mono.empty ().then(mono.fromrunnable (() -> {// if (logger.istraceEnabled ()) {19: logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]"); 21:20:}}))); 22:}Copy the code
- Line 4: Settings
GATEWAY_HANDLER_MAPPER_ATTR
For RoutePredicateHandlerMapping. - Line 6: Call
#lookupRoute(ServerWebExchange)
Method, matching the Route. - Lines 8 through 16: Return the Route handler FilteringWebHandler.
- Line 14: Settings
GATEWAY_ROUTE_ATTR
δΈΊmatchingThe Route. - Line 16: Returns FilteringWebHandler.
- Line 14: Settings
- Lines 17 to 21:Can’t matchThe Route, return
Mono.empty()
That is, no processor is returned.Is there a problem with that? No, inDispatcherHandler#handle(ServerWebExchange)
Methods the γLine 21], we can see that when there is no suitable Handler, returnMono.error(HANDLER_NOT_FOUND_EXCEPTION)
γ
The lookupRoute(ServerWebExchange) method matches the Route in sequence. The code is as follows:
1: protected Mono<Route> lookupRoute(ServerWebExchange exchange) { 2: return this.routeLocator.getRoutes() 3: .filter(route -> route.getPredicate().test(exchange)) 4: .next() 5: //TODO: error handling 6: .map(route -> { 7: if (logger.isDebugEnabled()) { 8: logger.debug("RouteDefinition matched: " + route.getId()); 9: } 10: validateRoute(route, exchange); 11: return route; 12:}); 13:}Copy the code
- Lines 2 through 4: calls
RouteLocator#getRoutes()
Method to get all the routes and callPredicate#test(ServerWebExchange)
Method,The ordermatchingaThe Route. - Line 5: Future exception handling will be added during the matching process. At the moment, any of them
Predicate#test(ServerWebExchange)
The Route cannot be matched when an exception occurs in the method call of.Be careful. - Lines 6-11: call
#validateRoute(Route, ServerWebExchange)
Method to verify the validity of the Route. The current method is aEmpty methods, can be covered through inheritance RoutePredicateHandlerMapping rewrite.
666. The eggs
The DispatcherHandler source code for WebFlux.
Fat friends, share a wave of friends can be good!