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
springboot gateway 动态路由-01的更多相关文章
- spring cloud 2.x版本 Gateway动态路由教程
摘要 本文采用的Spring cloud为2.1.8RELEASE,version=Greenwich.SR3 本文基于前面的几篇Spring cloud Gateway文章的实现. 参考 Gatew ...
- springcloud3(五) spring cloud gateway动态路由的四类实现方式
写这篇博客主要是为了汇总下动态路由的多种实现方式,没有好坏之分,任何的方案都是依赖业务场景需求的,现在网上实现方式主要有: 基于Nacos, 基于数据库(PosgreSQL/Redis), 基于Mem ...
- springboot+zuul(一)------实现自定义过滤器、动态路由、动态负载。
参考:https://blog.csdn.net/u014091123/article/details/75433656 https://blog.csdn.net/u013815546/articl ...
- Spring Cloud Gateway实战之三:动态路由
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Spring Cloud Gateway的动态路由怎样做?集成Nacos实现很简单
一.说明 网关的核心概念就是路由配置和路由规则,而作为所有请求流量的入口,在实际生产环境中为了保证高可靠和高可用,是尽量要避免重启的,所以实现动态路由是非常有必要的:本文主要介绍 Spring Clo ...
- Spring Cloud gateway 网关四 动态路由
微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...
- 使用Gateway配置路由以及动态路由
1. 新建module cloud-gateway-gateway9527 2. pom.xml <!--注意不需要web模块依赖,否则报错--> <?xml version=&qu ...
- Spring Cloud Gateway之动态路由(数据库版)
1.实现动态路由的关键是RouteDefinitionRepository接口,该接口存在一个默认实现(InMemoryRouteDefinitionRepository) 通过名字我们应该也知道该实 ...
- CCNP路由实验之七 动态路由之BGP
CCNP路由实验之七 动态路由之BGP 动态路由协议能够自己主动的发现远程网络,仅仅要网络拓扑结构发生了变化,路由器就会相互交换路由信息,不仅能够自己主动获知新添加的网络,还能够在当前网络连接失 ...
随机推荐
- ASP.NET Core 6框架揭秘实例演示[13]:日志的基本编程模式[上篇]
<诊断跟踪的几种基本编程方式>介绍了四种常用的诊断日志框架.其实除了微软提供的这些日志框架,还有很多第三方日志框架可供我们选择,比如Log4Net.NLog和Serilog 等.虽然这些框 ...
- 案例六:shell脚本监控httpd服务80端口状态
这里是举例监控httpd服务端口状态,根据端口判断服务器是否启动,如果没有启动则脚本自动拉起服务,如果服务正在运行则退出脚本程序:如果换成别的服务端口也可以,但是脚本程序需要做调整. #!/bin/b ...
- Nullable<T> 结构 |T? 可为空的值类型
参考链接:https://www.cnblogs.com/tdfblog/p/Nullable-Types-in-Csharp-Net.html https://www.cnblogs.com/min ...
- C#帕斯卡命名法
帕斯卡命名法 命名规则. 单字之间不以空格断开或 连接号 (-).底线(_)连结,第一个单词首字母采用 大写字母 :后续单词的首字母亦用大写字母,例如:FirstName.LastName.. 每一个 ...
- kyverno VS gateKeeper
kyverno VS gateKeeper 概述 这两组开源工具都是是基于kubernetes 的webhook机制,支持validatingwebhook和mutatingwebhook.整体思路上 ...
- STL漫游之vector
std::vector 源码分析 从源码视角观察 STL 设计,代码实现为 libstdc++(GCC 4.8.5). 由于只关注 vector 的实现,并且 vector 实现几乎全部在头文件中,可 ...
- csrf跨站请求、相关装饰器、auth模块使用
昨日内容回顾 django操作cookie和session # 作用:就是保存用户信息,保存一系列数据,还可以做缓存 保留一段时间 # session是基于cookie工作的 1. 数据是保存在服务端 ...
- 超强视频超分AI算法,从此只看高清视频
最近发现一个特别强的视频超分算法----BasicVSR,在真实世界数据集中,实现了前所未有的视觉重建效果,最近它还拿下了超分比赛NTIRE 2021三冠一亚的优异成绩,登上了CVPR 2022. 视 ...
- 分享自研实现的多数据源(支持同DB不同表、跨DB表、内存数据、外部系统数据等)分页查询工具类实现原理及使用
思考: 提起分页查询,想必任何一个开发人员(不论是新手还是老手)都能快速编码实现,实现原理再简单不过,无非就是写一条SELECT查询的SQL语句,ORDER BY分页排序的字段, 再结合limit ( ...
- layui ajax删除
表单页面 //监听行工具事件 table.on('tool(test)', function(obj){ var data = obj.data; //console.log(obj) if(obj. ...