首页 > 其他分享 >boot3+JDK17+spring-cloud-gateway:4.0.0+spring-cloud:2022.0.0.0+Nacos2.2.1配置动态路由的网关

boot3+JDK17+spring-cloud-gateway:4.0.0+spring-cloud:2022.0.0.0+Nacos2.2.1配置动态路由的网关

时间:2023-11-20 17:58:07浏览次数:43  
标签:网关 spring nacos routeDefinition import public cloud

项目依赖

image

配置

# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
# Nacos认证信息
spring.cloud.nacos.config.username=nacos
spring.cloud.nacos.config.password=nacos
spring.cloud.nacos.config.contextPath=/nacos
# 设置配置中心服务端地址
spring.cloud.nacos.config.server-addr=localhost:8848
# Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可
spring.cloud.nacos.config.namespace=1c5ae1c6-cac5-40ef-b090-b4e9677ea2aa
# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
spring.application.name=zuul-client
spring.cloud.util.enabled=false
spring.profiles.active=dev
spring.cloud.nacos.discovery.group=cloud-test
spring.cloud.nacos.config.group=cloud-test
spring.cloud.nacos.config.file-extension=properties
# Nacos认证信息
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
# Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 注册到 nacos 的指定 namespace,默认为 public
spring.cloud.nacos.discovery.namespace=1c5ae1c6-cac5-40ef-b090-b4e9677ea2aa
#dataId 的完整格式如下:prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置
# ${prefix}-${spring.profiles.active}.${file-extension}
# 数据库连接信息{单数据源}

路由配置

sidecar:
  # 异构微服务的IP
  ip: 127.0.0.1
  # 异构微服务的端口
  port: 8060
  # 异构微服务的健康检查URL
  health-check-url: http://localhost:8060/health.json

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启通过服务中心的自动根据 serviceId 创建路由的功能
      routes:
        - id: ldapsso-client
          uri: lb://ldapsso-client
          predicates:
            - Path=/ldapsso/**
          filters:
            - StripPrefix=1
        - id: service-b
          uri: lb://service-b
          predicates:
            - Path=/service-b/test-service-b/**
          filters:
            - StripPrefix=1
    inetutils:
      ignored-interfaces: 'VMware Virtual Ethernet Adapter for VMnet1,VMware Virtual Ethernet Adapter for VMnet8'
    nacos:
      discovery:
        server-addr: localhost:8848
  application:
    name: zuul-client

management:
  endpoint:
    health:
      show-details: always
server:
  port: 28083

启动器

@SpringBootApplication
@EnableDiscoveryClient
public class ZuulApplication {

    public static void main(String[] args) {
        try {
            SpringApplication.run(ZuulApplication.class, args);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }


    @Bean
    public InetIPv6Utils inetIPv6Utils() {
        InetUtilsProperties properties = new InetUtilsProperties();
        return new InetIPv6Utils(properties);
    }

    @Bean
    public InetUtils inetUtils() {
        InetUtilsProperties properties = new InetUtilsProperties();
        return new InetUtils(properties);
    }


}

测试类

@RestController
public class IndexController {


    @RequestMapping("/index")
    public String getIndex(){
        return "Zuul";
    }
}

路由更新业务处理

public interface RouteService {

    /**
     * 更新路由配置
     *
     * @param routeDefinition
     */
    void update(RouteDefinition routeDefinition);

    /**
     * 添加路由配置
     *
     * @param routeDefinition
     */
    void add(RouteDefinition routeDefinition);

}

@Slf4j
@Service
public class RouteServiceImpl implements RouteService, ApplicationEventPublisherAware {

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    /**
     * 事件发布者
     */
    private ApplicationEventPublisher publisher;

