天天看点

gateway动态路由实现 mysql+redis 实现

前言

大家都知道咱们在通常是使用配置文件来实现配置,但是这样就有一个弊端,就是每次修改的时候都要去重启来实现,并且管理起来非常麻烦,所有就有了这种实现方式。

现在的实现方式:

spring:
  application:
    name: gateway-service
    gateway:
      routes:
        - id: mqtt-service-route
          uri: lb://mqtt-service
          predicates:
            - Path=/mqtt/**
        - id: usermgr-service-route
          uri: lb://usermgr-service
          predicates:
            - Path=/usermgr/**      

新的动态实现方式

pom.xml依赖

<dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.53</version>
        </dependency>
        <!-- springcloud gateway网关依赖 start-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gateway-webflux</artifactId>
        </dependency>
        <!-- springcloud gateway网关依赖 end-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.3</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </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>      

数据库脚本实现

/*
 Navicat MySQL Data Transfer

 Source Server         : 阿里云服务器
 Source Server Type    : MySQL
 Source Server Version : 50725
 Source Host           : youxiu326.xin:3306
 Source Schema         : super_man

 Target Server Type    : MySQL
 Target Server Version : 50725
 File Encoding         : 65001

 Date: 23/03/2020 14:47:09
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for gateway_route
-- ----------------------------
DROP TABLE IF EXISTS `gateway_route`;
CREATE TABLE `gateway_route` (
  `id` bigint(28) NOT NULL AUTO_INCREMENT,
  `service_id` varchar(64) DEFAULT NULL,
  `uri` varchar(100) DEFAULT NULL COMMENT '转发地址',
  `predicates` varchar(200) DEFAULT NULL COMMENT '访问路径',
  `filters` varchar(100) DEFAULT NULL COMMENT '过滤',
  `order_` varchar(2) DEFAULT '0' COMMENT '顺序',
  `creator_id` varchar(64) DEFAULT NULL,
  `create_date` datetime DEFAULT NULL,
  `update_id` varchar(64) DEFAULT NULL,
  `update_date` datetime DEFAULT NULL,
  `remarks` varchar(255) DEFAULT NULL COMMENT '备注信息',
  `del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of gateway_route
-- ----------------------------
BEGIN;
INSERT INTO `gateway_route` VALUES (1, 'serviceNode1', 'https://baidu.com/', '/api-baidu/**', '1', '0', '', '2020-03-02 00:05:59', '', '2020-03-02 00:50:27', NULL, '0');
INSERT INTO `gateway_route` VALUES (2, 'serviceNode2', 'https://www.taobao.com/', '/api-taobao/**', '1', '0', '', '2020-03-02 00:51:30', NULL, NULL, NULL, '0');
INSERT INTO `gateway_route` VALUES (8, 'serviceNode3', 'https://youxiu326.xin/', '/youxiu326/**', '1', '1', '', '2020-03-23 01:41:45', NULL, NULL, NULL, '0');
INSERT INTO `gateway_route` VALUES (10, 'serviceNode4', 'https://suggest.taobao.com/', '/search/**', '1', '1', '', '2020-03-23 01:45:59', NULL, NULL, NULL, '0');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;      

核心配置类的实现

核心配置类,项目初始化加载数据库的路由配置,主要实现数据载入,以及数据的初始化,为了提高效率是被数据中数据同步到redis 中。

import com.alibaba.fastjson.JSON;
import com.hou.dao.GatewayRouteMapper;
import com.hou.entity.GatewayRoute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
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.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 *
 * 核心配置类,项目初始化加载数据库的路由配置
 *
 */
@Service
public class GatewayServiceHandler implements ApplicationEventPublisherAware, CommandLineRunner {

    private final static Logger log = LoggerFactory.getLogger(GatewayServiceHandler.class);

    @Autowired
    private RedisRouteDefinitionRepository routeDefinitionWriter;

    private ApplicationEventPublisher publisher;

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

