基于SpringCloudGateway的动态路由配置

tech2022-10-21  110

该项目基于SpringBoot+Eureka+Mybaties实现动态路由。

1、引入SpringCloudGateway的maven依赖:

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <version>2.1.2.RELEASE</version> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-gateway-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <artifactId>spring-cloud-gateway-core</artifactId> <groupId>org.springframework.cloud</groupId> <version>2.1.2.RELEASE</version> </dependency> <!-- 引入健康监控依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>2.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> <scope>runtime</scope> </dependency> <!--阿里数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.14</version> </dependency> <!-- mybatis --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>2.1.5</version> </dependency>

若引入其他base项目,请排除对 spring-boot-starter-web 的依赖:

<exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </exclusion> </exclusions>

2、基础数据结构构建

路由配置表结构:

CREATE TABLE `gateway_route` ( `id` bigint(20) NOT NULL COMMENT '主键', `route_name` varchar(500) NOT NULL COMMENT '路由名称', `predicates` varchar(500) DEFAULT NULL COMMENT '路由断言', `filters` varchar(500) DEFAULT NULL COMMENT '过滤器', `service_uri` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '服务定位符 lb://XXX', `route_order` int(6) DEFAULT NULL COMMENT '优先级', `status` int(3) NOT NULL DEFAULT '1' COMMENT '状态: 1-有效,2-无效', `create_by` varchar(30) NOT NULL COMMENT '创建人', `create_time` datetime NOT NULL COMMENT '创建日期', `modify_by` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '更新人', `modify_time` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='服务路由'; //数据如下: INSERT INTO gateway_route (`id`, `route_name`, `predicates`, `filters`, `service_uri`, `route_order`, `status`, `create_by`, `create_time`, `modify_by`, `modify_time`) VALUES ('202009011800', 'sys', '[{\"name\": \"Path\",\"args\": {\"pattern\": \"/sys/**\"}}]', '[{\"name\": \"RewritePath\",\"args\": {\"regexp\": \"/sys/(?<remaining>.*)\",\"replacement\": \"/${remaining}\"}}]', 'lb://appl-zb-hospital-system', '0', '1', 'sys', '2020-09-01 17:59:21', NULL, NULL);

3、项目配置:

spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://XX.XX.XX.XX:3306/dbName?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: password server: port: xxx ssl: #ssl配置,若gateway使用HTTPS,需要添加如下配置, #注意若使用该方式 服务实例向Eureka注册时应开启安全通信的端口 key-store: classpath:xxx.pfx key-store-password: xxx key-store-type: xxx enabled: true mybatis: #对应项目中的model对应位置 type-aliases-package: com.xxx.gateway.model #对应项目中xxxMapper.xml对应位置,一般为 resources/mapper/ mapper-locations: classpath*:mapper/**/*Mapper.xml logging: level: #打印输出执行sql 对应xxxxMapper.java 路径 com.xxxx.gateway.mapper: debug

4、项目相关Bean的配置:

@EnableDiscoveryClient @EnableEurekaClient //@MapperScan("com.xxxx.gateway.mapper") 扫描 mybaties对应的 xxxxMapper.java 亦可在对应类上使用@Mapper注解 @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } //路由定义定位器,用以加载路由信息到内存中 @Bean public InMemoryRouteDefinitionRepository routeDefinitionRepository() { return new InMemoryRouteDefinitionRepository(); } }

5、路由信息加载(GatewayServiceImpl):

@Autowired private InMemoryRouteDefinitionRepository routeDefinitionRepository; @Autowired private GatewayRouteMapper gatewayRouteMapper; /** * 加载数据库路由信息到内存 * @return * @throws Exception */ @Override public String loadRouteDefinition() throws Exception { try { //获取数据库中路由配置信息 List<GatewayRoute> gatewayRouteList = gatewayRouteMapper.getRoutes(); for (GatewayRoute gatewayRoute: gatewayRouteList) { //将库中路由信息封装为RouteDefinition对象,加载到内存中 RouteDefinition definition = assembleRouteDefinition(gatewayRoute); if(definition!=null){ routeDefinitionRepository.save(Mono.just(definition)).subscribe(); } } return "success"; } catch (Exception e) { log.error("Exception: ",e); return "failure"; } } /** * 封装成为 RouteDefinition 对象 * @param gatewayDefine * @return */ private RouteDefinition assembleRouteDefinition(GatewayRoute gatewayRoute) { RouteDefinition definition = new RouteDefinition(); definition.setId(gatewayRoute.getId()); definition.setOrder(gatewayRoute.getRouteOrder()); if(StringUtils.isEmpty(gatewayRoute.getPredicates()) || StringUtils.isEmpty(gatewayRoute.getFilters()) || StringUtils.isEmpty(gatewayRoute.getServiceUri())){ return null; } if(gatewayRoute.getPredicateDefinition().size()>0) definition.setPredicates(gatewayRoute.getPredicateDefinition()); if(gatewayRoute.getFilterDefinition().size()>0) definition.setFilters(gatewayRoute.getFilterDefinition()); URI uri = UriComponentsBuilder.fromUriString(gatewayRoute.getServiceUri()).build().toUri(); definition.setUri(uri); return definition; }

6、启动路由加载配置:

@Component public class ApplicationStartup implements ApplicationRunner { private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationStartup.class); @Autowired private GatewayService gatewayService; @Override public void run(ApplicationArguments args) throws Exception { //调用上述方法 gatewayService.loadRouteDefinition(); } }

之后启动项目,查看加载路由信息:

https://localhost:xxx/actuator/gateway/routes

最新回复(0)