網關服務核心是將進入的請求正確合理的路由到下層具體的服務進行業務處理,因而可知網關服務的核心就是路由信息的構建。html
Spring Cloud Gateway旨在提供一種簡單而有效的方式來路由到API,併爲他們提供橫切關注點,例如:安全性,監控/指標和彈性。java
Spring Cloud Gateway 做爲 Spring Cloud 生態系統中的網關,目標是替代 Netflix Zuul,其不只提供統一的路由方式,而且基於 Filter 鏈的方式提供了網關基本的功能,例如:安全、監控、埋點和限流等。react
Spring Cloud Gateway 的特徵:web
源碼:spring
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; }
一個Route路由的基本構建塊:api
ServerWebExchange容許開發人員匹配HTTP請求中的任何內容,例如標頭或參數。
org.springframework.cloud.gateway.filter.GatewayFilter
的實例。這裏,能夠在發送下游請求以前或以後修改請求和響應。源碼:數組
@Validated public class RouteDefinition { @NotEmpty private String id = UUID.randomUUID().toString(); @NotEmpty @Valid private List<PredicateDefinition> predicates = new ArrayList(); @Valid private List<FilterDefinition> filters = new ArrayList(); @NotNull private URI uri; private int order = 0; }
PredicateDefinition : 斷言條件(謂語)定義,構建 Route 時,PredicateDefinition 轉換成 Predicate
FilterDefinition : 過濾條件的定義,構建Route 時,FilterDefinition 轉換成 GatewayFilter安全
PredicateDefinition源碼:springboot
@Validated public class PredicateDefinition { @NotNull private String name; private Map<String, String> args = new LinkedHashMap(); }
FilterDefinition源碼:websocket
@Validated public class FilterDefinition { @NotNull private String name; private Map<String, String> args = new LinkedHashMap(); }
綜合上述,Spring-Cloud-Gateway構建路由的數據流向
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,\ org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration
附註:springboot經常使用的註解的含義
執行順序
@AutoConfigureAfter:在指定的配置類初始化後再加載
@AutoConfigureBefore:在指定的配置類初始化前加載
@AutoConfigureOrder:數越小越先初始化
條件配置
@ConditionalOnClass : classpath中存在該類時起效
@ConditionalOnMissingClass : classpath中不存在該類時起效
@ConditionalOnBean : DI容器中存在該類型Bean時起效
@ConditionalOnMissingBean : DI容器中不存在該類型Bean時起效
@ConditionalOnSingleCandidate : DI容器中該類型Bean只有一個或@Primary的只有一個時起效
@ConditionalOnExpression : SpEL表達式結果爲true時
@ConditionalOnProperty : 參數設置或者值一致時起效
@ConditionalOnResource : 指定的文件存在時起效
@ConditionalOnJndi : 指定的JNDI存在時起效
@ConditionalOnJava : 指定的Java版本存在時起效
@ConditionalOnWebApplication : Web應用環境下起效
@ConditionalOnNotWebApplication : 非Web應用環境下起效
配置文件分析
GatewayClassPathWarningAutoConfiguration配置用於檢查項目是否正確導入 spring-boot-starter-webflux 依賴,而不是錯誤導入 spring-boot-starter-web 依賴,同時 GatewayClassPathWarningAutoConfiguration配置在EnableAutoConfiguration配置加載前加載。
@Configuration //執行順序註解 //當前註解標識須要在GatewayAutoConfiguration前加載此配置 @AutoConfigureBefore({GatewayAutoConfiguration.class}) public class GatewayClassPathWarningAutoConfiguration { private static final Log log = LogFactory.getLog(GatewayClassPathWarningAutoConfiguration.class); private static final String BORDER = "\n\n**********************************************************\n\n"; public GatewayClassPathWarningAutoConfiguration() {} @Configuration //條件判斷註解 //classpath中不存在org.springframework.web.reactive.DispatcherHandler時起效,標識項目未導入了spring-boot-starter-webflux包 @ConditionalOnMissingClass({"org.springframework.web.reactive.DispatcherHandler"}) protected static class WebfluxMissingFromClasspathConfiguration { public WebfluxMissingFromClasspathConfiguration() { GatewayClassPathWarningAutoConfiguration.log.warn("\n\n**********************************************************
\n\nSpring Webflux is missing from the classpath, which is required for Spring Cloud Gateway at this time. Please add spring-boot-starter-webflux dependency.\n\n**********************************************************\n\n"); } } @Configuration //條件判斷註解 //classpath中存在org.springframework.web.servlet.DispatcherServlet時起效,標識項目導入了spring-boot-starter-web包 @ConditionalOnClass(name = {"org.springframework.web.servlet.DispatcherServlet"}) protected static class SpringMvcFoundOnClasspathConfiguration { public SpringMvcFoundOnClasspathConfiguration() { GatewayClassPathWarningAutoConfiguration.log.warn("\n\n**********************************************************
\n\nSpring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. Please remove spring-boot-starter-web dependency.\n\n**********************************************************\n\n"); } } }
@Configuration //條件判斷註解 //classpath中存在LoadBalancerClient和RibbonAutoConfiguration和DispatcherHandler時此配置起效 @ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class, DispatcherHandler.class}) //執行順序註解 @AutoConfigureAfter({RibbonAutoConfiguration.class}) public class GatewayLoadBalancerClientAutoConfiguration { public GatewayLoadBalancerClientAutoConfiguration() { } // GlobalFilter beans @Bean //條件判斷註解 //DI容器中存在LoadBalancerClient類型Bean時起效 @ConditionalOnBean({LoadBalancerClient.class}) public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client) { return new LoadBalancerClientFilter(client); } }
GatewayAutoConfiguration配置是Spring Cloud Gateway 核心配置類,初始化以下 :
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.cloud.gateway.config; import com.netflix.hystrix.HystrixObservableCommand; import io.netty.channel.ChannelOption; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import java.security.cert.X509Certificate; import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint; import org.springframework.cloud.gateway.config.HttpClientProperties.Pool; import org.springframework.cloud.gateway.config.HttpClientProperties.Proxy; import org.springframework.cloud.gateway.config.HttpClientProperties.Ssl; import org.springframework.cloud.gateway.config.HttpClientProperties.Pool.PoolType; import org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter; import org.springframework.cloud.gateway.filter.ForwardPathFilter; import org.springframework.cloud.gateway.filter.ForwardRoutingFilter; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.NettyRoutingFilter; import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter; import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter; import org.springframework.cloud.gateway.filter.WebsocketRoutingFilter; import org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter; import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SecureHeadersProperties; import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory; import org.springframework.cloud.gateway.filter.headers.ForwardedHeadersFilter; import org.springframework.cloud.gateway.filter.headers.HttpHeadersFilter; import org.springframework.cloud.gateway.filter.headers.RemoveHopByHopHeadersFilter; import org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilter; import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; import org.springframework.cloud.gateway.filter.ratelimit.PrincipalNameKeyResolver; import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter; import org.springframework.cloud.gateway.handler.FilteringWebHandler; import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; import org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.CloudFoundryRouteServiceRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory; import org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.WeightRoutePredicateFactory; import org.springframework.cloud.gateway.route.CachingRouteLocator; import org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator; import org.springframework.cloud.gateway.route.CompositeRouteLocator; import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository; import org.springframework.cloud.gateway.route.RouteDefinitionLocator; import org.springframework.cloud.gateway.route.RouteDefinitionRepository; import org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator; import org.springframework.cloud.gateway.route.RouteDefinitionWriter; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.RouteRefreshListener; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Primary; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.StringUtils; import org.springframework.validation.Validator; import org.springframework.web.reactive.DispatcherHandler; import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; import org.springframework.web.reactive.socket.client.WebSocketClient; import org.springframework.web.reactive.socket.server.WebSocketService; import org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService; import reactor.core.publisher.Flux; import reactor.ipc.netty.http.client.HttpClient; import reactor.ipc.netty.http.client.HttpClientOptions.Builder; import reactor.ipc.netty.resources.PoolResources; import rx.RxReactiveStreams; @Configuration @ConditionalOnProperty( name = {"spring.cloud.gateway.enabled"}, matchIfMissing = true ) @EnableConfigurationProperties @AutoConfigureBefore({HttpHandlerAutoConfiguration.class}) @AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class}) @ConditionalOnClass({DispatcherHandler.class}) public class GatewayAutoConfiguration { public GatewayAutoConfiguration() { } @Bean public RouteLocatorBuilder routeLocatorBuilder(ConfigurableApplicationContext context) { return new RouteLocatorBuilder(context); } @Bean @ConditionalOnMissingBean public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) { return new PropertiesRouteDefinitionLocator(properties); } @Bean @ConditionalOnMissingBean({RouteDefinitionRepository.class}) public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() { return new InMemoryRouteDefinitionRepository(); } @Bean @Primary public RouteDefinitionLocator routeDefinitionLocator(List<RouteDefinitionLocator> routeDefinitionLocators) { return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators)); } @Bean public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties, List<GatewayFilterFactory> GatewayFilters, List<RoutePredicateFactory> predicates, RouteDefinitionLocator routeDefinitionLocator) { return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties); } @Bean @Primary public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) { return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators))); } @Bean public RouteRefreshListener routeRefreshListener(ApplicationEventPublisher publisher) { return new RouteRefreshListener(publisher); } @Bean public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) { return new FilteringWebHandler(globalFilters); } @Bean public GlobalCorsProperties globalCorsProperties() { return new GlobalCorsProperties(); } @Bean public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties) { return new RoutePredicateHandlerMapping(webHandler, routeLocator, globalCorsProperties); } @Bean public GatewayProperties gatewayProperties() { return new GatewayProperties(); } @Bean public SecureHeadersProperties secureHeadersProperties() { return new SecureHeadersProperties(); } @Bean @ConditionalOnProperty( name = {"spring.cloud.gateway.forwarded.enabled"}, matchIfMissing = true ) public ForwardedHeadersFilter forwardedHeadersFilter() { return new ForwardedHeadersFilter(); } @Bean public RemoveHopByHopHeadersFilter removeHopByHopHeadersFilter() { return new RemoveHopByHopHeadersFilter(); } @Bean @ConditionalOnProperty( name = {"spring.cloud.gateway.x-forwarded.enabled"}, matchIfMissing = true ) public XForwardedHeadersFilter xForwardedHeadersFilter() { return new XForwardedHeadersFilter(); } @Bean public AdaptCachedBodyGlobalFilter adaptCachedBodyGlobalFilter() { return new AdaptCachedBodyGlobalFilter(); } @Bean public RouteToRequestUrlFilter routeToRequestUrlFilter() { return new RouteToRequestUrlFilter(); } @Bean @ConditionalOnBean({DispatcherHandler.class}) public ForwardRoutingFilter forwardRoutingFilter(DispatcherHandler dispatcherHandler) { return new ForwardRoutingFilter(dispatcherHandler); } @Bean public ForwardPathFilter forwardPathFilter() { return new ForwardPathFilter(); } @Bean public WebSocketService webSocketService() { return new HandshakeWebSocketService(); } @Bean public WebsocketRoutingFilter websocketRoutingFilter(WebSocketClient webSocketClient, WebSocketService webSocketService, ObjectProvider<List<HttpHeadersFilter>> headersFilters) { return new WebsocketRoutingFilter(webSocketClient, webSocketService, headersFilters); } @Bean public WeightCalculatorWebFilter weightCalculatorWebFilter(Validator validator) { return new WeightCalculatorWebFilter(validator); } @Bean public AfterRoutePredicateFactory afterRoutePredicateFactory() { return new AfterRoutePredicateFactory(); } @Bean public BeforeRoutePredicateFactory beforeRoutePredicateFactory() { return new BeforeRoutePredicateFactory(); } @Bean public BetweenRoutePredicateFactory betweenRoutePredicateFactory() { return new BetweenRoutePredicateFactory(); } @Bean public CookieRoutePredicateFactory cookieRoutePredicateFactory() { return new CookieRoutePredicateFactory(); } @Bean public HeaderRoutePredicateFactory headerRoutePredicateFactory() { return new HeaderRoutePredicateFactory(); } @Bean public HostRoutePredicateFactory hostRoutePredicateFactory() { return new HostRoutePredicateFactory(); } @Bean public MethodRoutePredicateFactory methodRoutePredicateFactory() { return new MethodRoutePredicateFactory(); } @Bean public PathRoutePredicateFactory pathRoutePredicateFactory() { return new PathRoutePredicateFactory(); } @Bean public QueryRoutePredicateFactory queryRoutePredicateFactory() { return new QueryRoutePredicateFactory(); } @Bean public ReadBodyPredicateFactory readBodyPredicateFactory(ServerCodecConfigurer codecConfigurer) { return new ReadBodyPredicateFactory(codecConfigurer); } @Bean public RemoteAddrRoutePredicateFactory remoteAddrRoutePredicateFactory() { return new RemoteAddrRoutePredicateFactory(); } @Bean @DependsOn({"weightCalculatorWebFilter"}) public WeightRoutePredicateFactory weightRoutePredicateFactory() { return new WeightRoutePredicateFactory(); } @Bean public CloudFoundryRouteServiceRoutePredicateFactory cloudFoundryRouteServiceRoutePredicateFactory() { return new CloudFoundryRouteServiceRoutePredicateFactory(); } @Bean public AddRequestHeaderGatewayFilterFactory addRequestHeaderGatewayFilterFactory() { return new AddRequestHeaderGatewayFilterFactory(); } @Bean public AddRequestParameterGatewayFilterFactory addRequestParameterGatewayFilterFactory() { return new AddRequestParameterGatewayFilterFactory(); } @Bean public AddResponseHeaderGatewayFilterFactory addResponseHeaderGatewayFilterFactory() { return new AddResponseHeaderGatewayFilterFactory(); } @Bean public ModifyRequestBodyGatewayFilterFactory modifyRequestBodyGatewayFilterFactory(ServerCodecConfigurer codecConfigurer) { return new ModifyRequestBodyGatewayFilterFactory(codecConfigurer); } @Bean public ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory(ServerCodecConfigurer codecConfigurer) { return new ModifyResponseBodyGatewayFilterFactory(codecConfigurer); } @Bean public PrefixPathGatewayFilterFactory prefixPathGatewayFilterFactory() { return new PrefixPathGatewayFilterFactory(); } @Bean public PreserveHostHeaderGatewayFilterFactory preserveHostHeaderGatewayFilterFactory() { return new PreserveHostHeaderGatewayFilterFactory(); } @Bean public RedirectToGatewayFilterFactory redirectToGatewayFilterFactory() { return new RedirectToGatewayFilterFactory(); } @Bean public RemoveRequestHeaderGatewayFilterFactory removeRequestHeaderGatewayFilterFactory() { return new RemoveRequestHeaderGatewayFilterFactory(); } @Bean public RemoveResponseHeaderGatewayFilterFactory removeResponseHeaderGatewayFilterFactory() { return new RemoveResponseHeaderGatewayFilterFactory(); } @Bean( name = {"principalNameKeyResolver"} ) @ConditionalOnBean({RateLimiter.class}) public PrincipalNameKeyResolver principalNameKeyResolver() { return new PrincipalNameKeyResolver(); } @Bean @ConditionalOnBean({RateLimiter.class, KeyResolver.class}) public RequestRateLimiterGatewayFilterFactory requestRateLimiterGatewayFilterFactory(RateLimiter rateLimiter, PrincipalNameKeyResolver resolver) { return new RequestRateLimiterGatewayFilterFactory(rateLimiter, resolver); } @Bean public RewritePathGatewayFilterFactory rewritePathGatewayFilterFactory() { return new RewritePathGatewayFilterFactory(); } @Bean public RetryGatewayFilterFactory retryGatewayFilterFactory() { return new RetryGatewayFilterFactory(); } @Bean public SetPathGatewayFilterFactory setPathGatewayFilterFactory() { return new SetPathGatewayFilterFactory(); } @Bean public SecureHeadersGatewayFilterFactory secureHeadersGatewayFilterFactory(SecureHeadersProperties properties) { return new SecureHeadersGatewayFilterFactory(properties); } @Bean public SetRequestHeaderGatewayFilterFactory setRequestHeaderGatewayFilterFactory() { return new SetRequestHeaderGatewayFilterFactory(); } @Bean public SetResponseHeaderGatewayFilterFactory setResponseHeaderGatewayFilterFactory() { return new SetResponseHeaderGatewayFilterFactory(); } @Bean public SetStatusGatewayFilterFactory setStatusGatewayFilterFactory() { return new SetStatusGatewayFilterFactory(); } @Bean public SaveSessionGatewayFilterFactory saveSessionGatewayFilterFactory() { return new SaveSessionGatewayFilterFactory(); } @Bean public StripPrefixGatewayFilterFactory stripPrefixGatewayFilterFactory() { return new StripPrefixGatewayFilterFactory(); } @Bean public RequestHeaderToRequestUriGatewayFilterFactory requestHeaderToRequestUriGatewayFilterFactory() { return new RequestHeaderToRequestUriGatewayFilterFactory(); } @Configuration @ConditionalOnClass({Health.class}) protected static class GatewayActuatorConfiguration { protected GatewayActuatorConfiguration() { } @Bean @ConditionalOnEnabledEndpoint public GatewayControllerEndpoint gatewayControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator, List<GlobalFilter> globalFilters, List<GatewayFilterFactory> GatewayFilters, RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) { return new GatewayControllerEndpoint(routeDefinitionLocator, globalFilters, GatewayFilters, routeDefinitionWriter, routeLocator); } } @Configuration @ConditionalOnClass({HystrixObservableCommand.class, RxReactiveStreams.class}) protected static class HystrixConfiguration { protected HystrixConfiguration() { } @Bean public HystrixGatewayFilterFactory hystrixGatewayFilterFactory(DispatcherHandler dispatcherHandler) { return new HystrixGatewayFilterFactory(dispatcherHandler); } } @Configuration @ConditionalOnClass({HttpClient.class}) protected static class NettyConfiguration { protected NettyConfiguration() { } @Bean @ConditionalOnMissingBean public HttpClient httpClient(@Qualifier("nettyClientOptions") Consumer<? super Builder> options) { return HttpClient.create(options); } @Bean public Consumer<? super Builder> nettyClientOptions(HttpClientProperties properties) { return (opts) -> { if (properties.getConnectTimeout() != null) { opts.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, properties.getConnectTimeout()); } Ssl ssl = properties.getSsl(); X509Certificate[] trustedX509Certificates = ssl.getTrustedX509CertificatesForTrustManager(); if (trustedX509Certificates.length > 0) { opts.sslSupport((sslContextBuilder) -> { sslContextBuilder.trustManager(trustedX509Certificates); }); } else if (ssl.isUseInsecureTrustManager()) { opts.sslSupport((sslContextBuilder) -> { sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE); }); } Pool pool = properties.getPool(); if (pool.getType() == PoolType.DISABLED) { opts.disablePool(); } else { PoolResources poolResources; if (pool.getType() == PoolType.FIXED) { poolResources = PoolResources.fixed(pool.getName(), pool.getMaxConnections(), pool.getAcquireTimeout()); opts.poolResources(poolResources); } else { poolResources = PoolResources.elastic(pool.getName()); opts.poolResources(poolResources); } } Proxy proxy = properties.getProxy(); if (StringUtils.hasText(proxy.getHost())) { opts.proxy((typeSpec) -> { reactor.ipc.netty.options.ClientProxyOptions.Builder builder = typeSpec.type(reactor.ipc.netty.options.ClientProxyOptions.Proxy.HTTP).host(proxy.getHost()); PropertyMapper map = PropertyMapper.get(); proxy.getClass(); map.from(proxy::getPort).whenNonNull().to(builder::port); proxy.getClass(); map.from(proxy::getUsername).whenHasText().to(builder::username); proxy.getClass(); map.from(proxy::getPassword).whenHasText().to((password) -> { builder.password((s) -> { return password; }); }); proxy.getClass(); map.from(proxy::getNonProxyHostsPattern).whenHasText().to(builder::nonProxyHosts); return builder; }); } }; } @Bean public HttpClientProperties httpClientProperties() { return new HttpClientProperties(); } @Bean public NettyRoutingFilter routingFilter(HttpClient httpClient, ObjectProvider<List<HttpHeadersFilter>> headersFilters, HttpClientProperties properties) { return new NettyRoutingFilter(httpClient, headersFilters, properties); } @Bean public NettyWriteResponseFilter nettyWriteResponseFilter(GatewayProperties properties) { return new NettyWriteResponseFilter(properties.getStreamingMediaTypes()); } @Bean public ReactorNettyWebSocketClient reactorNettyWebSocketClient(@Qualifier("nettyClientOptions") Consumer<? super Builder> options) { return new ReactorNettyWebSocketClient(options); } } }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.cloud.gateway.discovery; import java.util.ArrayList; import java.util.List; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration; import org.springframework.cloud.gateway.config.GatewayAutoConfiguration; import org.springframework.cloud.gateway.filter.FilterDefinition; import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory; import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.springframework.cloud.gateway.support.NameUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.DispatcherHandler; @Configuration @ConditionalOnProperty( name = {"spring.cloud.gateway.enabled"}, matchIfMissing = true ) @AutoConfigureBefore({GatewayAutoConfiguration.class}) @AutoConfigureAfter({CompositeDiscoveryClientAutoConfiguration.class}) @ConditionalOnClass({DispatcherHandler.class, DiscoveryClient.class}) @EnableConfigurationProperties public class GatewayDiscoveryClientAutoConfiguration { public GatewayDiscoveryClientAutoConfiguration() { } @Bean @ConditionalOnBean({DiscoveryClient.class}) @ConditionalOnProperty( name = {"spring.cloud.gateway.discovery.locator.enabled"} ) public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) { return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties); } @Bean public DiscoveryLocatorProperties discoveryLocatorProperties() { DiscoveryLocatorProperties properties = new DiscoveryLocatorProperties(); properties.setPredicates(initPredicates()); properties.setFilters(initFilters()); return properties; } public static List<PredicateDefinition> initPredicates() { ArrayList<PredicateDefinition> definitions = new ArrayList(); PredicateDefinition predicate = new PredicateDefinition(); predicate.setName(NameUtils.normalizeRoutePredicateName(PathRoutePredicateFactory.class)); predicate.addArg("pattern", "'/'+serviceId+'/**'"); definitions.add(predicate); return definitions; } public static List<FilterDefinition> initFilters() { ArrayList<FilterDefinition> definitions = new ArrayList(); FilterDefinition filter = new FilterDefinition(); filter.setName(NameUtils.normalizeFilterFactoryName(RewritePathGatewayFilterFactory.class)); String regex = "'/' + serviceId + '/(?<remaining>.*)'"; String replacement = "'/${remaining}'"; filter.addArg("regexp", regex); filter.addArg("replacement", replacement); definitions.add(filter); return definitions; } }
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
關閉:spring.cloud.gateway.enabled=false
注意:Spring Cloud Gateway須要Spring Boot和Spring Webflux提供的Netty運行時。它不能在傳統的Servlet容器中工做或構建爲WAR。