spring cloud gateway 源码讲解(一)

spring cloud gateway的核心类DispatcherHandler 这个类就和springmvc的dispatcherHandler的地位是一样的,所有的请求都会经过他。他的主要方法是handler

@Override

public Mono handle(ServerWebExchange exchange) {

if (logger.isDebugEnabled()) {

ServerHttpRequest request = exchange.getRequest();

logger.debug("Processing " + request.getMethodValue() +" request for [" + request.getURI() +"]");

}

if (this.handlerMappings ==null) {

return Mono.error(HANDLER_NOT_FOUND_EXCEPTION);

}

return Flux.fromIterable(this.handlerMappings)

.concatMap(mapping -> mapping.getHandler(exchange))

.next()

.switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION))

.flatMap(handler -> invokeHandler(exchange, handler))

.flatMap(result -> handleResult(exchange, result));

}

这是核心的代码,因为spring cloud gateway 采用webflux+reactor的响应式编程的方式,所以他的代码就一行

下面将这一行代码进行分析:

一. 关键代码getHandler()

1. Flux.fromIterable(this.handlerMappings) 是获取一个handlerMapping的集合,然后对这个集合进行轮训处理

2.mapping.getHandler(exchange)这里面调用了getHandlerInternal(该方法是RoutePredicateHandlerMapping类下面的)这个就是调用了getHandlerInternal将路由放到了请求的上下文中,然后解决了跨域的问题关键代码:

public Mono getHandler(ServerWebExchange exchange) {

return getHandlerInternal(exchange).map(handler -> {

if (CorsUtils.isCorsRequest(exchange.getRequest())) {

CorsConfiguration configA =this.globalCorsConfigSource.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;

});

}

3.getHandlerInternal()方法解析:这里面的代码也是一行搞定的,关键的是lookupRoute()方法,这个方法顾名思义,是寻找路由的。这个方法就是将lookupRoute()过滤出来的route放到了exchange的GATEWAY_ROUTE_ATTR(请求的上下文中)

protected Mono getHandlerInternal(ServerWebExchange exchange) {

exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getClass().getSimpleName());

return lookupRoute(exchange)

// .log("route-predicate-handler-mapping", Level.FINER) //name this

        .flatMap((Function>) r -> {

if (logger.isDebugEnabled()) {

logger.debug("Mapping [" + getExchangeDesc(exchange) +"] to " + r);

}

exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);

return Mono.just(webHandler);

}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {

if (logger.isTraceEnabled()) {

logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) +"]");

}

})));

}

4..lookupRoute()方法又调用了RouteDefinitionRouteLocator 里面的getRoutes方法,通过getRoutes获取配置的所有的route之后,获取其中的predicate和请求exchange中的路径进行匹配,看那个满足predicate

protected Mono lookupRoute(ServerWebExchange exchange) {

return this.routeLocator.getRoutes()

.filter(route -> route.getPredicate().test(exchange))

// .defaultIfEmpty() put a static Route not found

// or .switchIfEmpty()

// .switchIfEmpty(Mono.empty().log("noroute"))

        .next()

//TODO: error handling

        .map(route -> {

if (logger.isDebugEnabled()) {

logger.debug("Route matched: " + route.getId());

}

validateRoute(route,exchange);

return route;

});

/* TODO: trace logging

if (logger.isTraceEnabled()) {

logger.trace("RouteDefinition did not match: " + routeDefinition.getId());

}*/

}

5.getRoutes()方法又调用了RouteDefinitionRouteLocator 里面的getRouteDefinitions方法,然后把获取到router使用convertToRoute方法进行过滤,convertToRoute方法就是对路由中predicate 和filter做了处理,重新生成了一个router,这个方法就是将配置文件中配置的router封装了一个router对象的集合返回。

public Flux getRoutes() {

return this.routeDefinitionLocator.getRouteDefinitions()

.map(this::convertToRoute)

//TODO: error handling

        .map(route -> {

if (logger.isDebugEnabled()) {

logger.debug("RouteDefinition matched: " + route.getId());

}

return route;

});

/* TODO: trace logging

if (logger.isTraceEnabled()) {

logger.trace("RouteDefinition did not match: " + routeDefinition.getId());

}*/

}

////////////////////////////////

private Route convertToRoute(RouteDefinition routeDefinition) {

Predicate predicate = combinePredicates(routeDefinition);

List gatewayFilters = getFilters(routeDefinition);

return Route.builder(routeDefinition)

.predicate(predicate)

.gatewayFilters(gatewayFilters)

.build();

}

6.getRoutes的关键是PropertiesRouteDefinitionLocator的getRouteDefinitions这个方法其实就是从配置文件中获取,我们在自动加载的配置文件的内容

public Flux getRouteDefinitions() {

return Flux.fromIterable(this.properties.getRoutes());

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。