Spring Cloud Gateway 3.1.1基于redis实现动态路由和管理功能
需求:
正常的提供一个网关服务,可以实现网关的管理(增删改查)
思路:
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实现动态路由和管理功能相关推荐
- Spring Cloud Gateway +Oauth2 +JWT+Vue 实现前后端分离RBAC权限管理
这是一篇很长的文章,所以需要有点耐心,当然也可以直接查看源码:源码 对于有不太明白的地方可以给我留言,如果网关是zuul或者不是基于spring cloud的实现的,那其实更简单了1.1.如果是zuu ...
- spring cloud gateway获取真实ip以及跨服务器时路由转发的一些问题
springCloud主版本Greenwitch SR2 gateway版本2.1.2 网上大多教程是添加如下一段代码,然后就可以在网关拿到真实路由ip而不是路由id 但是网上教程杂七杂八,我也不记 ...
- 在CentOS 6.9 x86_64的OpenResty 1.13.6.1上使用基于Redis实现动态路由示例
下面是我阅读春哥OpenResty官网主页中"Dynamic Routing Based On Redis"一节的实操记录,整理如下. https://openresty.org/ ...
- 三分钟了解Spring Cloud Gateway路由转发之自动路由
文章目录 一.前言 二.路由配置 1. 静态路由 2. 动态路由 3. 自动路由 三.Spring Cloud Gateway 是如何实现动态路由 工作原理 源码解析 路由转发原理 路由转发源码解析 ...
- spring cloud gateway 之动态路由
前面分别对 Spring Cloud Zuul 与 Spring Cloud Gateway 进行了简单的说明,它门是API网关,API网关负责服务请求路由.组合及协议转换,客户端的所有请求都首先经过 ...
- 微服务网关Zuul迁移到Spring Cloud Gateway
https://juejin.im/post/5ba8daa56fb9a05cfe486ebf 背景 在之前的文章中,我们介绍过微服务网关Spring Cloud Netflix Zuul,前段时间有 ...
- Spring Cloud Gateway介绍(二)
Spring Cloud Gateway介绍(一) 全局Filters GlobalFilter与GatewayFilter具有一样的接口. 这些全局过滤器都有对应的配置类,例如: org.sprin ...
- 网关 跨域_好文推荐:微服务网关实战—Spring Cloud Gateway
作者:博云BoCloud| 前言 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用. ...
- ws配置 zuul_微服务网关 Spring Cloud Gateway
1. 为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...
- Spring Cloud Gateway 3.1.3最新版中文手册官网2022
Spring Cloud Gateway 3.1.3 该项目提供了一个库,用于在 Spring WebFlux 之上构建 API 网关.Spring Cloud Gateway 旨在提供一种简单而有效 ...
最新文章
- 基于比特币现金BCH二层网络能实现区块链2.0以太坊的智能化吗
- NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成...
- ios NSAttributedString 具体解释
- 从0到1简易区块链开发手册V0.3-数据持久化与创世区块
- [蓝桥杯2016初赛]密码脱落
- win10打字突然变成繁体
- 每日一题(39)—— sizeof
- 从零搭建ES搜索服务(一)基本概念及环境搭建
- iterator总结(未完)
- STM32利用AES加密数据、解密数据
- 解决谷歌Chrome浏览器默认主页被毒霸篡改的问题
- 企业网站排名,站内布局,不只有关键词密度
- python画国际象棋_python用turtle画国际象棋棋盘
- 读《终身学习》 哈佛毕业后的六堂课,整理总结
- 史上最简单的rar压缩包文档解密方法,rar压缩包权限密码如何解开?
- 施主,贫僧乃东土大唐而来,恳请在此借宿一晚……...
- Document.createEvent() 创建自定义事件
- VMware虚拟机更改Mac系统的屏幕分辨率
- py-21-Android
- 读《我想要的记忆魔法书》有感
热门文章
- 【文献笔记】NOMA+D2D模型3 (D2D group)
- 实现闲鱼自动化脚本-方案对比分析
- 奥林匹克计算机竞赛保送,电脑奥赛中最寂寥的竞赛 5学生夺牌直通清华
- 详解ARM的AMBA设备中的DMA设备(Linux驱动之DMA)
- Arduino-ESP8266 控制舵机开门
- 手把手教你搭建一个OPCDA/UA服务器
- ⭐算法入门⭐《二分枚举》中等05 —— LeetCode 1201. 丑数 III
- spring mvc +maven 集成 quartz实现定时任务
- 乒乓球比赛赛程_这家律所再次摘得业余乒乓球赛事冠军,为何结缘乒乓?
- Android录屏技术方案