Spring Cloud Gateway之動態路由(數據庫版)


1、實現動態路由的關鍵是RouteDefinitionRepository接口,該接口存在一個默認實現(InMemoryRouteDefinitionRepository)

通過名字我們應該也知道該實現是將配置文件中配置的信息加載到內存中。因此無法實現動態路由。

2、如果想實現動態路由,我們可以參考默認實現,自己編寫一個實現,代碼如下:

import static java.util.Collections.synchronizedMap;

@Component
public class UnifiedRouteRepositoryImpl implements RouteDefinitionRepository {

    public  final Map<String, RouteDefinition> routes =
            synchronizedMap(new LinkedHashMap<>());


    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        return Flux.fromIterable(routes.values());
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap( r -> {
            routes.put(r.getId(), r);
            return Mono.empty();
        });
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            if (routes.containsKey(id)) {
                routes.remove(id);
                return Mono.empty();
            }
            return Mono.defer(() -> Mono.error(new NotFoundException("RouteDefinition not found: "+routeId)));
        });
    }

}

 3、雖然我們模仿默認實現,實現了自己的路由處理,但是我們還存在幾個問題,就是如何將數據庫中的數據加載到Map<String, RouteDefinition> routes =synchronizedMap(new LinkedHashMap<>());

還有就是當數據庫數據變化時,如何刷新routes?

CommandLineRunner 作用當項目啟動以后調用該類中的run(String... args)方法
ApplicationEventPublisherAware 可以理解為觀察者模式,當存在數據變化時,就刷新緩存中的路由
@Slf4j
@Component
public class GatewayServiceHandler implements ApplicationEventPublisherAware, CommandLineRunner {
 @Autowired @Qualifier(value = "unifiedRouteRepositoryImpl") private RouteDefinitionWriter routeDefinitionWriter; 
  //該類需要你自己編寫(將數據庫中的動態路由加載到內存中) @Autowired private RouteRepository routeRepository; private ApplicationEventPublisher publisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { this.publisher = publisher; } @Override public void run(String... args){ this.loadRouteConfig(); } public void loadRouteConfig() { List<Map<String, Object>> lists = routeRepository.getListAll(); lists.forEach(r ->{ RouteDefinition route = new RouteDefinition(); PredicateDefinition predicate = new PredicateDefinition(); Map<String, String> predicateParams = new HashMap<>(2); FilterDefinition filter = new FilterDefinition(); Map<String, String> filterParams = new HashMap<>(2); //設置Id route.setId((String)r.get("routeId")); try { route.setUri(new URI((String)r.get("uri"))); } catch (URISyntaxException e) { e.printStackTrace(); } predicate.setName((String)r.get("predicateName")); predicateParams.put("pattern",(String)r.get("predicateArgs")); predicate.setArgs(predicateParams); if(!StringUtils.isBlank(predicate.getName())){ route.setPredicates(Arrays.asList(predicate)); } filter.setName((String)r.get("filterName")); filterParams.put("_genkey_0",(String)r.get("filterArgs")); filter.setArgs(filterParams); if(!StringUtils.isBlank(filter.getName())){ route.setFilters(Arrays.asList(filter)); } routeDefinitionWriter.save(Mono.just(route)).subscribe(); }); this.publisher.publishEvent(new RefreshRoutesEvent(this)); } public void deleteRoute(String routeId){ routeDefinitionWriter.delete(Mono.just(routeId)).subscribe(); this.publisher.publishEvent(new RefreshRoutesEvent(this)); }

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM