SpringCloud Gateway设计改造
因为要做一个兼容多网络协议,多报文兼容的动态网关
设计架构
动态路由相关设置类
RouteDefinitionRepository
路由存储器
用于存储路由规则的接口,通过实现它,可以进行自定义存储路由规则到不同的中间件(redis/db等)
实现三个方法
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
| @Component public class RedisRouteDefinitionRepository implements RouteDefinitionRepository { private static final Logger log = LoggerFactory.getLogger(RedisRouteDefinitionRepository.class); public static final String GATEWAY_ROUTES = CacheConstants.GATEWAY_ROUTES; @Autowired private RedisService redisService;
@Override public Flux<RouteDefinition> getRouteDefinitions() { log.debug("get route info by redis/db"); List<RouteDefinition> routeDefinitions = new ArrayList<>(); redisService.getAllCacheMapValues(GATEWAY_ROUTES).stream().forEach(routeDefinition -> { routeDefinitions.add(JSON.parseObject(routeDefinition.toString(), RouteDefinition.class)); }); return Flux.fromIterable(routeDefinitions); }
@Override public Mono<Void> save(Mono<RouteDefinition> route) { log.debug("save route info to redis/db"); return route.flatMap(routeDefinition -> { redisService.setCacheMapValue(GATEWAY_ROUTES, routeDefinition.getId(), JSON.toJSONString(routeDefinition)); return Mono.empty(); }); }
@Override public Mono<Void> delete(Mono<String> routeId) { log.debug("delete route info by redis/db"); return routeId.flatMap(id -> { if (redisService.getCacheMapValue(GATEWAY_ROUTES, id)) { redisService.delCacheMapValue(GATEWAY_ROUTES, id); return Mono.empty(); } return Mono.defer(() -> Mono.error(new BaseException("路由配置没有找到: " + routeId))); }); } }
|
ApplicationEventPublisherAware
事件发布接口
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
| @Service public class GatewayServiceHandler implements ApplicationEventPublisherAware { private static final Logger log = LoggerFactory.getLogger(GatewayServiceHandler.class);
@Autowired private RedisRouteDefinitionRepository routeDefinitionWriter;
private ApplicationEventPublisher publisher;
@Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.publisher = applicationEventPublisher; }
public String saveOrUpdateMultiRouteConfig(List<JSONObject> gatewayRouteList) { log.debug("begin add multi route config"); gatewayRouteList.forEach(gatewayRoute -> { RouteDefinition definition = handleData(gatewayRoute); routeDefinitionWriter.save(Mono.just(definition)).subscribe(); }); this.publisher.publishEvent(new RefreshRoutesEvent(this)); return "success"; }
private RouteDefinition handleData(JSONObject gatewayRoute) { RouteDefinition definition; definition = JSONObject.toJavaObject(gatewayRoute, RouteDefinition.class); return definition; } }
|
然后添加一个设置接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @RestController @RequestMapping("/route") public class RouteConfigController extends BaseController { @Autowired private GatewayServiceHandler gatewayServiceHandler;
@PostMapping public AjaxResult add(@Validated @RequestBody List<JSONObject> gatewayRouteList) { String result = gatewayServiceHandler.saveOrUpdateMultiRouteConfig(gatewayRouteList); return AjaxResult.success(result); } }
|
测试发送路由配置添加请求{{gateway}}/route
json报文数据如下:
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
| [ { "id": "xkiot-auth", "order": 2, "predicates": [ { "args": { "pattern": "/auth/**" }, "name": "Path" } ], "uri": "lb://xkiot-auth" }, { "id": "xkiot-system", "order": 1, "predicates": [ { "args": { "pattern": "/system/**" }, "name": "Path" } ], "uri": "lb://xkiot-system" } ]
|
其中order
设置为0,代表不起用该路由配置,id
代表服务id,uri
代表微服务地址,predicates
路由规则,对应的yml配置如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| spring: cloud: gateway: routes: - id: xkiot-auth uri: lb://xkiot-auth predicates: - Path=/auth/** filters: - CacheRequestFilter - ValidateCodeFilter - StripPrefix=1 - id: xkiot-system uri: lb://xkiot-system predicates: - Path=/system/** filters: - StripPrefix=1
|
redis数据存储如下:
参考
Srping cloud gateway 实现动态路由(MySQL持久化+redis分布式缓存)
Nacos+Spring Cloud Gateway动态路由配置