网关动态路可以从redis中取,或者nacos都可以。好处有:修了配置能够动态更新
依赖配置类org.springframework.boot spring-boot-starter org.springframework.cloud spring-cloud-starter-gateway com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config com.alibaba fastjson 1.2.47 org.springframework.boot spring-boot-starter-test test org.projectlombok lombok 1.18.10 true cn.hutool hutool-all 5.4.7 org.springframework.cloud spring-cloud-dependencies Hoxton.SR9 pom import com.alibaba.cloud spring-cloud-alibaba-dependencies 2.2.6.RELEASE pom import
这里可以从nacos注入,我是直接写死了
@Configuration
public class DynamicRouteConfig {
public static final String NACOS_SERVICE_ADDR="localhost:8848";
public static final String NACOS_SERVICE_NAMESPACE="7990000d-2835-42d9-86a6-76d998d8c5ea";
public static final String NACOS_ROUTE_DATA_ID="route.json";
public static final String NACOS_SROUTE_GROUP="DEFAULT_GROUP";
}
监听类与初始化
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.util.List;
@Service
@Slf4j
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {
@Resource
private RouteDefinitionWriter routeDefinitionWriter;
@Resource
private RouteDefinitionLocator routeDefinitionLocator;
@Resource
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher =applicationEventPublisher;
}
public void delete(String id){
try {
log.info("gateway delete route id {}",id);
this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}catch (Exception e){
}
}
public void updateList(List definitions){
log.info("gateway update route {}",definitions);
List routeDefinitionsExits = routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst();
if (!CollectionUtils.isEmpty(routeDefinitionsExits)){
routeDefinitionsExits.forEach(routeDefinition ->{
log.info("delete routeDefinition:{}",routeDefinition);
delete(routeDefinition.getId());
});
}
definitions.forEach(this::updateById);
}
private void updateById(RouteDefinition definition) {
try {
log.info("gateway update route {}",definition);
this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
}catch (Exception e) {
definition.getId();
return;
}
try{
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}catch (Exception e){
}
}
public String addRoute(RouteDefinition definition){
log.info("gateway add route {}",definition);
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
}
}
import com.alibaba.fastjson.JSON;
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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;
@Component
@Slf4j
@DependsOn("dynamicRouteConfig")
public class DynamicRouteServiceImolByNacos {
@Resource
private DynamicRouteServiceImpl dynamicRouteService;
private ConfigService configService;
@PostConstruct
public void init(){
log.info("gateway route init......");
try {
configService=initConfigService();
if (configService == null){
log.info("gateway initConfigService fail");
return;
}
String configInfo = configService.getConfig(DynamicRouteConfig.NACOS_ROUTE_DATA_ID,
DynamicRouteConfig.NACOS_SROUTE_GROUP, 3000);
if (StringUtils.isEmpty(configInfo)) {
throw new RuntimeException("ddd");
}
log.info("获取网关配置:rn{}",configInfo);
List definitionList = JSON.parseArray(configInfo, RouteDefinition.class);
for (RouteDefinition definition : definitionList) {
log.info("update route :{}",definition.toString());
dynamicRouteService.addRoute(definition);
}
}catch (Exception e) {
log.error("初始化网关路由时失败:",e);
}
dynamicRouteByNacosListener(DynamicRouteConfig.NACOS_ROUTE_DATA_ID,
DynamicRouteConfig.NACOS_SROUTE_GROUP);
}
private void dynamicRouteByNacosListener(String dataId, String group) {
try {
configService.addListener(dataId, group, new Listener() {
@Override
public Executor getExecutor() {
log.info("getExecutor rn");
return null;
}
@Override
public void receiveConfigInfo(String configInfo) {
log.info("进行网关更新:nr{}",configInfo);
List definitionList = JSON.parseArray(configInfo, RouteDefinition.class);
log.info("update route :{}",definitionList.toString());
dynamicRouteService.updateList(definitionList);
}
});
} catch (NacosException e) {
log.error("从nacos 接受动态路由配置出错!!!:",e);
}
}
private ConfigService initConfigService(){
try {
Properties properties = new Properties();
properties.setProperty("serverAddr",DynamicRouteConfig.NACOS_SERVICE_ADDR);
properties.setProperty("namespace",DynamicRouteConfig.NACOS_SERVICE_NAMESPACE);
return NacosFactory.createConfigService(properties);
}catch (Exception e){
log.error("初始化网关路由时失败:",e);
return null;
}
}
}
效果
当nacos 路由文件修改之后,这里可以监听到。
1-要想真正了解,需要了解Gateway源码。
2-了解一些,SPring 的反应式编程



