SpringCloud GateWay 自定义AbstractRoutePredicateFactory
主要为了解决原有的断言配置不满足业务
自定义模板套路
- 开头任意取名,但是必须以RoutePredicateFactory后缀结尾
- 继承AbstractRoutePredicateFactory抽象类
自定义路由断言规则步骤套路
需要重写的源码
仿照这个源码写,这个源码的路由规则是根据时间来定义的
接下来以示例演示
public class AfterRoutePredicateFactory extends AbstractRoutePredicateFactory<Config> {
public static final String DATETIME_KEY = "datetime";
public AfterRoutePredicateFactory() {
super(Config.class);
}
//支持shortcut 如果不重写 用简便形式写就会报错
public List<String> shortcutFieldOrder() {
return Collections.singletonList("datetime");
}
//ServerWebExchange这个类似与request,这个是判断是否让请求通过的规则
public Predicate<ServerWebExchange> apply(final Config config) {
return new GatewayPredicate() {
public boolean test(ServerWebExchange serverWebExchange) {
ZonedDateTime now = ZonedDateTime.now();
return now.isAfter(config.getDatetime());
}
public Object getConfig() {
return config;
}
public String toString() {
return String.format("After: %s", config.getDatetime());
}
};
}
//路由规则
public static class Config {
private @NotNull ZonedDateTime datetime;
public Config() {
}
public ZonedDateTime getDatetime() {
return this.datetime;
}
public void setDatetime(ZonedDateTime datetime) {
this.datetime = datetime;
}
}
}
1.新建类名XXX需要以RoutePredicateFactory结尾并继承AbstractRoutePredicateFactory类
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<WeGateWay.Config>
{
}
2.重写Config
根据什么来断言 ,这里是根据是请求参数是否有userType这个字符串
@Validated
public static class Config {
@NotEmpty
@Setter
@Getter
private String userType;
public Config() {
}
}
3.重写apply方法
@Override
//ServerWebExchange这个类似与request
public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
if(userType==null)
return false;
//这里的config是网关中是否yaml中配置的
if(userType.equalsIgnoreCase(config.getUserType())) return true;
return false;
}
};
}
4 .yaml配置之后开始测试
gateway:
routes:
- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
- after=2024-03-08T16:16:20.512583800+08:00[Asia/Shanghai]
- My=gold
#如果请求参数中有useType=gold 就会成功请求
测试结果 加userType
GET http://localhost:9527/pay/gateway/get/1?userType=gold
HTTP/1.1 200 OK
transfer-encoding: chunked
Content-Type: application/json
Date: Fri, 08 Mar 2024 13:22:16 GMT
{
"code": "200",
"message": "success",
"data": null,
"timestamp": 1709904136045
}
Response file saved.
> 2024-03-08T212216.200.json
Response code: 200 (OK); Time: 147ms (147 ms); Content length: 72 bytes (72 B)
不加
GET http://localhost:9527/pay/gateway/get/1?userType=g
HTTP/1.1 404 Not Found
Content-Type: application/json
Content-Length: 131
{
"timestamp": "2024-03-08T13:23:11.114+00:00",
"path": "/pay/gateway/get/1",
"status": 404,
"error": "Not Found",
"requestId": "a4ff3329-8"
}
Response file saved.
> 2024-03-08T212311.404.json
Response code: 404 (Not Found); Time: 23ms (23 ms); Content length: 131 bytes (131 B)