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 动态路由协议能够自己主动的发现远程网络,仅仅要网络拓扑结构发生了变化,路由器就会相互交换路由信息,不仅能够自己主动获知新添加的网络,还能够在当前网络连接失 ...
随机推荐
- jar工具常用命令
参考链接:https://www.ibm.com/developerworks/cn/java/j-jar/index.html
- 【C#TAP 异步编程】异步接口 OOP
在我们深入研究"异步OOP"之前,让我们解决一个相当常见的问题:如何处理异步方法的继承?那么"异步接口"呢? 幸运的是,它确实可以很好地与继承(和接口)一起使用 ...
- Hive常用函数大全-数值计算
1 1.取整函数:round(X)(遵循四舍五入) 2 select round(3.1415926) from table --3 3 select round(3.5) from table -- ...
- MySQL:修改MySQL登录密码
在MySQL cmd中: 1.1:ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; #修改加密 ...
- webstorm安装vue插件及安装过程出现的问题
想要编辑器识别vue文件需要安装vue插件 1. 安装方法: File--> setting --> plugin ,点击plugin,在内容部分的左侧输入框输入vue,会出现1个关于 ...
- Spring框架第一天(搭建项目)
Spring框架 1.简介 1.1 Spring是什么 一个开源的框架,是JavaEE开源框架 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以IoC(Inve ...
- 分子动力学模拟之SETTLE约束算法
技术背景 在上一篇文章中,我们讨论了在分子动力学里面使用LINCS约束算法及其在具备自动微分能力的Jax框架下的代码实现.约束算法,在分子动力学模拟的过程中时常会使用到,用于固定一些既定的成键关系.例 ...
- JZ-037-数字在排序数组中出现的次数
数字在排序数组中出现的次数 题目描述 统计一个数字在升序数组中出现的次数. 题目链接: 数字在排序数组中出现的次数 代码 /** * 标题:数字在排序数组中出现的次数 * 题目描述 * 统计一个数字在 ...
- Comparator.comparing排序使用示例
Comparator.comparing排序使用示例 目录 Comparator.comparing排序使用示例 背景 实体类 示例一 示例二 背景 以前常用的排序方式是通过实现Comparator接 ...
- 二级py--day5 软件工程基础
二级py--day5软件工程基础 软件工程基础 1.软件工程三要素:方法.工具和过程 2.软件生命周期可以分为:项目可行性研究与规划.软件需求分析.软件设计.软件实现.软件测试.软件运行与维护等阶段 ...