Enrutamiento dinámico de Spring Cloud Gateway

1. Defina el modelo de enrutamiento

import lombok.Data;

import java.util.LinkedHashMap;
import java.util.List;

/**
 * 路由模型
 *
 * @author 向振华
 * @date 2021/02/04 10:26
 */
@Data
public class RouteDefinitionDTO {

    /**
     * 路由的Id
     */
    private String id;

    /**
     * 路由断言集合配置
     */
    private List<PredicateDefinitionDTO> predicates;

    /**
     * 路由过滤器集合配置
     */
    private List<FilterDefinitionDTO> filters;

    /**
     * 路由规则转发的目标uri
     */
    private String uri;

    /**
     * 路由执行的顺序
     */
    private Integer order;

    @Data
    public static class PredicateDefinitionDTO {

        /**
         * 断言名称
         */
        private String name;

        /**
         * 断言规则
         */
        private LinkedHashMap<String, String> args;
    }

    @Data
    public static class FilterDefinitionDTO {

        /**
         * 过滤器名称
         */
        private String name;

        /**
         * 路由规则
         */
        private LinkedHashMap<String, String> args;
    }
}

2. Definir el enrutamiento y modificar el controlador

import com.bzcst.bop.gateway.entity.RouteDefinitionDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.util.List;

/**
 * @author 向振华
 * @date 2021/02/04 10:26
 */
@RestController
@RequestMapping("/route")
public class DynamicRouteController {

    @Autowired
    private DynamicRouteService dynamicRouteService;

    /**
     * 获取路由
     */
    @GetMapping
    public Flux<RouteDefinition> get() {
        return dynamicRouteService.get();
    }

    /**
     * 更新路由
     */
    @PutMapping
    public void update(@RequestBody List<RouteDefinitionDTO> dto) {
        dynamicRouteService.updateRoutes(dto);
    }

    /**
     * 删除路由
     */
    @DeleteMapping("/{id}")
    public void delete(@PathVariable String id) {
        dynamicRouteService.delete(id);
    }
}

3. Defina el servicio para manejar el enrutamiento dinámico y guárdelo en la memoria local.

import com.bzcst.bop.gateway.entity.RouteDefinitionDTO;
import org.apache.commons.lang3.StringUtils;
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.RouteDefinitionLocator;
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.util.CollectionUtils;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

/**
 * 动态路由服务
 *
 * @author 向振华
 * @date 2021/02/04 10:26
 */
@Service
public class DynamicRouteService implements ApplicationEventPublisherAware {

    @Resource
    private RouteDefinitionLocator routeDefinitionLocator;

    @Resource
    private RouteDefinitionWriter routeDefinitionWriter;

    private ApplicationEventPublisher publisher;

    /**
     * 获取路由
     *
     * @return
     */
    public Flux<RouteDefinition> get() {
        return routeDefinitionLocator.getRouteDefinitions();
    }

    /**
     * 更新路由
     *
     * @param dtos
     */
    public void updateRoutes(List<RouteDefinitionDTO> dtos) {
        if (CollectionUtils.isEmpty(dtos)) {
            return;
        }
        for (RouteDefinitionDTO dto : dtos) {
            RouteDefinition routeDefinition = convertRouteDefinition(dto);
            update(routeDefinition);
        }
    }

    /**
     * 更新路由
     *
     * @param definition
     */
    public void update(RouteDefinition definition) {
        delete(definition.getId());
        save(definition);
    }

    /**
     * 删除路由
     *
     * @param id
     */
    public void delete(String id) {
        try {
            routeDefinitionWriter.delete(Mono.just(id)).subscribe();
        } catch (Exception ignored) {
        }
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    /**
     * 保存路由
     *
     * @param definition
     */
    public void save(RouteDefinition definition) {
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    /**
     * 参数转换成路由对象
     *
     * @param dto
     * @return
     */
    private RouteDefinition convertRouteDefinition(RouteDefinitionDTO dto) {
        RouteDefinition definition = new RouteDefinition();
        // 设置id
        definition.setId(dto.getId());
        // 设置order
        definition.setOrder(dto.getOrder());
        // 设置断言
        List<PredicateDefinition> pdList = new ArrayList<>();
        List<RouteDefinitionDTO.PredicateDefinitionDTO> predicateDefinitionDTOList = dto.getPredicates();
        for (RouteDefinitionDTO.PredicateDefinitionDTO gpDefinition : predicateDefinitionDTOList) {
            PredicateDefinition predicate = new PredicateDefinition();
            predicate.setArgs(gpDefinition.getArgs());
            predicate.setName(gpDefinition.getName());
            pdList.add(predicate);
        }
        definition.setPredicates(pdList);
        // 设置过滤器
        List<FilterDefinition> filters = new ArrayList<>();
        List<RouteDefinitionDTO.FilterDefinitionDTO> gatewayFilters = dto.getFilters();
        for (RouteDefinitionDTO.FilterDefinitionDTO filterDefinition : gatewayFilters) {
            FilterDefinition filter = new FilterDefinition();
            filter.setName(filterDefinition.getName());
            filter.setArgs(filterDefinition.getArgs());
            filters.add(filter);
        }
        definition.setFilters(filters);
        // 设置uri
        URI uri = null;
        String uriStr = dto.getUri();
        if (StringUtils.isNotBlank(uriStr)) {
            String http = "http";
            if (uriStr.startsWith(http)) {
                uri = UriComponentsBuilder.fromHttpUrl(dto.getUri()).build().toUri();
            } else {
                uri = URI.create(dto.getUri());
            }
        }
        definition.setUri(uri);
        return definition;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
}

4. Utilice

 

Habrá un problema aquí. Modificar una ruta existente en el archivo de configuración local agregará una nueva ruta. Mi solución es eliminar la configuración de enrutamiento local y usar la configuración de enrutamiento dinámico.

La interfaz de enrutamiento debe estar bien controlada por motivos de seguridad, puede estar cifrada y firmada, o modificada por otros servicios, y luego usar redis para actualizar regularmente, actualizar dinámicamente, etc.

 

Adjuntar parámetro json

[
 {
    "id":"xxx服务",
    "predicates":[
      {
        "name":"Path",
        "args":{
          "_genkey_0":"/xxx/**"
        }
      }
    ],
    "filters":[
      {
        "name":"Login",
        "args":{

        }
      },
      {
        "name":"FileSize",
        "args":{
          "_genkey_0":"10485760",
          "_genkey_1":"/*/x/z;/*/h/a"
        }
      }
    ],
    "uri":"lb://xxx",
    "order":0
  }
]

 

Supongo que te gusta

Origin blog.csdn.net/Anenan/article/details/113627950
Recomendado
Clasificación