最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringCloud Gateway自定義filter獲取body中的數(shù)據(jù)為空的問題

 更新時間:2020年10月31日 13:34:18   作者:mameng1998  
這篇文章主要介紹了SpringCloud Gateway自定義filter獲取body中的數(shù)據(jù)為空,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

最近在使用SpringCloud Gateway進(jìn)行網(wǎng)關(guān)的開發(fā),我使用的版本是:SpringBoot的2.3.4.RELEASE+SpringCloud的Hoxton.SR8,在自定義過濾器時需要獲取ServerHttpRequest中body的數(shù)據(jù),發(fā)現(xiàn)一直無法獲取到數(shù)據(jù),經(jīng)過各種百度、谷歌,再加上自己的實踐,終于找到解決方案:
1、首先創(chuàng)建一個全局過濾器把body中的數(shù)據(jù)緩存起來

package com.cloudpath.gateway.portal.filter;

import lombok.extern.slf4j.Slf4j;
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;

/**
 * @author mazhen
 * @className CacheBodyGlobalFilter
 * @Description 把body中的數(shù)據(jù)緩存起來
 * @date 2020/10/28 18:02
 */
@Slf4j
@Component
public class CacheBodyGlobalFilter implements Ordered, GlobalFilter {

  // public static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";

  @Override
  public 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()) {
              @Override
              public Flux<DataBuffer> getBody() {
                return cachedFlux;
              }
            };
            //exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, cachedFlux);

            return chain.filter(exchange.mutate().request(mutatedRequest).build());
          });
    }
  }

  @Override
  public int getOrder() {
    return Ordered.HIGHEST_PRECEDENCE;
  }

}

CacheBodyGlobalFilter這個全局過濾器的目的就是把原有的request請求中的body內(nèi)容讀出來,并且使用ServerHttpRequestDecorator這個請求裝飾器對request進(jìn)行包裝,重寫getBody方法,并把包裝后的請求放到過濾器鏈中傳遞下去。這樣后面的過濾器中再使用exchange.getRequest().getBody()來獲取body時,實際上就是調(diào)用的重載后的getBody方法,獲取的最先已經(jīng)緩存了的body數(shù)據(jù)。這樣就能夠?qū)崿F(xiàn)body的多次讀取了。
值得一提的是,這個過濾器的order設(shè)置的是Ordered.HIGHEST_PRECEDENCE,即最高優(yōu)先級的過濾器。優(yōu)先級設(shè)置這么高的原因是某些系統(tǒng)內(nèi)置的過濾器可能也會去讀body,這樣就會導(dǎo)致我們自定義過濾器中獲取body的時候報body只能讀取一次這樣的錯誤如下:

java.lang.IllegalStateException: Only one connection receive subscriber allowed.
	at reactor.ipc.netty.channel.FluxReceive.startReceiver(FluxReceive.java:279)
	at reactor.ipc.netty.channel.FluxReceive.lambda$subscribe$2(FluxReceive.java:129)
	at 

所以,必須把CacheBodyGlobalFilter的優(yōu)先級設(shè)到最高。
2、在自定義的過濾器中嘗試獲取body中的數(shù)據(jù)

package com.cloudpath.iam.gateway.customerfilter;

import com.cloudpath.iam.gateway.utils.FilterRequestResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;

import java.util.Arrays;
import java.util.List;

/**
 * @author by mazhen
 * @Classname TestGatewayFilterFactory
 * @Description 自定義過濾器獲取body中的數(shù)據(jù)
 * @Date 2020/10/27 14:38
 */
@Component
@Slf4j
public class TestGatewayFilterFactory extends AbstractGatewayFilterFactory<TestGatewayFilterFactory.Config> {


  @Override
  public List<String> shortcutFieldOrder() {
    return Arrays.asList("enabled");
  }

  public TestGatewayFilterFactory() {
    super(Config.class);
    log.info("Loaded TestGatewayFilterFactory");
  }

  @Override
  public GatewayFilter apply(Config config) {
    return (exchange, chain) -> {
      if (!config.isEnabled()) {
        return chain.filter(exchange);
      }

      if (null != exchange) {
        ServerHttpRequest httpRequest = exchange.getRequest();
          try {

            Flux<DataBuffer> dataBufferFlux = httpRequest.getBody();
            //獲取body中的數(shù)據(jù)
            String body = FilterRequestResponseUtil.resolveBodyFromRequest(dataBufferFlux);
            log.info("body:{}",body);

          } catch (Exception e) {
            log.error("異常:",e);
            return chain.filter(exchange);
          }
      }
      return chain.filter(exchange);
    };
  }


  public static class Config {
    /**
     * 控制是否開啟統(tǒng)計
     */
    private boolean enabled;

    public Config() {
    }

    public boolean isEnabled() {
      return enabled;
    }

    public void setEnabled(boolean enabled) {
      this.enabled = enabled;
    }
  }
}

3、解析body的工具類

package com.cloudpath.iam.gateway.utils;


import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import reactor.core.publisher.Flux;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author mazhen
 * @className FilterHeadersUtil
 * @Description 過濾器請求/響應(yīng)工具類
 * @date 2020/10/29 9:31
 */
public final class FilterRequestResponseUtil {

  /**
   * spring cloud gateway 獲取post請求的body體
   * @param body
   * @return
   */
  public static String resolveBodyFromRequest( Flux<DataBuffer> body){
    AtomicReference<String> bodyRef = new AtomicReference<>();
    // 緩存讀取的request body信息
    body.subscribe(dataBuffer -> {
      CharBuffer charBuffer = StandardCharsets.UTF_8.decode(dataBuffer.asByteBuffer());
      DataBufferUtils.release(dataBuffer);
      bodyRef.set(charBuffer.toString());
    });
    //獲取request body
    return bodyRef.get();

  }