    //自己的获取数据dao
    @Autowired
    private GatewayRouteMapper gatewayRouteMapper;

    // springboot启动后执行
    @Override
    public void run(String... args){
        this.loadRouteConfig();
    }

    public String loadRouteConfig() {
        //从数据库拿到路由配置
        List<GatewayRoute> gatewayRouteList = gatewayRouteMapper.queryAllRoutes();

        log.info("网关配置信息:=====>"+ JSON.toJSONString(gatewayRouteList));

        gatewayRouteList.forEach(gatewayRoute -> {
            RouteDefinition definition = new RouteDefinition();

            Map<String, String> predicateParams = new HashMap<>(8);
            PredicateDefinition predicate = new PredicateDefinition();

            FilterDefinition filter = new FilterDefinition();
            Map<String, String> filterParams = new HashMap<>(8);

            URI uri = UriComponentsBuilder.fromHttpUrl(gatewayRoute.getUri()).build().toUri();

            definition.setId(gatewayRoute.getId().toString());
            // 名称是固定的,spring gateway会根据名称找对应的PredicateFactory
            predicate.setName("Path");
            predicateParams.put("pattern",gatewayRoute.getPredicates());
            predicate.setArgs(predicateParams);

            // 名称是固定的, 路径去前缀(从前面截取一个,实际上就是截取url,后面的部分才是转发的url)
            filter.setName("StripPrefix");
            filterParams.put("_genkey_0", gatewayRoute.getFilters().toString());
            filter.setArgs(filterParams);

            definition.setPredicates(Arrays.asList(predicate));
            definition.setFilters(Arrays.asList(filter));

            definition.setUri(uri);
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        });

        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return "success";
    }


    public void deleteRoute(String routeId){
        routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }
}      

数据库管理类

import java.util.List;

public interface GatewayRouteMapper {
    int deleteByPrimaryKey(Long id);

    int insert(GatewayRoute record);

    int insertSelective(GatewayRoute record);

    GatewayRoute selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(GatewayRoute record);

    int updateByPrimaryKey(GatewayRoute record);

    List<GatewayRoute> queryAllRoutes();
}      

Table 管理类

import java.util.Date;

/**
 * 实体
 */
public class GatewayRoute {

    private Long id;

    private String serviceId;

    private String uri;

    private String predicates;

    private String filters;

    private String order;

    private String creatorId;

    private Date createDate;

    private String updateId;

    private Date updateDate;

    private String remarks;

    private String delFlag;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getServiceId() {
        return serviceId;
    }

    public void setServiceId(String serviceId) {
        this.serviceId = serviceId == null ? null : serviceId.trim();
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri == null ? null : uri.trim();
    }

    public String getPredicates() {
        return predicates;
    }

    public void setPredicates(String predicates) {
        this.predicates = predicates == null ? null : predicates.trim();
    }

    public String getFilters() {
        return filters;
    }

    public void setFilters(String filters) {
        this.filters = filters == null ? null : filters.trim();
    }

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order == null ? null : order.trim();
    }

    public String getCreatorId() {
        return creatorId;
    }

    public void setCreatorId(String creatorId) {
        this.creatorId = creatorId == null ? null : creatorId.trim();
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public String getUpdateId() {
        return updateId;
    }

    public void setUpdateId(String updateId) {
        this.updateId = updateId == null ? null : updateId.trim();
    }

    public Date getUpdateDate() {
        return updateDate;
    }

    public void setUpdateDate(Date updateDate) {
        this.updateDate = updateDate;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks == null ? null : remarks.trim();
    }

    public String getDelFlag() {
        return delFlag;
    }

    public void setDelFlag(String delFlag) {
        this.delFlag = delFlag == null ? null : delFlag.trim();
    }
}      

Map 操作类

<?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.youxiu326.dao.GatewayRouteMapper" >
  <resultMap id="BaseResultMap" type="com.youxiu326.entity.GatewayRoute" >
    <id column="id" property="id" jdbcType="BIGINT" />
    <result column="service_id" property="serviceId" jdbcType="VARCHAR" />
    <result column="uri" property="uri" jdbcType="VARCHAR" />
    <result column="predicates" property="predicates" jdbcType="VARCHAR" />
    <result column="filters" property="filters" jdbcType="VARCHAR" />
    <result column="order_" property="order" jdbcType="VARCHAR" />
    <result column="creator_id" property="creatorId" jdbcType="VARCHAR" />
    <result column="create_date" property="createDate" jdbcType="TIMESTAMP" />
    <result column="update_id" property="updateId" jdbcType="VARCHAR" />
    <result column="update_date" property="updateDate" jdbcType="TIMESTAMP" />
    <result column="remarks" property="remarks" jdbcType="VARCHAR" />
    <result column="del_flag" property="delFlag" jdbcType="CHAR" />
  </resultMap>
  <sql id="Base_Column_List" >
    id, service_id, uri, predicates, filters,order_, creator_id, create_date, update_id,
    update_date, remarks, del_flag
  </sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" >
    select 
    <include refid="Base_Column_List" />
    from gateway_route
    where id = #{id,jdbcType=BIGINT}
  </select>
  <select id="queryAllRoutes" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from gateway_route where del_flag=0
  </select>

  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long" >
    delete from gateway_route
    where id = #{id,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="com.youxiu326.entity.GatewayRoute" >
    insert into gateway_route (id, service_id, uri, 
      predicates, filters, order_,
      creator_id, create_date, update_id, 
      update_date, remarks, del_flag
      )
    values (#{id,jdbcType=BIGINT}, #{serviceId,jdbcType=VARCHAR}, #{uri,jdbcType=VARCHAR}, 
      #{predicates,jdbcType=VARCHAR}, #{filters,jdbcType=VARCHAR}, #{order,jdbcType=VARCHAR}, 
      #{creatorId,jdbcType=VARCHAR}, #{createDate,jdbcType=TIMESTAMP}, #{updateId,jdbcType=VARCHAR}, 
      #{updateDate,jdbcType=TIMESTAMP}, #{remarks,jdbcType=VARCHAR}, #{delFlag,jdbcType=CHAR}
      )
  </insert>
  <insert id="insertSelective" parameterType="com.youxiu326.entity.GatewayRoute" >
    insert into gateway_route
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="serviceId != null" >
        service_id,
      </if>
      <if test="uri != null" >
        uri,
      </if>
      <if test="predicates != null" >
        predicates,
      </if>
      <if test="filters != null" >
        filters,
      </if>
      <if test="order != null" >
        order_,
      </if>
      <if test="creatorId != null" >
        creator_id,
      </if>
      <if test="createDate != null" >
        create_date,
      </if>
      <if test="updateId != null" >
        update_id,
      </if>
      <if test="updateDate != null" >
        update_date,
      </if>
      <if test="remarks != null" >
        remarks,
      </if>
      <if test="delFlag != null" >
        del_flag,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=BIGINT},
      </if>
      <if test="serviceId != null" >
        #{serviceId,jdbcType=VARCHAR},
      </if>
      <if test="uri != null" >
        #{uri,jdbcType=VARCHAR},
      </if>
      <if test="predicates != null" >
        #{predicates,jdbcType=VARCHAR},
      </if>
      <if test="filters != null" >
        #{filters,jdbcType=VARCHAR},
      </if>
      <if test="order != null" >
        #{order,jdbcType=VARCHAR},
      </if>
      <if test="creatorId != null" >
        #{creatorId,jdbcType=VARCHAR},
      </if>
      <if test="createDate != null" >
        #{createDate,jdbcType=TIMESTAMP},
      </if>
      <if test="updateId != null" >
        #{updateId,jdbcType=VARCHAR},
      </if>
      <if test="updateDate != null" >
        #{updateDate,jdbcType=TIMESTAMP},
      </if>
      <if test="remarks != null" >
        #{remarks,jdbcType=VARCHAR},
      </if>
      <if test="delFlag != null" >
        #{delFlag,jdbcType=CHAR},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.youxiu326.entity.GatewayRoute" >
    update gateway_route
    <set >
      <if test="serviceId != null" >
        service_id = #{serviceId,jdbcType=VARCHAR},
      </if>
      <if test="uri != null" >
        uri = #{uri,jdbcType=VARCHAR},
      </if>
      <if test="predicates != null" >
        predicates = #{predicates,jdbcType=VARCHAR},
      </if>
      <if test="filters != null" >
        filters = #{filters,jdbcType=VARCHAR},
      </if>
      <if test="order != null" >
        order_ = #{order,jdbcType=VARCHAR},
      </if>
      <if test="creatorId != null" >
        creator_id = #{creatorId,jdbcType=VARCHAR},
      </if>
      <if test="createDate != null" >
        create_date = #{createDate,jdbcType=TIMESTAMP},
      </if>
      <if test="updateId != null" >
        update_id = #{updateId,jdbcType=VARCHAR},
      </if>
      <if test="updateDate != null" >
        update_date = #{updateDate,jdbcType=TIMESTAMP},
      </if>
      <if test="remarks != null" >
        remarks = #{remarks,jdbcType=VARCHAR},
      </if>
      <if test="delFlag != null" >
        del_flag = #{delFlag,jdbcType=CHAR},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.youxiu326.entity.GatewayRoute" >
    update gateway_route
    set service_id = #{serviceId,jdbcType=VARCHAR},
      uri = #{uri,jdbcType=VARCHAR},
      predicates = #{predicates,jdbcType=VARCHAR},
      filters = #{filters,jdbcType=VARCHAR},
      order_ = #{order,jdbcType=VARCHAR},
      creator_id = #{creatorId,jdbcType=VARCHAR},
      create_date = #{createDate,jdbcType=TIMESTAMP},
      update_id = #{updateId,jdbcType=VARCHAR},
      update_date = #{updateDate,jdbcType=TIMESTAMP},
      remarks = #{remarks,jdbcType=VARCHAR},
      del_flag = #{delFlag,jdbcType=CHAR}
    where id = #{id,jdbcType=BIGINT}
  </update>
