欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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)過各種百度、谷歌,再加上自己的實(shí)踐,終于找到解決方案:
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時,實(shí)際上就是調(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)文章

  • java編程兩種樹形菜單結(jié)構(gòu)的轉(zhuǎn)換代碼

    java編程兩種樹形菜單結(jié)構(gòu)的轉(zhuǎn)換代碼

    這篇文章主要介紹了java編程兩種樹形菜單結(jié)構(gòu)的轉(zhuǎn)換代碼,首先介紹了兩種樹形菜單結(jié)構(gòu)的代碼,然后展示了轉(zhuǎn)換器實(shí)例代碼,最后分享了相關(guān)實(shí)例及結(jié)果演示,具有一定借鑒價值,需要的朋友可以了解下。
    2017-12-12
  • SpringBoot自定義HttpMessageConverter操作

    SpringBoot自定義HttpMessageConverter操作

    這篇文章主要介紹了SpringBoot自定義HttpMessageConverter的操作,具有很好的參考價值,如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java重點(diǎn)梳理類與對象核心原理

    Java重點(diǎn)梳理類與對象核心原理

    類(class)和對象(object)是兩種以計算機(jī)為載體的計算機(jī)語言的合稱。對象是對客觀事物的抽象,類是對對象的抽象。類是一種抽象的數(shù)據(jù)類型
    2022-07-07
  • spring boot 部署為jar包的方法示例

    spring boot 部署為jar包的方法示例

    本篇文章主要介紹了spring boot 部署為jar的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • 詳解Java的Hibernate框架中的搜索工具的運(yùn)用

    詳解Java的Hibernate框架中的搜索工具的運(yùn)用

    這篇文章主要介紹了詳解Java的Hibernate框架中的搜索工具的運(yùn)用,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-11-11
  • 淺談從Java中的棧和堆,進(jìn)而衍生到值傳遞

    淺談從Java中的棧和堆,進(jìn)而衍生到值傳遞

    這篇文章主要介紹了淺談從Java中的棧和堆,進(jìn)而衍生到值傳遞,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • SpringBoot jar包大小優(yōu)化問題及解決

    SpringBoot jar包大小優(yōu)化問題及解決

    這篇文章主要介紹了SpringBoot jar包大小優(yōu)化問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Java中synchronized的四種用法詳解

    Java中synchronized的四種用法詳解

    這篇文章主要介紹了Java中synchronized的四種用法詳解,當(dāng)我們處理多線程處理同步問題的時候就會用到synchronized這個關(guān)鍵字,下面介紹下synchronized的四種用法,需要的朋友可以參考下
    2024-01-01
  • 基于CyclicBarrier和CountDownLatch的使用區(qū)別說明

    基于CyclicBarrier和CountDownLatch的使用區(qū)別說明

    這篇文章主要介紹了基于CyclicBarrier和CountDownLatch的使用區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 詳解Spring3.x 升級至 Spring4.x的方法

    詳解Spring3.x 升級至 Spring4.x的方法

    本篇文章主要介紹了詳解Spring3.x 升級至 Spring4.x的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04

最新評論