当前位置: 首页 > 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.jsqmd.com/news/4800/

相关文章:

  • 20250927Sat VIM 在函数内部任一行,按 [[ 即跳转到函数的开头
  • macOS 多 Java 版本管理(jenv 方案)
  • AI 落地教育智慧招生:从 “热线占线” 到 “724 小时精准应答” 的实践分享
  • 软件技术基础第一次课程
  • 石子合并(一排的和一个环的)
  • 思维题练习
  • NXP - 用MCUXpresso IDE导入lpcopen_2_10_lpcxpresso_nxp_lpcxpresso_1769.zip中的工程 - 教程
  • US$42 BDM01 Adapter for Yanhua Mini ACDP Module1 BMW CAS1-CAS4+
  • spatial项目的主要领导者斯坦福大学ppl实验室的 Kunle Olukotun 教授和 Christos Kozyrakis 教授
  • 程序杂谈:概述
  • 字符串基础
  • Kubernetes 进阶实战:CRD、Gateway API 与优先级调度 - 实践
  • 初识MYSQL —— 数据库基础 - 指南
  • 多态下,构造函数和析构函数的顺序,以及父类、子类的转换
  • US$49 B48 amp; MSV90 ISN Reading via OBD Authorization for Yanhua Mini ACDP
  • 在CodeBolcks下wxSmith的C++编程教程——使用 wxGrid
  • 题解:P12479 [集训队互测 2024] 长野原龙势流星群
  • 详细介绍:Docker(一)—— Docker入门到精通:从基础概念到容器管理
  • linux下nginx
  • OI 笑传 #12
  • spatial芯片设计语言 学习笔记
  • 非诚勿扰 —— 大龄单身男,找人生合伙人,有意者邮件联系
  • soul 这款APP太差劲了,天天都有婚介加我,怎么个事情,还能不能好好的解决解决个人问题了
  • 【C++】23. C++11(上) - 教程
  • kali2025搭建ARL灯塔系统
  • 单片机 -- USART总线 - 实践
  • 实用指南:AI 术语通俗词典:LLM(大语言模型)
  • java学习 2025-9-27
  • 揭秘JUC:volatile与CAS,并发编程的两大基石
  • 题解:P11667 [USACO25JAN] Astral Superposition B