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
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.1.6.RELEASE</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.youxiu326</groupId>
  12. <artifactId>sb_gateway</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>sb_gateway</name>
  15. <description>Demo project for Spring Boot</description>
  16.  
  17. <properties>
  18. <java.version>1.8</java.version>
  19. <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
  20. </properties>
  21.  
  22. <dependencies>
  23. <dependency>
  24. <groupId>org.apache.commons</groupId>
  25. <artifactId>commons-lang3</artifactId>
  26. <version>3.7</version>
  27. </dependency>
  28.  
  29. <dependency>
  30. <groupId>com.alibaba</groupId>
  31. <artifactId>fastjson</artifactId>
  32. <version>1.2.53</version>
  33. </dependency>
  34.  
  35. <!-- springcloud gateway网关依赖 start-->
  36. <dependency>
  37. <groupId>org.springframework.cloud</groupId>
  38. <artifactId>spring-cloud-starter-gateway</artifactId>
  39. </dependency>
  40.  
  41. <dependency>
  42. <groupId>org.springframework.cloud</groupId>
  43. <artifactId>spring-cloud-gateway-webflux</artifactId>
  44. </dependency>
  45. <!-- springcloud gateway网关依赖 end-->
  46.  
  47. <dependency>
  48. <groupId>org.springframework.boot</groupId>
  49. <artifactId>spring-boot-starter-data-redis</artifactId>
  50. </dependency>
  51.  
  52. <dependency>
  53. <groupId>org.springframework.boot</groupId>
  54. <artifactId>spring-boot-starter-freemarker</artifactId>
  55. </dependency>
  56.  
  57. <dependency>
  58. <groupId>org.mybatis.spring.boot</groupId>
  59. <artifactId>mybatis-spring-boot-starter</artifactId>
  60. <version>1.3.3</version>
  61. </dependency>
  62.  
  63. <dependency>
  64. <groupId>mysql</groupId>
  65. <artifactId>mysql-connector-java</artifactId>
  66. <scope>runtime</scope>
  67. </dependency>
  68.  
  69. <dependency>
  70. <groupId>org.springframework.boot</groupId>
  71. <artifactId>spring-boot-starter-test</artifactId>
  72. <scope>test</scope>
  73. </dependency>
  74. </dependencies>
  75.  
  76. <dependencyManagement>
  77. <dependencies>
  78. <dependency>
  79. <groupId>org.springframework.cloud</groupId>
  80. <artifactId>spring-cloud-dependencies</artifactId>
  81. <version>${spring-cloud.version}</version>
  82. <type>pom</type>
  83. <scope>import</scope>
  84. </dependency>
  85. </dependencies>
  86. </dependencyManagement>
  87.  
  88. <build>
  89. <plugins>
  90. <plugin>
  91. <groupId>org.springframework.boot</groupId>
  92. <artifactId>spring-boot-maven-plugin</artifactId>
  93. </plugin>
  94.  
  95. <plugin>
  96. <groupId>org.mybatis.generator</groupId>
  97. <artifactId>mybatis-generator-maven-plugin</artifactId>
  98. <version>1.3.2</version>
  99. </plugin>
  100. </plugins>
  101. </build>
  102.  
  103. </project>
  • yml
  1. spring:
  2. datasource:
  3. password: zz123456.ZZ
  4. url: jdbc:mysql://youxiu326.xin:3306/super_man?useUnicode=true&characterEncoding=utf8
  5. username: youxiu326
  6. redis:
  7. host: youxiu326.xin
  8. freemarker:
  9. settings:
  10. classic_compatible: true
  11. datetime_format: yyyy-MM-dd HH:mm:ss
  12. number_format: '#.##'
  13. template_exception_handler: debug
  14. suffix: .html
  15.  
  16. server:
  17. port: 8080
  18.  
  19. mybatis:
  20. configuration:
  21. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  22. mapper-locations: classpath:/mapper/*.xml

  

  

  • 定义gateway实体类
  1. package com.youxiu326.gateway.model;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. /**
  7. * Gateway的路由定义模型
  8. *
  9. */
  10. public class GatewayRouteDefinition {
  11.  
  12. /**
  13. * 路由的Id
  14. */
  15. private String id;
  16.  
  17. /**
  18. * 路由断言集合配置
  19. */
  20. private List<GatewayPredicateDefinition> predicates = new ArrayList<>();
  21.  
  22. /**
  23. * 路由过滤器集合配置
  24. */
  25. private List<GatewayFilterDefinition> filters = new ArrayList<>();
  26.  
  27. /**
  28. * 路由规则转发的目标uri
  29. */
  30. private String uri;
  31.  
  32. /**
  33. * 路由执行的顺序
  34. */
  35. private int order = 0;
  36.  
  37. /**
  38. * 断言集合json字符串
  39. */
  40. private String predicatesJson;
  41.  
  42. /**
  43. * 路由过滤器json字符串
  44. */
  45. private String filtersJson;
  46.  
  47. public String getId() {
  48. return id;
  49. }
  50.  
  51. public void setId(String id) {
  52. this.id = id;
  53. }
  54.  
  55. public List<GatewayPredicateDefinition> getPredicates() {
  56. return predicates;
  57. }
  58.  
  59. public void setPredicates(List<GatewayPredicateDefinition> predicates) {
  60. this.predicates = predicates;
  61. }
  62.  
  63. public List<GatewayFilterDefinition> getFilters() {
  64. return filters;
  65. }
  66.  
  67. public void setFilters(List<GatewayFilterDefinition> filters) {
  68. this.filters = filters;
  69. }
  70.  
  71. public String getUri() {
  72. return uri;
  73. }
  74.  
  75. public void setUri(String uri) {
  76. this.uri = uri;
  77. }
  78.  
  79. public int getOrder() {
  80. return order;
  81. }
  82.  
  83. public void setOrder(int order) {
  84. this.order = order;
  85. }
  86.  
  87. public String getPredicatesJson() {
  88. return predicatesJson;
  89. }
  90.  
  91. public void setPredicatesJson(String predicatesJson) {
  92. this.predicatesJson = predicatesJson == null ? null : predicatesJson.trim();
  93. }
  94.  
  95. public String getFiltersJson() {
  96. return filtersJson;
  97. }
  98.  
  99. public void setFiltersJson(String filtersJson) {
  100. this.filtersJson = filtersJson == null ? null : filtersJson.trim();
  101. }
  102. }

