Spring Cloud系列Gateway:自定义断言规则

尽管Spring Cloud Gateway已经包含了很多路由匹配规则,有时候我们需要开发自定义路由匹配规则来满足需求,下面简单的介绍一下如何自定义路由匹配规则。

需求

转发请求参数中带有token并且token值为123的请求。

实现

实现有三步步骤,如下所示

  1. 修改配置文件
spring:   profiles: customPredicate   cloud:     gateway:       routes:         - id: product-service         # 路由ID 唯一           uri: http://localhost:8890   # 目标URL,路由到对应的微服务地址           predicates:                 # 断言             - Token=123,abc        # 匹配请求参数中包含token并且参数正则表达式是abc.的请求
  1. 定义配置类
@Data public class Config {     private String token; }
  1. 定义断言工厂,在测试案例中将配置类作为内部类放到断言工厂里,如下所示
/**  * @author yanyu  * @date 2020/12/8  */ @Slf4j @Component public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<TokenRoutePredicateFactory.Config> {      public TokenRoutePredicateFactory() {         super(Config.class);     }      /**      * 配置类参数      * @return      */     @Override     public List<String> shortcutFieldOrder() {         return Arrays.asList("test1","test2");     }      /**      * 配置类参数解析规则      * @return      */     @Override     public ShortcutType shortcutType() {         return ShortcutType.DEFAULT;     }      /**      * 断言业务逻辑      * @param config      * @return      */     @Override     public Predicate<ServerWebExchange> apply(Config config) {         return exchange -> {             // 打印配置文件参数值             String test1 = config.getTest1();             String test2 = config.getTest1();             log.info("test1的值:{}",test1);             log.info("test2的值:{}",test2);              // 封装数据             MultiValueMap<String,String> params = exchange.getRequest().getQueryParams();             List<String> tokens = params.get("token");             if(tokens == null || tokens.size() < 1) {                 return false;             }              // 校验             boolean flag = false;             for(int i = 0; i< tokens.size();i++) {                 if(StringUtils.equalsIgnoreCase(test1, tokens.get(i))) {                     flag=true;                     break;                 }             }              log.info("验证:{}",flag?"成功":"失败");             return flag;         };     }      /**      * 配置类      */     @Data     public static class Config {         private String test1;          private String test2;     } }


该类继承AbstractRoutePredicateFactory同时需要注册到Spring的上下文中,Config配置类会按照如下规则进行封装,具体规则有两种如下:

通过shortcutFieldOrder方法设置Config配置类中的属性。

通过shortcutType方法获取具体规则,规则包括以下几种:

  • DEFAULT : 按照shortcutFieldOrder顺序依次赋值,如上文示例,test1->123;test2->abc。

Spring Cloud系列Gateway:自定义断言规则

  • GATHER_LIST:shortcutFiledOrder只能有一个参数,如果值有多个拼成一个集合,如果将上文示例修改成该规则将报错,因为只能有一个参数。具体可以看org.springframework.cloud.gateway.support.ShortcutConfigurable.ShortcutType.GATHER_LIST
  • GATHER_LIST_TAIL_FLAG:shortcutFiledOrder只能有两个参数,其中最后一个值为true或者false,其余的值变成一个集合付给第一个参数
  1. 测试,请求http://localhost:8892/product/1?token=123,日志打印如下

Spring Cloud系列Gateway:自定义断言规则

注:断言工厂默认命名规则必须按照"名称"+RoutePredicateFactory,如上TokenRoutePredicateFactory的断言名称为Token,命名规则生成代码如下

public final class NameUtils {    public static String normalizeRoutePredicateName(          Class<? extends RoutePredicateFactory> clazz) {       return removeGarbage(clazz.getSimpleName()             .replace(RoutePredicateFactory.class.getSimpleName(), ""));    } }

您可能还会对下面的文章感兴趣: