配置gateway+nacos动态路由
第一步:首先是设置配置文件的配置列表
然后在配置读取配置类上增加刷新注解@RefreshScope
import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.cloud.gateway.filter.FilterDefinition; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author :lhb * @date :Created in 2020-09-09 08:59 * @description:GateWay路由配置 * @modified By: * @version: $ */ @Slf4j @RefreshScope @Component @ConfigurationProperties(prefix = "spring.cloud.gateway") public class GatewayRoutes { /** * 路由列表. */ @NotNull @Valid private List<RouteDefinition> routes = new ArrayList<>(); /** * 适用于每条路线的过滤器定义列表 */ private List<FilterDefinition> defaultFilters = new ArrayList<>(); private List<MediaType> streamingMediaTypes = Arrays .asList(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_STREAM_JSON); public List<RouteDefinition> getRoutes() { return routes; } public void setRoutes(List<RouteDefinition> routes) { this.routes = routes; if (routes != null && routes.size() > 0 && log.isDebugEnabled()) { log.debug("Routes supplied from Gateway Properties: " + routes); } } public List<FilterDefinition> getDefaultFilters() { return defaultFilters; } public void setDefaultFilters(List<FilterDefinition> defaultFilters) { this.defaultFilters = defaultFilters; } public List<MediaType> getStreamingMediaTypes() { return streamingMediaTypes; } public void setStreamingMediaTypes(List<MediaType> streamingMediaTypes) { this.streamingMediaTypes = streamingMediaTypes; } @Override public String toString() { return "GatewayProperties{" + "routes=" + routes + ", defaultFilters=" + defaultFilters + ", streamingMediaTypes=" + streamingMediaTypes + '}'; } }
第二步:配置监听nacos监听器
import cn.hutool.co<span>本文来源gaodai#ma#com搞*!代#%^码$网*</span>re.exceptions.ExceptionUtil; import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.PropertyKeyConst; 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.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.scope.refresh.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 javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * @author :lhb * @date :Created in 2020-09-08 16:39 * @description:监听nacos配置变更 * @modified By: * @version: $ */ @Slf4j @Component public class GateWayNacosConfigListener implements ApplicationEventPublisherAware { @Autowired private RouteDefinitionWriter routedefinitionWriter; private ApplicationEventPublisher publisher; private static final Map<String, RouteDefinition> ROUTE_MAP = new ConcurrentHashMap<>(); @Autowired private GatewayRoutes gatewayRoutes; @Resource private RefreshScope refreshScope; @Value(value = "${spring.cloud.nacos.config.server-addr}") private String serverAddr; @Value(value = "${spring.cloud.nacos.config.group:DEFAULT_GROUP}") private String group; @Value(value = "${spring.cloud.nacos.config.namespace}") private String namespace; private String routeDataId = "gateway-routes.yml"; @PostConstruct public void onMessage() throws NacosException { log.info("serverAddr={}", serverAddr); Properties properties = new Properties(); properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr); properties.put(PropertyKeyConst.NAMESPACE, namespace); ConfigService configService = NacosFactory.createConfigService(properties); this.publisher(gatewayRoutes.getRoutes()); log.info("gatewayProperties=" + JSONObject.toJSONString(gatewayRoutes)); configService.addListener(routeDataId, group, new Listener() { @Override public Executor getExecutor() { return null; } @Override public void receiveConfigInfo(String config) { log.info("监听nacos配置: {}, 旧的配置: {}, 新的配置: {}", routeDataId, gatewayRoutes, config); refreshScope.refresh("gatewayRoutes"); try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { log.error(ExceptionUtil.getMessage(e)); } publisher(gatewayRoutes.getRoutes()); } }); } private boolean rePut(List<RouteDefinition> routeDefinitions) { if (MapUtils.isEmpty(ROUTE_MAP) && CollectionUtils.isEmpty(routeDefinitions)) { return true; } if (CollectionUtils.isEmpty(routeDefinitions)) { return true; } Set<String> strings = ROUTE_MAP.keySet(); return strings.stream().sorted().collect(Collectors.joining()) .equals(routeDefinitions.stream().map(v -> v.getId()).sorted().collect(Collectors.joining())); } /** * 增加路由 * * @param def * @return */ public Boolean addRoute(RouteDefinition def) { try { log.info("添加路由: {} ", def); routedefinitionWriter.save(Mono.just(def)).subscribe(); ROUTE_MAP.put(def.getId(), def); } catch (Exception e) { e.printStackTrace(); } return true; } /** * 删除路由 * * @return */ public Boolean clearRoute() { for (String id : ROUTE_MAP.keySet()) { routedefinitionWriter.delete(Mono.just(id)).subscribe(); } ROUTE_MAP.clear(); return false; } /** * 发布路由 */ private void publisher(String config) { this.clearRoute(); try { log.info("重新更新动态路由"); List<RouteDefinition> gateway = JSONObject.parseArray(config, RouteDefinition.class); for (RouteDefinition route : gateway) { this.addRoute(route); } publisher.publishEvent(new RefreshRoutesEvent(this.routedefinitionWriter)); } catch (Exception e) { e.printStackTrace(); } } /** * 发布路由 */ private void publisher(List<RouteDefinition> routeDefinitions) { this.clearRoute(); try { log.info("重新更新动态路由: "); for (RouteDefinition route : routeDefinitions) { this.addRoute(route); } publisher.publishEvent(new RefreshRoutesEvent(this.routedefinitionWriter)); } catch (Exception e) { e.printStackTrace(); } } @Override public void setApplicationEventPublisher(ApplicationEventPublisher app) { publisher = app; } }
第三步:配置nacos的yml文件
spring: cloud: gateway: discovery: locator: enabled: true lower-case-service-id: true routes: # 认证中心 - id: firefighting-service-user uri: lb://firefighting-service-user predicates: - Path=/user/** # - Weight=group1, 8 filters: - StripPrefix=1 # 转流服务 - id: liveStream uri: http://192.168.1.16:8081 predicates: - Path=/liveStream/** # - Weight=group1, 8 filters: - StripPrefix=1 - id: firefighting-service-directcenter uri: lb://firefighting-service-directcenter predicates: - Path=/directcenter/** filters: - StripPrefix=1 - id: firefighting-service-datainput uri: lb://firefighting-service-datainput predicates: - Path=/datainput/** filters: - StripPrefix=1 - id: firefighting-service-squadron uri: lb://firefighting-service-squadron predicates: - Path=/squadron/** filters: - StripPrefix=1 - id: firefighting-service-iot uri: lb://firefighting-service-iot predicates: - Path=/iot/** filters: - StripPrefix=1 - id: websocket uri: lb:ws://firefighting-service-notice predicates: - Path=/notice/socket/** filters: - StripPrefix=1 - id: firefighting-service-notice uri: lb://firefighting-service-notice predicates: - Path=/notice/** filters: # 验证码处理 # - CacheRequest # - ImgCodeFilter - StripPrefix=1 - id: websocket uri: lb:ws://firefighting-service-notice predicates: - Path=/notice/socket/** filters: - StripPrefix=1 - id: firefighting-service-supervise uri: lb://firefighting-service-supervise predicates: - Path=/supervise/** filters: - StripPrefix=1 - id: firefighting-service-new-supervise uri: lb://firefighting-service-new-supervise predicates: - Path=/new/supervise/** filters: - StripPrefix=2 - id: firefighting-service-train uri: lb://firefighting-service-train predicates: - Path=/train/** filters: - StripPrefix=1 - id: firefighting-support-user uri: lb://firefighting-support-user predicates: - Path=/support/** filters: - StripPrefix=1 - id: firefighting-service-firesafety uri: lb://firefighting-service-firesafety predicates: - Path=/firesafety/** filters: - StripPrefix=1 - id: firefighting-service-bigdata uri: lb://firefighting-service-bigdata predicates: - Path=/bigdata/** filters: - StripPrefix=1 - id: firefighting-service-act-datainput uri: lb://firefighting-service-act-datainput predicates: - Path=/act_datainput/** filters: - StripPrefix=1 - id: firefighting-service-publicity uri: lb://firefighting-service-publicity predicates: - Path=/publicity/** filters: - StripPrefix=1 - id: firefighting-service-preplan uri: lb://firefighting-service-preplan predicates: - Path=/preplan/** filters: - StripPrefix=1 - id: firefighting-service-uav uri: lb://firefighting-service-uav predicates: - Path=/uav/** filters: - StripPrefix=1 - id: firefighting-service-ard-mgr uri: lb://firefighting-service-ard-mgr predicates: - Path=/ard_mgr/** filters: - StripPrefix=1 - id: admin-server uri: lb://admin-server predicates: - Path=/adminsServer/** filters: - StripPrefix=1