以上两种方式都不支持动态路由的方式
public class GatewayAutoConfiguration {
@Bean
public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
List<GatewayFilterFactory> gatewayFilters,
List<RoutePredicateFactory> predicates,
//PropertiesRouteDefinitionLocator、InMemoryRouteDefinitionRepository
RouteDefinitionLocator routeDefinitionLocator,
ConfigurationService configurationService) {
return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates,
gatewayFilters, properties, configurationService);
}
@Bean
@Primary
@ConditionalOnMissingBean(name = "cachedCompositeRouteLocator")
public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
//routeLocators 中包含了上述两种类型的RouteLocator
return new CachingRouteLocator(
new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
}
//发布订阅者模式
@Bean
public RouteRefreshListener routeRefreshListener(
ApplicationEventPublisher publisher) {
return new RouteRefreshListener(publisher);
}
}
RouteRefreshListener
其实例在初始化完成后会被系统调用其RouteRefreshListener#onApplicationEvent方法。RefreshRoutesEvent
事件。该事件最终会被ApplicationEventPublisher
发布者发布。RefreshRoutesEvent
事件最终会被CachingRouteLocator监听订阅。其目的就是处理CachingRouteLocator持有的多个RouteLocator。public class CompositeRouteLocator implements RouteLocator {
private final Flux<RouteLocator> delegates;
public CompositeRouteLocator(Flux<RouteLocator> delegates) {
this.delegates = delegates;
}
@Override
public Flux<Route> getRoutes() {
return this.delegates.flatMap(RouteLocator::getRoutes);
}
}
CachingRouteLocator
的代理RouteLocator。public class CachingRouteLocator
implements Ordered, RouteLocator, ApplicationListener<RefreshRoutesEvent> {
private static final String CACHE_KEY = "routes";
private final RouteLocator delegate;
private final Flux<Route> routes;
private final Map<String, List> cache = new ConcurrentHashMap<>();
public CachingRouteLocator(RouteLocator delegate) {
this.delegate = delegate;
// 1、订阅后先从缓存cache获取Route。
// 2、如果缓存中没有通过fetch获取,并将其设置到缓存cache中
routes = CacheFlux.lookup(cache, CACHE_KEY, Route.class)
.onCacheMissResume(this::fetch);
}
private Flux<Route> fetch() {
// 根据order配置对全部Route进行排序,值越小优先级越高
return this.delegate.getRoutes().sort(AnnotationAwareOrderComparator.INSTANCE);
}
// 该方法会在请求过程中通过以下方法获取服务中初始化的全部Route
@Override
public Flux<Route> getRoutes() {
return this.routes;
}
@Override
public void onApplicationEvent(RefreshRoutesEvent event) {
fetch().materialize().collect(Collectors.toList())
.doOnNext(routes -> cache.put(CACHE_KEY, routes)).subscribe();
}
public Flux<Route> refresh() {
this.cache.clear();
return this.routes;
}
}
作用:
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder){
// r:PredicateSpec
return builder.routes().route(r -> r
.path("/custom/filter/**")
.uri("lb://provider-service")
.filter(new CustomGwFilter())
.id("provider-service")).build();
}
RouteLocatorBuilder目的是创建Route。
public class RouteLocatorBuilder {
private ConfigurableApplicationContext context;
public RouteLocatorBuilder(ConfigurableApplicationContext context) {
this.context = context;
}
public Builder routes() {
return new Builder(context);
}
public static class Builder {
private List<Route.AsyncBuilder> routes = new ArrayList<>();
private ConfigurableApplicationContext context;
public Builder(ConfigurableApplicationContext context) {
this.context = context;
}
public Builder route(String id, Function<PredicateSpec, Route.AsyncBuilder> fn) {
// new RouteSpec(this).id(id):返回 PredicateSpec,可以作用于 路径 相关的断言
// 回调自定义的uri、path、filter
Route.AsyncBuilder routeBuilder = fn.apply(new RouteSpec(this).id(id));
add(routeBuilder);
return this;
}
public Builder route(Function<PredicateSpec, Route.AsyncBuilder> fn) {
Route.AsyncBuilder routeBuilder = fn.apply(new RouteSpec(this).randomId());
add(routeBuilder);
return this;
}
// 遍历集合 routes,通过响应式编程创建真正的Route
public RouteLocator build() {
return () -> Flux.fromIterable(this.routes)
.map(routeBuilder -> routeBuilder.build());
}
void add(Route.AsyncBuilder route) {
routes.add(route);
}
}
public static class RouteSpec {
private final Route.AsyncBuilder routeBuilder = Route.async();
private final Builder builder;
RouteSpec(Builder builder) {
this.builder = builder;
}
public PredicateSpec id(String id) {
this.routeBuilder.id(id);
return predicateBuilder();
}
public PredicateSpec randomId() {
return id(UUID.randomUUID().toString());
}
private PredicateSpec predicateBuilder() {
return new PredicateSpec(this.routeBuilder, this.builder);
}
}
}
public class PredicateSpec extends UriSpec {
PredicateSpec(Route.AsyncBuilder routeBuilder, RouteLocatorBuilder.Builder builder) {
super(routeBuilder, builder);//由父类UriSpec持有routeBuilder、builder
}
public BooleanSpec path(String... patterns) {
//内部方法返回DefaultAsyncPredicate
return asyncPredicate(getBean(PathRoutePredicateFactory.class)
// 调用父类RoutePredicateFactory#applyAsync
.applyAsync(c -> c.setPatterns(Arrays.asList(patterns))));
}
//predicate:DefaultAsyncPredicate
public BooleanSpec asyncPredicate(AsyncPredicate<ServerWebExchange> predicate) {
this.routeBuilder.asyncPredicate(predicate);
return new BooleanSpec(this.routeBuilder, this.builder);
}
}
public class UriSpec {
final Route.AsyncBuilder routeBuilder;
final RouteLocatorBuilder.Builder builder;
UriSpec(Route.AsyncBuilder routeBuilder, RouteLocatorBuilder.Builder builder) {
this.routeBuilder = routeBuilder;
this.builder = builder;
}
public Route.AsyncBuilder uri(String uri) {
return this.routeBuilder.uri(uri);
}
public Route.AsyncBuilder uri(URI uri) {
return this.routeBuilder.uri(uri);
}
}
public class Route implements Ordered {
private final String id;
private final URI uri;
private final int order;
private final AsyncPredicate<ServerWebExchange> predicate;
private final List<GatewayFilter> gatewayFilters;
private final Map<String, Object> metadata;
@Deprecated
private Route(String id, URI uri, int order,
AsyncPredicate<ServerWebExchange> predicate,
List<GatewayFilter> gatewayFilters) {
this(id, uri, order, predicate, gatewayFilters, new HashMap<>());
}
private Route(String id, URI uri, int order,
AsyncPredicate<ServerWebExchange> predicate,
List<GatewayFilter> gatewayFilters, Map<String, Object> metadata) {
this.id = id;
this.uri = uri;
this.order = order;
this.predicate = predicate;
this.gatewayFilters = gatewayFilters;
this.metadata = metadata;
}
public static Builder builder() {
return new Builder();
}
public static Builder builder(RouteDefinition routeDefinition) {
// @formatter:off
return new Builder().id(routeDefinition.getId())
.uri(routeDefinition.getUri())
.order(routeDefinition.getOrder())
.metadata(routeDefinition.getMetadata());
// @formatter:on
}
public static AsyncBuilder async() {
return new AsyncBuilder();
}
public static AsyncBuilder async(RouteDefinition routeDefinition) {
// @formatter:off
return new AsyncBuilder().id(routeDefinition.getId())
.uri(routeDefinition.getUri())
.order(routeDefinition.getOrder())
.metadata(routeDefinition.getMetadata());
// @formatter:on
}
public abstract static class AbstractBuilder<B extends AbstractBuilder<B>> {
protected String id;
protected URI uri;
protected int order = 0;
protected List<GatewayFilter> gatewayFilters = new ArrayList<>();
protected Map<String, Object> metadata = new HashMap<>();
protected AbstractBuilder() {
}
protected abstract B getThis();
public B uri(URI uri) {
this.uri = uri;
String scheme = this.uri.getScheme();
if (this.uri.getPort() < 0 && scheme.startsWith("http")) {
// default known http ports
int port = this.uri.getScheme().equals("https") ? 443 : 80;
this.uri = UriComponentsBuilder.fromUri(this.uri).port(port).build(false)
.toUri();
}
return getThis();
}
public B filter(GatewayFilter gatewayFilter) {
this.gatewayFilters.add(gatewayFilter);
return getThis();
}
// 由 RouteLocatorBuilder#build方法调用返回Route
public Route build() {
AsyncPredicate<ServerWebExchange> predicate = getPredicate();
return new Route(this.id, this.uri, this.order, predicate,
this.gatewayFilters, this.metadata);
}
}
public static class AsyncBuilder extends AbstractBuilder<AsyncBuilder> {
protected AsyncPredicate<ServerWebExchange> predicate;
@Override
public AsyncPredicate<ServerWebExchange> getPredicate() {
return this.predicate;
}
public AsyncBuilder predicate(Predicate<ServerWebExchange> predicate) {
return asyncPredicate(toAsyncPredicate(predicate));
}
public AsyncBuilder asyncPredicate(AsyncPredicate<ServerWebExchange> predicate) {
this.predicate = predicate;
return this;
}
this.predicate = this.predicate.and(predicate);
return this;
}
public AsyncBuilder or(AsyncPredicate<ServerWebExchange> predicate) {
this.predicate = this.predicate.or(predicate);
return this;
}
public AsyncBuilder negate() {
this.predicate = this.predicate.negate();
return this;
}
}
public static class Builder extends AbstractBuilder<Builder> {
protected Predicate<ServerWebExchange> predicate;
@Override
protected Builder getThis() {
return this;
}
@Override
public AsyncPredicate<ServerWebExchange> getPredicate() {
return ServerWebExchangeUtils.toAsyncPredicate(this.predicate);
}
public Builder and(Predicate<ServerWebExchange> predicate) {
this.predicate = this.predicate.and(predicate);
return this;
}
public Builder or(Predicate<ServerWebExchange> predicate) {
this.predicate = this.predicate.or(predicate);
return this;
}
public Builder negate() {
this.predicate = this.predicate.negate();
return this;
}
}
}
public interface RoutePredicateFactory<C> extends ShortcutConfigurable, Configurable<C> {
default AsyncPredicate<ServerWebExchange> applyAsync(Consumer<C> consumer) {
C config = newConfig();// PathRoutePredicateFactory内部静态类 Config
consumer.accept(config);// PathRoutePredicateFactory【Config】持有 路由匹配的模式 patterns 设置
beforeApply(config);
return applyAsync(config);
}
default AsyncPredicate<ServerWebExchange> applyAsync(C config) {
//PathRoutePredicateFactory#apply,返回 GatewayPredicate
return toAsyncPredicate(apply(config));//DefaultAsyncPredicate
}
}
public Predicate<ServerWebExchange> apply(Config config) {
final ArrayList<PathPattern> pathPatterns = new ArrayList<>();
synchronized (this.pathPatternParser) {
pathPatternParser.setMatchOptionalTrailingSeparator(
config.isMatchOptionalTrailingSeparator());
config.getPatterns().forEach(pattern -> {
PathPattern pathPattern = this.pathPatternParser.parse(pattern);
pathPatterns.add(pathPattern);
});
}
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange exchange) {
PathContainer path = parsePath(
exchange.getRequest().getURI().getRawPath());
Optional<PathPattern> optionalPathPattern = pathPatterns.stream()
.filter(pattern -> pattern.matches(path)).findFirst();
if (optionalPathPattern.isPresent()) {
PathPattern pathPattern = optionalPathPattern.get();
traceMatch("Pattern", pathPattern.getPatternString(), path, true);
PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(path);
putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());
return true;
}
else {
traceMatch("Pattern", config.getPatterns(), path, false);
return false;
}
}
};
}