需求:

正常的提供一个网关服务,可以实现网关的管理(增删改查)

思路:

1、创建一个网关路由数据表来实现网关的配置管理
2、低版本Spring Cloud Gateway 框架要实现基于reids网关动态路由,有两步
(1)实现RouteDefinitionRepository接口,实现下面三个 方法即可分别对应路由的获取、保存和删除
Flux getRouteDefinitions();
Mono save(Mono route);
Mono delete(Mono routeId);
(2)创建spring事件发布器实现ApplicationEventPublisherAware,可以不重启服务就让spring框架的网关服务自动刷新网关配置

但是!!!
Spring Cloud Gateway 新版本,比如我们这次使用的3.1.1人家给你提供好了,不需要自己再创建(1)了,就是RedisRouteDefinitionRepository类,在配置文件启用下即可,下面步骤有展示

3、集群环境下,网关也可能部署多台服务器,上面步骤(2)中的发布器值针对当前服务生效,考虑用消息队列来通知集群的网关服务一起刷新路由

注意:

如果采用MQ来实现集群网关的刷新,生产环境 推荐使用一个独立的MQ,基本省可以达到秒刷的效果,否则和业务公用一个MQ的话,一旦消息积压,那刷新的延时就很大了

技术栈:

spring cloud gateway + zookeeper + redis + rocketmq +mysql

网关入门的老哥清先阅读最下面的参考文档,找到了几个不错哦的博客

实操:

1、创建网关路由表实现管理路由

CREATE TABLE `manage_gateway_route`  (`unid` bigint(20) NOT NULL COMMENT '主键',`gateway_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '网关Code',`route_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '路由名称',`route_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '路由Code',`route_uri` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '路由URI',`route_paths` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '路由分发地址\",\"分隔',`route_sort` int(3) NOT NULL DEFAULT 0 COMMENT '路由排序',`limit_strategy_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '限流策略code',`limit_strategy` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '限流策略',`limit_replenish_rate` int(5) NULL DEFAULT NULL COMMENT '每秒并发量',`limit_burst_capacity` int(5) NULL DEFAULT NULL COMMENT '最大并发量',`enable_flag` tinyint(2) NOT NULL DEFAULT 1 COMMENT '是否启用:1-启用 0-禁用 ',`create_time` datetime(0) NOT NULL COMMENT '创建时间',`update_time` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',`creator_unid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人ID',`creator_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人名称',PRIMARY KEY (`unid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '网关路由管理表' ROW_FORMAT = Dynamic;

插入几条模拟数据,分别是用户服务、两个业务服务

INSERT INTO `manage_gateway_route` VALUES (10001, 'app2-service', '业务服务2', 'demo-app2', 'lb://demo-app2', '/app2/**', 5, '#{@ipKeyResolver}', 'IP限流', 10, 10, 1, '2022-03-24 17:22:29', '2022-04-06 09:16:40', '1111', 'test');
INSERT INTO `manage_gateway_route` VALUES (10002, 'app-service', '业务服务', 'demo-app', 'lb://demo-app', '/app/**', 4, '#{@ipKeyResolver}', 'IP限流', 10, 10, 1, '2022-03-24 15:49:42', '2022-04-06 09:16:46', '1111', 'test');
INSERT INTO `manage_gateway_route` VALUES (10003, 'user-service', '用户服务', 'demo-user', 'lb://demo-user', '/user/**,/account/**', 21, '#{@ipKeyResolver}', 'IP限流', 10, 10, 1, '2022-02-22 06:39:11', '2022-04-06 09:16:56', '1111', 'test');

2、引入pom依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.4</version><relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.gateway</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway</name>
<description>Demo project for gateway</description>
<properties><java.version>1.8</java.version><spring-cloud.version>2021.0.1</spring-cloud.version>
</properties>
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zookeeper-discovery</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId><version>2.6.4</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId><version>2.6.4</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.1</version></dependency>
</dependencies>
<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

3、application.yml配置文件

# 应用服务
server.port: 8099
# 应用名称
spring.application.name: gateway# spring-cloud
spring:cloud:zookeeper.connect-string: 192.168.8.49:2181
#    启用redis存储路由,不加这个的话需要自己注册beangateway:redis-route-definition-repository:enabled: true# redis
spring.redis:database: 1host: 192.168.8.49password: 123456port: 6379timeout: 3000# mysql
spring.datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/gateway?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=trueusername: rootpassword: 123456# mybatis
mybatis:mapper-locations: classpath:mapper/**/*Mapper.xmltype-aliases-package: com.gateway.demo.*.entity# rocketmq
rocketmq:name-server: 192.168.8.49:9876producer:send-message-timeout: 3000group: gatewaytopic:prefix: test# 网关刷新topicgateway-refresh-topic: ${rocketmq.topic.prefix}_gateway_refresh_topic

4、根据ip限流GatewayRateLimiterConfig

我们已最常用的IP限流进行配置,接口限流和用户限流也注册了bean,根据需要引用即可

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import reactor.core.publisher.Mono;
import java.util.Objects;/**
* 限流配置
* @author pym
* @date 2022/4/1
*/
@Configuration
public class GatewayRateLimiterConfig {/*** Gateway通过内置的RequestRateLimiter过滤器实现限流,用的是令牌桶算法,借助Redis保存中间数据* 这里自定义一个KeyResolver* 作用是对来源ip进行限流*/@Primary@Bean(value = "ipKeyResolver")public KeyResolver ipKeyResolver() {return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress());}/*** 对接口进行限流*/@Bean(value = "apiKeyResolver")public KeyResolver apiKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getPath().value());}/*** 对用户进行限流*/@Bean(value = "userKeyResolver")public KeyResolver userKeyResolver() {return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getHeaders().getFirst("Authorization")));}}