    @Override
    public void update(RouteDefinition routeDefinition) {
        log.info("更新路由配置项:{}", routeDefinition);
        this.routeDefinitionWriter.delete(Mono.just(routeDefinition.getId()));
        routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    @Override
    public void add(RouteDefinition routeDefinition) {
        log.info("新增路由配置项:{}", routeDefinition);
        routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
}

动态路由加载

package com.example.zuul.listner;

import com.alibaba.fastjson.JSONArray;
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.annotation.NacosConfigListener;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.UuidUtils;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.stereotype.Component;

import java.net.URI;
import java.util.*;
import java.util.concurrent.Executor;

@Component
@Slf4j
public class NacosRefreshConfig {


    @Autowired
    private RouteService routeService;

    @Value("${spring.cloud.nacos.config.server-addr}")
    private String nacosAddr;
    @Value("${spring.cloud.nacos.config.namespace}")
    private String nameSpace;

    @Value("${spring.cloud.nacos.config.username}")
    private String username;

    @Value("${spring.cloud.nacos.config.password}")
    private String password;

    @PostConstruct
    public void initBindListner() throws NacosException {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, nacosAddr);
        properties.put(PropertyKeyConst.NAMESPACE, nameSpace);
        properties.put(PropertyKeyConst.USERNAME, username);
        properties.put(PropertyKeyConst.PASSWORD, password);
        ConfigService configService = NacosFactory.createConfigService(properties);
        configService.addListener(Constants.CONFIG_FILE_NAME, Constants.CONFIG_FILE_GROUP, new Listener() {
            @Override
            public Executor getExecutor() {
                return null;
            }

            @Override
            public void receiveConfigInfo(String configInfo) {
                // 刷新路由
                List<RouteDefinition> extracted = extracted(configInfo);
                for (RouteDefinition routeDefinition : extracted) {
                    routeService.update(routeDefinition);
                }
            }
        });
    }

    private static List<RouteDefinition> extracted(String configInfo) {
        List<RouteDefinition> list = new ArrayList<>();
        JSONArray jsonObjectArr = JSONArray.parseArray(configInfo);
        for (int i = 0; i < jsonObjectArr.size(); i++) {
            RouteDefinition routeDefinition = new RouteDefinition();
            JSONObject jsonObject = jsonObjectArr.getJSONObject(i);
            routeDefinition.setId(StringUtils.defaultIfEmpty(jsonObject.getString("id"), UuidUtils.generateUuid()));
            routeDefinition.setUri(URI.create(jsonObject.getString("uri")));
            List<PredicateDefinition> predicates = routeDefinition.getPredicates();
            JSONArray predicates1 = jsonObject.getJSONArray("predicates");
            if (predicates1 != null && predicates1.size() > 1) {
                for (int ii = 0; ii < predicates1.size(); ii++) {
                    Set<Map.Entry<String, Object>> entries = predicates1.getJSONObject(ii).entrySet();
                    for (Map.Entry<String, Object> entry : entries) {
                        PredicateDefinition predicateDefinition = new PredicateDefinition();
                        predicateDefinition.setName(entry.getKey());
                        Map<String, String> args = predicateDefinition.getArgs();
                        args.put(entry.getKey(), entry.getValue().toString());
                        predicates.add(predicateDefinition);
                    }
                }
            } else {
                Set<Map.Entry<String, Object>> entries = predicates1.getJSONObject(0).entrySet();
                for (Map.Entry<String, Object> entry : entries) {
                    PredicateDefinition predicateDefinition = new PredicateDefinition();
                    predicateDefinition.setName(entry.getKey());
                    Map<String, String> args = predicateDefinition.getArgs();
                    args.put(entry.getKey(), entry.getValue().toString());
                    predicates.add(predicateDefinition);
                }
            }

            List<FilterDefinition> filters = routeDefinition.getFilters();
            JSONArray var6 = jsonObject.getJSONArray("filters");
            if (var6 != null && var6.size() > 1) {
                for (int ij = 0; ij < var6.size(); ij++) {
                    Set<Map.Entry<String, Object>> entries = var6.getJSONObject(ij).entrySet();
                    for (Map.Entry<String, Object> entry : entries) {
                        FilterDefinition filterDefinition = new FilterDefinition();
                        filterDefinition.setName(entry.getKey());
                        Map<String, String> args = filterDefinition.getArgs();
                        args.put(entry.getKey(), entry.getValue().toString());
                        filters.add(filterDefinition);
                    }
                }

            } else {
                Set<Map.Entry<String, Object>> entries = var6.getJSONObject(0).entrySet();
                for (Map.Entry<String, Object> entry : entries) {
                    FilterDefinition filterDefinition = new FilterDefinition();
                    filterDefinition.setName(entry.getKey());
                    Map<String, String> args = filterDefinition.getArgs();
                    args.put(entry.getKey(), entry.getValue().toString());
                    filters.add(filterDefinition);
                }
            }
            list.add(routeDefinition);
        }
        return list;
    }

    @NacosConfigListener(dataId = Constants.CONFIG_FILE_NAME)
    public void refresh(String msg) {
        log.error("-----------------------");
        JSONObject jsonObject = JSONObject.parseObject(msg);
        log.error(jsonObject.toJSONString());
    }
}


public interface Constants {
    String CONFIG_FILE_NAME = "zuul-client";
    String CONFIG_FILE_GROUP = "cloud-test";
}

Nacos配置

[
    {"id":"ldapsso-client","uri":"lb://ldapsso-client","predicates":[{"Path":"/ldapsso/**"}],"filters":[{"StripPrefix":1}]},
     {"id":"baidu","uri":"https://www.baidu.com","predicates":[{"Path":"/baidu/**"}],"filters":[{"StripPrefix":1}]},
     {"id":"client","uri":"lb://ldapsso-client","predicates":[{"Path":"/client/**"}],"filters":[{"StripPrefix":1}]}
]

image

测试动态路由生效

image

完结====

标签:网关,spring,nacos,routeDefinition,import,public,cloud
From: https://www.cnblogs.com/gtnotgod/p/17844490.html

相关文章

