zoukankan      html  css  js  c++  java
  • springboot gateway 动态路由-01

    SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

    SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 2.0之前的非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty

     项目结构:

    • pom.xml
    <?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.youxiu326</groupId>
        <artifactId>sb_gateway</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>sb_gateway</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
        </properties>
    
        <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>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</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>
    
                <plugin>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-maven-plugin</artifactId>
                    <version>1.3.2</version>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    • yml
    spring:
      datasource:
        password: zz123456.ZZ
        url: jdbc:mysql://youxiu326.xin:3306/super_man?useUnicode=true&characterEncoding=utf8
        username: youxiu326
      redis:
        host: youxiu326.xin
      freemarker:
        settings:
          classic_compatible: true
          datetime_format: yyyy-MM-dd HH:mm:ss
          number_format: '#.##'
          template_exception_handler: debug
        suffix: .html
    
    server:
      port: 8080
    
    mybatis:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      mapper-locations: classpath:/mapper/*.xml
    

      

      

    • 定义gateway实体类
    package com.youxiu326.gateway.model;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Gateway的路由定义模型
     *
     */
    public class GatewayRouteDefinition {
    
        /**
         * 路由的Id
         */
        private String id;
    
        /**
         * 路由断言集合配置
         */
        private List<GatewayPredicateDefinition> predicates = new ArrayList<>();
    
        /**
         * 路由过滤器集合配置
         */
        private List<GatewayFilterDefinition> filters = new ArrayList<>();
    
        /**
         * 路由规则转发的目标uri
         */
        private String uri;
    
        /**
         * 路由执行的顺序
         */
        private int order = 0;
    
        /**
         * 断言集合json字符串
         */
        private String predicatesJson;
    
        /**
         * 路由过滤器json字符串
         */
        private String filtersJson;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public List<GatewayPredicateDefinition> getPredicates() {
            return predicates;
        }
    
        public void setPredicates(List<GatewayPredicateDefinition> predicates) {
            this.predicates = predicates;
        }
    
        public List<GatewayFilterDefinition> getFilters() {
            return filters;
        }
    
        public void setFilters(List<GatewayFilterDefinition> filters) {
            this.filters = filters;
        }
    
        public String getUri() {
            return uri;
        }
    
        public void setUri(String uri) {
            this.uri = uri;
        }
    
        public int getOrder() {
            return order;
        }
    
        public void setOrder(int order) {
            this.order = order;
        }
    
        public String getPredicatesJson() {
            return predicatesJson;
        }
    
        public void setPredicatesJson(String predicatesJson) {
            this.predicatesJson = predicatesJson == null ? null : predicatesJson.trim();
        }
    
        public String getFiltersJson() {
            return filtersJson;
        }
    
        public void setFiltersJson(String filtersJson) {
            this.filtersJson = filtersJson == null ? null : filtersJson.trim();
        }
    }
    GatewayRouteDefinition.java
    package com.youxiu326.gateway.model;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * 路由断言定义模型
     */
    public class GatewayPredicateDefinition {
    
        /**
         * 断言对应的Name
         */
        private String name;
    
        /**
         * 配置的断言规则
         */
        private Map<String, String> args = new LinkedHashMap<>();
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Map<String, String> getArgs() {
            return args;
        }
    
        public void setArgs(Map<String, String> args) {
            this.args = args;
        }
    
    }
    GatewayPredicateDefinition.java
    package com.youxiu326.gateway.model;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * 过滤器定义模型
     */
    public class GatewayFilterDefinition {
    
        /**
         * Filter Name
         */
        private String name;
    
        /**
         * 对应的路由规则
         */
        private Map<String, String> args = new LinkedHashMap<>();
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Map<String, String> getArgs() {
            return args;
        }
    
        public void setArgs(Map<String, String> args) {
            this.args = args;
        }
    
    }
    GatewayFilterDefinition.java
    实体类设计,其实就是为了和原生路由对象对应

    public class RouteDefinition {
    @NotEmpty
    private String id = UUID.randomUUID().toString();
    @NotEmpty
    @Valid
    private List<PredicateDefinition> predicates = new ArrayList();
    @Valid
    private List<FilterDefinition> filters = new ArrayList();
    @NotNull
    private URI uri;
    private int order = 0;
    }
    • 实体类增删改查 dao service
    package com.youxiu326.gateway.dao;
    
    import com.youxiu326.gateway.model.GatewayRouteDefinition;
    
    import java.util.List;
    
    public interface GatewayRouteDefinitionMapper {
        int deleteByPrimaryKey(String id);
    
        int insert(GatewayRouteDefinition record);
    
        int insertSelective(GatewayRouteDefinition record);
    
        GatewayRouteDefinition selectByPrimaryKey(String id);
    
        int updateByPrimaryKeySelective(GatewayRouteDefinition record);
    
        int updateByPrimaryKey(GatewayRouteDefinition record);
    
        List<GatewayRouteDefinition> queryAllRoutes();
    }
    GatewayRouteDefinitionMapper.java
    <?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.gateway.dao.GatewayRouteDefinitionMapper" >
      <resultMap id="BaseResultMap" type="com.youxiu326.gateway.model.GatewayRouteDefinition" >
        <id column="id" property="id" jdbcType="VARCHAR" />
        <result column="uri" property="uri" jdbcType="VARCHAR" />
        <result column="order_" property="order" jdbcType="INTEGER" />
        <result column="predicates_json" property="predicatesJson" jdbcType="VARCHAR" />
        <result column="filters_json" property="filtersJson" jdbcType="VARCHAR" />
      </resultMap>
      <sql id="Base_Column_List" >
        id, uri, order_, predicates_json, filters_json
      </sql>
      <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" >
        select 
        <include refid="Base_Column_List" />
        from gateway_route_definition
        where id = #{id,jdbcType=VARCHAR}
      </select>
    
      <select id="queryAllRoutes" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from gateway_route_definition order by order_
      </select>
    
      <delete id="deleteByPrimaryKey" parameterType="java.lang.String" >
        delete from gateway_route_definition
        where id = #{id,jdbcType=VARCHAR}
      </delete>
      <insert id="insert" parameterType="com.youxiu326.gateway.model.GatewayRouteDefinition" >
        insert into gateway_route_definition (id, uri, order_,
          predicates_json, filters_json)
        values (#{id,jdbcType=VARCHAR}, #{uri,jdbcType=VARCHAR}, #{order,jdbcType=INTEGER}, 
          #{predicatesJson,jdbcType=VARCHAR}, #{filtersJson,jdbcType=VARCHAR})
      </insert>
      <insert id="insertSelective" parameterType="com.youxiu326.gateway.model.GatewayRouteDefinition" >
        insert into gateway_route_definition
        <trim prefix="(" suffix=")" suffixOverrides="," >
          <if test="id != null" >
            id,
          </if>
          <if test="uri != null" >
            uri,
          </if>
          <if test="order != null" >
            order_,
          </if>
          <if test="predicatesJson != null" >
            predicates_json,
          </if>
          <if test="filtersJson != null" >
            filters_json,
          </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
          <if test="id != null" >
            #{id,jdbcType=VARCHAR},
          </if>
          <if test="uri != null" >
            #{uri,jdbcType=VARCHAR},
          </if>
          <if test="order != null" >
            #{order,jdbcType=INTEGER},
          </if>
          <if test="predicatesJson != null" >
            #{predicatesJson,jdbcType=VARCHAR},
          </if>
          <if test="filtersJson != null" >
            #{filtersJson,jdbcType=VARCHAR},
          </if>
        </trim>
      </insert>
      <update id="updateByPrimaryKeySelective" parameterType="com.youxiu326.gateway.model.GatewayRouteDefinition" >
        update gateway_route_definition
        <set >
          <if test="uri != null" >
            uri = #{uri,jdbcType=VARCHAR},
          </if>
          <if test="order != null" >
            order_ = #{order,jdbcType=INTEGER},
          </if>
          <if test="predicatesJson != null" >
            predicates_json = #{predicatesJson,jdbcType=VARCHAR},
          </if>
          <if test="filtersJson != null" >
            filters_json = #{filtersJson,jdbcType=VARCHAR},
          </if>
        </set>
        where id = #{id,jdbcType=VARCHAR}
      </update>
      <update id="updateByPrimaryKey" parameterType="com.youxiu326.gateway.model.GatewayRouteDefinition" >
        update gateway_route_definition
        set uri = #{uri,jdbcType=VARCHAR},
          order_ = #{order,jdbcType=INTEGER},
          predicates_json = #{predicatesJson,jdbcType=VARCHAR},
          filters_json = #{filtersJson,jdbcType=VARCHAR}
        where id = #{id,jdbcType=VARCHAR}
      </update>
    </mapper>
    GatewayRouteDefinitionMapper.xml
    package com.youxiu326.gateway.service;
    
    import com.youxiu326.gateway.model.GatewayRouteDefinition;
    
    import java.util.List;
    
    public interface GatewayRouteService{
    
        public Integer add(GatewayRouteDefinition gatewayRouteDefinition);
    
        public Integer update(GatewayRouteDefinition gatewayRouteDefinition);
    
        public Integer delete(String id);
    
        public List<GatewayRouteDefinition> queryAllRoutes();
    
    }
    GatewayRouteService.java
    package com.youxiu326.gateway.service.impl;
    
    import com.youxiu326.gateway.dao.GatewayRouteDefinitionMapper;
    import com.youxiu326.gateway.model.GatewayRouteDefinition;
    import com.youxiu326.gateway.service.GatewayRouteService;
    import com.youxiu326.gateway.utils.JsonUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import java.util.List;
    
    /**
     *  自定义service层,增、删、改、查数据库路由配置信息
     */
    @Service
    public class GatewayRouteServiceImpl implements GatewayRouteService {
    
        @Autowired
        private GatewayRouteDefinitionMapper gatewayRouteMapper;
    
        public Integer add(GatewayRouteDefinition gatewayRouteDefinition) {
    
            if (!gatewayRouteDefinition.getPredicates().isEmpty())
                gatewayRouteDefinition.setPredicatesJson(
                        JsonUtils.parseString(gatewayRouteDefinition.getPredicates()));
    
            if (!gatewayRouteDefinition.getFilters().isEmpty())
                gatewayRouteDefinition.setFiltersJson(
                        JsonUtils.parseString(gatewayRouteDefinition.getFilters()));
    
    //        if (gatewayRouteDefinition.getId()!=null)
    //            return gatewayRouteMapper.updateByPrimaryKeySelective(gatewayRouteDefinition);
    
            return gatewayRouteMapper.insertSelective(gatewayRouteDefinition);
        }
    
        public Integer update(GatewayRouteDefinition gatewayRouteDefinition) {
    
            if (!gatewayRouteDefinition.getPredicates().isEmpty())
                gatewayRouteDefinition.setPredicatesJson(
                        JsonUtils.parseString(gatewayRouteDefinition.getPredicates()));
    
            if (!gatewayRouteDefinition.getFilters().isEmpty())
                gatewayRouteDefinition.setFiltersJson(
                        JsonUtils.parseString(gatewayRouteDefinition.getFilters()));
    
            return gatewayRouteMapper.updateByPrimaryKeySelective(gatewayRouteDefinition);
        }
    
        public Integer delete(String id) {
            return gatewayRouteMapper.deleteByPrimaryKey(id);
        }
    
        public List<GatewayRouteDefinition> queryAllRoutes(){
            return gatewayRouteMapper.queryAllRoutes();
        }
    
    }
    GatewayRouteServiceImpl.java
    • 一个配置类(解决redis乱码) , 一个工具类(json转对象)
    package com.youxiu326.gateway.utils;
    
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.fasterxml.jackson.core.JsonFactory;
    import com.fasterxml.jackson.core.JsonParseException;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.JsonMappingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.type.TypeFactory;
    
    public class JsonUtils {
        
        private static Logger log = LoggerFactory.getLogger(JsonUtils.class);
        private static JsonFactory jsonfactory = new JsonFactory(); 
        private static ObjectMapper mapper = new ObjectMapper(jsonfactory);
        
        public static <T> T parseObject(String json,Class<T> clzz) {
            //设置JSON时间格式    
            SimpleDateFormat myDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   
            mapper.setDateFormat(myDateFormat);
            try {
                return mapper.readValue(json, clzz);
            } catch (JsonParseException e) {
                e.printStackTrace();
            } catch (JsonMappingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } 
            return null;
        }
        
        /**
         * json转map
         * 
         * @param json
         * @return
         */
        public static Map<String,Object> parseMap(String json){
            TypeReference<HashMap<String,Object>> typeRef = new TypeReference<HashMap<String,Object>>() {}; 
            try {
                return mapper.readValue(json, typeRef);
            } catch (JsonParseException e) {
                log.error("字符串转json出错!"+json, e);
            } catch (JsonMappingException e) {
                log.error("json映射map出错!"+json, e);
            } catch (IOException e) {
                log.error("json转map流错误!"+json, e);
            }
            return null;
        }
        
        
        public static <T> List<T> parseList(String json,Class<?> clazz){
            TypeFactory t = TypeFactory.defaultInstance(); 
            try {
                List<T> list = mapper.readValue(json,t.constructCollectionType(ArrayList.class,clazz));
                return list;
            } catch (JsonParseException e) {
                e.printStackTrace();
            } catch (JsonMappingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        
        /**
         * 对像转json字符串
         * 
         * @param obj
         * @return
         */
        public static String parseString(Object obj){
            String result = null;
            try {
                SimpleDateFormat myDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   
                mapper.setDateFormat(myDateFormat);
                result = mapper.writeValueAsString(obj);
            } catch (JsonParseException e) {
                log.error("字符串转json出错!", e);
            } catch (JsonMappingException e) {
                log.error("json映射map出错!", e);
            } catch (IOException e) {
                log.error("json转map流错误!", e);
            }
            return result;
        }
    }
    JsonUtils.java
    package com.youxiu326.gateway.configuration;
    
    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());
        }
    
    }
    RedisConfig.java

    以下是核心代码,自定义路由关键代码:

    1.实现了RouteDefinitionRepository接口的RedisRouteDefinitionRepository扩展类,我们可以通过它来新增路由,删除路由。

    即调用它的save方法与delete方法

    2.实现了CommandLineRunner接口后可通过run方法在项目启动后调用loadRouteConfig()方法从而实现从数据库中加载路由

    3.实现了ApplicationEventPublisherAware接口获得了ApplicationEventPublisher对象,通过它可发送更新路由的事件,从而实现刷新路由

    // 发送更新路由事件
    this.publisher.publishEvent(new RefreshRoutesEvent(this));
    package com.youxiu326.gateway.configuration;
    
    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;
    
    /**
     *
     * Spring Cloud Gateway 扩展接口RouteDefinitionRepository,实现该接口实现自定义路由
     *
     *  重写以下三个方法
     *  Flux<RouteDefinition> getRouteDefinitions();
     *  Mono<Void> save(Mono<RouteDefinition> route);
     *  Mono<Void> delete(Mono<String> routeId);
     *
     *
     * 核心配置类,加载数据库的路由配置信息到redis,将定义好的路由表信息通过此类读写到redis中
     */
    @Component
    public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
    
        public static final String GATEWAY_ROUTES = "youxiu326:gateway";
    
        @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)));
            });
        }
    }
    

      

    package com.youxiu326.gateway.configuration;
    
    import com.alibaba.fastjson.JSON;
    import com.youxiu326.gateway.dao.GatewayRouteDefinitionMapper;
    import com.youxiu326.gateway.model.GatewayFilterDefinition;
    import com.youxiu326.gateway.model.GatewayPredicateDefinition;
    import com.youxiu326.gateway.model.GatewayRouteDefinition;
    import com.youxiu326.gateway.utils.JsonUtils;
    import org.apache.commons.lang3.StringUtils;
    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.*;
    
    
    /**
     *
     * 核心配置类,项目初始化加载数据库的路由配置
     *
     */
    @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 GatewayRouteDefinitionMapper gatewayRouteMapper;
    
        // springboot启动后执行
        @Override
        public void run(String... args){
            this.loadRouteConfig();
        }
    
        /**
         * 更新路由
         * @return
         */
        public String loadRouteConfig() {
    
            //从数据库拿到路由配置
            List<GatewayRouteDefinition> gatewayRouteList = gatewayRouteMapper.queryAllRoutes();
    
            log.info("网关配置信息:=====>"+ JSON.toJSONString(gatewayRouteList));
    
            gatewayRouteList.forEach(gatewayRoute -> {
    
                // 创建路由对象
                RouteDefinition definition = new RouteDefinition();
    
                definition.setId(gatewayRoute.getId());
    
                // 设置路由执行顺序
                definition.setOrder(gatewayRoute.getOrder());
    
                // 设置路由规则转发的目标uri
                URI uri = UriComponentsBuilder.fromHttpUrl(gatewayRoute.getUri()).build().toUri();
                definition.setUri(uri);
    
    
                // 设置路由断言
                String predicatesJson = gatewayRoute.getPredicatesJson();
                List<PredicateDefinition> predicates = new ArrayList<>();
                if (StringUtils.isNotBlank(predicatesJson)){
                    List<GatewayPredicateDefinition> predicateDefinitions = JsonUtils.parseList(predicatesJson, GatewayPredicateDefinition.class);
                    predicateDefinitions.stream().forEach(it->{
                        PredicateDefinition p = new PredicateDefinition();
                        p.setName(it.getName());
                        p.setArgs(it.getArgs());
                        predicates.add(p);
                    });
                }
                definition.setPredicates(predicates);
    
                // 设置过滤器
                String filtersJson = gatewayRoute.getFiltersJson();
                List<FilterDefinition> filters = new ArrayList<>();
                if (StringUtils.isNotBlank(filtersJson)){
                    List<GatewayFilterDefinition> filterDefinitions = JsonUtils.parseList(filtersJson, GatewayFilterDefinition.class);
                    filterDefinitions.stream().forEach(it->{
                        FilterDefinition f = new FilterDefinition();
                        f.setName(it.getName());
                        f.setArgs(it.getArgs());
                        filters.add(f);
                    });
                }
                definition.setFilters(filters);
    
                // 保存路由
                routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            });
    
            // 发送更新路由事件
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return "success";
        }
    
    
        /**
         * 删除路由
         * @param routeId
         */
        public void deleteRoute(String routeId){
            routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
    
            // 发送更新路由事件
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        }
    }
    

      

    • Controller
    package com.youxiu326.gateway.controller;
    
    import com.youxiu326.gateway.configuration.GatewayServiceHandler;
    import com.youxiu326.gateway.model.GatewayRouteDefinition;
    import com.youxiu326.gateway.service.GatewayRouteService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    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 GatewayRouteDefinition gatewayRouteDefinition) throws Exception {
            gatewayRouteService.add(gatewayRouteDefinition);
            // 刷新路由
            gatewayServiceHandler.loadRouteConfig();
            return "success";
        }
    
        @PostMapping("/update")
        public String update(@RequestBody GatewayRouteDefinition gatewayRouteDefinition) throws Exception {
            gatewayRouteService.update(gatewayRouteDefinition);
            // 刷新路由
            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<GatewayRouteDefinition> routes() throws Exception {
            return gatewayRouteService.queryAllRoutes();
        }
    
    }
    

      

    新增路由对象:

    访问 http://localhost:8080/pinduoduo 可以看见跳转到了官网

    代码地址:https://github.com/youxiu326/sb_gateway

  • 相关阅读:
    Internet Explorer 安全区域注册表项说明
    Android强制设置横屏或竖屏
    SQLite to Asp.net Entity Framework 部署问题
    获取地里位置信息
    通信API、使用Web Workers处理线程
    本地存储、离线应用程序
    多媒体播放
    绘制图形
    表单与文件
    HTML5的结构
  • 原文地址:https://www.cnblogs.com/youxiu326/p/cloud_gateway.html
Copyright © 2011-2022 走看看