栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Cloud Gateway③编码实现动态增加、修改、删除路由

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Cloud Gateway③编码实现动态增加、修改、删除路由

目录
  • 背景
  • 本文开发环境介绍
  • 新增路由
    • 实现ApplicationEventPublisherAware接口
    • 验证新路由
    • 注意
  • 修改路由
    • 源码解析
    • 构建类型为PropertiesRouteDefinitionLocator的Bean
    • 验证修改后的路由
  • 删除路由
    • 重新修改上面的RouteDefinitionLocatorAutoConfiguration类
    • 验证删除后的效果
  • 总结

背景
  • Spring Cloud Gateway①入门以及自定义过滤器开发
  • Spring Cloud Gateway②聚合Swagger

以上文章演示了Gateway的部分功能的自定义开发,我们在实际业务中,很多转发的路由并不是通过配置文件提前配置好的,可能是通过配置中心获取并且会动态变化,新开发好的API需要挂到API网关上,希望通过仅修改配置解决,API网关不需要重启,那么我们就需要基于Gateway动态增加、修改、删除路由的能力。

本文开发环境介绍
开发依赖版本
Spring Boot2.7.0
Spring Cloud2021.0.1
Spring Cloud Alibaba2021.0.1.0

本文继续接着上一篇文章往下讲,代码和配置都是接着上一篇,如有看不懂的地方可以把前面关于Gateway的内容过目一下。

新增路由 实现ApplicationEventPublisherAware接口
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.SneakyThrows;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.net.URI;
import java.util.ArrayList;

@RequiredArgsConstructor
@Configuration
public class RouteAutoConfiguration implements ApplicationEventPublisherAware {

    private final RouteDefinitionWriter routeDefinitionWriter;
    private final RouteLocator routeLocator;
    @Setter
    private ApplicationEventPublisher applicationEventPublisher;

    @SneakyThrows
    @PostConstruct
    public void init() {
        RouteDefinition routeDefinition = new RouteDefinition();
        routeDefinition.setId("manual-route-1");
        routeDefinition.setUri(new URI("https://news.baidu.com/"));
        routeDefinition.setPredicates(new ArrayList() {{
            add(new PredicateDefinition("Path=/baidu/news/**"));
        }});
        routeDefinition.setFilters(new ArrayList() {{
            add(new FilterDefinition("StripPrefix=2"));
        }});
        routeDefinition.setOrder(-1);
        routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
        applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
    }
}

代码新增了一条新的路由转发规则,把/baidu/news/转发到https://news.baidu.com/

验证新路由

在浏览器输入http://localhost:8081/baidu/news

出现以上图片内容,表示成功转发。

注意

在配置文件中有一个/baidu的转发,新增的/baidu/news/是/baidu子路径,Gateway会根据顺序进行匹配,先匹配到哪条符合条件的规则就会执行哪个规则,所以新增路由的代码中有一句routeDefinition.setOrder(-1);,这个顺序放在了配置文件中/baidu的前面。

修改路由

在第①篇文章中,演示了Demo过滤器的配置,那么我们现在尝试通过编码的方式动态修改已经配置好的路由规则,把/baidu/的Demo过滤器的第3个参数进行修改

源码解析
  • 在yml文件中配置的路由规则会映射到GatewayProperties这个类中
  • 根据GatewayProperties类会生成PropertiesRouteDefinitionLocator这个Bean
  • 具体的Bean构造可以查看GatewayAutoConfiguration这个类的源码
	@Bean
	@ConditionalOnMissingBean
	public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
		return new PropertiesRouteDefinitionLocator(properties);
	}

看到上面这段代码,我们就可以生成我们自己的PropertiesRouteDefinitionLocator

构建类型为PropertiesRouteDefinitionLocator的Bean
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.config.PropertiesRouteDefinitionLocator;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Optional;

@Configuration
public class RouteDefinitionLocatorAutoConfiguration {

    @Bean
    public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
        Optional optional = properties.getRoutes().stream().filter(r->r.getId().equals("baidu")).findAny();
        if(optional.isPresent()) {
            Optional filterOptional = optional.get().getFilters().stream().filter(f->f.getName().equals("Demo")).findAny();
            filterOptional.get().getArgs().put(NameUtils.generateName(2), "manual");
        }
        return new PropertiesRouteDefinitionLocator(properties);
    }
}

上面的代码把配置文件中的world2修改成了manual

验证修改后的路由
  • 在浏览器输入http://localhost:8081/baidu
  • 在控制台可以看到如下输出
删除路由 重新修改上面的RouteDefinitionLocatorAutoConfiguration类
@Configuration
public class RouteDefinitionLocatorAutoConfiguration {

    @Bean
    public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
        Optional optional = properties.getRoutes().stream().filter(r->r.getId().equals("baidu")).findAny();
        if(optional.isPresent()) {
            Optional filterOptional = optional.get().getFilters().stream().filter(f->f.getName().equals("Demo")).findAny();
            filterOptional.get().getArgs().put(NameUtils.generateName(2), "manual");
        }

        Optional optional2 = properties.getRoutes().stream().filter(r->r.getId().equals("demoSwagger")).findAny();
        if(optional2.isPresent()) {
            properties.getRoutes().remove(optional2.get());
        }

        return new PropertiesRouteDefinitionLocator(properties);
    }
}

代码中把demoSwagger这个路由删除了

验证删除后的效果

在浏览器再次输入http://localhost:8081/swagger-ui/index.html

总结

以上示例通过代码的方式对路由进行了动态新增、修改和删除,有了这些动态的操作,基本上可以满足我们很多实际的业务场景了,比如在配置中心修改路由规则后,可以使用RouteDefinitionWriter动态刷新路由,勿需重启Gateway服务;也可以通过构造PropertiesRouteDefinitionLocator方式,结合实际业务规则,修改静态配置的路由。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1007725.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号