Spring Cloud系列Gateway:自定义断言规则
尽管Spring Cloud Gateway已经包含了很多路由匹配规则,有时候我们需要开发自定义路由匹配规则来满足需求,下面简单的介绍一下如何自定义路由匹配规则。
需求
转发请求参数中带有token并且token值为123的请求。
实现
实现有三步步骤,如下所示
- 修改配置文件
spring: profiles: customPredicate cloud: gateway: routes: - id: product-service # 路由ID 唯一 uri: http://localhost:8890 # 目标URL,路由到对应的微服务地址 predicates: # 断言 - Token=123,abc # 匹配请求参数中包含token并且参数正则表达式是abc.的请求
- 定义配置类
@Data public class Config { private String token; }
- 定义断言工厂,在测试案例中将配置类作为内部类放到断言工厂里,如下所示
/** * @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。
- GATHER_LIST:shortcutFiledOrder只能有一个参数,如果值有多个拼成一个集合,如果将上文示例修改成该规则将报错,因为只能有一个参数。具体可以看org.springframework.cloud.gateway.support.ShortcutConfigurable.ShortcutType.GATHER_LIST
- GATHER_LIST_TAIL_FLAG:shortcutFiledOrder只能有两个参数,其中最后一个值为true或者false,其余的值变成一个集合付给第一个参数
- 测试,请求http://localhost:8892/product/1?token=123,日志打印如下
注:断言工厂默认命名规则必须按照"名称"+RoutePredicateFactory,如上TokenRoutePredicateFactory的断言名称为Token,命名规则生成代码如下
public final class NameUtils { public static String normalizeRoutePredicateName( Class<? extends RoutePredicateFactory> clazz) { return removeGarbage(clazz.getSimpleName() .replace(RoutePredicateFactory.class.getSimpleName(), "")); } }