springcloud gateway结合mysql+redis实现动态路由

14 篇文章 1 订阅
14 篇文章 0 订阅

1、数据库脚本和pom
mysql 8版本
在这里插入图片描述

/*
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 80019
 Source Host           : localhost:3306
 Source Schema         : test

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

 Date: 11/11/2021 10:21:56
*/

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(0) NOT NULL AUTO_INCREMENT,
  `service_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `uri` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `predicates` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `filters` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `order` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0',
  `create_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `create_date` datetime(0) NULL DEFAULT NULL,
  `update_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `update_date` datetime(0) NULL DEFAULT NULL,
  `remarks` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

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.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-cloud-gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-gateway</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gateway-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.56</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</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>

</project>

2、dto

package com.example.springcloudgateway.dto;

/**
 * @author code
 * @Date 2021/11/11 11:14
 * Description
 * Version 1.0
 */

import java.io.Serializable;
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;
    }
}

3、eneity

package com.example.springcloudgateway.entity;

import java.util.Date;

/**
 * @author code
 * @Date 2021/11/11 10:24
 * Description 路由实体
 * Version 1.0
 */
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;
    }

    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 getCreatorId() {
        return creatorId;
    }

    public void setCreatorId(String creatorId) {
        this.creatorId = creatorId;
    }

    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;
    }

    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;
    }

    public String getDelFlag() {
        return delFlag;
    }

    public void setDelFlag(String delFlag) {
        this.delFlag = delFlag;
    }
}

4、控制层

package com.example.springcloudgateway.controller;

import com.example.springcloudgateway.service.GatewayRouteService;
import com.example.springcloudgateway.service.impl.GatewayServiceHandler;
import com.example.springcloudgateway.dto.GatewayRouteDto;
import com.example.springcloudgateway.entity.GatewayRoute;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author code
 * @Date 2021/11/11 11:00
 * Description 路由控制层
 * Version 1.0
 */

@RestController
@RequestMapping("/route")
public class RouteController {

    @Autowired
    private GatewayServiceHandler gatewayServiceHandler;

    @Autowired
    private GatewayRouteService gatewayRouteService;

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

    /**
     * 增加路由记录
     *
     * @param
     * @return
     */
    @PostMapping("/add")
    public String add(@RequestBody GatewayRouteDto gatewayRouteDto) throws Exception {
        gatewayRouteService.add(gatewayRouteDto);
        GatewayRoute gatewayRoute=new GatewayRoute();
        BeanUtils.copyProperties(gatewayRouteDto, gatewayRoute);
        gatewayServiceHandler.saveRoute(gatewayRoute);
        return "success";
    }

    @PostMapping("/update")
    public String update(@RequestBody GatewayRouteDto gatewayRouteDto) throws Exception {
        gatewayRouteService.update(gatewayRouteDto);
        GatewayRoute gatewayRoute=new GatewayRoute();
        BeanUtils.copyProperties(gatewayRouteDto, gatewayRoute);
        gatewayServiceHandler.update(gatewayRoute);
        return "success";
    }

    @GetMapping("/delete")
    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();
    }
}

5、接口层

package com.example.springcloudgateway.service;

import com.example.springcloudgateway.dto.GatewayRouteDto;
import com.example.springcloudgateway.entity.GatewayRoute;
import org.springframework.beans.BeanUtils;

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

/**
 * @author code
 * @Date 2021/11/11 12:30
 * Description
 * Version 1.0
 */
public interface GatewayRouteService {
    public Integer add(GatewayRouteDto gatewayRouteDto);

    public Integer update(GatewayRouteDto gatewayRouteDto);

    public Integer delete(String id);

    public List<GatewayRoute> queryAllRoutes();
}

6、实现层

package com.example.springcloudgateway.service.impl;

import com.example.springcloudgateway.dto.GatewayRouteDto;
import com.example.springcloudgateway.entity.GatewayRoute;
import com.example.springcloudgateway.mapper.GatewayRouteMapper;
import com.example.springcloudgateway.service.GatewayRouteService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @author code
 * @Date 2021/11/11 10:59
 * Description 路由service
 * Version 1.0
 */
@Service
public class GatewayRouteServiceImpl implements GatewayRouteService {

    @Autowired
    private GatewayRouteMapper gatewayRouteMapper;

    @Override
    public Integer add(GatewayRouteDto gatewayRouteDto) {
        GatewayRoute gatewayRoute = new GatewayRoute();
        BeanUtils.copyProperties(gatewayRouteDto, gatewayRoute);
        gatewayRoute.setCreateDate(new Date());
        gatewayRoute.setCreatorId("");
        return gatewayRouteMapper.insertSelective(gatewayRoute);
    }

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

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

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

7、mapper

package com.example.springcloudgateway.mapper;

import com.example.springcloudgateway.entity.GatewayRoute;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * @author code
 * @Date 2021/11/11 11:08
 * Description
 * Version 1.0
 */
@Mapper
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();
}

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.example.springcloudgateway.mapper.GatewayRouteMapper" >
    <resultMap id="BaseResultMap" type="com.example.springcloudgateway.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="create_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, create_id, create_date, update_id,
    update_date, remarks, del_flag
    </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" >
        select *
        from gateway_route
        where id = #{id,jdbcType=BIGINT}
    </select>
    <select id="queryAllRoutes" resultMap="BaseResultMap">
        select *
        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.example.springcloudgateway.entity.GatewayRoute" >
        insert into gateway_route (id, service_id, uri,
                                   predicates, filters, order,
                                   create_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.example.springcloudgateway.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" >
                create_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.example.springcloudgateway.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" >
                create_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.example.springcloudgateway.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},
            create_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>

8、redis

package com.example.springcloudgateway.repository;

import com.alibaba.fastjson.JSON;
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.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author code
 * @Date 2021/11/11 11:04
 * Description
 * Version 1.0
 */

/**
 *将定义好的路由表信息通过此类读写到redis中
 */
@Component
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {

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

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

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

    //请注意,此方法很重要,从redis取路由信息的方法,官方核心包要用,核心路由功能都是从redis取的
    @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)));
        });
    }

}

9、初始化加载方法

package com.example.springcloudgateway.service.impl;

import com.example.springcloudgateway.entity.GatewayRoute;
import com.example.springcloudgateway.mapper.GatewayRouteMapper;
import com.example.springcloudgateway.repository.RedisRouteDefinitionRepository;
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.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;

import reactor.core.publisher.Mono;

import javax.annotation.Resource;
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 GatewayRouteMapper gatewayRouteMapper;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private RedisRouteDefinitionRepository routeDefinitionWriter;

    private ApplicationEventPublisher publisher;

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

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

    public String loadRouteConfig() {
        log.info("=======开始加载=====网关配置信息====");
        redisTemplate.delete(RedisRouteDefinitionRepository.GATEWAY_ROUTES);

        //从数据库拿到基本路由配置
        List<GatewayRoute> gatewayRouteList = gatewayRouteMapper.queryAllRoutes();
        gatewayRouteList.forEach(gatewayRoute -> {
            RouteDefinition definition=handleData(gatewayRoute);
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        });

        this.publisher.publishEvent(new RefreshRoutesEvent(this));

        log.info("=======网关配置信息===加载完成======");
        return "success";
    }

    public void saveRoute(GatewayRoute gatewayRoute){
        RouteDefinition definition=handleData(gatewayRoute);
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    public void update(GatewayRoute gatewayRoute) {
        RouteDefinition definition=handleData(gatewayRoute);
        try {
            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

    /**
     * 路由数据转换公共方法
     * @param gatewayRoute
     * @return
     */
    private RouteDefinition handleData(GatewayRoute gatewayRoute){
        RouteDefinition definition = new RouteDefinition();
        Map<String, String> predicateParams = new HashMap<>(8);
        PredicateDefinition predicate = new PredicateDefinition();
        FilterDefinition filterDefinition = new FilterDefinition();
        Map<String, String> filterParams = new HashMap<>(8);

        URI uri = null;
        if(gatewayRoute.getUri().startsWith("http")){
            //http地址
            uri = UriComponentsBuilder.fromHttpUrl(gatewayRoute.getUri()).build().toUri();
        }else{
            //注册中心
            uri = UriComponentsBuilder.fromUriString("lb://"+gatewayRoute.getUri()).build().toUri();
        }

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

        // 名称是固定的, 路径去前缀
        filterDefinition.setName("StripPrefix");
        filterParams.put("_genkey_0", gatewayRoute.getFilters().toString());
        filterDefinition.setArgs(filterParams);

        definition.setPredicates(Arrays.asList(predicate));
        definition.setFilters(Arrays.asList(filterDefinition));
        definition.setUri(uri);
        definition.setOrder(Integer.parseInt(gatewayRoute.getOrder()));

        return definition;
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值