123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- package org.jeecg.loader;
- import cn.hutool.core.util.ObjectUtil;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.alibaba.nacos.api.NacosFactory;
- import com.alibaba.nacos.api.config.ConfigService;
- import com.alibaba.nacos.api.config.listener.Listener;
- import com.alibaba.nacos.api.exception.NacosException;
- import com.google.common.collect.Lists;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang.StringUtils;
- import org.jeecg.common.constant.CacheConstant;
- import org.jeecg.common.util.RedisUtil;
- import org.jeecg.config.GatewayRoutersConfiguration;
- import org.jeecg.config.RouterDataType;
- 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.InMemoryRouteDefinitionRepository;
- import org.springframework.cloud.gateway.route.RouteDefinition;
- import org.springframework.context.ApplicationEventPublisher;
- import org.springframework.context.ApplicationEventPublisherAware;
- import org.springframework.context.annotation.DependsOn;
- import org.springframework.stereotype.Component;
- import reactor.core.publisher.Mono;
- import javax.annotation.PostConstruct;
- import java.net.URI;
- import java.net.URISyntaxException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Properties;
- import java.util.concurrent.Executor;
- /**
- * 动态路由加载器
- *
- * @author : zyf
- * @date :2020-11-10
- */
- @Slf4j
- @Component
- @DependsOn({"gatewayRoutersConfiguration"})
- public class DynamicRouteLoader implements ApplicationEventPublisherAware {
- private ApplicationEventPublisher publisher;
- private InMemoryRouteDefinitionRepository repository;
- private DynamicRouteService dynamicRouteService;
- private ConfigService configService;
- private RedisUtil redisUtil;
- public DynamicRouteLoader(InMemoryRouteDefinitionRepository repository, DynamicRouteService dynamicRouteService, RedisUtil redisUtil) {
- this.repository = repository;
- this.dynamicRouteService = dynamicRouteService;
- this.redisUtil = redisUtil;
- }
- @PostConstruct
- public void init() {
- String dataType = GatewayRoutersConfiguration.DATA_TYPE;
- log.info("初始化路由,dataType:"+ dataType);
- if (RouterDataType.nacos.toString().endsWith(dataType)) {
- loadRoutesByNacos();
- }
- //从数据库加载路由
- if (RouterDataType.database.toString().endsWith(dataType)) {
- loadRoutesByRedis();
- }
- }
- /**
- * 刷新路由
- *
- * @return
- */
- public Mono<Void> refresh() {
- String dataType = GatewayRoutersConfiguration.DATA_TYPE;
- if (!RouterDataType.yml.toString().endsWith(dataType)) {
- this.init();
- }
- return Mono.empty();
- }
- /**
- * 从nacos中读取路由配置
- *
- * @return
- */
- private void loadRoutesByNacos() {
- List<RouteDefinition> routes = Lists.newArrayList();
- configService = createConfigService();
- if (configService == null) {
- log.warn("initConfigService fail");
- }
- try {
- String configInfo = configService.getConfig(GatewayRoutersConfiguration.DATA_ID, GatewayRoutersConfiguration.ROUTE_GROUP, GatewayRoutersConfiguration.DEFAULT_TIMEOUT);
- if (StringUtils.isNotBlank(configInfo)) {
- log.info("获取网关当前配置:\r\n{}", configInfo);
- routes = JSON.parseArray(configInfo, RouteDefinition.class);
- }
- } catch (NacosException e) {
- log.error("初始化网关路由时发生错误", e);
- e.printStackTrace();
- }
- for (RouteDefinition definition : routes) {
- log.info("update route : {}", definition.toString());
- dynamicRouteService.add(definition);
- }
- this.publisher.publishEvent(new RefreshRoutesEvent(this));
- dynamicRouteByNacosListener(GatewayRoutersConfiguration.DATA_ID, GatewayRoutersConfiguration.ROUTE_GROUP);
- }
- /**
- * 从redis中读取路由配置
- *
- * @return
- */
- private void loadRoutesByRedis() {
- List<MyRouteDefinition> routes = Lists.newArrayList();
- configService = createConfigService();
- if (configService == null) {
- log.warn("initConfigService fail");
- }
- Object configInfo = redisUtil.get(CacheConstant.GATEWAY_ROUTES);
- if (ObjectUtil.isNotEmpty(configInfo)) {
- log.info("获取网关当前配置:\r\n{}", configInfo);
- JSONArray array = JSON.parseArray(configInfo.toString());
- try {
- routes = getRoutesByJson(array);
- } catch (URISyntaxException e) {
- e.printStackTrace();
- }
- }
- for (MyRouteDefinition definition : routes) {
- log.info("update route : {}", definition.toString());
- Integer status=definition.getStatus();
- if(status.equals(0)){
- dynamicRouteService.delete(definition.getId());
- }else{
- dynamicRouteService.add(definition);
- }
- }
- this.publisher.publishEvent(new RefreshRoutesEvent(this));
- }
- /**
- * redis中的信息需要处理下 转成RouteDefinition对象
- * - id: login
- * uri: lb://cloud-jeecg-system
- * predicates:
- * - Path=/jeecg-boot/sys/**,
- *
- * @param array
- * @return
- */
- public static List<MyRouteDefinition> getRoutesByJson(JSONArray array) throws URISyntaxException {
- List<MyRouteDefinition> ls = new ArrayList<>();
- for (int i = 0; i < array.size(); i++) {
- JSONObject obj = array.getJSONObject(i);
- MyRouteDefinition route = new MyRouteDefinition();
- route.setId(obj.getString("routerId"));
- route.setStatus(obj.getInteger("status"));
- Object uri = obj.get("uri");
- if (uri == null) {
- route.setUri(new URI("lb://" + obj.getString("name")));
- } else {
- route.setUri(new URI(obj.getString("uri")));
- }
- Object predicates = obj.get("predicates");
- if (predicates != null) {
- JSONArray list = JSON.parseArray(predicates.toString());
- List<PredicateDefinition> predicateDefinitionList = new ArrayList<>();
- for (Object map : list) {
- JSONObject json = (JSONObject) map;
- PredicateDefinition predicateDefinition = new PredicateDefinition();
- predicateDefinition.setName(json.getString("name"));
- JSONArray jsonArray = json.getJSONArray("args");
- for (int j = 0; j < jsonArray.size(); j++) {
- predicateDefinition.addArg("_genkey" + j, jsonArray.get(j).toString());
- }
- predicateDefinitionList.add(predicateDefinition);
- }
- route.setPredicates(predicateDefinitionList);
- }
- Object filters = obj.get("filters");
- if (filters != null) {
- JSONArray list = JSON.parseArray(filters.toString());
- List<FilterDefinition> filterDefinitionList = new ArrayList<>();
- if (ObjectUtil.isNotEmpty(list)) {
- for (Object map : list) {
- JSONObject json = (JSONObject) map;
- JSONArray jsonArray = json.getJSONArray("args");
- String name = json.getString("name");
- FilterDefinition filterDefinition = new FilterDefinition();
- for (Object o : jsonArray) {
- JSONObject params = (JSONObject) o;
- filterDefinition.addArg(params.getString("key"), params.get("value").toString());
- }
- filterDefinition.setName(name);
- filterDefinitionList.add(filterDefinition);
- }
- route.setFilters(filterDefinitionList);
- }
- }
- ls.add(route);
- }
- return ls;
- }
- // private void loadRoutesByDataBase() {
- // List<GatewayRouteVo> routeList = jdbcTemplate.query(SELECT_ROUTES, new RowMapper<GatewayRouteVo>() {
- // @Override
- // public GatewayRouteVo mapRow(ResultSet rs, int i) throws SQLException {
- // GatewayRouteVo result = new GatewayRouteVo();
- // result.setId(rs.getString("id"));
- // result.setName(rs.getString("name"));
- // result.setUri(rs.getString("uri"));
- // result.setStatus(rs.getInt("status"));
- // result.setRetryable(rs.getInt("retryable"));
- // result.setPredicates(rs.getString("predicates"));
- // result.setStripPrefix(rs.getInt("strip_prefix"));
- // result.setPersist(rs.getInt("persist"));
- // return result;
- // }
- // });
- // if (ObjectUtil.isNotEmpty(routeList)) {
- // // 加载路由
- // routeList.forEach(route -> {
- // RouteDefinition definition = new RouteDefinition();
- // List<PredicateDefinition> predicatesList = Lists.newArrayList();
- // List<FilterDefinition> filtersList = Lists.newArrayList();
- // definition.setId(route.getId());
- // String predicates = route.getPredicates();
- // String filters = route.getFilters();
- // if (StringUtils.isNotEmpty(predicates)) {
- // predicatesList = JSON.parseArray(predicates, PredicateDefinition.class);
- // definition.setPredicates(predicatesList);
- // }
- // if (StringUtils.isNotEmpty(filters)) {
- // filtersList = JSON.parseArray(filters, FilterDefinition.class);
- // definition.setFilters(filtersList);
- // }
- // URI uri = UriComponentsBuilder.fromUriString(route.getUri()).build().toUri();
- // definition.setUri(uri);
- // this.repository.save(Mono.just(definition)).subscribe();
- // });
- // log.info("加载路由:{}==============", routeList.size());
- // Mono.empty();
- // }
- // }
- /**
- * 监听Nacos下发的动态路由配置
- *
- * @param dataId
- * @param group
- */
- public void dynamicRouteByNacosListener(String dataId, String group) {
- try {
- configService.addListener(dataId, group, new Listener() {
- @Override
- public void receiveConfigInfo(String configInfo) {
- log.info("进行网关更新:\n\r{}", configInfo);
- List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class);
- for (RouteDefinition definition : definitionList) {
- log.info("update route : {}", definition.toString());
- dynamicRouteService.update(definition);
- }
- }
- @Override
- public Executor getExecutor() {
- log.info("getExecutor\n\r");
- return null;
- }
- });
- } catch (Exception e) {
- log.error("从nacos接收动态路由配置出错!!!", e);
- }
- }
- /**
- * 创建ConfigService
- *
- * @return
- */
- private ConfigService createConfigService() {
- try {
- Properties properties = new Properties();
- properties.setProperty("serverAddr", GatewayRoutersConfiguration.SERVER_ADDR);
- properties.setProperty("namespace", GatewayRoutersConfiguration.NAMESPACE);
- properties.setProperty("username",GatewayRoutersConfiguration.USERNAME);
- properties.setProperty("password",GatewayRoutersConfiguration.PASSWORD);
- return configService = NacosFactory.createConfigService(properties);
- } catch (Exception e) {
- log.error("创建ConfigService异常", e);
- return null;
- }
- }
- @Override
- public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
- this.publisher = applicationEventPublisher;
- }
- }
|