gateway实现动态路由

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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值