5、限流配置GatewayRateLimiterConfig

/**
* 限流配置
* @author ppp
* @date 2022/4/1
*/
@Configuration
public class GatewayRateLimiterConfig {/*** Gateway通过内置的RequestRateLimiter过滤器实现限流,用的是令牌桶算法,借助Redis保存中间数据* 这里自定义一个KeyResolver* 作用是对来源ip进行限流*/@Primary@Bean(value = "ipKeyResolver")public KeyResolver ipKeyResolver() {return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress());}/*** 对接口进行限流*/@Bean(value = "apiKeyResolver")public KeyResolver apiKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getPath().value());}/*** 对用户进行限流*/@Bean(value = "userKeyResolver")public KeyResolver userKeyResolver() {return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getHeaders().getFirst("Authorization")));}}

6、controller类

import com.gateway.demo.service.IManageGatewayRouteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;import java.util.List;
/**
* 路由控制Controller
* @author ppp
* @date 2022/3/31
*/
@RestController
@RequestMapping("/route")
public class Controller {@AutowiredIManageGatewayRouteService gatewayRouteService;/*** 获取网关* @return 是否成功:true-成功,false-失败*/@GetMapping("/getGateway")public Mono<List<RouteDefinition>> getGateway(){return gatewayRouteService.getGateway();}/*** 路由手动刷新* @return 是否成功:true-成功,false-失败*/@GetMapping("/refresh")public Boolean refresh(){return gatewayRouteService.loadAndRefresh();}}

7、(核心1)ManageGatewayRouteServiceImpl网关管理实现类

接口类:

/*** 网关路由管理表 服务类** @author ppp* @since 2022-04-01*/
public interface IManageGatewayRouteService {/*** 路由加载刷新* @return 是否成功:true-成功,false-失败*/public boolean loadAndRefresh();/*** 获取网关* @return 是否成功:true-成功,false-失败*/Mono<List<RouteDefinition>> getGateway();}

接口实现类