</mapper>      

service 层的实现 service层,增、删、改、查数据库路由配置信息

import java.util.Date;
import java.util.List;

import com.hou.dao.GatewayRouteMapper;
import com.hou.dto.GatewayRouteDto;
import com.hou.entity.GatewayRoute;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 *  自定义service层,增、删、改、查数据库路由配置信息
 */
@Service
public class GatewayRouteService {

    @Autowired
    private GatewayRouteMapper gatewayRouteMapper;

    public Integer add(GatewayRouteDto gatewayRouteDto) {
        GatewayRoute gatewayRoute = new GatewayRoute();
        BeanUtils.copyProperties(gatewayRouteDto, gatewayRoute);
        gatewayRoute.setCreateDate(new Date());
        gatewayRoute.setCreatorId("");
        if (gatewayRoute.getId()!=null){
            return gatewayRouteMapper.updateByPrimaryKeySelective(gatewayRoute);
        }
        return gatewayRouteMapper.insertSelective(gatewayRoute);
    }

    public Integer update(GatewayRouteDto gatewayRouteDto) {
        GatewayRoute gatewayRoute = new GatewayRoute();
        BeanUtils.copyProperties(gatewayRouteDto, gatewayRoute);
        gatewayRoute.setUpdateDate(new Date());
        gatewayRoute.setUpdateId("");
        return gatewayRouteMapper.updateByPrimaryKeySelective(gatewayRoute);
    }

    public Integer delete(String id) {
        return gatewayRouteMapper.deleteByPrimaryKey(Long.parseLong(id));
    }

    public List<GatewayRoute> queryAllRoutes(){
        return gatewayRouteMapper.queryAllRoutes();
    }

}      

