gateway实现动态路由
需求说明:项目用gateway做路由,每次修改完规则,都需要重新启动,现在不想重启项目,每次更改完规则就能生效。
1.首先新创建一个dto
package com.cloudH.dto;
import lombok.Data;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import java.io.Serializable;
import java.util.List;
@Data
public class GatewayConfigDto implements Serializable {
/**
* Path 路由规则
*/
private List<PredicateDefinition> predicateList;
/**
* filter
*/
private List<FilterDefinition> filterList;
/**
* 注册中心路径
*/
String fromUriString;
}
2.主要更新 route 的类,实现 ApplicationEventPublisherAware 接口;loadRoute 是主要实现动态更新的接口;updRoute 是应该是查询数据库的接口,或者查询数据中心的接口,总之就是能拿到配置的路由规则就好,由于时间原因我就先写死了。
package com.cloudH.service;
import com.cloudH.dto.GatewayConfigDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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.cloud.gateway.route.RouteDefinitionWriter;
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
@Slf4j
public class GatewayService implements ApplicationEventPublisherAware {
@Autowired
ApplicationEventPublisher publisher;
@Autowired
RouteDefinitionWriter routeDefinitionWriter;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
/**
* 查询数据库更新route
* @return
*/
public void updRoute(){
List<PredicateDefinition> predicates = new ArrayList<PredicateDefinition>();
PredicateDefinition predicate = new PredicateDefinition();
Map<String,String> predicateParams = new HashMap<>();
predicate.setName("Path");
//路由转发地址
predicateParams.put("pattern","/client/**");
predicate.setArgs(predicateParams);
predicates.add(predicate);
//路由 url参数 规则
PredicateDefinition predicate1 = new PredicateDefinition();
Map<String,String> predicateParams1 = new HashMap<>();
predicate1.setName("Query");
predicateParams1.put("_genkey_0","version");
predicateParams1.put("_genkey_1","1");
predicate1.setArgs(predicateParams1);
predicates.add(predicate1);
List<FilterDefinition> filterDefinitions = new ArrayList<FilterDefinition>();
FilterDefinition filterDefinition = new FilterDefinition();
Map<String,String> filterParams = new HashMap<>();
//名称是固定的,路径去前缀
filterDefinition.setName("StripPrefix");
// filterParams.put("_genkey_0","1");
filterDefinition.setArgs(filterParams);
filterDefinitions.add(filterDefinition);
String isOpen = "0";
List<GatewayConfigDto> gatewayConfigDtos = new ArrayList<GatewayConfigDto>();
GatewayConfigDto gatewayConfigDto = new GatewayConfigDto();
gatewayConfigDto.setFilterList(filterDefinitions);
gatewayConfigDto.setPredicateList(predicates);
gatewayConfigDto.setIsOpen(isOpen);
gatewayConfigDto.setFromUriString("lb://client1/");
gatewayConfigDtos.add(gatewayConfigDto);
for(GatewayConfigDto gatewayConfigDto1 : gatewayConfigDtos){
loadRoute(gatewayConfigDto1);
}
}
/**
* 更新route
* @return
*/
public String loadRoute(GatewayConfigDto gatewayConfigDto){
RouteDefinition definition = new RouteDefinition();
URI uri = UriComponentsBuilder.fromUriString(gatewayConfigDto.getFromUriString()).build().toUri();
definition.setPredicates(gatewayConfigDto.getPredicateList());
definition.setFilters(gatewayConfigDto.getFilterList());
definition.setUri(uri);
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
}
}
3.新建controller,用于修改配置后进行触发
package com.cloudH.controller;
import com.cloudH.service.GatewayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("gatewayCon")
public class GatewayController {
@Autowired
GatewayService gatewayService;
@RequestMapping("add")
public String addRoute(){
return gatewayService.updRoute();
}
}
4.在项目启动时,先加载一遍规则配置
package com.cloudH.config;
import com.cloudH.service.GatewayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class InitRouteConfig {
@Autowired
GatewayService gatewayService;
@PostConstruct
public void init() {
gatewayService.updRoute();
}
}
说明:
- 由于gateway配置种类太多了,我只写了一个根据路径和路径后的参数的例子,如果想改成更多种例子参考 updRoute 方法;
- 配置大全:https://blog.csdn.net/z_z_k/article/details/111313391