Spring Cloud Gateway动态路由实现
在实现动态路由之前,你至少能搭建一个简单的Gateway
项目,并对其有一定的了解,具体可以参考Spring Cloud Gateway 入门学习
本文要实现的动态路由为在数据库中存储路由配置,并提供一个页面可以配置路由。
准备工作
数据库脚本(以下脚本针对PostgreSQL
数据库,脚本源文件地址):
1 2 3 4 5 6 7 8 9 10 11 12
| create schema db_base;
create table db_base.t_route( c_id varchar(300) primary key not null, c_name varchar(300) not null, c_predicates varchar(1200), c_url varchar(900) not null, c_filters varchar(1200) );
INSERT INTO "db_base"."t_route"("c_id", "c_name", "c_predicates", "c_url", "c_filters") VALUES ('scs-blog', '我的博客', '["Path=/blog/**"]', 'https://jiangliuhong.top/', '["RewritePath=/blog(?<segment>/?.*), $\\{segment}"]');
|
在Gateway
中追加以下依赖:
1 2 3 4 5 6 7 8 9 10 11 12
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency>
|
修改application.yml
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| spring: datasource: url: jdbc:postgresql://127.0.0.1:5432/scs username: sa password: 6789@jkl type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.postgresql.Driver druid: initial-size: 5 min-idle: 5 max-active: 20 validation-query: select version() jpa: database: postgresql show-sql: true properties: hibernate: hbm2ddl: auto: update
|
核心方法
Gateway源码地址:https://github.com/jiangliuhong/springcloud-stu/tree/master/scs-gateway
RouteService
原文件地址:https://github.com/jiangliuhong/springcloud-stu/blob/master/scs-gateway/src/main/java/top/jiangliuhong/scs/gateway/service/RouteService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| @Service public class RouteService {
private static final Logger logger = LoggerFactory.getLogger(RouteService.class);
@Resource private RouteRepository routeRepository;
@Autowired private RouteDefinitionWriter routeDefinitionWriter;
public void loadRoute() { List<Route> routes = getRoutes(); if (CollectionUtils.isEmpty(routes)) { logger.warn("当前没有路由需要加载"); return; } for (Route route : routes) { RouteDefinition definition = new RouteDefinition(); definition.setId(route.getId()); try { definition.setUri(new URI(route.getUrl())); } catch (URISyntaxException e) { logger.error("初始化uri失败:" + route.getUrl(), e); continue; } if (StringUtils.isBlank(route.getPredicates())) { logger.warn("{}[{}]的Predicates为空", route.getId(), route.getName()); continue; } List<PredicateDefinition> predicates = Lists.newArrayList(); List<String> predicatesList = JSON.parseArray(route.getPredicates(), String.class); for (String p : predicatesList) { predicates.add(new PredicateDefinition(p)); } definition.setPredicates(predicates); if (StringUtils.isNotBlank(route.getFilters())) { List<FilterDefinition> filters = Lists.newArrayList(); List<String> filtersList = JSON.parseArray(route.getFilters(), String.class); for (String f : filtersList) { filters.add(new FilterDefinition(f)); } definition.setFilters(filters); } routeDefinitionWriter.save(Mono.just(definition)).subscribe(); } ApplicationEventUtils.pushEvent(new RefreshRoutesEvent(this)); } }
|
RouteRunner
启动时加载数据库路由
1 2 3 4 5 6 7 8 9 10 11
| @Component @Order(Ordered.HIGHEST_PRECEDENCE) public class RouteRunner implements CommandLineRunner { @Autowired private RouteService routeService;
@Override public void run(String... args) throws Exception { routeService.loadRoute(); } }
|
前端页面
前端源码:https://github.com/jiangliuhong/springcloud-stu/tree/master/scs-websource/scsweb-gateway
