赞
踩
<!-- 网关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--Spring boot 依赖(微服务基础)--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <!--使用exclusions标签来标明要排除的包--> <!--排除logback--> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <!--Web 服务相关--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 生成配置元数据,比如你平常在yml文件里面配置 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <!--单元测试依赖,子工程中需要单元测试时,不需要再次引入此依赖了--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!--bootstrap 相关--> <!--SpringBoot2.4.x之后默认不加载bootstrap.yml文件,需要在pom里加上依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> <version>4.0.0</version> </dependency> <!--服务的注册和发现--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--lombok 依赖,子工程中假如需要lombok,不需要再引入--> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency> <!-- 网关 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
server: port: 9999 tomcat: max-http-form-post-size: -1 max-threads: 500 min-spare-threads: 50 servlet: context-path: / spring: main: web-application-type: reactive #当遇到同样名字的时候,是否允许覆盖注册 allow-bean-definition-overriding: true profiles: active: ${SYS_ENV:} # local:本地,dev:测试,uat:uat application: name: gateway-service cloud: nacos: # 配置中心# config: username: ${NACOS_USER:nacos} password: ${NACOS_PASSWORD:nacos} server-addr: ${NACOS_IP:nacos.com}:${NACOS_POST:8848} namespace: ${NACOS_NAMESPACE:} file-extension: yml refresh-enabled: true override-none: true #本地配置优先 shared-configs: - application.${spring.cloud.nacos.config.file-extension} # 配置文件名-Data Id # 路由网关配置 gateway: # 启用了自动根据服务名建立路由 discovery: locator: enabled: true lower-case-service-id: true # 动态路由配置 config: # 动态 gateway-route: # nacos 配置dataId dataId: gateway-router # nacos服务地址 server-addr: ${spring.cloud.nacos.config.server-addr} # 命名空间 namespace: ${spring.cloud.nacos.config.namespace} # 账号密码 username: ${spring.cloud.nacos.config.username} password: ${spring.cloud.nacos.config.password}

[ { "id": "auth-service", "uri": "lb://auth-service", "predicates": [ { "args": { "pattern": "/auth-service/**" }, "name": "Path" } ], "filters": [ { "args": { "parts": 1 }, "name": "StripPrefix" } ], "order": 1 }, { "id": "user-service", "uri": "lb://user-service", "predicates": [ { "args": { "pattern": "/user-service/**" }, "name": "Path" } ], "filters": [ { "args": { "parts": 1 }, "name": "StripPrefix" } ], "order": 2 } ]
import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.config.listener.Listener; import com.alibaba.nacos.api.exception.NacosException; import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinitionWriter; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.concurrent.Executor; /** * 类描述:通过Nacos的配置动态更新网管路由 * <pre> * ApplicationEventPublisherAware 是由 Spring 提供的用于为 Service 注入 ApplicationEventPublisher 事件发布器的接口,使用这个接口, * 我们自己的 Service 就拥有了发布事件的能力。用户注册后,不再是显示地调用其他的业务 Service,而是发布一个用户注册事件。 * </pre> * */ @Slf4j @RefreshScope @Component public class GatewayRouteConfig implements ApplicationEventPublisherAware { /** 常量 */ private static final String PROPERTIES_SERVER_ADDR = "serverAddr"; private static final String PROPERTIES_NAMESPACE = "namespace"; private static final String PROPERTIES_GROUP = "group"; private static final String PROPERTIES_USERNAME = "username"; private static final String PROPERTIES_PASSWORD = "password"; /** nacos 配置dataId */ @Value("${config.gateway-route.dataId:gateway-router}") private String dataId = "gateway-routes"; /** nacos 配置group */ @Value("${config.gateway-route.group:DEFAULT_GROUP}") private String group = "DEFAULT_GROUP"; /** nacos 配置地址 */ @Value("${config.gateway-route.server-addr}") private String serverAddr; /** nacos 命名空间 */ @Value("${config.gateway-route.namespace}") private String namespace; /** nacos 账号 */ @Value("${config.gateway-route.username}") private String username; /** nacos 密码 */ @Value("${config.gateway-route.password}") private String password; /** 已加载的路由id集合 */ private static final List<String> ROUTE_LIST = new ArrayList<>(); private final RouteDefinitionWriter routeDefinitionWriter; /** 事件发布器 */ private ApplicationEventPublisher applicationEventPublisher; /** * 方法描述: 构造函数 * * @param routeDefinitionWriter 路由定义写对象 */ public GatewayRouteConfig(RouteDefinitionWriter routeDefinitionWriter) { this.routeDefinitionWriter = routeDefinitionWriter; } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } /** * 方法描述: 从Nacos的配置中加载动态路由 * */ @PostConstruct public void loadRouteFromNacosAndListener() { try { ConfigService configService = NacosFactory.createConfigService(getProperties()); // 程序启动时调用Nacos的配置进行路由加载 String initConfigInfo = configService.getConfig(dataId, group, 5000); addRouteAndPublish(initConfigInfo); // 添加监听路由变化 addListener(configService); } catch (NacosException e) { log.error("加载路由配置错误,详情:", e); } } /** * 方法描述: 添加监听 * * @param cs 配置服务对象 */ private void addListener(ConfigService cs) throws NacosException { // 添加监听 cs.addListener(dataId, group, new Listener() { @Override public void receiveConfigInfo(String configInfo) { // 将监听到的路由加载到路由定义器中 addRouteAndPublish(configInfo); } @Override public Executor getExecutor() { return null; } }); } /** * 方法描述: Nacos配置属性 * * @return {@link Properties} */ private Properties getProperties() { Assert.notBlank(serverAddr, "Nacos的服务地址为空了!"); Properties properties = new Properties(); properties.put(PROPERTIES_SERVER_ADDR, serverAddr); if (StrUtil.isNotBlank(namespace)) { properties.put(PROPERTIES_NAMESPACE, namespace); } if (StrUtil.isNotBlank(group)) { properties.put(PROPERTIES_GROUP, group); } return properties; } /** * 添加并发布配置的路由 * * @param configInfo 路由配置字符串;格式:JSON数组 */ private void addRouteAndPublish(String configInfo) { // 加载前需要清空有存在的路由 clearRoute(); // 解析从Nacos配置中读取的路由配置信息 List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class); for (RouteDefinition routeDefinition : gatewayRouteDefinitions) { // 将路由写到定义器中 routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe(); // 将路由id加入内存集合中 ROUTE_LIST.add(routeDefinition.getId()); } // 刷新路由定义器 this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter)); } /** * 方法描述: 清空已存在的路由 */ private void clearRoute() { ROUTE_LIST.forEach(id -> this.routeDefinitionWriter.delete(Mono.just(id)).subscribe()); ROUTE_LIST.clear(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。