前言
Filter,又名过滤器,当然不是我们日常中见到的,诸如此类构件:
而应该是微服务中常使用的,诸如此类(图片来自官网,点击可查看原图):
一般用于字符编码转换,日志处理等场景。而我们今天提到的Filter
是基于springcloud gateway
而言的。
一、Gateway Filter
1. 按生命周期划分
通过springcloud gateway
的工作原理图,我们可以发现,过滤器在数据的请求和返回的过程中发挥它应有的作用。此类过滤器生命周期有两类:
过滤器阶段 | 过滤器作用 |
---|---|
Pre-req | 业务逻辑请求前 (pre-request),完成相关操作 |
Post-req | 业务逻辑请求后 (post-request),完成相关操作 |
2. 按职责范围划分
过滤器名称 | 过滤器简介 |
---|---|
GateWayFilter | 单一过滤器,即仅可完成单一功能的Filter,一般可建多个 |
GlobalFilter | 全局过滤器,可完成所有路由功能的Filter,一般只建1个 |
其他内容可参考官网,这里不再赘述。如需请速戳:springcloud gateway。
当然不管是什么生命周期,还是什么职责范围,过滤器都会按照指定的路由执行,否则那不乱成一锅粥了。
因此,每个过滤器都应指定一个顺序Order
值。
二、Gateway Filter Order
一句话总结
:Order值越小,优先级越高,执行越靠前。
以下是springcloud gateway
filter中的order定义:
public interface Ordered {/*** Useful constant for the highest precedence value.* @see java.lang.Integer#MIN_VALUE*/int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;/*** Useful constant for the lowest precedence value.* @see java.lang.Integer#MAX_VALUE*/int LOWEST_PRECEDENCE = Integer.MAX_VALUE;/*** Get the order value of this object.* <p>Higher values are interpreted as lower priority. As a consequence,* the object with the lowest value has the highest priority (somewhat* analogous to Servlet {@code load-on-startup} values).* <p>Same order values will result in arbitrary sort positions for the* affected objects.* @return the order value* @see #HIGHEST_PRECEDENCE* @see #LOWEST_PRECEDENCE*/int getOrder();}
而我们在使用的过程中,一般这样定义顺序:
@Component
public class TestGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {return chain.filter(exchange);}@Overridepublic int getOrder() {return 123;}
}
三、问题案例
因为我们在项目开发过程中, 为完成某些特定功能,会经常使用过滤器,所以难免遇到一些问题。而今天博主重点介绍其中的一个问题:请求体丢失
,即只能消费一次的问题。
废话无需多言,直接参考以下代码,即可满足你的需要:
1. 缓存requestbody
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;/*** 定义一个全局过滤器,实现requestbody缓存* @date 2024/01/07 09:06*/
@Component
public class ReqGlobalFilter implements Ordered, GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {if (exchange.getRequest().getHeaders().getContentType() == null) {return chain.filter(exchange);} else {return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {DataBufferUtils.retain(dataBuffer);Flux<DataBuffer> cachedFlux = Flux.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {@Overridepublic Flux<DataBuffer> getBody() {return cachedFlux;}};return chain.filter(exchange.mutate().request(mutatedRequest).build());});}}@Overridepublic int getOrder() {return -10000;//也可设置为最高优先级}
}
2. 获取requestbody
在其他过滤器中,引用以下代码,实现requestbody获取:
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){// 获取请求体Flux<DataBuffer> body = serverHttpRequest.getBody();AtomicReference<String> bodyRef = new AtomicReference<>();body.subscribe(buffer -> {CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());DataBufferUtils.release(buffer);bodyRef.set(charBuffer.toString());});return bodyRef.get();}
结语
Filter是完成业务逻辑前或后应有操作的必要环节,也是实现统一服务的典型武器,所以我们应该了解它、学习它、掌握它。
好了,今日话题到此为止,下一篇是啥,继续期待!
历史回顾
-
微服务实战系列之API加密
-
微服务实战系列之Dubbo(下)
-
微服务实战系列之Dubbo(上)
-
微服务实战系列之ZooKeeper(实践篇)
-
微服务实战系列之ZooKeeper(下)
-
微服务实战系列之ZooKeeper(中)
-
微服务实战系列之ZooKeeper(上)
-
微服务实战系列之MQ
-
微服务实战系列之通信
-
微服务实战系列之J2Cache
-
微服务实战系列之Cache(技巧篇)
-
微服务实战系列之MemCache
-
微服务实战系列之EhCache
-
微服务实战系列之Redis
-
微服务实战系列之Cache
-
微服务实战系列之Nginx(技巧篇)
-
微服务实战系列之Nginx
-
微服务实战系列之Feign
-
微服务实战系列之Sentinel
-
微服务实战系列之Token
-
微服务实战系列之Nacos
-
微服务实战系列之Gateway
-
微服务实战系列之加密RSA
-
微服务实战系列之签名Sign