  • spring-boot-starter-thymeleaf 避坑指南
    spring-boot-starter-thymeleaf避坑指南第一步:pom配置环境先不要管包是做什么的总之必须要有否则进坑1234567891011<!--避坑包-->      <dependency>          <groupId>net.sourceforge.nekohtml</groupId>          <a......
  • bgp:边界网关协议 border gateway protocol
    基础:1.作用范围:作用在AS之间:EGP------>BGP:路由条目数量较多,相对不安全(单播,GTSM TTL=1\没有被动接口),使用TCP底层,路由更新方式,增量更新,只要是路由表里存在的network,import,着眼点传递路由控制路由,单进程,为大型网络设计,很多属性,可以跨设备建立邻居关系,默认不负载,BGP黑洞,BGP排错......
  • MODBUS转PROFINET网关TS-180 网关连接西门子 PLC 和工业称重仪表
    随着科技的高速发展,工业自动化行业对日益多样的称重需求越来越高,上海某公司在国内的一个工业自动化项目中,监控中心系统需要远程实时采集工业称重仪表测量的各种称重参数。该系统使用的是西门子S7-300PLC,支持PROFINET以太网协议,工业称重仪表为该公司生产的称重显示控制器,提供......
  • 基于springboot vue的宿舍管理系统
    项目源码免费获取方式放在文章末尾处项目技术数据库:Mysql5.7数据表:7张开发语言:Java(jdk1.8)开发工具:idea前端技术:Vue后端技术:SpringBoot 功能简介该项目是一个宿舍管理系统,分为管理员端,宿管员端。 管理员端:       登录        宿管模块            ......
  • Modbus通用串口转PROFINET IO网关TS-180 在锅炉厂智能温湿度监控系统中的应用
    背景:现代科学技术和工业的迅速发展,不断促进着自动化控制技术及设备通信技术的创新和发展。当前,PLC、DCS、智能仪表等已广泛应用到现场生产控制系统中,本应用案例是在锅炉行业的温湿度监控系统中,西门子S7-300PLC及CP343-1模块与智能温度仪表的通讯,上海泗博自动化技术有限公司......
  • Modbus转PROFINET网关 TS-180
    TS-180实现PROFINET网络与串口网络之间的数据通信。三串口可分别连接具有RS232或RS485接口的设备到PROFINET网络,三串口相同,全为RS232或RS485。即将串口设备转换为PROFINET设备。在PROFINET一端为从站,支持标准的PROFINETRT和IRT协议,PROFINET支持的最多32个槽位,支持最......
  • 网关
    网关是指连接两个不同网络的设备或程序。它可以将来自一个网络的数据转发到另一个网络,实现数据在不同网络之间的传输和交流。网关通常位于网络边缘,作为两个网络之间的接口。它充当了一个中转站,将数据从一个网络转发到另一个网络,同时还可以执行一些网络安全和协议转换的功能。......
  • springboot使用拦截器实现登录拦截
    参考文档https://blog.csdn.net/qq_50652600/article/details/127250413HandlerInterceptor作用:自定义拦截器如何创建:这个接口我们通常会自定义一个类。加上@Component注解,并且使它实现HandlerInterceptor接口(根据需求重写里面的三个方法)publicinterfaceHandlerInterceptor......
  • SpringBoot 策略模式 切换上传文件模式
    策略模式策略模式是指有一定行动内容的相对稳定的策略名称。我们定义一个接口(就比如接下来要实现的文件上传接口)我们定义所需要实现的策略实现类A、B、C、D(也就是项目中所使用的四种策略阿里云Oss上传、腾讯云Cos上传、七牛云Kodo上传、本地上传)我们通过策略上下文来调用策......
  • Spring_2023_11_20_1
    Spring基础依赖pom依赖<!--Spring基础包括:Spring-core/Spring-beans/Spring-app/Spring-expression--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId&......