• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

从0到1学SpringCloud——12 gateway 动态配置网关路由规则

武飞扬头像
月夜烛峰
帮助1

目录

一、前言

二、动态路由

1、数据库设计

2、路由代码

3、效果演示

三、自定义路由

1、代码实现

2、新增路由规则

3、效果演示


一、前言

二、动态路由

1、数据库设计

  1.  
    CREATE TABLE `zf_gateway_route` (
  2.  
    `route_id` varchar(16) NOT NULL DEFAULT '' COMMENT '路由id',
  3.  
    `uri` varchar(64) DEFAULT NULL COMMENT '路由地址',
  4.  
    `path_name` varchar(8) DEFAULT '' COMMENT 'path断言名称',
  5.  
    `path_pattern` varchar(32) DEFAULT NULL COMMENT 'path断言匹配路径',
  6.  
    `method_name` varchar(8) DEFAULT NULL COMMENT 'method断言名称',
  7.  
    `method_pattern` varchar(8) DEFAULT NULL COMMENT 'method匹配方法',
  8.  
    `msg_name` varchar(32) DEFAULT NULL COMMENT 'header断言名称',
  9.  
    `msg_type` varchar(64) DEFAULT NULL COMMENT '消息类型,多个值之间用,分割',
  10.  
    `filter_name` varchar(16) DEFAULT NULL COMMENT '过滤器名称',
  11.  
    `new_path` varchar(64) DEFAULT NULL COMMENT '转发地址',
  12.  
    `remark` varchar(32) DEFAULT NULL COMMENT '备注',
  13.  
    `status` int(2) DEFAULT NULL COMMENT '状态:0、停用;1、启用',
  14.  
    `index` int(2) DEFAULT NULL COMMENT '排序',
  15.  
    PRIMARY KEY (`route_id`)
  16.  
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='网关路由信息表';

首先设计一张路由表,用来存储路由信息。

添加两条测试数据:

  1.  
    INSERT INTO `zf_gateway_route` (`route_id`, `uri`, `path_name`, `path_pattern`, `method_name`, `method_pattern`, `msg_name`, `msg_type`, `filter_name`, `new_path`, `remark`, `status`, `index`) VALUES ('zhufeng-route-csdn', 'https://blog.csdn.net/', 'Path', '/csdn/**', 'Method', 'Get', NULL, NULL, 'MsgPath', '/nav/java', '第三方测试', 0, 1);
  2.  
    INSERT INTO `zf_gateway_route` (`route_id`, `uri`, `path_name`, `path_pattern`, `method_name`, `method_pattern`, `msg_name`, `msg_type`, `filter_name`, `new_path`, `remark`, `status`, `index`) VALUES ('zhufeng-web-msg', 'lb://zhufeng-web-msg', 'Path', '/msg/info', 'Method', 'Get', NULL, NULL, NULL, NULL, '路由测试', 0, 2);

数据说明:

1、uri:路由地址,也就是通过配置的微服务或者http地址发送请求

2、path_name:断言规则,命名规则为: Name  RoutePredicateFactory,

比如:数据库配置为 Path ,gateway会自动找到 PathRoutePredicateFactory

3、path_pattern:请求的路径规则进行适配

4、method_name:断言规则 ,为方便演示,把method单独列了一项,

调用 MethodRoutePredicateFactory 来校验是否为Get或Post请求。

2、路由代码

  1.  
    package com.zhufeng.gateway.db.route;
  2.  
     
  3.  
    import com.alibaba.fastjson.JSONObject;
  4.  
    import com.zhufeng.gateway.db.service.GatewayService;
  5.  
    import org.springframework.cloud.gateway.filter.FilterDefinition;
  6.  
    import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
  7.  
    import org.springframework.cloud.gateway.route.RouteDefinition;
  8.  
    import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
  9.  
    import org.springframework.stereotype.Component;
  10.  
    import reactor.core.publisher.Flux;
  11.  
    import reactor.core.publisher.Mono;
  12.  
     
  13.  
    import javax.annotation.PostConstruct;
  14.  
    import javax.annotation.Resource;
  15.  
    import java.net.URI;
  16.  
    import java.util.ArrayList;
  17.  
    import java.util.List;
  18.  
     
  19.  
    /**
  20.  
    * @ClassName: ZhufengRouteDefinitionRepository
  21.  
    * @Description 动态配置路由规则
  22.  
    * @author 月夜烛峰
  23.  
    * @date 2022/9/15 19:38
  24.  
    */
  25.  
    @Component
  26.  
    public class ZhufengRouteDefinitionRepository implements RouteDefinitionRepository {
  27.  
     
  28.  
    private List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>();
  29.  
     
  30.  
    @Resource
  31.  
    private GatewayService gatewayService;
  32.  
     
  33.  
    /**
  34.  
    * 初始化参数
  35.  
    */
  36.  
    @PostConstruct
  37.  
    public void init() {
  38.  
    load();
  39.  
    }
  40.  
     
  41.  
    /**
  42.  
    * 通过数据库配置路由规则
  43.  
    */
  44.  
    private void load() {
  45.  
    List<JSONObject> routeList = gatewayService.findRouteList();
  46.  
    for(JSONObject routeJson:routeList) {
  47.  
    //配置路由规则
  48.  
    RouteDefinition route= new RouteDefinition();
  49.  
    route.setId(routeJson.getString("routeId"));
  50.  
    URI uri = URI.create(routeJson.getString("uri"));
  51.  
    route.setUri(uri);
  52.  
    //配置请求路径规则
  53.  
    PredicateDefinition path = new PredicateDefinition();
  54.  
    path.setName(routeJson.getString("pathName"));
  55.  
    path.addArg("pattern", routeJson.getString("pathPattern"));
  56.  
    route.getPredicates().add(path);
  57.  
     
  58.  
    //配置方法规则:Get、Post等
  59.  
    PredicateDefinition method = new PredicateDefinition();
  60.  
    method.setName(routeJson.getString("methodName"));
  61.  
    String methodPattern = routeJson.getString("methodPattern");
  62.  
    String[] methodArr = methodPattern.split(",");
  63.  
    for(int i=0;i<methodArr.length;i ) {
  64.  
    method.addArg("pattern" 0, methodArr[i]);
  65.  
    }
  66.  
    route.getPredicates().add(method);
  67.  
     
  68.  
     
  69.  
    routeDefinitions.add(route);
  70.  
     
  71.  
    }
  72.  
     
  73.  
    }
  74.  
     
  75.  
    @Override
  76.  
    public Flux<RouteDefinition> getRouteDefinitions() {
  77.  
    return Flux.fromIterable(routeDefinitions);
  78.  
    }
  79.  
     
  80.  
    @Override
  81.  
    public Mono<Void> save(Mono<RouteDefinition> route) {
  82.  
    // TODO Auto-generated method stub
  83.  
    return null;
  84.  
    }
  85.  
     
  86.  
    @Override
  87.  
    public Mono<Void> delete(Mono<String> routeId) {
  88.  
    // TODO Auto-generated method stub
  89.  
    return null;
  90.  
    }
  91.  
     
  92.  
    }

Service比较简单:

  1.  
    public interface GatewayService {
  2.  
     
  3.  
    public List<JSONObject> findRouteList();
  4.  
    }

Service实现:

  1.  
    @Service
  2.  
    public class GatewayServiceImpl implements GatewayService {
  3.  
     
  4.  
    @Resource
  5.  
    private GatewayMapper gatewayMapper;
  6.  
     
  7.  
    @Override
  8.  
    public List<JSONObject> findRouteList() {
  9.  
    return gatewayMapper.findRouteList();
  10.  
    }
  11.  
    }

Mapper:

  1.  
    @Mapper
  2.  
    public interface GatewayMapper {
  3.  
     
  4.  
    public List<JSONObject> findRouteList();
  5.  
    }
  1.  
    <?xml version="1.0" encoding="UTF-8"?>
  2.  
     
  3.  
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  4.  
    <mapper namespace="com.zhufeng.gateway.db.mapper.GatewayMapper">
  5.  
     
  6.  
    <!--获取所有路由信息-->
  7.  
    <select id="findRouteList" resultType="com.alibaba.fastjson.JSONObject">
  8.  
    SELECT
  9.  
    route_id as routeId,
  10.  
    uri,
  11.  
    path_name as pathName,
  12.  
    path_pattern as pathPattern,
  13.  
    method_name as methodName,
  14.  
    method_pattern as methodPattern,
  15.  
    msg_name as msgName,
  16.  
    msg_type as msgType,
  17.  
    filter_name as filterName,
  18.  
    new_path as newPath,
  19.  
    remark
  20.  
    FROM
  21.  
    zf_gateway_route
  22.  
    WHERE status = 0
  23.  
    </select>
  24.  
    </mapper>

application.properties配置文件:

  1.  
    #服务端口
  2.  
    server.port=9990
  3.  
    #服务名称
  4.  
    spring.application.name=zhufeng-gateway-db
  5.  
     
  6.  
    mybatis.type-aliases-package=com.zhufeng.gateway.db.mapper
  7.  
    mybatis.mapper-locations=classpath:mapper/*.xml

3、效果演示

启动前需先启动nacos服务端,再创建两个微服务 zhufeng-web-user、zhufeng-web-msg,

从0到1学SpringCloud——11 gateway网关路由配置详解》有具体过程。

启动后先测试第一个路由规则,访问 http://127.0.0.1:9990/csdn/test

根据路由规则,会被转发到 blog.csdn.net /csdn/test 会被替换为 /nav/java 

学新通

虽然地址栏还是显示csdn/test,但是实际已经路由到了csdn的java博客专栏,通过标题可以看出Java博客,说明第一个配置生效。

然后测试第二个路由规则,请求被转发到 zhufeng-web-msg 微服务。

启动zhufeng-web-msg微服务,写一个简单的Controller

  1.  
    /**
  2.  
    * @ClassName: MsgController
  3.  
    * @Description 消息路由测试
  4.  
    * @author 月夜烛峰
  5.  
    * @date 2022/7/22 20:33
  6.  
    */
  7.  
    @RequestMapping("msg")
  8.  
    @RestController
  9.  
    public class MsgController {
  10.  
     
  11.  
    @RequestMapping("info")
  12.  
    public String showInfo() {
  13.  
    return "good luck~";
  14.  
    }
  15.  
     
  16.  
    }

为了方便演示Get请求和Post请求的不同,使用PostMan来测试,

分别请求 http://127.0.0.1:9990/msg/info

Get请求

学新通

 Post请求

学新通

 Get请求可以正常访问,Post请求被拦截,说明数据库配置的路由拦截条件生效。

三、自定义路由

1、代码实现

通过上述配置,简单了解了路由工厂的明明规范,我们可以遵循gateway定义自己的路由信息。

学新通

打开Gateway的源码,可以看到内部设置了很多断言规则,都有对应的路由工厂,途中标注的就是刚才用到的两个,仿照源码格式,我们写一个自己的路由工厂。

命名格式:Name RoutePredicateFactory

Name:ZhufengVersion

工厂类:ZhufengVersionRoutePredicateFactory 

校验逻辑:

当发起post请求时,如果Head中的版本号为 1.0 或者版本号不存在时放行,否则拦截。

ZhufengVersionRoutePredicateFactory代码:

  1.  
    package com.zhufeng.gateway.db.route;
  2.  
     
  3.  
    import lombok.extern.slf4j.Slf4j;
  4.  
    import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
  5.  
    import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
  6.  
    import org.springframework.stereotype.Component;
  7.  
    import org.springframework.validation.annotation.Validated;
  8.  
    import org.springframework.web.server.ServerWebExchange;
  9.  
     
  10.  
    import java.util.Arrays;
  11.  
    import java.util.List;
  12.  
    import java.util.function.Predicate;
  13.  
     
  14.  
    /**
  15.  
    * @ClassName: ZhufengVersionRoutePredicateFactory
  16.  
    * @Description 动态路由版本判断
  17.  
    * @author 月夜烛峰
  18.  
    * @date 2022/9/15 19:49
  19.  
    */
  20.  
    @Slf4j
  21.  
    @Component
  22.  
    public class ZhufengVersionRoutePredicateFactory extends AbstractRoutePredicateFactory<ZhufengVersionRoutePredicateFactory.Config> {
  23.  
     
  24.  
    public static final String VERSION_KEY = "version";
  25.  
     
  26.  
    public ZhufengVersionRoutePredicateFactory() {
  27.  
    super(Config.class);
  28.  
    }
  29.  
     
  30.  
    @Override
  31.  
    public List<String> shortcutFieldOrder() {
  32.  
    return Arrays.asList(VERSION_KEY);
  33.  
    }
  34.  
     
  35.  
    @Override
  36.  
    public Predicate<ServerWebExchange> apply(Config config) {
  37.  
     
  38.  
    return new GatewayPredicate() {
  39.  
    @Override
  40.  
    public boolean test(ServerWebExchange exchange) {
  41.  
    String version = exchange.getRequest().getHeaders().getFirst("version");
  42.  
    log.info("系统版本:{},当前请求版本:{}", config.version, version);
  43.  
    if (config.version == null || config.version.length() == 0) {
  44.  
    log.info("默认不拦截...");
  45.  
    return true;
  46.  
    }
  47.  
     
  48.  
    if (version == null || version.length() == 0) {
  49.  
    log.info("header中版本为空,不拦截...");
  50.  
    return true;
  51.  
    }
  52.  
    if (config.version.equals(version)) {
  53.  
    log.info("校验通过,请求放行!当前请求版本:{},系统要求版本:{}", version, config.version);
  54.  
    return true;
  55.  
    }
  56.  
    return false;
  57.  
    }
  58.  
     
  59.  
    @Override
  60.  
    public String toString() {
  61.  
    return String.format("version: %s", config.version);
  62.  
    }
  63.  
    };
  64.  
    }
  65.  
     
  66.  
    @Validated
  67.  
    public static class Config {
  68.  
     
  69.  
     
  70.  
    private String version;
  71.  
     
  72.  
    public String getVersion() {
  73.  
    return version;
  74.  
    }
  75.  
     
  76.  
    public void setVersion(String version) {
  77.  
    this.version = version;
  78.  
    }
  79.  
     
  80.  
     
  81.  
    }
  82.  
     
  83.  
    }

2、新增路由规则

修改ZhufengRouteDefinitionRepository代码,新增:

学新通

代码:

  1.  
    //自定义版本断言(仅作为演示),request请求中,只有版本为1.0时放行
  2.  
    PredicateDefinition version = new PredicateDefinition();
  3.  
    version.setName("ZhufengVersion");
  4.  
    version.addArg("version", "1.0");
  5.  
    route.getPredicates().add(version);

3、效果演示

通过PostMan测试,在Headers中新增version字段 

当version为1.0时

学新通

当version为2.0时

学新通

控制台打印:

学新通 

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfjaaak
系列文章
更多 icon
同类精品
更多 icon
继续加载