Bootstrap

springCloud 整合gateway 网关配置信息存mysql

背景

最近在个人在学习整合SpringCloud,以往都是在公司框架中使用,或者零碎的学习部分。于是想系统的从零开始整合SC。昨天已经把sc框架搭建就绪。本篇博客是基于上一篇而来。如果未搭建好的请移步:https://blog.csdn.net/fly_west/article/details/122203075
本篇博客主要讲述整合gateway。用过网关的人都知道,网关路由转发学习阶段一般都是配置在配置文件里面在,不管是用yml还是Apollo等,都会面临一个问题那就是网关启动后,再新增微服务,修改配置文件后,需要重启服务。这个是一大弊端,因此本篇博客主要讲述mysql数据库维护网关配置。当然也可以再维护一份到redis中,我在这暂时没有这样做。只抛砖引玉实现了存储到mysql中。

网关实现

库表结构

CREATE TABLE `basic_gateway`  (
  `id` int(11) NOT NULL,
  `system_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '系统编号',
  `service_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '服务名称',
  `uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '转发地址',
  `predicates` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '访问前缀',
  `filters` int(1) NULL DEFAULT NULL COMMENT '是否过滤',
  `remarks` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`) USING BTREE
) 

yml配置文件

server:
  port: 8082
spring:
  application:
    name: demo-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        register-enabled: true
    gateway:
      discovery:
        locator:
          #让gateway通过服务发现组件找到其他的微服务
          enabled: true

entity

@Data
@TableName("basic_gateway")
public class BasicGateway {

    @TableId("id")
    private long id;

    @TableField("system_id")
    private String systemId;

    @TableField("service_name")
    private String serviceName;

    @TableField("uri")
    private String uri;

    @TableField("predicates")
    private String predicates;

    @TableField("filters")
    private Integer filters;

    @TableField("remarks")
    private String remarks;


}

网关router实现类

@Component
@Slf4j
public class GateWayService implements ApplicationEventPublisherAware, CommandLineRunner {

    private ApplicationEventPublisher publisher;
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    @Autowired
    private GatewayMapper gatewayMapper;

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

    public void refresh() {
        loadRouteConfig();
    }

    @Override
    public void run(String... args) throws Exception {
        //CommandLineRunner 项目启动时加载,且只加载一次
        log.info("网关路由开始加载------------------------");
        loadRouteConfig();
        log.info("网关路由加载结束--------------------------");
    }

    private void loadRouteConfig() {
        List<BasicGateway> gatewayList = gatewayMapper.selectList(null);
        if (!CollectionUtils.isEmpty(gatewayList)) {
            for (BasicGateway gateway : gatewayList) {
                RouteDefinition definition = handleData(gateway);
                routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            }
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        }
    }

    /**
     * 数据库路由数据转换
     *
     * @return org.springframework.cloud.gateway.route.RouteDefinition
     * @Author zhuiri
     * @Date 2021/12/29 14:03
     **/
    private RouteDefinition handleData(BasicGateway gateway) {
        RouteDefinition definition = new RouteDefinition();
        Map<String, String> predicateParams = new HashMap<>(8);
        PredicateDefinition predicate = new PredicateDefinition();
        FilterDefinition filterDefinition = new FilterDefinition();
        Map<String, String> filterParams = new HashMap<>(8);
        URI url = null;
        if (gateway.getUri().startsWith("http") || gateway.getUri().startsWith("https")) {
            //http地址
            url = UriComponentsBuilder.fromHttpUrl(gateway.getUri()).build().toUri();
        } else {
            //注册中心
            url = UriComponentsBuilder.fromUriString("lb://" + gateway.getUri()).build().toUri();
        }
        definition.setId(String.valueOf(gateway.getId()));
        predicate.setName("Path");
        predicateParams.put("pattern", gateway.getPredicates() + "/**");
        predicate.setArgs(predicateParams);
        // 名称是固定的, 路径去前缀
        filterDefinition.setName("StripPrefix");
        filterParams.put("_genkey_0", gateway.getFilters().toString());
        filterDefinition.setArgs(filterParams);

        definition.setPredicates(Arrays.asList(predicate));
        definition.setFilters(Arrays.asList(filterDefinition));
        definition.setUri(url);
        definition.setOrder(Integer.parseInt("0"));

        return definition;
    }

    public void saveRoute(BasicGateway gateway) {
        RouteDefinition definition = handleData(gateway);
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    public void update(BasicGateway gateway) {
        RouteDefinition definition = handleData(gateway);
        try {
            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
            routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void deleteRoute(String routeId) {
        routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }


}

此处扩充说了一下增删改查还有刷新功能

mapper文件

public interface GatewayMapper extends BaseMapper<BasicGateway> {
}

服务端

yml配置文件

server:
  port: 8081
swagger:
  title: demo_project
  description: project description
  version: 1.0
  contactEmail: 123456@qq.com
spring:
  application:
    name: cloud-business
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        register-enabled: true

**注意:**此处一定要加register-enabled:true,否则网关就会报错Caused by: java.net.ConnectException: Connection timed out: no further information

如有问题,希望大家评论区留言多多指教!如觉得写得还可以,就给一个赞吧!

;