Spring Cloud GateWay集成
spring-cloud-starter-gateway:路由转发、请求过滤(权限校验、限流以及监控等)
spring-boot-starter-webflux:反应式Web框架
spring-boot-starter-actuator:监控系统健康
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
动态路由
DynamicRouteServiceImpl:提供动态路由的基础方法,可通过获取bean操作该类的方法。该类提供新增路由、更新路由、删除路由,然后实现发布的功能。
1 @Service
2 public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware { 3 4 @Autowired 5 private RouteDefinitionWriter routeDefinitionWriter; 6 7 private ApplicationEventPublisher publisher; 8 9 10 /** 11 * 增加路由 12 * @param definition 13 * @return 14 */ 15 public String add(RouteDefinition definition) { 16 routeDefinitionWriter.save(Mono.just(definition)).subscribe(); 17 this.publisher.publishEvent(new RefreshRoutesEvent(this)); 18 return "success"; 19 } 20 21 22 /** 23 * 更新路由 24 * @param definition 25 * @return 26 */ 27 public String update(RouteDefinition definition) { 28 try { 29 this.routeDefinitionWriter.delete(Mono.just(definition.getId())); 30 } catch (Exception e) { 31 return "update fail,not find route routeId: "+definition.getId(); 32 } 33 try { 34 routeDefinitionWriter.save(Mono.just(definition)).subscribe(); 35 this.publisher.publishEvent(new RefreshRoutesEvent(this)); 36 return "success"; 37 } catch (Exception e) { 38 return "update route fail"; 39 } 40 41 42 } 43 /** 44 * 删除路由 45 * @param id 46 * @return 47 */ 48 public String delete(String id) { 49 try { 50 this.routeDefinitionWriter.delete(Mono.just(id)); 51 return "delete success"; 52 } catch (Exception e) { 53 e.printStackTrace(); 54 return "delete fail"; 55 } 56 57 } 58 59 @Override 60 public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { 61 this.publisher = applicationEventPublisher; 62 } 63 64 }
RouteDefinition: 提供路由实体类,主要有predicates匹配来自用户的请求,filters服务路由
@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; public RouteDefinition() {} public RouteDefinition(String text) { int eqIdx = text.indexOf("="); if (eqIdx <= 0) { throw new ValidationException("Unable to parse RouteDefinition text '" + text + "'" + ", must be of the form name=value"); } setId(text.substring(0, eqIdx)); String[] args = tokenizeToStringArray(text.substring(eqIdx+1), ","); setUri(URI.create(args[0])); for (int i=1; i < args.length; i++) { this.predicates.add(new PredicateDefinition(args[i])); } } public String getId() { return id; } public void setId(String id) { this.id = id; } public List<PredicateDefinition> getPredicates() { return predicates; } public void setPredicates(List<PredicateDefinition> predicates) { this.predicates = predicates; } public List<FilterDefinition> getFilters() { return filters; } public void setFilters(List<FilterDefinition> filters) { this.filters = filters; } public URI getUri() { return uri; } public void setUri(URI uri) { this.uri = uri; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; RouteDefinition routeDefinition = (RouteDefinition) o; return Objects.equals(id, routeDefinition.id) && Objects.equals(predicates, routeDefinition.predicates) && Objects.equals(order, routeDefinition.order) && Objects.equals(uri, routeDefinition.uri); } @Override public int hashCode() { return Objects.hash(id, predicates, uri); } @Override public String toString() { return "RouteDefinition{" + "id='" + id + '\'' + ", predicates=" + predicates + ", filters=" + filters + ", uri=" + uri + ", order=" + order + '}'; } }
NacosGatewayProperties:自定义属性绑定值,可通过配置文件配置属性。
@ConfigurationProperties(prefix="nacos", ignoreUnknownFields = true)
@Configuration
public class NacosGatewayProperties { private String address; private String dataId; private String groupId; private Long timeout; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getDataId() { return dataId; } public void setDataId(String dataId) { this.dataId = dataId; } public String getGroupId() { return groupId; } public void setGroupId(String groupId) { this.groupId = groupId; } public Long getTimeout() { return timeout; } public void setTimeout(Long timeout) { this.timeout = timeout; } }
DynamicRouteServiceImplByNacos: 实现runner,通过nacos下发动态路由配置
@Component
public class DynamicRouteServiceImplByNacos implements CommandLineRunner{ @Autowired private DynamicRouteServiceImpl dynamicRouteService; @Autowired private NacosGatewayProperties nacosGatewayProperties; /** * 监听Nacos Server下发的动态路由配置 * @param dataId * @param group */ public void dynamicRouteByNacosListener (){ try { ConfigService configService=NacosFactory.createConfigService(nacosGatewayProperties.getAddress()); String content = configService.getConfig(nacosGatewayProperties.getDataId(), nacosGatewayProperties.getGroupId(), nacosGatewayProperties.getTimeout()); System.out.println(content); configService.addListener(nacosGatewayProperties.getDataId(), nacosGatewayProperties.getGroupId(), new Listener() { @Override public void receiveConfigInfo(String configInfo) { List<RouteDefinition> list = JsonUtils.toList(configInfo, RouteDefinition.class); list.forEach(definition->{ dynamicRouteService.update(definition); }); } @Override public Executor getExecutor() { return null; } }); } catch (NacosException e) { e.printStackTrace(); } } @Override public void run(String... args) throws Exception { dynamicRouteByNacosListener(); } }
nacos属性文件定义
[
{
"id": "desk-route", "order": 0, "predicates": [ { "name": "Path", "args": { "pattern": "/blade-desk/**" } } ], "filters": [], "uri": "lb://blade-desk-me" }, { "id": "example-route", "order": 0, "predicates": [{ "name": "Path", "args": { "pattern": "/example" } }], "filters": [], "uri": "http://www.example.com" } ]