import com.gateway.demo.entity.dto.ManageGatewayRouteDO;
import com.gateway.demo.entity.enums.MessageTagEnum;
import com.gateway.demo.mapper.ManageGatewayRouteMapper;
import com.gateway.demo.rocketmq.producer.GatewayRefreshProducer;
import com.gateway.demo.service.IManageGatewayRouteService;
import com.gateway.demo.service.IRoutePublishService;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RedisRouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.net.URI;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;/*** 网关路由管理表 服务实现类** @author ppp* @since 2022-04-01*/
@Service
public class ManageGatewayRouteServiceImpl implements IManageGatewayRouteService {@ResourceIRoutePublishService routePublishService;@ResourceRedisRouteDefinitionRepository redisRouteDefinitionRepository;@ResourceManageGatewayRouteMapper manageGatewayRouteMapper;@ResourceGatewayRefreshProducer gatewayRefreshProducer;@Overridepublic boolean loadAndRefresh() {List<ManageGatewayRouteDO> gatewayRouteList = manageGatewayRouteMapper.getEnableList();for (ManageGatewayRouteDO gatewayRoute : gatewayRouteList) {RouteDefinition routeDefinition = new RouteDefinition();routeDefinition.setId(gatewayRoute.getRouteCode());URI routeUri = UriComponentsBuilder.fromUriString(gatewayRoute.getRouteUri()).build().toUri();routeDefinition.setUri(routeUri);routeDefinition.setOrder(gatewayRoute.getRouteSort());List<PredicateDefinition> predicates = getPredicates(gatewayRoute.getRoutePaths());if (!predicates.isEmpty()) {routeDefinition.setPredicates(predicates);}// 获取限流过滤器List<FilterDefinition> filters = new ArrayList();if(!ObjectUtils.isEmpty(gatewayRoute.getLimitStrategy())){Map<String, String> args = new LinkedHashMap();args.put("key-resolver", gatewayRoute.getLimitStrategyCode());args.put("redis-rate-limiter.replenishRate", String.valueOf(gatewayRoute.getLimitReplenishRate()));args.put("redis-rate-limiter.burstCapacity", String.valueOf(gatewayRoute.getLimitBurstCapacity()));FilterDefinition filterDefinition = new FilterDefinition();filterDefinition.setName("RequestRateLimiter");filterDefinition.setArgs(args);filters.add(filterDefinition);}routeDefinition.setFilters(filters);redisRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();}// 集群模式下,用mq广播刷新路由消息,这样每个节点都能刷新gatewayRefreshProducer.sendMessage(MessageTagEnum.SUCCESS.getValue());// 单机部署直接用这个即可,不发消息,直接刷新
//        routePublishService.refreshRoutes();return Boolean.TRUE;}@Overridepublic Mono<List<RouteDefinition>> getGateway() {return redisRouteDefinitionRepository.getRouteDefinitions().collectList();}/*** 获取地址断言** @param routePaths 路由地址* @return java.util.List*/private List<PredicateDefinition> getPredicates(String routePaths) {Map<String, String> args = new LinkedHashMap();String[] paths = routePaths.split(",");for (int i = 0; i < paths.length; i++) {args.put("_genkey_" + i, paths[i]);}PredicateDefinition predicate = new PredicateDefinition();predicate.setName("Path");predicate.setArgs(args);List<PredicateDefinition> predicates = new ArrayList();predicates.add(predicate);return predicates;}}

8、(核心2)事件发布类

接口类

/**
* 路由发布服务
* @author ppp
* @date 2022/4/2
*/
public interface IRoutePublishService {/*** 发布路由*/public void publishRoutes();}

接口实现类

import com.gateway.demo.service.IRoutePublishService;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;/**
* 路由发布服务* gateway在配置类GatewayAutoConfiguration中初始化了一个刷新路由的监听器RouteRefreshListener作为加载路由的入口,里面有一个重置方法reset()*     private void reset() {*         this.publisher.publishEvent(new RefreshRoutesEvent(this));*     }* 内容是通过Spring事件触发 发布RefreshRoutesEvent事件即可达到路由的刷新
* @author ppp
* @date 2022/3/23
*/
@Service
public class RoutePublishServiceImpl implements ApplicationEventPublisherAware, IRoutePublishService {/*** spring事件发布器*/private ApplicationEventPublisher publisher;@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.publisher = applicationEventPublisher;}@Overridepublic void publishRoutes() {publisher.publishEvent(new RefreshRoutesEvent(this));}
}

9、消息生产者

import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;/**
* 网关刷新mq消息生产者
* @author ppp
* @date 2022/4/2
*/
@Component
public class GatewayRefreshProducer {private static final Logger logger = LoggerFactory.getLogger(GatewayRefreshProducer.class);@Value("${rocketmq.topic.gateway-refresh-topic}")String gatewayRefreshTopic;@AutowiredRocketMQTemplate rocketMqTemplate;public void sendMessage(String tag){// 消息体没啥需要发送的内容对象,就搞个"-"字符串把Message<String> message = MessageBuilder.withPayload("-").build();rocketMqTemplate.asyncSend(gatewayRefreshTopic + ":" + tag, message, new SendCallback() {@Overridepublic void onSuccess(SendResult sendResult) {logger.info("发送网关刷新消息成功");}@Overridepublic void onException(Throwable throwable) {logger.info(throwable.getMessage(), throwable);logger.info("发送网关刷新消息失败");}});}}

10、消息消费者

import com.gateway.demo.entity.enums.MessageTagEnum;
import com.gateway.demo.service.IRoutePublishService;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;/**
* 网关刷新mq消息消费者
* @author ppp
* @date 2022/4/2
*/
@Component
public class GatewayRefreshConsumer implements ApplicationRunner {private static final Logger logger = LoggerFactory.getLogger(GatewayRefreshConsumer.class);@Value("${rocketmq.topic.gateway-refresh-topic}")String gatewayRefreshTopic;@Value("${rocketmq.name-server}")private String rocketMqNameServer;@AutowiredIRoutePublishService routePublishService;@Overridepublic void run(ApplicationArguments args) throws Exception {DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(gatewayRefreshTopic + "_group");consumer.setNamesrvAddr(rocketMqNameServer);consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);consumer.setConsumeThreadMin(4);consumer.setConsumeThreadMax(20);// 设置为广播消息消费consumer.setMessageModel(MessageModel.BROADCASTING);consumer.subscribe(gatewayRefreshTopic, MessageTagEnum.SUCCESS.getValue());consumer.registerMessageListener((MessageListenerConcurrently) (messageExts, consumeconcurrentlycontext) -> {for (MessageExt message : messageExts) {logger.info("接收【网关刷新】消息,msg:{}", message);routePublishService.publishRoutes();logger.info("刷新路由成功");}return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;});consumer.start();logger.info("GatewayRefreshConsumer Listener Start Success");}}

11、表entity、mapper、xml

表实体类

import com.fasterxml.jackson.annotation.JsonInclude;import java.io.Serializable;
import java.util.Date;/*** 网关路由管理表** @author ppp* @since 2022-04-01*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ManageGatewayRouteDO implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/private Long unid;/*** 网关Code*/private String gatewayCode;/*** 路由名称*/private String routeName;/*** 路由Code*/private String routeCode;/*** 路由URI*/private String routeUri;/*** 路由分发地址","分隔*/private String routePaths;/*** 路由排序*/private Integer routeSort;/*** 限流策略code*/private String limitStrategyCode;/*** 限流策略*/private String limitStrategy;/*** 每秒并发量*/private Integer limitReplenishRate;/*** 最大并发量*/private Integer limitBurstCapacity;/*** 是否启用:1-启用 0-禁用*/private Integer enableFlag;/*** 创建时间*/private Date createTime;/*** 更新时间*/private Date updateTime;/*** 创建人ID*/private String creatorUnid;/*** 创建人名称*/private String creatorName;public Long getUnid() {return unid;}public void setUnid(Long unid) {this.unid = unid;}public String getGatewayCode() {return gatewayCode;}public void setGatewayCode(String gatewayCode) {this.gatewayCode = gatewayCode;}public String getRouteName() {return routeName;}public void setRouteName(String routeName) {this.routeName = routeName;}public String getRouteCode() {return routeCode;}public void setRouteCode(String routeCode) {this.routeCode = routeCode;}public String getRouteUri() {return routeUri;}public void setRouteUri(String routeUri) {this.routeUri = routeUri;}public String getRoutePaths() {return routePaths;}public void setRoutePaths(String routePaths) {this.routePaths = routePaths;}public Integer getRouteSort() {return routeSort;}public void setRouteSort(Integer routeSort) {this.routeSort = routeSort;}public String getLimitStrategyCode() {return limitStrategyCode;}public void setLimitStrategyCode(String limitStrategyCode) {this.limitStrategyCode = limitStrategyCode;}public String getLimitStrategy() {return limitStrategy;}public void setLimitStrategy(String limitStrategy) {this.limitStrategy = limitStrategy;}public Integer getLimitReplenishRate() {return limitReplenishRate;}public void setLimitReplenishRate(Integer limitReplenishRate) {this.limitReplenishRate = limitReplenishRate;}public Integer getLimitBurstCapacity() {return limitBurstCapacity;}public void setLimitBurstCapacity(Integer limitBurstCapacity) {this.limitBurstCapacity = limitBurstCapacity;}public Integer getEnableFlag() {return enableFlag;}public void setEnableFlag(Integer enableFlag) {this.enableFlag = enableFlag;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}public String getCreatorUnid() {return creatorUnid;}public void setCreatorUnid(String creatorUnid) {this.creatorUnid = creatorUnid;}public String getCreatorName() {return creatorName;}public void setCreatorName(String creatorName) {this.creatorName = creatorName;}@Overridepublic String toString() {return "ManageGatewayRouteDO{" +"unid=" + unid +", gatewayCode=" + gatewayCode +", routeName=" + routeName +", routeCode=" + routeCode +", routeUri=" + routeUri +", routePaths=" + routePaths +", routeSort=" + routeSort +", limitStrategyCode=" + limitStrategyCode +", limitStrategy=" + limitStrategy +", limitReplenishRate=" + limitReplenishRate +", limitBurstCapacity=" + limitBurstCapacity +", enableFlag=" + enableFlag +", createTime=" + createTime +", updateTime=" + updateTime +", creatorUnid=" + creatorUnid +", creatorName=" + creatorName +"}";}
}

消息枚举

/**
* 消息枚举
* @author ppp
* @date 2022/4/2
*/
public enum  MessageTagEnum {/*** 消息Tag枚举*/SUCCESS("success", "成功"),FAILURE("failure", "失败");MessageTagEnum(String value, String desc) {this.value = value;this.desc = desc;}private final String value;private final String desc;public String getValue() {return value;}public String getDesc() {return desc;}
}

mapper接口

import com.gateway.demo.entity.dto.ManageGatewayRouteDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;/*** 网关路由管理表 Mapper 接口** @author ppp* @since 2022-04-01*/
@Mapper
public interface ManageGatewayRouteMapper {/*** 获取启用的路由列表* @return  List<ManageGatewayRouteDO>*/List<ManageGatewayRouteDO> getEnableList();/*** 根据unid查询网关路由管理表* @param unid 网关路由管理表ID* @return 网关路由管理表数据对象*/ManageGatewayRouteDO selectByUnid(Long unid);/*** 新增* @param record 网关路由管理表数据对象* @return 影响行数*/int insert(ManageGatewayRouteDO record);/*** 根据unid更新* @param record 网关路由管理表数据对象* @return 影响行数*/int updateByUnid(ManageGatewayRouteDO record);/*** 根据unid删除* @param unid 网关路由管理表ID* @return 影响行数*/int deleteByUnid(Long unid);}

mapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gateway.demo.mapper.ManageGatewayRouteMapper"><!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.gateway.demo.entity.dto.ManageGatewayRouteDO"><id column="unid" jdbcType="BIGINT" property="unid" /><result column="gateway_code" jdbcType="VARCHAR" property="gatewayCode" /><result column="route_name" jdbcType="VARCHAR" property="routeName" /><result column="route_code" jdbcType="VARCHAR" property="routeCode" /><result column="route_uri" jdbcType="VARCHAR" property="routeUri" /><result column="route_paths" jdbcType="VARCHAR" property="routePaths" /><result column="route_sort" jdbcType="INTEGER" property="routeSort" /><result column="limit_strategy_code" jdbcType="VARCHAR" property="limitStrategyCode" /><result column="limit_strategy" jdbcType="VARCHAR" property="limitStrategy" /><result column="limit_replenish_rate" jdbcType="INTEGER" property="limitReplenishRate" /><result column="limit_burst_capacity" jdbcType="INTEGER" property="limitBurstCapacity" /><result column="enable_flag" jdbcType="TINYINT" property="enableFlag" /><result column="create_time" jdbcType="TIMESTAMP" property="createTime" /><result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /><result column="creator_unid" jdbcType="VARCHAR" property="creatorUnid" /><result column="creator_name" jdbcType="VARCHAR" property="creatorName" />
</resultMap><!-- 通用查询结果列 -->
<sql id="Base_Column_List">unid, gateway_code, route_name, route_code, route_uri,route_paths, route_sort, limit_strategy_code, limit_strategy, limit_replenish_rate,limit_burst_capacity, enable_flag, create_time, update_time, creator_unid,creator_name
</sql><!--根据unid查询-->
<select id="selectByUnid" parameterType="java.lang.Long" resultMap="BaseResultMap">select <include refid="Base_Column_List" />from manage_gateway_routewhere unid = #{unid,jdbcType=BIGINT}
</select><select id="getEnableList" resultMap="BaseResultMap">select <include refid="Base_Column_List" />from manage_gateway_routewhere enable_flag = 1
</select><!--新增-->
<insert id="insert" parameterType="com.gateway.demo.entity.dto.ManageGatewayRouteDO">insert into manage_gateway_route ( unid, gateway_code, route_name, route_code, route_uri,route_paths, route_sort, limit_strategy_code, limit_strategy, limit_replenish_rate,limit_burst_capacity, enable_flag, create_time, update_time, creator_unid,creator_name )values ( #{unid,jdbcType=BIGINT}, #{gatewayCode,jdbcType=VARCHAR}, #{routeName,jdbcType=VARCHAR},#{routeCode,jdbcType=VARCHAR}, #{routeUri,jdbcType=VARCHAR}, #{routePaths,jdbcType=VARCHAR},#{routeSort,jdbcType=INTEGER}, #{limitStrategyCode,jdbcType=VARCHAR}, #{limitStrategy,jdbcType=VARCHAR},#{limitReplenishRate,jdbcType=INTEGER}, #{limitBurstCapacity,jdbcType=INTEGER}, #{enableFlag,jdbcType=TINYINT},#{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}, #{creatorUnid,jdbcType=VARCHAR},#{creatorName,jdbcType=VARCHAR} )
</insert><!--根据unid更新-->
<update id="updateByUnid" parameterType="com.gateway.demo.entity.dto.ManageGatewayRouteDO">update manage_gateway_route<set><if test="gatewayCode != null and gatewayCode != ''">gateway_code = #{gatewayCode,jdbcType=VARCHAR},</if><if test="routeName != null and routeName != ''">route_name = #{routeName,jdbcType=VARCHAR},</if><if test="routeCode != null and routeCode != ''">route_code = #{routeCode,jdbcType=VARCHAR},</if><if test="routeUri != null and routeUri != ''">route_uri = #{routeUri,jdbcType=VARCHAR},</if><if test="routePaths != null and routePaths != ''">route_paths = #{routePaths,jdbcType=VARCHAR},</if><if test="routeSort != null">route_sort = #{routeSort,jdbcType=INTEGER},</if><if test="limitStrategyCode != null and limitStrategyCode != ''">limit_strategy_code = #{limitStrategyCode,jdbcType=VARCHAR},</if><if test="limitStrategy != null and limitStrategy != ''">limit_strategy = #{limitStrategy,jdbcType=VARCHAR},</if><if test="limitReplenishRate != null">limit_replenish_rate = #{limitReplenishRate,jdbcType=INTEGER},</if><if test="limitBurstCapacity != null">limit_burst_capacity = #{limitBurstCapacity,jdbcType=INTEGER},</if><if test="enableFlag != null">enable_flag = #{enableFlag,jdbcType=TINYINT},</if><if test="createTime != null">create_time = #{createTime,jdbcType=TIMESTAMP},</if><if test="updateTime != null">update_time = #{updateTime,jdbcType=TIMESTAMP},</if><if test="creatorUnid != null and creatorUnid != ''">creator_unid = #{creatorUnid,jdbcType=VARCHAR},</if><if test="creatorName != null and creatorName != ''">creator_name = #{creatorName,jdbcType=VARCHAR},</if></set>where unid = #{unid,jdbcType=BIGINT}
</update><!--根据unid删除-->
<delete id="deleteByUnid" parameterType="java.lang.Long">delete from manage_gateway_routewhere unid = #{unid,jdbcType=BIGINT}
</delete>

参考文档:

(这几篇都写的不错)
Gateway网关简介及使用:

https://blog.csdn.net/rain_web/article/details/102469745?spm=1001.2014.3001.5506

Gateway 源码解析 :

https://blog.csdn.net/X5fnncxzq4/article/details/80221488?spm=1001.2014.3001.5506

详解动态路由的两种方式:

https://tianyalei.blog.csdn.net/article/details/83412301?spm=1001.2014.3001.5506

基于Redis实现Spring Cloud Gateway的动态管理:

https://blog.csdn.net/weixin_45443931/article/details/100017121?spm=1001.2014.3001.5506

Spring Cloud Gateway 3.1.1基于redis实现动态路由和管理功能相关推荐

  1. Spring Cloud Gateway +Oauth2 +JWT+Vue 实现前后端分离RBAC权限管理

    这是一篇很长的文章,所以需要有点耐心,当然也可以直接查看源码:源码 对于有不太明白的地方可以给我留言,如果网关是zuul或者不是基于spring cloud的实现的,那其实更简单了1.1.如果是zuu ...

  2. spring cloud gateway获取真实ip以及跨服务器时路由转发的一些问题

    springCloud主版本Greenwitch SR2  gateway版本2.1.2 网上大多教程是添加如下一段代码,然后就可以在网关拿到真实路由ip而不是路由id 但是网上教程杂七杂八,我也不记 ...

  3. 在CentOS 6.9 x86_64的OpenResty 1.13.6.1上使用基于Redis实现动态路由示例

    下面是我阅读春哥OpenResty官网主页中"Dynamic Routing Based On Redis"一节的实操记录,整理如下. https://openresty.org/ ...

  4. 三分钟了解Spring Cloud Gateway路由转发之自动路由

    文章目录 一.前言 二.路由配置 1. 静态路由 2. 动态路由 3. 自动路由 三.Spring Cloud Gateway 是如何实现动态路由 工作原理 源码解析 路由转发原理 路由转发源码解析 ...

  5. spring cloud gateway 之动态路由

    前面分别对 Spring Cloud Zuul 与 Spring Cloud Gateway 进行了简单的说明,它门是API网关,API网关负责服务请求路由.组合及协议转换,客户端的所有请求都首先经过 ...

  6. 微服务网关Zuul迁移到Spring Cloud Gateway

    https://juejin.im/post/5ba8daa56fb9a05cfe486ebf 背景 在之前的文章中,我们介绍过微服务网关Spring Cloud Netflix Zuul,前段时间有 ...

  7. Spring Cloud Gateway介绍(二)

    Spring Cloud Gateway介绍(一) 全局Filters GlobalFilter与GatewayFilter具有一样的接口. 这些全局过滤器都有对应的配置类,例如: org.sprin ...

  8. 网关 跨域_好文推荐:微服务网关实战—Spring Cloud Gateway

    作者:博云BoCloud| 前言 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用. ...

  9. ws配置 zuul_微服务网关 Spring Cloud Gateway

    1.  为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...

  10. Spring Cloud Gateway 3.1.3最新版中文手册官网2022

    Spring Cloud Gateway 3.1.3 该项目提供了一个库,用于在 Spring WebFlux 之上构建 API 网关.Spring Cloud Gateway 旨在提供一种简单而有效 ...

最新文章

  1. 基于比特币现金BCH二层网络能实现区块链2.0以太坊的智能化吗
  2. NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成...
  3. ios NSAttributedString 具体解释
  4. 从0到1简易区块链开发手册V0.3-数据持久化与创世区块
  5. [蓝桥杯2016初赛]密码脱落
  6. win10打字突然变成繁体
  7. 每日一题(39)—— sizeof
  8. 从零搭建ES搜索服务(一)基本概念及环境搭建
  9. iterator总结(未完)
  10. STM32利用AES加密数据、解密数据
  11. 解决谷歌Chrome浏览器默认主页被毒霸篡改的问题
  12. 企业网站排名,站内布局,不只有关键词密度
  13. python画国际象棋_python用turtle画国际象棋棋盘
  14. 读《终身学习》 哈佛毕业后的六堂课,整理总结
  15. 史上最简单的rar压缩包文档解密方法,rar压缩包权限密码如何解开?
  16. 施主,贫僧乃东土大唐而来,恳请在此借宿一晚……...
  17. Document.createEvent() 创建自定义事件
  18. VMware虚拟机更改Mac系统的屏幕分辨率
  19. py-21-Android
  20. 读《我想要的记忆魔法书》有感

热门文章

  1. 【文献笔记】NOMA+D2D模型3 (D2D group)
  2. 实现闲鱼自动化脚本-方案对比分析
  3. 奥林匹克计算机竞赛保送,电脑奥赛中最寂寥的竞赛 5学生夺牌直通清华
  4. 详解ARM的AMBA设备中的DMA设备(Linux驱动之DMA)
  5. Arduino-ESP8266 控制舵机开门
  6. 手把手教你搭建一个OPCDA/UA服务器
  7. ⭐算法入门⭐《二分枚举》中等05 —— LeetCode 1201. 丑数 III
  8. spring mvc +maven 集成 quartz实现定时任务
  9. 乒乓球比赛赛程_这家律所再次摘得业余乒乓球赛事冠军,为何结缘乒乓?
  10. Android录屏技术方案