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:

  1. RocketMQ/MyCAT/Sharding-JDBC all source code analysis article list
  2. RocketMQ/MyCAT/Sharding-JDBC δΈ­ζ–‡ 解 决 source GitHub address
  3. 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.
  4. New source code parsing articles are notified in real time. It’s updated about once a week.
  5. 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:

  1. org.springframework.web.reactive.DispatcherHandler: receives the request, matching HandlerMapping, here will match to the RoutePredicateHandlerMapping.
  2. org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping: Received the request and matched the Route.
  3. 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

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

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: callWebHandler#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: SettingsGATEWAY_HANDLER_MAPPER_ATTRFor RoutePredicateHandlerMapping.
  • Line 6: Call#lookupRoute(ServerWebExchange)Method, matching the Route.
  • Lines 8 through 16: Return the Route handler FilteringWebHandler.
    • Line 14: SettingsGATEWAY_ROUTE_ATTR δΈΊmatchingThe Route.
    • Line 16: Returns FilteringWebHandler.
  • Lines 17 to 21:Can’t matchThe Route, returnMono.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: callsRouteLocator#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 themPredicate#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!