需求:
正常的提供一个网关服务,可以实现网关的管理(增删改查)
思路:
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)中的发布器值针对当前服务生效,考虑用消息队列来通知集群的网关服务一起刷新路由,当然也可以使用zk或者nacos注册中心来实现
注意:
如果采用MQ来实现集群网关的刷新,尽量使用一个独立的MQ,基本省可以达到秒刷的效果,否则和业务公用一个MQ的话,一旦消息积压,那刷新的延时就很大了
不过生产环境还是用注册中心来实现更好(推荐),注册中心的实现方式下次有空再补
技术栈:
spring cloud gateway + 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存储路由,不加这个的话需要自己注册bean
gateway:
redis-route-definition-repository:
enabled: true
# redis
spring.redis:
database: 1
host: 192.168.8.49
password: 123456
port: 6379
timeout: 3000
# mysql
spring.datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/gateway?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true
username: root
password: 123456
# mybatis
mybatis:
mapper-locations: classpath:mapper/**/*Mapper.xml
type-aliases-package: com.gateway.demo.*.entity
# rocketmq
rocketmq:
name-server: 192.168.8.49:9876
producer:
send-message-timeout: 3000
group: gateway
topic:
prefix: test
# 网关刷新topic
gateway-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、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 {
@Autowired
IManageGatewayRouteService 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();
}
}
6、(核心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 {
@Resource
IRoutePublishService routePublishService;
@Resource
RedisRouteDefinitionRepository redisRouteDefinitionRepository;
@Resource
ManageGatewayRouteMapper manageGatewayRouteMapper;
@Resource
GatewayRefreshProducer gatewayRefreshProducer;
@Override
public 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;
}
@Override
public 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;
}
}
7、(核心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;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
@Override
public void publishRoutes() {
publisher.publishEvent(new RefreshRoutesEvent(this));
}
}
8、消息生产者
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;
@Autowired
RocketMQTemplate rocketMqTemplate;
public void sendMessage(String tag){
// 消息体没啥需要发送的内容对象,就搞个"-"字符串把
Message<String> message = MessageBuilder.withPayload("-").build();
rocketMqTemplate.asyncSend(gatewayRefreshTopic + ":" + tag, message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
logger.info("发送网关刷新消息成功");
}
@Override
public void onException(Throwable throwable) {
logger.info(throwable.getMessage(), throwable);
logger.info("发送网关刷新消息失败");
}
});
}
}
9、消息消费者
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;
@Autowired
IRoutePublishService routePublishService;
@Override
public 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");
}
}
10、表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;
}
@Override
public 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_route
where unid = #{unid,jdbcType=BIGINT}
</select>
<select id="getEnableList" resultMap="BaseResultMap">
select <include refid="Base_Column_List" />
from manage_gateway_route
where 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_route
where 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