GatewayRouteDefinition.java

  1. package com.youxiu326.gateway.model;
  2.  
  3. import java.util.LinkedHashMap;
  4. import java.util.Map;
  5.  
  6. /**
  7. * 路由断言定义模型
  8. */
  9. public class GatewayPredicateDefinition {
  10.  
  11. /**
  12. * 断言对应的Name
  13. */
  14. private String name;
  15.  
  16. /**
  17. * 配置的断言规则
  18. */
  19. private Map<String, String> args = new LinkedHashMap<>();
  20.  
  21. public String getName() {
  22. return name;
  23. }
  24.  
  25. public void setName(String name) {
  26. this.name = name;
  27. }
  28.  
  29. public Map<String, String> getArgs() {
  30. return args;
  31. }
  32.  
  33. public void setArgs(Map<String, String> args) {
  34. this.args = args;
  35. }
  36.  
  37. }

GatewayPredicateDefinition.java

  1. package com.youxiu326.gateway.model;
  2.  
  3. import java.util.LinkedHashMap;
  4. import java.util.Map;
  5.  
  6. /**
  7. * 过滤器定义模型
  8. */
  9. public class GatewayFilterDefinition {
  10.  
  11. /**
  12. * Filter Name
  13. */
  14. private String name;
  15.  
  16. /**
  17. * 对应的路由规则
  18. */
  19. private Map<String, String> args = new LinkedHashMap<>();
  20.  
  21. public String getName() {
  22. return name;
  23. }
  24.  
  25. public void setName(String name) {
  26. this.name = name;
  27. }
  28.  
  29. public Map<String, String> getArgs() {
  30. return args;
  31. }
  32.  
  33. public void setArgs(Map<String, String> args) {
  34. this.args = args;
  35. }
  36.  
  37. }

GatewayFilterDefinition.java

  1. 实体类设计,其实就是为了和原生路由对象对应

    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
  1. package com.youxiu326.gateway.dao;
  2.  
  3. import com.youxiu326.gateway.model.GatewayRouteDefinition;
  4.  
  5. import java.util.List;
  6.  
  7. public interface GatewayRouteDefinitionMapper {
  8. int deleteByPrimaryKey(String id);
  9.  
  10. int insert(GatewayRouteDefinition record);
  11.  
  12. int insertSelective(GatewayRouteDefinition record);
  13.  
  14. GatewayRouteDefinition selectByPrimaryKey(String id);
  15.  
  16. int updateByPrimaryKeySelective(GatewayRouteDefinition record);
  17.  
  18. int updateByPrimaryKey(GatewayRouteDefinition record);
  19.  
  20. List<GatewayRouteDefinition> queryAllRoutes();
  21. }