自定义controller层

import com.hou.configuration.GatewayServiceHandler;
import com.hou.dto.GatewayRouteDto;
import com.hou.entity.GatewayRoute;
import com.hou.service.GatewayRouteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


/**
 *  1.直接在数据库添加路由配置信息,手动刷新,使配置信息立即生效;
 *
 *  2.前端页面增、删、改路由配置信息,并使配置信息立即生效;
 *
 */
@RestController
@RequestMapping("/route")
public class RouteController {

    @Autowired
    private GatewayServiceHandler gatewayServiceHandler;

    @Autowired
    private GatewayRouteService gatewayRouteService;

    /**
     * 刷新路由配置
     * @return
     */
    @GetMapping("/refresh")
    public String refresh() throws Exception {
        return this.gatewayServiceHandler.loadRouteConfig();
    }

    /**
     * 增加路由记录
     *
     * @return
     */
    @PostMapping("/add")
    public String add(@RequestBody GatewayRouteDto gatewayRouteDto) throws Exception {
        gatewayRouteService.add(gatewayRouteDto);
        gatewayServiceHandler.loadRouteConfig();
        return "success";
    }

    @PostMapping("/update")
    public String update(@RequestBody GatewayRouteDto gatewayRouteDto) throws Exception {
        gatewayRouteService.update(gatewayRouteDto);
        gatewayServiceHandler.loadRouteConfig();
        return "success";
    }

    @GetMapping("/delete/{id}")
    public String delete(@PathVariable String id) throws Exception {
        gatewayRouteService.delete(id);
        gatewayServiceHandler.deleteRoute(id);
        return "success";
    }

    @GetMapping("/routes")
    public List<GatewayRoute> routes() throws Exception {
        return gatewayRouteService.queryAllRoutes();
    }

}      

前端参数dto

import java.io.Serializable;

/**
 * DTO
 */
public class GatewayRouteDto implements Serializable {

    private Long id;

    private String serviceId;

    private String uri;

    private String predicates;

    private String filters;

    private String order;

    private String remarks;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getServiceId() {
        return serviceId;
    }

    public void setServiceId(String serviceId) {
        this.serviceId = serviceId;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public String getPredicates() {
        return predicates;
    }

    public void setPredicates(String predicates) {
        this.predicates = predicates;
    }

    public String getFilters() {
        return filters;
    }

    public void setFilters(String filters) {
        this.filters = filters;
    }

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }
}      

redis 实现类

那么接下来就是redis的配置和实现类了。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import javax.annotation.PostConstruct;

/**
 * 防止redis  中文乱码
 */
@Configuration
public class RedisConfig {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @PostConstruct
    public void initRedisTemplate() {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
    }

}      
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * 核心配置类,加载数据库的路由配置信息到redis
 * 将定义好的路由表信息通过此类读写到redis中
 */
@Component
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {

    public static final String GATEWAY_ROUTES = "gateway:routes";

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        List<RouteDefinition> routeDefinitions = new ArrayList<>();
        redisTemplate.opsForHash().values(GATEWAY_ROUTES).stream().forEach(routeDefinition -> {
            routeDefinitions.add(JSON.parseObject(routeDefinition.toString(), RouteDefinition.class));
        });
        return Flux.fromIterable(routeDefinitions);
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route
                .flatMap(routeDefinition -> {
                    redisTemplate.opsForHash().put(GATEWAY_ROUTES, routeDefinition.getId(),
                            JSON.toJSONString(routeDefinition));
                    return Mono.empty();
                });
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            if (redisTemplate.opsForHash().hasKey(GATEWAY_ROUTES, id)) {
                redisTemplate.opsForHash().delete(GATEWAY_ROUTES, id);
                return Mono.empty();
            }
            return Mono.defer(() -> Mono.error(new NotFoundException("路由文件没有找到: " + routeId)));
        });
    }
}      

总结

继续阅读