1、maven 依赖
主要依赖
<!-- 网关 --><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>
2、bootstrap.yml配置
server:port: 9999tomcat:max-http-form-post-size: -1max-threads: 500min-spare-threads: 50servlet:context-path: /
spring:main:web-application-type: reactive#当遇到同样名字的时候,是否允许覆盖注册allow-bean-definition-overriding: true profiles:active: ${SYS_ENV:} # local:本地,dev:测试,uat:uatapplication:name: gateway-servicecloud:nacos:# 配置中心#config:username: ${NACOS_USER:nacos}password: ${NACOS_PASSWORD:nacos}server-addr: ${NACOS_IP:nacos.com}:${NACOS_POST:8848}namespace: ${NACOS_NAMESPACE:}file-extension: ymlrefresh-enabled: trueoverride-none: true #本地配置优先shared-configs:- application.${spring.cloud.nacos.config.file-extension} # 配置文件名-Data Id# 路由网关配置gateway:# 启用了自动根据服务名建立路由discovery:locator:enabled: truelower-case-service-id: true# 动态路由配置
config:# 动态gateway-route:# nacos 配置dataIddataId: gateway-router# nacos服务地址server-addr: ${spring.cloud.nacos.config.server-addr}# 命名空间namespace: ${spring.cloud.nacos.config.namespace}
3、nacos 中心网关路由配置
[{"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}
]
4、配置文件 GatewayRouteConfig
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;
@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";@Value("${config.gateway-route.dataId:gateway-router}")private String dataId = "gateway-routes";@Value("${config.gateway-route.group:DEFAULT_GROUP}")private String group = "DEFAULT_GROUP";@Value("${config.gateway-route.server-addr}")private String serverAddr;@Value("${config.gateway-route.namespace}")private String namespace;private static final List<String> ROUTE_LIST = new ArrayList<>();private final RouteDefinitionWriter routeDefinitionWriter;private ApplicationEventPublisher applicationEventPublisher;public GatewayRouteConfig(RouteDefinitionWriter routeDefinitionWriter) {this.routeDefinitionWriter = routeDefinitionWriter;}@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.applicationEventPublisher = applicationEventPublisher;}@PostConstructpublic void loadRouteFromNacosAndListener() {try {ConfigService configService = NacosFactory.createConfigService(getProperties());String initConfigInfo = configService.getConfig(dataId, group, 5000);addRouteAndPublish(initConfigInfo);addListener(configService);} catch (NacosException e) {log.error("加载路由配置错误,详情:", e);}}private void addListener(ConfigService cs) throws NacosException {cs.addListener(dataId, group, new Listener() {@Overridepublic void receiveConfigInfo(String configInfo) {addRouteAndPublish(configInfo);}@Overridepublic Executor getExecutor() {return null;}});}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;}private void addRouteAndPublish(String configInfo) {clearRoute();List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();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();}
}