GatewayRouteDefinitionMapper.java

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="com.youxiu326.gateway.dao.GatewayRouteDefinitionMapper" >
  4. <resultMap id="BaseResultMap" type="com.youxiu326.gateway.model.GatewayRouteDefinition" >
  5. <id column="id" property="id" jdbcType="VARCHAR" />
  6. <result column="uri" property="uri" jdbcType="VARCHAR" />
  7. <result column="order_" property="order" jdbcType="INTEGER" />
  8. <result column="predicates_json" property="predicatesJson" jdbcType="VARCHAR" />
  9. <result column="filters_json" property="filtersJson" jdbcType="VARCHAR" />
  10. </resultMap>
  11. <sql id="Base_Column_List" >
  12. id, uri, order_, predicates_json, filters_json
  13. </sql>
  14. <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" >
  15. select
  16. <include refid="Base_Column_List" />
  17. from gateway_route_definition
  18. where id = #{id,jdbcType=VARCHAR}
  19. </select>
  20.  
  21. <select id="queryAllRoutes" resultMap="BaseResultMap">
  22. select
  23. <include refid="Base_Column_List" />
  24. from gateway_route_definition order by order_
  25. </select>
  26.  
  27. <delete id="deleteByPrimaryKey" parameterType="java.lang.String" >
  28. delete from gateway_route_definition
  29. where id = #{id,jdbcType=VARCHAR}
  30. </delete>
  31. <insert id="insert" parameterType="com.youxiu326.gateway.model.GatewayRouteDefinition" >
  32. insert into gateway_route_definition (id, uri, order_,
  33. predicates_json, filters_json)
  34. values (#{id,jdbcType=VARCHAR}, #{uri,jdbcType=VARCHAR}, #{order,jdbcType=INTEGER},
  35. #{predicatesJson,jdbcType=VARCHAR}, #{filtersJson,jdbcType=VARCHAR})
  36. </insert>
  37. <insert id="insertSelective" parameterType="com.youxiu326.gateway.model.GatewayRouteDefinition" >
  38. insert into gateway_route_definition
  39. <trim prefix="(" suffix=")" suffixOverrides="," >
  40. <if test="id != null" >
  41. id,
  42. </if>
  43. <if test="uri != null" >
  44. uri,
  45. </if>
  46. <if test="order != null" >
  47. order_,
  48. </if>
  49. <if test="predicatesJson != null" >
  50. predicates_json,
  51. </if>
  52. <if test="filtersJson != null" >
  53. filters_json,
  54. </if>
  55. </trim>
  56. <trim prefix="values (" suffix=")" suffixOverrides="," >
  57. <if test="id != null" >
  58. #{id,jdbcType=VARCHAR},
  59. </if>
  60. <if test="uri != null" >
  61. #{uri,jdbcType=VARCHAR},
  62. </if>
  63. <if test="order != null" >
  64. #{order,jdbcType=INTEGER},
  65. </if>
  66. <if test="predicatesJson != null" >
  67. #{predicatesJson,jdbcType=VARCHAR},
  68. </if>
  69. <if test="filtersJson != null" >
  70. #{filtersJson,jdbcType=VARCHAR},
  71. </if>
  72. </trim>
  73. </insert>
  74. <update id="updateByPrimaryKeySelective" parameterType="com.youxiu326.gateway.model.GatewayRouteDefinition" >
  75. update gateway_route_definition
  76. <set >
  77. <if test="uri != null" >
  78. uri = #{uri,jdbcType=VARCHAR},
  79. </if>
  80. <if test="order != null" >
  81. order_ = #{order,jdbcType=INTEGER},
  82. </if>
  83. <if test="predicatesJson != null" >
  84. predicates_json = #{predicatesJson,jdbcType=VARCHAR},
  85. </if>
  86. <if test="filtersJson != null" >
  87. filters_json = #{filtersJson,jdbcType=VARCHAR},
  88. </if>
  89. </set>
  90. where id = #{id,jdbcType=VARCHAR}
  91. </update>
  92. <update id="updateByPrimaryKey" parameterType="com.youxiu326.gateway.model.GatewayRouteDefinition" >
  93. update gateway_route_definition
  94. set uri = #{uri,jdbcType=VARCHAR},
  95. order_ = #{order,jdbcType=INTEGER},
  96. predicates_json = #{predicatesJson,jdbcType=VARCHAR},
  97. filters_json = #{filtersJson,jdbcType=VARCHAR}
  98. where id = #{id,jdbcType=VARCHAR}
  99. </update>
  100. </mapper>

GatewayRouteDefinitionMapper.xml

  1. package com.youxiu326.gateway.service;
  2.  
  3. import com.youxiu326.gateway.model.GatewayRouteDefinition;
  4.  
  5. import java.util.List;
  6.  
  7. public interface GatewayRouteService{
  8.  
  9. public Integer add(GatewayRouteDefinition gatewayRouteDefinition);
  10.  
  11. public Integer update(GatewayRouteDefinition gatewayRouteDefinition);
  12.  
  13. public Integer delete(String id);
  14.  
  15. public List<GatewayRouteDefinition> queryAllRoutes();
  16.  
  17. }

GatewayRouteService.java

  1. package com.youxiu326.gateway.service.impl;
  2.  
  3. import com.youxiu326.gateway.dao.GatewayRouteDefinitionMapper;
  4. import com.youxiu326.gateway.model.GatewayRouteDefinition;
  5. import com.youxiu326.gateway.service.GatewayRouteService;
  6. import com.youxiu326.gateway.utils.JsonUtils;
  7. import org.apache.commons.lang3.StringUtils;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.stereotype.Service;
  10. import java.util.List;
  11.  
  12. /**
  13. * 自定义service层,增、删、改、查数据库路由配置信息
  14. */
  15. @Service
  16. public class GatewayRouteServiceImpl implements GatewayRouteService {
  17.  
  18. @Autowired
  19. private GatewayRouteDefinitionMapper gatewayRouteMapper;
  20.  
  21. public Integer add(GatewayRouteDefinition gatewayRouteDefinition) {
  22.  
  23. if (!gatewayRouteDefinition.getPredicates().isEmpty())
  24. gatewayRouteDefinition.setPredicatesJson(
  25. JsonUtils.parseString(gatewayRouteDefinition.getPredicates()));
  26.  
  27. if (!gatewayRouteDefinition.getFilters().isEmpty())
  28. gatewayRouteDefinition.setFiltersJson(
  29. JsonUtils.parseString(gatewayRouteDefinition.getFilters()));
  30.  
  31. // if (gatewayRouteDefinition.getId()!=null)
  32. // return gatewayRouteMapper.updateByPrimaryKeySelective(gatewayRouteDefinition);
  33.  
  34. return gatewayRouteMapper.insertSelective(gatewayRouteDefinition);
  35. }
  36.  
  37. public Integer update(GatewayRouteDefinition gatewayRouteDefinition) {
  38.  
  39. if (!gatewayRouteDefinition.getPredicates().isEmpty())
  40. gatewayRouteDefinition.setPredicatesJson(
  41. JsonUtils.parseString(gatewayRouteDefinition.getPredicates()));
  42.  
  43. if (!gatewayRouteDefinition.getFilters().isEmpty())
  44. gatewayRouteDefinition.setFiltersJson(
  45. JsonUtils.parseString(gatewayRouteDefinition.getFilters()));
  46.  
  47. return gatewayRouteMapper.updateByPrimaryKeySelective(gatewayRouteDefinition);
  48. }
  49.  
  50. public Integer delete(String id) {
  51. return gatewayRouteMapper.deleteByPrimaryKey(id);
  52. }
  53.  
  54. public List<GatewayRouteDefinition> queryAllRoutes(){
  55. return gatewayRouteMapper.queryAllRoutes();
  56. }
  57.  
  58. }

GatewayRouteServiceImpl.java

  • 一个配置类(解决redis乱码) , 一个工具类(json转对象)
  1. package com.youxiu326.gateway.utils;
  2.  
  3. import java.io.IOException;
  4. import java.text.SimpleDateFormat;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;
  9.  
  10. import org.slf4j.Logger;
  11. import org.slf4j.LoggerFactory;
  12.  
  13. import com.fasterxml.jackson.core.JsonFactory;
  14. import com.fasterxml.jackson.core.JsonParseException;
  15. import com.fasterxml.jackson.core.type.TypeReference;
  16. import com.fasterxml.jackson.databind.JsonMappingException;
  17. import com.fasterxml.jackson.databind.ObjectMapper;
  18. import com.fasterxml.jackson.databind.type.TypeFactory;
  19.  
  20. public class JsonUtils {
  21.  
  22. private static Logger log = LoggerFactory.getLogger(JsonUtils.class);
  23. private static JsonFactory jsonfactory = new JsonFactory();
  24. private static ObjectMapper mapper = new ObjectMapper(jsonfactory);
  25.  
  26. public static <T> T parseObject(String json,Class<T> clzz) {
  27. //设置JSON时间格式
  28. SimpleDateFormat myDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  29. mapper.setDateFormat(myDateFormat);
  30. try {
  31. return mapper.readValue(json, clzz);
  32. } catch (JsonParseException e) {
  33. e.printStackTrace();
  34. } catch (JsonMappingException e) {
  35. e.printStackTrace();
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. return null;
  40. }
  41.  
  42. /**
  43. * json转map
  44. *
  45. * @param json
  46. * @return
  47. */
  48. public static Map<String,Object> parseMap(String json){
  49. TypeReference<HashMap<String,Object>> typeRef = new TypeReference<HashMap<String,Object>>() {};
  50. try {
  51. return mapper.readValue(json, typeRef);
  52. } catch (JsonParseException e) {
  53. log.error("字符串转json出错!"+json, e);
  54. } catch (JsonMappingException e) {
  55. log.error("json映射map出错!"+json, e);
  56. } catch (IOException e) {
  57. log.error("json转map流错误!"+json, e);
  58. }
  59. return null;
  60. }
  61.  
  62. public static <T> List<T> parseList(String json,Class<?> clazz){
  63. TypeFactory t = TypeFactory.defaultInstance();
  64. try {
  65. List<T> list = mapper.readValue(json,t.constructCollectionType(ArrayList.class,clazz));
  66. return list;
  67. } catch (JsonParseException e) {
  68. e.printStackTrace();
  69. } catch (JsonMappingException e) {
  70. e.printStackTrace();
  71. } catch (IOException e) {
  72. e.printStackTrace();
  73. }
  74. return null;
  75. }
  76.  
  77. /**
  78. * 对像转json字符串
  79. *
  80. * @param obj
  81. * @return
  82. */
  83. public static String parseString(Object obj){
  84. String result = null;
  85. try {
  86. SimpleDateFormat myDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  87. mapper.setDateFormat(myDateFormat);
  88. result = mapper.writeValueAsString(obj);
  89. } catch (JsonParseException e) {
  90. log.error("字符串转json出错!", e);
  91. } catch (JsonMappingException e) {
  92. log.error("json映射map出错!", e);
  93. } catch (IOException e) {
  94. log.error("json转map流错误!", e);
  95. }
  96. return result;
  97. }
  98. }

JsonUtils.java

  1. package com.youxiu326.gateway.configuration;
  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.data.redis.core.RedisTemplate;
  6. import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
  7. import org.springframework.data.redis.serializer.StringRedisSerializer;
  8.  
  9. import javax.annotation.PostConstruct;
  10.  
  11. /**
  12. * 防止redis 中文乱码
  13. */
  14. @Configuration
  15. public class RedisConfig {
  16.  
  17. @Autowired
  18. private RedisTemplate<Object, Object> redisTemplate;
  19.  
  20. @PostConstruct
  21. public void initRedisTemplate() {
  22. redisTemplate.setKeySerializer(new StringRedisSerializer());
  23. redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
  24. redisTemplate.setHashKeySerializer(new StringRedisSerializer());
  25. redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
  26. }
  27.  
  28. }

RedisConfig.java

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

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

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

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

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

  1. // 发送更新路由事件
    this.publisher.publishEvent(new RefreshRoutesEvent(this));
  1. package com.youxiu326.gateway.configuration;
  2.  
  3. import com.alibaba.fastjson.JSON;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.cloud.gateway.route.RouteDefinition;
  6. import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
  7. import org.springframework.cloud.gateway.support.NotFoundException;
  8. import org.springframework.data.redis.core.RedisTemplate;
  9. import org.springframework.stereotype.Component;
  10. import reactor.core.publisher.Flux;
  11. import reactor.core.publisher.Mono;
  12. import java.util.ArrayList;
  13. import java.util.List;
  14.  
  15. /**
  16. *
  17. * Spring Cloud Gateway 扩展接口RouteDefinitionRepository,实现该接口实现自定义路由
  18. *
  19. * 重写以下三个方法
  20. * Flux<RouteDefinition> getRouteDefinitions();
  21. * Mono<Void> save(Mono<RouteDefinition> route);
  22. * Mono<Void> delete(Mono<String> routeId);
  23. *
  24. *
  25. * 核心配置类,加载数据库的路由配置信息到redis,将定义好的路由表信息通过此类读写到redis中
  26. */
  27. @Component
  28. public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
  29.  
  30. public static final String GATEWAY_ROUTES = "youxiu326:gateway";
  31.  
  32. @Autowired
  33. private RedisTemplate redisTemplate;
  34.  
  35. @Override
  36. public Flux<RouteDefinition> getRouteDefinitions() {
  37. List<RouteDefinition> routeDefinitions = new ArrayList<>();
  38. redisTemplate.opsForHash().values(GATEWAY_ROUTES).stream().forEach(routeDefinition -> {
  39. routeDefinitions.add(JSON.parseObject(routeDefinition.toString(), RouteDefinition.class));
  40. });
  41. return Flux.fromIterable(routeDefinitions);
  42. }
  43.  
  44. @Override
  45. public Mono<Void> save(Mono<RouteDefinition> route) {
  46. return route
  47. .flatMap(routeDefinition -> {
  48. redisTemplate.opsForHash().put(GATEWAY_ROUTES, routeDefinition.getId(),
  49. JSON.toJSONString(routeDefinition));
  50. return Mono.empty();
  51. });
  52. }
  53.  
  54. @Override
  55. public Mono<Void> delete(Mono<String> routeId) {
  56. return routeId.flatMap(id -> {
  57. if (redisTemplate.opsForHash().hasKey(GATEWAY_ROUTES, id)) {
  58. redisTemplate.opsForHash().delete(GATEWAY_ROUTES, id);
  59. return Mono.empty();
  60. }
  61. return Mono.defer(() -> Mono.error(new NotFoundException("路由文件没有找到: " + routeId)));
  62. });
  63. }
  64. }

  

  1. package com.youxiu326.gateway.configuration;
  2.  
  3. import com.alibaba.fastjson.JSON;
  4. import com.youxiu326.gateway.dao.GatewayRouteDefinitionMapper;
  5. import com.youxiu326.gateway.model.GatewayFilterDefinition;
  6. import com.youxiu326.gateway.model.GatewayPredicateDefinition;
  7. import com.youxiu326.gateway.model.GatewayRouteDefinition;
  8. import com.youxiu326.gateway.utils.JsonUtils;
  9. import org.apache.commons.lang3.StringUtils;
  10. import org.slf4j.Logger;
  11. import org.slf4j.LoggerFactory;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.boot.CommandLineRunner;
  14. import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
  15. import org.springframework.cloud.gateway.filter.FilterDefinition;
  16. import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
  17. import org.springframework.cloud.gateway.route.RouteDefinition;
  18. import org.springframework.context.ApplicationEventPublisher;
  19. import org.springframework.context.ApplicationEventPublisherAware;
  20. import org.springframework.stereotype.Service;
  21. import org.springframework.web.util.UriComponentsBuilder;
  22. import reactor.core.publisher.Mono;
  23. import java.net.URI;
  24. import java.util.*;
  25.  
  26. /**
  27. *
  28. * 核心配置类,项目初始化加载数据库的路由配置
  29. *
  30. */
  31. @Service
  32. public class GatewayServiceHandler implements ApplicationEventPublisherAware, CommandLineRunner {
  33.  
  34. private final static Logger log = LoggerFactory.getLogger(GatewayServiceHandler.class);
  35.  
  36. @Autowired
  37. private RedisRouteDefinitionRepository routeDefinitionWriter;
  38.  
  39. private ApplicationEventPublisher publisher;
  40.  
  41. @Override
  42. public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
  43. this.publisher = applicationEventPublisher;
  44. }
  45.  
  46. // 获取数据dao
  47. @Autowired
  48. private GatewayRouteDefinitionMapper gatewayRouteMapper;
  49.  
  50. // springboot启动后执行
  51. @Override
  52. public void run(String... args){
  53. this.loadRouteConfig();
  54. }
  55.  
  56. /**
  57. * 更新路由
  58. * @return
  59. */
  60. public String loadRouteConfig() {
  61.  
  62. //从数据库拿到路由配置
  63. List<GatewayRouteDefinition> gatewayRouteList = gatewayRouteMapper.queryAllRoutes();
  64.  
  65. log.info("网关配置信息:=====>"+ JSON.toJSONString(gatewayRouteList));
  66.  
  67. gatewayRouteList.forEach(gatewayRoute -> {
  68.  
  69. // 创建路由对象
  70. RouteDefinition definition = new RouteDefinition();
  71.  
  72. definition.setId(gatewayRoute.getId());
  73.  
  74. // 设置路由执行顺序
  75. definition.setOrder(gatewayRoute.getOrder());
  76.  
  77. // 设置路由规则转发的目标uri
  78. URI uri = UriComponentsBuilder.fromHttpUrl(gatewayRoute.getUri()).build().toUri();
  79. definition.setUri(uri);
  80.  
  81. // 设置路由断言
  82. String predicatesJson = gatewayRoute.getPredicatesJson();
  83. List<PredicateDefinition> predicates = new ArrayList<>();
  84. if (StringUtils.isNotBlank(predicatesJson)){
  85. List<GatewayPredicateDefinition> predicateDefinitions = JsonUtils.parseList(predicatesJson, GatewayPredicateDefinition.class);
  86. predicateDefinitions.stream().forEach(it->{
  87. PredicateDefinition p = new PredicateDefinition();
  88. p.setName(it.getName());
  89. p.setArgs(it.getArgs());
  90. predicates.add(p);
  91. });
  92. }
  93. definition.setPredicates(predicates);
  94.  
  95. // 设置过滤器
  96. String filtersJson = gatewayRoute.getFiltersJson();
  97. List<FilterDefinition> filters = new ArrayList<>();
  98. if (StringUtils.isNotBlank(filtersJson)){
  99. List<GatewayFilterDefinition> filterDefinitions = JsonUtils.parseList(filtersJson, GatewayFilterDefinition.class);
  100. filterDefinitions.stream().forEach(it->{
  101. FilterDefinition f = new FilterDefinition();
  102. f.setName(it.getName());
  103. f.setArgs(it.getArgs());
  104. filters.add(f);
  105. });
  106. }
  107. definition.setFilters(filters);
  108.  
  109. // 保存路由
  110. routeDefinitionWriter.save(Mono.just(definition)).subscribe();
  111. });
  112.  
  113. // 发送更新路由事件
  114. this.publisher.publishEvent(new RefreshRoutesEvent(this));
  115. return "success";
  116. }
  117.  
  118. /**
  119. * 删除路由
  120. * @param routeId
  121. */
  122. public void deleteRoute(String routeId){
  123. routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
  124.  
  125. // 发送更新路由事件
  126. this.publisher.publishEvent(new RefreshRoutesEvent(this));
  127. }
  128. }

  

  • Controller
  1. package com.youxiu326.gateway.controller;
  2.  
  3. import com.youxiu326.gateway.configuration.GatewayServiceHandler;
  4. import com.youxiu326.gateway.model.GatewayRouteDefinition;
  5. import com.youxiu326.gateway.service.GatewayRouteService;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.web.bind.annotation.*;
  8. import java.util.List;
  9.  
  10. /**
  11. * 1.直接在数据库添加路由配置信息,手动刷新,使配置信息立即生效;
  12. *
  13. * 2.前端页面增、删、改路由配置信息,并使配置信息立即生效;
  14. *
  15. */
  16. @RestController
  17. @RequestMapping("/route")
  18. public class RouteController {
  19.  
  20. @Autowired
  21. private GatewayServiceHandler gatewayServiceHandler;
  22.  
  23. @Autowired
  24. private GatewayRouteService gatewayRouteService;
  25.  
  26. /**
  27. * 刷新路由配置
  28. * @return
  29. */
  30. @GetMapping("/refresh")
  31. public String refresh() throws Exception {
  32. return this.gatewayServiceHandler.loadRouteConfig();
  33. }
  34.  
  35. /**
  36. * 增加路由记录
  37. *
  38. * @return
  39. */
  40. @PostMapping("/add")
  41. public String add(@RequestBody GatewayRouteDefinition gatewayRouteDefinition) throws Exception {
  42. gatewayRouteService.add(gatewayRouteDefinition);
  43. // 刷新路由
  44. gatewayServiceHandler.loadRouteConfig();
  45. return "success";
  46. }
  47.  
  48. @PostMapping("/update")
  49. public String update(@RequestBody GatewayRouteDefinition gatewayRouteDefinition) throws Exception {
  50. gatewayRouteService.update(gatewayRouteDefinition);
  51. // 刷新路由
  52. gatewayServiceHandler.loadRouteConfig();
  53. return "success";
  54. }
  55.  
  56. @GetMapping("/delete/{id}")
  57. public String delete(@PathVariable String id) throws Exception {
  58. gatewayRouteService.delete(id);
  59. // 删除路由并刷新路由
  60. gatewayServiceHandler.deleteRoute(id);
  61. return "success";
  62. }
  63.  
  64. @GetMapping("/routes")
  65. public List<GatewayRouteDefinition> routes() throws Exception {
  66. return gatewayRouteService.queryAllRoutes();
  67. }
  68.  
  69. }

  

