• SpringCloud-Gateway自定义过滤器,解决body流不能重复读的问题


            网上的代码千奇百怪,这个是我测试后整理的。

            当前端请求不含body时,也能兼容。

    1.读取body流进行缓存

    1. /**
    2. * 获取body请求数据(解决流不能重复读取问题)
    3. * 这个过滤器的order设置的是Ordered.HIGHEST_PRECEDENCE,即最高优先级的过滤器。
    4. * 优先级设置这么高的原因是某些系统内置的过滤器可能也会去读body,
    5. * 这样就会导致我们自定义过滤器中获取body的时候报body只能读取一次这样的错误
    6. * @author yuchen
    7. */
    8. @Slf4j
    9. @Component
    10. public class CacheRequestFilter implements GlobalFilter, Ordered {
    11. @Override
    12. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    13. ServerHttpRequest request = exchange.getRequest();
    14. if (request.getHeaders().getContentType() == null) {
    15. return chain.filter(exchange);
    16. }
    17. HttpMethod method = request.getMethod();
    18. if (method == null || method.matches("GET") || method.matches("DELETE")) {
    19. return chain.filter(exchange);
    20. }
    21. //当body中没有缓存时,只会执行这一个拦截器, 原因是fileMap中的代码没有执行,所以需要在波多野为空时构建一个空的缓存
    22. DefaultDataBufferFactory defaultDataBufferFactory = new DefaultDataBufferFactory();
    23. DefaultDataBuffer defaultDataBuffer = defaultDataBufferFactory.allocateBuffer(0);
    24. //构建新数据流, 当body为空时,构建空流
    25. Flux<DataBuffer> bodyDataBuffer = exchange.getRequest().getBody().defaultIfEmpty(defaultDataBuffer);
    26. return DataBufferUtils.join(bodyDataBuffer)
    27. .flatMap(dataBuffer -> {
    28. DataBufferUtils.retain(dataBuffer);
    29. Flux<DataBuffer> cachedFlux = Flux
    30. .defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
    31. ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
    32. @Override
    33. public Flux<DataBuffer> getBody() {
    34. return cachedFlux;
    35. }
    36. };
    37. //exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, cachedFlux);
    38. return chain.filter(exchange.mutate().request(mutatedRequest).build());
    39. });
    40. }
    41. @Override
    42. public int getOrder() {
    43. return Ordered.HIGHEST_PRECEDENCE;
    44. }
    45. }

    2.从缓存读取body,就可以重复读:

    1. private static String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
    2. // 获取请求体
    3. Flux<DataBuffer> body = serverHttpRequest.getBody();
    4. AtomicReference<String> bodyRef = new AtomicReference<>();
    5. body.subscribe(buffer -> {
    6. CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
    7. DataBufferUtils.release(buffer);
    8. bodyRef.set(charBuffer.toString());
    9. });
    10. return bodyRef.get();
    11. }

  • 相关阅读:
    unity 烘焙的时候出现模型没有光影的情况
    Web渗透_手动漏洞挖掘
    微服务知识03
    asp.net core在其他程序集获取HttpContext
    牛客SQL非技术快速入门题解
    SpringBoot2.x+MybatisPlus+HikariCP多数据源动态配置
    [附源码]计算机毕业设计基于SpringBoot的玉石交易系统
    “华为杯”研究生数学建模竞赛2015年-【华为杯】E题:数控加工刀具运动的优化控制模型研究(附MATLAB代码实现)
    Java-API-ES
    Scala基础教程--19--Actor
  • 原文地址:https://blog.csdn.net/qq_38971617/article/details/128083327