springcloud gateway动态路由,存储到mysql中。
springcloud gateway动态路由,存储到mysql中一、表结构二、导入依赖pom配置文件核心配置类请求示例参考连接一、表结构二、导入依赖pom我这里使用到了nacos,数据库操作使用的是jpa,如果不用的包请自行忽略或更改。<dependencies><dependency><groupId>org.springframework.cloud<
·
一、表结构
二、导入依赖pom
我这里使用到了nacos,数据库操作使用的是jpa,如果不用的包请自行忽略或更改。
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
配置文件
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.254.128:8848
application:
name: gateway
datasource:
url: jdbc:mysql://localhost:3306/gateway?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
jpa:
show-sql: true
hibernate:
ddl-auto: update
核心配置类
GatewayServiceHandler
package au.com.koalaclass.config;
import au.com.koalaclass.dao.GatewayRouteDao;
import au.com.koalaclass.entity.GatewayRouteEntity;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
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 javax.annotation.Resource;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* 核心配置类,项目初始化加载数据库的路由配置
*
*/
@Service
@Slf4j
public class GatewayServiceHandler implements ApplicationEventPublisherAware, CommandLineRunner {
@Resource
private RedisRouteDefinitionRepository routeDefinitionWriter;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
//自己的获取数据dao
@Resource
private GatewayRouteDao gatewayRouteDao;
// springboot启动后执行
@Override
public void run(String... args){
this.loadRouteConfig();
}
public String loadRouteConfig() {
//从数据库拿到路由配置
List<GatewayRouteEntity> gatewayRouteList = gatewayRouteDao.findAll();
log.info("网关配置信息:=====>"+ JSON.toJSONString(gatewayRouteList));
gatewayRouteList.forEach(gatewayRoute -> {
RouteDefinition definition = new RouteDefinition();
Map<String, String> predicateParams = new HashMap<>(8);
PredicateDefinition predicate = new PredicateDefinition();
FilterDefinition filter = new FilterDefinition();
Map<String, String> filterParams = new HashMap<>(8);
URI uri = UriComponentsBuilder.fromHttpUrl(gatewayRoute.getUri()).build().toUri();
definition.setId(gatewayRoute.getId().toString());
// 名称是固定的,spring gateway会根据名称找对应的PredicateFactory
predicate.setName("Path");
predicateParams.put("pattern",gatewayRoute.getPredicates());
predicate.setArgs(predicateParams);
// 名称是固定的, 路径去前缀(从前面截取一个,实际上就是截取url,后面的部分才是转发的url)
filter.setName("StripPrefix");
filterParams.put("_genkey_0", gatewayRoute.getFilters().toString());
filter.setArgs(filterParams);
definition.setPredicates(Arrays.asList(predicate));
definition.setFilters(Arrays.asList(filter));
definition.setUri(uri);
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
});
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
}
public void deleteRoute(String routeId){
routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
}
RedisRouteDefinitionRepository
package au.com.koalaclass.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 核心配置类,加载数据库的路由配置信息到redis
* 将定义好的路由表信息通过此类读写到redis中
*/
@Component
@Slf4j
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
private Map<Object,RouteDefinition> routeDefinitionMap=new HashMap<>();
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
List<RouteDefinition> routeDefinitions = new ArrayList<>();
routeDefinitionMap.forEach((k,v) ->{
routeDefinitions.add(v);
});
return Flux.fromIterable(routeDefinitions);
}
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route
.flatMap(routeDefinition -> {
log.info("routeDefinition:"+routeDefinition);
routeDefinitionMap.put(routeDefinition.getId(),routeDefinition);
return Mono.empty();
});
}
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap(id -> {
if (routeDefinitionMap.containsKey(id)) {
routeDefinitionMap.remove(id);
return Mono.empty();
}
return Mono.defer(() -> Mono.error(new NotFoundException("路由文件没有找到: " + routeId)));
});
}
}
实体类GatewayRouteEntity
package au.com.koalaclass.entity;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import javax.persistence.*;
import java.util.Date;
/**
* 实体
*/
@Table(name = "gateway_route")
@Entity
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class GatewayRouteEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", columnDefinition = "int(11)")
private Long id;
@Column(name = "service_id")
private String serviceId;
@Column(name = "uri")
private String uri;
@Column(name = "predicates")
private String predicates;
@Column(name = "filters")
private String filters;
@Column(name = "order_")
private String order;
@Column(name = "creator_id")
private String creatorId;
@Column(name = "create_date")
private Date createDate;
@Column(name = "update_Id")
private String updateId;
@Column(name = "update_date")
private Date updateDate;
@Column(name = "remarks")
private String remarks;
@Column(name = "del_flag")
private String delFlag;
}
Dao层
package au.com.koalaclass.dao;
import au.com.koalaclass.entity.GatewayRouteEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface GatewayRouteDao extends JpaRepository<GatewayRouteEntity, Long> {
}
controller层
package au.com.koalaclass.controller;
import au.com.koalaclass.config.GatewayServiceHandler;
import au.com.koalaclass.dao.GatewayRouteDao;
import au.com.koalaclass.entity.GatewayRouteEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* @author Superlu
* @version 1.0.0
* @ClassName RouteController
* @Description TODO
* @createTime 2021/11/15 11:18
*/
@RestController
@RequestMapping("/router")
public class RouteController {
@Resource
private GatewayServiceHandler gatewayServiceHandler;
@Resource
private GatewayRouteDao gatewayDao;
@GetMapping("/refresh")
public String refresh(){
return gatewayServiceHandler.loadRouteConfig();
}
@GetMapping("/findAll")
public List<GatewayRouteEntity> findAll(){
return gatewayDao.findAll();
}
@PostMapping("/add")
public GatewayRouteEntity add(@RequestBody GatewayRouteEntity gateway){
GatewayRouteEntity save = gatewayDao.save(gateway);
gatewayServiceHandler.loadRouteConfig();
return save;
}
}
请求示例
访问localhost/api-taobao
参考连接
动态路由实现参考代码
https://gitee.com/evoup/sb_cloud_gateway
这里没有使用redis。若要使用redis请参考以上内容
本文代码示例:https://gitee.com/luzhiyong_erfou/gateway-dynamic-routing
仓库代码根据业务略有修改。如有出入请自行根据自己业务修改。
更多推荐
所有评论(0)