新增路由对象:

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

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

springboot gateway 动态路由-01的更多相关文章

  1. spring cloud 2.x版本 Gateway动态路由教程

    摘要 本文采用的Spring cloud为2.1.8RELEASE,version=Greenwich.SR3 本文基于前面的几篇Spring cloud Gateway文章的实现. 参考 Gatew ...

  2. springcloud3(五) spring cloud gateway动态路由的四类实现方式

    写这篇博客主要是为了汇总下动态路由的多种实现方式,没有好坏之分,任何的方案都是依赖业务场景需求的,现在网上实现方式主要有: 基于Nacos, 基于数据库(PosgreSQL/Redis), 基于Mem ...

  3. springboot+zuul(一)------实现自定义过滤器、动态路由、动态负载。

    参考:https://blog.csdn.net/u014091123/article/details/75433656 https://blog.csdn.net/u013815546/articl ...

  4. Spring Cloud Gateway实战之三:动态路由

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  5. Spring Cloud Gateway的动态路由怎样做?集成Nacos实现很简单

    一.说明 网关的核心概念就是路由配置和路由规则,而作为所有请求流量的入口,在实际生产环境中为了保证高可靠和高可用,是尽量要避免重启的,所以实现动态路由是非常有必要的:本文主要介绍 Spring Clo ...

  6. Spring Cloud gateway 网关四 动态路由

    微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...

  7. 使用Gateway配置路由以及动态路由

    1. 新建module cloud-gateway-gateway9527 2. pom.xml <!--注意不需要web模块依赖,否则报错--> <?xml version=&qu ...

  8. Spring Cloud Gateway之动态路由(数据库版)

    1.实现动态路由的关键是RouteDefinitionRepository接口,该接口存在一个默认实现(InMemoryRouteDefinitionRepository) 通过名字我们应该也知道该实 ...

  9. CCNP路由实验之七 动态路由之BGP

     CCNP路由实验之七 动态路由之BGP 动态路由协议能够自己主动的发现远程网络,仅仅要网络拓扑结构发生了变化,路由器就会相互交换路由信息,不仅能够自己主动获知新添加的网络,还能够在当前网络连接失 ...

