discuz做影视网站,WordPress文章生成不是HTML,建站网站关键词优化,岳阳网站开发商城Predicate(断言)
Predicate(断言)#xff0c;用于进行判断#xff0c;如果返回为真#xff0c;才会路由到具体服务。SpirnngCloudGateway由路由断言工厂实现#xff0c;直接配置即生效#xff0c;当然也支持自定义路由断言工厂。
内置路由断言工厂实现
SpringClo…Predicate(断言)
Predicate(断言)用于进行判断如果返回为真才会路由到具体服务。SpirnngCloudGateway由路由断言工厂实现直接配置即生效当然也支持自定义路由断言工厂。
内置路由断言工厂实现
SpringCloudGateway路由断言工厂实现有很多可以帮助开发者完成不同的功能。
AfterRoutePredicateFactory:设定日期参数允许在指定日期时间之后的请求通过
- After2020-01-20T17:42:47.78908:00[Asia/Shanghai]BeforeRoutePredicateFactory:设定日期参数允许在指定日期时间之前的请求通过
- Before2020-01-20T17:42:47.78908:00[Asia/Shanghai]BetweenRoutePredicateFactory:设定日期区间使用逗号分隔表示允许在时间段内的请求通过
- Between2020-01-20T17:42:47.78908:00[Asia/Shanghai],2023-02-20T17:42:47.78908:00[Asia/Shanghai]CookieRoutePredicateFactory:设置Cookie的名称和cookie值的正则表达式判断请求是否含有该Cookie名称且值与正则表达式相匹配
- Cookiechocolate, ch.pHeaderRoutePredicateFactory:设定请求头名称和请求头值的正则表达式判断请求是否含有该请求头且值与正则相匹配
- HeaderX-Request-Id, \dHostRoutePredicateFactory:设定host判断请求的host是否满足条件。
- Host**.test.comMethodRoutePredicateFactory:设定请求方式只允许满足请求类型的请求方式通过
- MethodGETPathRoutePredicateFactory:设定路由规则判断请求地址是否满足设定的路径规则
- Path/shop/**QueryRoutePredicateFactory:设定参数名称和参数值的正则判断请求是否含有该参数且值符合正则规则
- Queryname,z.RemoteAddrRoutePredicateFactory:设置IP地址段判断请求的主机地址是否满足条件
- RemoteAddr10.xxx.xxx.xxx/24注意这里是一个IP的地址段不是单纯的IP地址
WeightRoutePredicateFactory:设定权重分组和权重值同一个分组名的路由根据权重值进行转发
routes:- id: user_group1uri: http://test1.compredicates:- Path/user/**- Weightuser_grp,8 # 设置user_grp组80%请求进入user_group1- id: user_group2uri: http://test2.compredicates:- Path/user/**- Weightuser_grp,2 # 设置user_grp组20%请求进入user_group2内置断言实例 指定POST请求 server:port: 8083spring:application:name: gateway # 服务名cloud:nacos:discovery:server-addr: localhost:8848 # nacos地址gateway:routes: # 路由可配置多个- id: user_route # 路由id唯一即可默认UUIDuri: lb://user # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称order: 1 # 路由优先级默认0越低优先级越高predicates:- Path/user/** # 断言匹配规则- MethodPOST # 表示需要POST请求使用CMD测试下当使用GET请求时gateway直接打回告知沒有找到
curl localhost:8083/user/findById?id1
{timestamp:2023-08-26T00:24:35.88400:00,path:/user/findById,status:404,error:Not Found,message:null,requestId:0c70f6cf-1}使用POST请求正确访问(-X POST表示使用POST请求方式)
curl -X POST localhost:8083/user/findById?id1
Zhangsan不指定为POST请求时请求会被404. 使用Query路由断言 使用Query路由断言工厂且设置参数名为id正则表达式\d(一个或多个数字)
server:port: 8083spring:application:name: gateway # 服务名cloud:nacos:discovery:server-addr: localhost:8848 # nacos地址gateway:routes: # 路由可配置多个- id: user_route # 路由id唯一即可默认UUIDuri: lb://user # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称order: 1 # 路由优先级默认0越低优先级越高predicates:- Path/user/** # 断言匹配规则- Queryid, \d # 参数名id且值是数字(一位或多位)使用cmd调用测试使用非数字时被告知404
curl localhost:8083/user/findById?idss
{timestamp:2023-08-26T00:29:38.25200:00,path:/user/findById,status:404,error:Not Found,message:null,requestId:bc0fe260-3}使用数字符合正则正确访问
curl localhost:8083/user/findById?id1
Zhangsan自定义路由断言工厂
在实际的项目开发中开发者也可以创建自定义的路由断言工厂进行自己的业务扩展。实际上前面所有的断言工厂都是继承自AbstractRoutePredicateFactory并且配置是-Method时那么类就是MethodRoutePredicateFactory要创建自定义断言工厂我们也需要集成自此类然后重写自己的扩展即可。
实例创建自定义断言工厂只允许id为1~1000的请求通过
编写自定义的断言工厂CustomRoutePredicateFactory那么配置时就是-Custom
Component // 交给Spring管理
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactoryCustomRoutePredicateFactory.Config {public static final String[] KEY_ARRAY {minId, maxId}; // 对象属性public CustomRoutePredicateFactory() { // 构造函数需要给父类初始化一个配置类super(CustomRoutePredicateFactory.Config.class);}Overridepublic ListString shortcutFieldOrder() {return Arrays.asList(KEY_ARRAY);}Overridepublic PredicateServerWebExchange apply(Config config) {return new GatewayPredicate() { // 设置断言逻辑Overridepublic String toString() {return String.format(minId:%d, maxId:%d, config.getMinId(), config.getMaxId());}Overridepublic boolean test(ServerWebExchange exchange) {// 得到idString id exchange.getRequest().getQueryParams().getFirst(id);if (id ! null) {int numberId Integer.parseInt(id);// 当 请求的id是在此范围内返回truereturn numberId config.getMinId() numberId config.getMaxId();}return false;}};}Validatedpublic static class Config { // 配置类(注意这里是静态类否则属性是注入不进去的)private Integer minId; // 最小idprivate Integer maxId; // 最大idpublic Integer getMinId() {return minId;}public void setMinId(Integer minId) {this.minId minId;}public Integer getMaxId() {return maxId;}public void setMaxId(Integer maxId) {this.maxId maxId;}}
}yml配置
server:port: 8083spring:application:name: gateway # 服务名cloud:nacos:discovery:server-addr: localhost:8848 # nacos地址gateway:routes: # 路由可配置多个- id: user_route # 路由id唯一即可默认UUIDuri: lb://user # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称order: 1 # 路由优先级默认0越低优先级越高predicates:- Path/user/** # 断言匹配规则- Custom1,1000 # 设置值为1,1000测试当id不在范围内
curl localhost:8083/user/findById?id0
{timestamp:2023-08-26T01:09:02.56700:00,path:/user/findById,status:404,error:Not Found,message:null,requestId:61dcf9de-1}在范围内
curl localhost:8083/user/findById?id1
Zhangsan没问题!~
Filter过滤器
做过J2EE开发的应该不会对这个词感到陌生。在SpringCloudGateway中的过滤器也有类似的功能都可以在请求和响应间做一些自定义的逻辑。
Gateway的过滤器又分为局部和全局而且同样有内置和自定义。
内置局部过滤器
局部过滤器只针对当前路由的
AddRequestHeader:设定Header的值为原始的请求添加Header
- AddRequestHeaderX-Request-token, 123456AddRequestParameter:设定参数名和值为原始请求添加参数
- AddRequestParametername, zhangsanAddResponseHeader:设定Header的值为响应添加Header
- AddResponseHeadertoken, 123456DedupeResponseHeader:设定去重的Header名称和去重策略删除响应头中的重复值
- DedupeResponseHeaderAccess-Control-Allow-Credentinals Access-Control-Allow-Origin多个Header使用空格分隔去重策略RETAIN_FIRST(保留第一个)、RETAIN_LAST(保留最后一个)、RETAIN_UNIQUE(保留所有的唯一值)
PrefixPath:给请求加前缀为原始请求添加路径
- PrefixPath/userPrefixRedirectTo:设定HTTP状态码和URL将原始请求重定向到指定的URL
- RedirectTo302, https://test.comRewritePath:设定原始路径(支持正则)和重写路径(支持正则)重写原始路径
- RewritePath/user/findById, /user/testStripPrefix:设定要拦截的路径数量用于修改原始路
- StripPrefix1 # 如果请求是 /user/findById那么会被拦截为 /findByIdRequestSize:设定请求包大小单位字节默认5MB
filters:- name: RequestSizeargs:maxSize: 5000000自定义局部过滤器
还是按照前面提到的id在1~1000内允许访问否则直接拒绝。同路由断言工厂类似是配置GatewayFilterFactory的命名然后继承AbstractGatewayFilterFactory
写一个UserGatewayFilterFactory的类
Component
public class UserGatewayFilterFactory extends AbstractGatewayFilterFactoryUserGatewayFilterFactory.Config {private static final String[] KEY_ARRAYS {minId, maxId};public UserGatewayFilterFactory() { // 构造函数super(UserGatewayFilterFactory.Config.class);}Overridepublic GatewayFilter apply(Config config) {return (exchange, chain) - {// 获取id String id exchange.getRequest().getQueryParams().getFirst(id);if (id ! null) {int number Integer.parseInt(id);if (number config.getMinId() number config.getMaxId()) {// 放行return chain.filter(exchange);}}byte[] bytes (您不能访问id用户的数据).getBytes(StandardCharsets.UTF_8);DataBuffer wrap exchange.getResponse().bufferFactory().wrap(bytes);// 设定HTTP状态码exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);// 返回友好提示return exchange.getResponse().writeWith(Flux.just(wrap));};}Overridepublic ListString shortcutFieldOrder() {return Arrays.asList(KEY_ARRAYS);}public static class Config {private Integer minId;private Integer maxId;public Integer getMinId() {return minId;}public void setMinId(Integer minId) {this.minId minId;}public Integer getMaxId() {return maxId;}public void setMaxId(Integer maxId) {this.maxId maxId;}}
}yml配置
server:port: 8083spring:application:name: gateway # 服务名cloud:nacos:discovery:server-addr: localhost:8848 # nacos地址gateway:routes: # 路由可配置多个- id: user_route # 路由id唯一即可默认UUIDuri: lb://user # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称order: 1 # 路由优先级默认0越低优先级越高predicates:- Path/user/** # 断言匹配规则filters:- User1,1000 # 设置id为1~1000的过滤测试一手id空或id并不在范围内
curl localhost:8083/user/findById
您不能访问null用户的数据curl localhost:8083/user/findById?id2000
您不能访问2000用户的数据成功测试
curl localhost:8083/user/findById?id1
Zhangsan全局过滤器
全局过滤器在前面的文章中也大概了解过几个如openFeign的超时时间等其他的也基本类似用的不是很多。
通常情况下自定义全局过滤器是比较常用的了下面看一个案例客户端访问时的token认证功能的。
处理类需要实现GlobalFilter和Ordered接口重写方法
Component
public class TokenFilter implements GlobalFilter, Ordered { // 自定义全局过滤private final static String token 123456; // 这里做个模拟tokenOverridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 从请求头中拿到tokenString token exchange.getRequest().getHeaders().getFirst(token);if (token ! null) {if (token.equals(TokenFilter.token)) { // 如果请求头中带的token是123456 那么放行// 放行return chain.filter(exchange);}}byte[] bytes (您不能访问 exchange.getRequest().getPath() 地址).getBytes(StandardCharsets.UTF_8);DataBuffer wrap exchange.getResponse().bufferFactory().wrap(bytes);exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);// 返回友好提示return exchange.getResponse().writeWith(Flux.just(wrap));}Overridepublic int getOrder() { // 排序值越小优先级越高(说的是过滤器的优先级当有多个过滤器时order可以控制它们的执行优先级)return 0;}
}下面用工具测试一下token