Spring Cloud Gateway官方教程講的都是提早在配置文件中配置網關,實際項目中,Spring Cloud Gateway做爲微服務的入口,須要儘可能避免重啓,因此咱們須要在Spring Cloud Gateway運行時動態配置網關。java
須要JAVA Spring Cloud大型企業分佈式微服務雲構建的B2B2C電子商務平臺源碼 一零三八七七四六二六react
Spring Cloud Gateway自帶接口web
Spring Cloud Gateway在2018年6月份發佈了2.0第一個release版本,官方文檔並無講如何動態配置,翻看Spring Cloud Gateway源碼,發現類org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint中提供了網關配置Restful接口,默認沒有啓用。在類org.springframework.cloud.gateway.config.GatewayAutoConfiguration中配置了GatewayControllerEndpointspring
@Configuration
@ConditionalOnClass(Health.class)
protected static class 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);
}
}
複製代碼
存在org.springframework.boot.actuate.health.Health時啓用,添加actuator依賴:編程
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
複製代碼
在gateway項目的application.yml中啓用gateway api:api
#開啓actuator管理api,後面要關閉bash
management:
endpoints:
web:
exposure:
include:
複製代碼
編碼方式app
不過這裏咱們不打算用自帶的Restful接口,一來官方文檔也沒說新增網關參數怎麼傳,再者咱們也不但願在網關暴露這些接口。參照org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint,咱們本身編程來動態改變網關。分佈式
直接上代碼:ide
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
@Service
public class TestGatewayService implements ApplicationEventPublisherAware {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
private ApplicationEventPublisher publisher;
public String save() {
RouteDefinition definition = new RouteDefinition();
PredicateDefinition predicate = new PredicateDefinition();
Map<String, String> predicateParams = new HashMap<>(8);
definition.setId("baiduRoute");
predicate.setName("Path");
predicateParams.put("pattern", "/baidu");
predicateParams.put("pathPattern", "/baidu");
predicate.setArgs(predicateParams);
definition.setPredicates(Arrays.asList(predicate));
URI uri = UriComponentsBuilder.fromHttpUrl("http://www.baidu.com").build().toUri();
definition.setUri(uri);
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
}
複製代碼
代碼說明:
一、predicate.setName("Path"); 設置predicat名稱,這個名稱不是亂起的,Spring會根據名稱去查找對應的FilterFactory,目前支持的名稱有:After、Before、Between、Cookie、Header、Host、Method、Path、Query、RemoteAddr。
二、definition.setId("baiduRoute"); 設置definition的id,須要全局惟一,默認使用UUID。
三、predicateParams.put("pattern", "/baidu"); 每一個Route Predicate的參數不一樣,詳情在官網文檔查看對應的Route Predicate配置示例,然而官方文檔也很坑,好比Path Route的- Path=/foo/{segment},把參數給省略了。仍是得看源碼,在包org.springframework.cloud.gateway.handler.predicate裏有Spring Cloud Gateway全部的Predicate,打開對應的RoutePredicateFactory,內部類Config就是該Predicate支持的參數。
四、routeDefinitionWriter.save(Mono.just(definition)).subscribe(); 默認的RouteDefinitionWriter實現類是org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository。注意最後必定要調用subscribe(),不然不執行。
至此已編碼動態配置了一個基本的網關。 java B2B2C Springcloud仿淘寶電子商城系統