随机推荐

  1. ASP.NET Core 6框架揭秘实例演示[13]:日志的基本编程模式[上篇]

    <诊断跟踪的几种基本编程方式>介绍了四种常用的诊断日志框架.其实除了微软提供的这些日志框架,还有很多第三方日志框架可供我们选择,比如Log4Net.NLog和Serilog 等.虽然这些框 ...

  2. 案例六:shell脚本监控httpd服务80端口状态

    这里是举例监控httpd服务端口状态,根据端口判断服务器是否启动,如果没有启动则脚本自动拉起服务,如果服务正在运行则退出脚本程序:如果换成别的服务端口也可以,但是脚本程序需要做调整. #!/bin/b ...

  3. Nullable<T> 结构 |T? 可为空的值类型

    参考链接:https://www.cnblogs.com/tdfblog/p/Nullable-Types-in-Csharp-Net.html https://www.cnblogs.com/min ...

  4. C#帕斯卡命名法

    帕斯卡命名法 命名规则. 单字之间不以空格断开或 连接号 (-).底线(_)连结,第一个单词首字母采用 大写字母 :后续单词的首字母亦用大写字母,例如:FirstName.LastName.. 每一个 ...

  5. kyverno VS gateKeeper

    kyverno VS gateKeeper 概述 这两组开源工具都是是基于kubernetes 的webhook机制,支持validatingwebhook和mutatingwebhook.整体思路上 ...

  6. STL漫游之vector

    std::vector 源码分析 从源码视角观察 STL 设计,代码实现为 libstdc++(GCC 4.8.5). 由于只关注 vector 的实现,并且 vector 实现几乎全部在头文件中,可 ...

  7. csrf跨站请求、相关装饰器、auth模块使用

    昨日内容回顾 django操作cookie和session # 作用:就是保存用户信息,保存一系列数据,还可以做缓存 保留一段时间 # session是基于cookie工作的 1. 数据是保存在服务端 ...

  8. 超强视频超分AI算法,从此只看高清视频

    最近发现一个特别强的视频超分算法----BasicVSR,在真实世界数据集中,实现了前所未有的视觉重建效果,最近它还拿下了超分比赛NTIRE 2021三冠一亚的优异成绩,登上了CVPR 2022. 视 ...

  9. 分享自研实现的多数据源(支持同DB不同表、跨DB表、内存数据、外部系统数据等)分页查询工具类实现原理及使用

    思考: 提起分页查询,想必任何一个开发人员(不论是新手还是老手)都能快速编码实现,实现原理再简单不过,无非就是写一条SELECT查询的SQL语句,ORDER BY分页排序的字段, 再结合limit ( ...

  10. layui ajax删除

    表单页面 //监听行工具事件 table.on('tool(test)', function(obj){ var data = obj.data; //console.log(obj) if(obj. ...