说明
动态路由配置免去了每新增路由跳转都需要重启网关的工作,如下则是保存到MongoDB的步骤
相关pom.xml文件配置
<dependencies>
<!--GateWay ⽹关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--引⼊webflux-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
application.yml配置
spring:
application:
name: api-gateway
data:
mongodb:
uri: mongodb://username:password@192.168.8.11:27017/databaseName
mongo相关类
#定义路由实体
@Getter
@Setter
public class Router {
/** 路由ID */
@Id
private String id;
/** 路由谓词 */
private List<PredicateDefinition> predicates = new ArrayList<>();
/** 过滤器 */
private List<FilterDefinition> filters = new ArrayList<>();
/** 跳转地址uri */
private String uri;
/** 路由顺序 */
private int order;
}
#定义service
public interface RouterService {
List<Router> listAll();
void add(Router router);
void modifyById(Router router);
void removeById(String id);
}
@Service
public class RouterServiceImpl implements RouterService {
@Autowired
private MongoTemplate mongoTemplate;
@Override
public List<Router> listAll() {
return mongoTemplate.findAll(Router.class);
}
@Override
public void add(Router router) {
mongoTemplate.save(router);
}
@Override
public void modifyById(Router router) {
mongoTemplate.save(router);
}
@Override
public void removeById(String id) {
Query query = Query.query(Criteria.where("id").is(id));
mongoTemplate.remove(query,Router.class);
}
}
实现路由保存接口 RouteDefinitionRepository
@Service
public class MongoRouteDefinitionRepository implements RouteDefinitionRepository {
@Autowired
private RouterService routerService;
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
List<Router> routers = routerService.listAll();
List<RouteDefinition> routeDefinitions = new ArrayList<>();
for (Router router : routers) {
RouteDefinition routeDefinition = new RouteDefinition();
routeDefinition.setId(router.getId());
routeDefinition.setFilters(router.getFilters());
routeDefinition.setPredicates(router.getPredicates());
routeDefinition.setUri(URI.create(router.getUri()));
routeDefinition.setOrder(router.getOrder());
routeDefinitions.add(routeDefinition);
}
return Flux.fromIterable(routeDefinitions);
}
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap(routeDefinition -> {
Router router = new Router();
router.setId(routeDefinition.getId());
router.setFilters(routeDefinition.getFilters());
router.setPredicates(routeDefinition.getPredicates());
router.setUri(routeDefinition.getUri().toString());
router.setOrder(routeDefinition.getOrder());
routerService.add(router);
return Mono.empty();
});
}
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap(id -> {
routerService.removeById(id);
return Mono.empty();
});
}
}
实现网关路由接口 ApplicationEventPublisherAware
@Service
public class GatewayDynamicRouteService implements ApplicationEventPublisherAware {
@Autowired
private MongoRouteDefinitionRepository mongoRouteDefinitionRepository;
private ApplicationEventPublisher applicationEventPublisher;
private void notifyChanged() {
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
}
/**
* 增加路由
*
* @param routeDefinition
* @return
*/
public int add(RouteDefinition routeDefinition) {
mongoRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
notifyChanged();
return 1;
}
/**
* 更新
*
* @param routeDefinition
* @return
*/
public int update(RouteDefinition routeDefinition) {
mongoRouteDefinitionRepository.delete(Mono.just(routeDefinition.getId()));
mongoRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
notifyChanged();
return 1;
}
/**
* 删除路由
*/
public int delete(String id) {
mongoRouteDefinitionRepository.delete(Mono.just(id)).subscribe();
notifyChanged();
return 1;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
控制类编写
@RestController
@RequestMapping("/gateway/route")
public class GatewayDynamicRouteController {
@Resource
private GatewayDynamicRouteService gatewayDynamicRouteService;
@PostMapping("/add")
public ResponseMessage create(@RequestBody RouteDefinition entity) {
int result = gatewayDynamicRouteService.add(entity);
return ResponseMessage.success(new HashMap<String, Object>(){{
put("result", result);
}});
}
@PostMapping("/update")
public ResponseMessage update(@RequestBody RouteDefinition entity) {
int result = gatewayDynamicRouteService.update(entity);
return ResponseMessage.success(new HashMap<String, Object>(){{
put("result", result);
}});
}
@GetMapping("/delete/{id}")
public ResponseMessage delete(@PathVariable String id) {
int result = gatewayDynamicRouteService.delete(id);
return ResponseMessage.success(new HashMap<String, Object>(){{
put("result", result);
}});
}
}
- 注意需要把yml中定义的路由配置删除掉
测试接口 具体配置规则,需要看官方文档
#postman调用
{
"id":"blog",
"predicates":[
{
"name": "Path",
"args":{
"pattern" : "/user/**"
}
}
],
"filters" : [
{
"name" : "StripPrefix",
"args" : {
"_genkey_0" : "1"
}
}
],
"uri": "https://blog.csdn.net",
"order": 0
}