当前位置: 首页 > news >正文

Gateway-断言 - 指南

断言就是一套规则,用来判断“什么样的请求,该走哪条路”。

网关内部配置了多个路由规则,每个规则都有对应的断言(Predicate)。网关会拿这个请求去逐一匹配这些断言条件

1.写法

短写法:

spring:cloud:gateway:routes:- id: order-routeuri: lb://service-order      #lb表示负载均衡# 断言predicates:      #短写法- Path=/api/order/**       #所有以api/order开头的路劲转给service-order处理order: 0                     #优先级,值越小优先级越高

全写法:

spring:cloud:gateway:routes:- id: order-routeuri: lb://service-order      #lb表示负载均衡# 断言predicates:- name: Path   #全写法args:pattern: /api/order/**match-trailing-slash: true

2.规则

3.测试

spring:cloud:gateway:routes:- id: order-routeuri: lb://service-order      #lb表示负载均衡# 断言predicates:- name: Pathargs:pattern: /api/order/**match-trailing-slash: trueorder: 0                     #优先级,值越小优先级越高- id: product-routeuri: lb://service-productpredicates:- Path=/api/product/**     #所有以api/product开头的路径转给service-product处理#  <--------全写法演示-------->- id: bing-routeuri: https://cn.bing.compredicates:- name: Pathargs:pattern: /search- name: Queryargs:param: qregexp: hello world# <---------全写法演示-------->#   <---------短写法演示------->- id: deepseek-routeuri: https://www.deepseek.compredicates:- Path=/search- Query=q,hello#   <---------短写法演示--------->

这里再写两个断言,一个用全写法,一个用短写法,体会两种写法的优劣

启动GatewayMainApplication,等待控制台出现Started GatewayMainApplication,即说明服务启动完毕,再执行下步操作 。

打开浏览器或者apipsot/postman/apifox等接口测试工具 (这里使用apipost)

浏览器网址口或者测试工具请求口输入localhost/search/?q=hello world 回车

可以看到,测试通过,匹配成功。

继续测试deepseek-route

如图可以看到,浏览器和apipost测试断言匹配,测试通过

4.自定义断言工厂

创建断言工厂

在com.atguigu.gateway包下连包带类创建VipRoutePredicateFactory类

创建完成后,我们使用ctrl+n来搜索断言工厂源码QueryRoutePredicateFactory类

我们可以通过源码看到,自定义一个断言工厂需要:

1.继承抽象父类 AbstractRoutePredicateFactory并需要指定一个配置类作为泛型参数

2.定义配置类,并添加getter和setter方法

3.实现构造函数调用 super(Config.class)

4.实现shortcutFieldOrder(可选):定义快捷配置的参数顺序

5.实现apply方法:编写核心逻辑,利用 ServerWebExchangeConfig 进行判断,返回 Predicat

6.注册为Bean:通常使用 @Component 注解将其声明为一个Spring Bean,这样框架就能自动发现它。

package org.springframework.cloud.gateway.handler.predicate;
import jakarta.validation.constraints.NotEmpty;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
public class QueryRoutePredicateFactory extends AbstractRoutePredicateFactory {
//定义常量字符串  k-vpublic static final String PARAM_KEY = "param";public static final String REGEXP_KEY = "regexp";
//构造函数public QueryRoutePredicateFactory() {super(Config.class);}
//短写法public List shortcutFieldOrder() {return Arrays.asList("param", "regexp");}
//这是核心方法,它创建了实际的断言逻辑public Predicate apply(final Config config) {return new GatewayPredicate() {public boolean test(ServerWebExchange exchange) {if (!StringUtils.hasText(config.regexp)) {return exchange.getRequest().getQueryParams().containsKey(config.param);} else {List values = (List)exchange.getRequest().getQueryParams().get(config.param);if (values == null) {return false;} else {Iterator var3 = values.iterator();String value;do {if (!var3.hasNext()) {return false;}value = (String)var3.next();} while(value == null || !value.matches(config.regexp));return true;}}}
//返回当前断言所使用的配置对象public Object getConfig() {return config;}public String toString() {return String.format("Query: param=%s regexp=%s", config.getParam(), config.getRegexp());}};}//内部配置类@Validatedpublic static class Config {private @NotEmpty String param;private String regexp;public Config() {}public String getParam() {return this.param;}public Config setParam(String param) {this.param = param;return this;}public String getRegexp() {return this.regexp;}public Config setRegexp(String regexp) {this.regexp = regexp;return this;}}
}

下面,我们根据源码来照猫画虎,定义一个自己的断言工厂VipRoutePredicateFactory

package com.atguigu.gateway.predicate;
import jakarta.validation.constraints.NotEmpty;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
//注册为bean,交给spring管理
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory {//构造函数调用public VipRoutePredicateFactory() {super(Config.class);}@Override// 实现apply方法public Predicate apply(Config config) {System.out.println("进入自定义断言工厂");return new Predicate() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {//  ServerWebExchange内部封装了请求参数和响应结果ServerHttpRequest request = serverWebExchange.getRequest();// 获取参数String first = request.getQueryParams().getFirst(config.param);//判空并判等if (StringUtils.hasText(first) && first.equals(config.value)) {return true;}return false;}};}// 定义参数顺序,重写shortcutFieldOrder方法@Overridepublic List shortcutFieldOrder() {return Arrays.asList("param", "value");}/*** 定义配置类*/@Validatedpublic static class Config {@NotEmptyprivate String param;@NotEmptyprivate String value;public @NotEmpty String getParam() {return param;}public @NotEmpty String getValue() {return value;}public void setParam(@NotEmpty String param) {this.param = param;}public void setValue(@NotEmpty String value) {this.value = value;}}
}

接着我们需要在配置文件中配置自定义断言工厂

5.测试(自定义断言工厂)

我们在启动GatewayMainApplication,然后等待服务启动完毕,然后浏览器访问

首先测试短写法演示

可以看到localhost/search?q=hello&user=yuexihuachen 访问deepseek成功

然后测试全写法演示 此时q=hello world,localhost/search?q=hello world&user=yuexihuachen访问bing也成功

最后我们再改变user的值,看看是否会失败,localhost/search?q=hello world&user=yuexihuache

果不其然,访问未通过,因为user参数的值与我们在idea中配置文件中不一致,返回404错误码。

http://www.rkmt.cn/news/12830.html

相关文章:

  • 字符串基础
  • Kubernetes 进阶实战:CRD、Gateway API 与优先级调度 - 实践
  • 单片机 -- USART总线 - 实践
  • 题解:P11667 [USACO25JAN] Astral Superposition B
  • 北极通讯网络题解(做题记录)
  • 个人学习——前端react项目框架
  • 软件基础第一次作业
  • 7、revision 是 Maven 3.5+ 引入的现代版本管理机制 - 实践
  • 如何有效提升代码覆盖率:从单元测试到集成测试的实践指南
  • 深入解析:SSM网络游戏交易系统a9n72(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
  • 调度器的各项指标以及计算方式
  • ​CentOS 7 安装 net-tools.rpm 包步骤详解(附 rpm 命令和 yum 方法)​附安装包
  • 29.Linux防火墙管理 - 详解
  • 昇腾多机推理极速上手:10倍简化的 DeepSeek R1 超大规模模型部署
  • B站油管抖音一键笔记
  • 对于Hash冲突的处理
  • 完整教程:事件驱动与CDS:基于FHIR R5 Subscriptions与Bulk Data的再考察(上)
  • 进程调度的时机,切换与过程
  • 网站多媒体加载卡顿?视频压缩 + 音频优化,加载速度提升 75% 的实操方法 - 实践
  • 用 Zig 实现英文数字验证码识别
  • 完整教程:数组(Java基础语法)
  • 深入解析:python+django/flask哈利波特书影音互动科普网站
  • 深入解析:CodeForces479A-Expression(数学+枚举)
  • 英语_阅读_Robot
  • 深入解析:PyTorch张量切片的陷阱:视图与副本
  • 英语_阅读_Industry 4.0_待读
  • Python获取CPU和内存使用率
  • 深入解析:实战:基于 BRPC+Etcd 打造轻量级 RPC 服务——从注册到调用的核心架构与基础实现
  • 完整教程:从另一个视角看Transformer:注意力机制就是可微分的k-NN算法
  • ACM 杂题选做 题解合集