  /**
   * 讀取body內(nèi)容
   * @param body
   * @return
   */
  public static String resolveBodyFromRequest2( Flux<DataBuffer> body){
    StringBuilder sb = new StringBuilder();

    body.subscribe(buffer -> {
      byte[] bytes = new byte[buffer.readableByteCount()];
      buffer.read(bytes);
      DataBufferUtils.release(buffer);
      String bodyString = new String(bytes, StandardCharsets.UTF_8);
      sb.append(bodyString);
    });
    return formatStr(sb.toString());
  }

  /**
   * 去掉空格,換行和制表符
   * @param str
   * @return
   */
  private static String formatStr(String str){
    if (str != null && str.length() > 0) {
      Pattern p = Pattern.compile("\\s*|\t|\r|\n");
      Matcher m = p.matcher(str);
      return m.replaceAll("");
    }
    return str;
  }
}

解析body的內(nèi)容,網(wǎng)上普遍是上面的兩種方式,親測resolveBodyFromRequest方法解析body中的數(shù)據(jù),沒有1024字節(jié)的限制。
ps:我傳的參數(shù)有1萬多字節(jié)。。。。。。。
大家可以按需所選。

到此這篇關(guān)于SpringCloud Gateway自定義filter獲取body中的數(shù)據(jù)為空的文章就介紹到這了,更多相關(guān)SpringCloud Gateway自定義filter內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springboot AOP開發(fā)教程

    Springboot AOP開發(fā)教程

    AOP是OOP的延續(xù),是軟件開發(fā)中的一個熱點,也是Spring框架中的一個重要內(nèi)容,是函數(shù)式編程的一種衍生范型,本文給大家介紹Springboot AOP開發(fā)教程,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • idea 無法創(chuàng)建Scala class 選項的原因分析及解決辦法匯總

    idea 無法創(chuàng)建Scala class 選項的原因分析及解決辦法匯總

    這篇文章主要介紹了idea 無法創(chuàng)建Scala class 選項的解決辦法匯總,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • RabbitMQ冪等性與優(yōu)先級及惰性詳細(xì)全面講解

    RabbitMQ冪等性與優(yōu)先級及惰性詳細(xì)全面講解

    關(guān)于MQ消費者的冪等性問題,在于MQ的重試機制,因為網(wǎng)絡(luò)原因或客戶端延遲消費導(dǎo)致重復(fù)消費。使用MQ重試機制需要注意的事項以及如何解決消費者冪等性與優(yōu)先級及惰性問題以下將逐一講解
    2022-11-11
  • Java?項目中使用遞歸的小結(jié)

    Java?項目中使用遞歸的小結(jié)

    在 Java 中,遞歸是指在方法的定義中調(diào)用自身的過程,遞歸是基于方法調(diào)用棧的原理實現(xiàn)的:當(dāng)一個方法被調(diào)用時,會在調(diào)用棧中創(chuàng)建一個對應(yīng)的棧幀,包含方法的參數(shù)、局部變量和返回地址等信息,這篇文章主要介紹了Java?項目中對使用遞歸的理解分享,需要的朋友可以參考下
    2024-07-07
  • MyBatis?核心組件Configuration實例詳解

    MyBatis?核心組件Configuration實例詳解

    Configuration用于描述 MyBatis 的主配置信息,其他組件需要獲取配置信息時,直接通過 Configuration 對象獲取,這篇文章主要介紹了MyBatis核心組件Configuration,需要的朋友可以參考下
    2023-08-08
  • spring mvc+localResizeIMG實現(xiàn)HTML5端圖片壓縮上傳

    spring mvc+localResizeIMG實現(xiàn)HTML5端圖片壓縮上傳

    這篇文章主要為大家詳細(xì)介紹了使用spring mvc+localResizeIMG實現(xiàn)HTML5端圖片壓縮上傳,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Java日志軟件Log4j的基本使用教程

    Java日志軟件Log4j的基本使用教程

    這篇文章主要介紹了Java日志軟件Log4j的基本使用教程,包括回滾和發(fā)送日志郵件等基本功能使用的講解,需要的朋友可以參考下
    2015-12-12
  • spring的Cache注解和redis的區(qū)別說明

    spring的Cache注解和redis的區(qū)別說明

    這篇文章主要介紹了spring的Cache注解和redis的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java之Scanner.nextLine()讀取回車的問題及解決

    Java之Scanner.nextLine()讀取回車的問題及解決

    這篇文章主要介紹了Java之Scanner.nextLine()讀取回車的問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Java遍歷Properties所有元素的方法實例

    Java遍歷Properties所有元素的方法實例

    這篇文章主要介紹了Java如何遍歷Properties所有元素的方法,大家可以參考使用
    2013-11-11

最新評論

巫山县| 志丹县| 当雄县| 兰溪市| 西吉县| 中方县| 芒康县| 北宁市| 鱼台县| 香河县| 曲阳县| 弋阳县| 绍兴市| 密云县| 襄垣县| 堆龙德庆县| 龙门县| 砚山县| 江北区| 临沧市| 新泰市| 阿拉善右旗| 广丰县| 七台河市| 郁南县| 肥西县| 维西| 嵩明县| 邯郸县| 老河口市| 泗洪县| 长武县| 鱼台县| 调兵山市| 广南县| 翁牛特旗| 教育| 惠州市| 武宣县| 淳化县| 乌海市|