亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot攔截器讀取流后不能再讀取的問題

 更新時間:2021年10月26日 10:04:26   作者:YUNDONG丶  
這篇文章主要介紹了SpringBoot攔截器讀取流后不能再讀取的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

在SpringBoot的攔截器中通過流 ( request.getInputStream() ) 的方式讀取body中傳來的數(shù)據(jù)會導致controller接收不到值。

這個問題其實就是一個流讀取的問題,眾所周知在Java中input流只能讀取一次,主要原因是通標記的方法來判斷流是否讀取完畢(讀取位 -1就是流讀取完畢)

解決這個問題我能想到兩種方式

1.通過修改標記的方式 ( inputstream.markSupported() 方法可以判斷這個流是否支持 mark 和 reset 方法。他們分別是標記 和 重新定位流。)

2.將流賦值給一個 byte[] 數(shù)組,或者其他變量保存起來。下載讀取流時就調(diào)用這個數(shù)組就行。

第一種方法

再回到問題上來我們可以先使用第一種方法判斷 requet 中的inputStream 是否支持標記和重新定位。因為這種方式實現(xiàn)起來比較簡單。無需考慮太多。

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
         boolean b = request.getInputStream().markSupported();
         System.out.println(b);
    }
// 輸出結(jié)果為 false 

上述代碼會返回一個 false 那么很明顯,request 中的 input 流是不支持標記和重新定位的。

第二種方法

我們再考慮第二種方法,我們需要一個變量保存這個流。并且還要保證再過濾器中和controller中都要拿到這個變量。直接定義一個全局變量獲取修改傳值方式,都是可以的。全局變量這種方式我就不演示了。

下面是改變傳值方式的 demo

  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        ServletInputStream inputStream1 = request.getInputStream();
        // 各種對 inputStream1 處理的操作...
        Object obejct = inputStream1;
        request.setAttribute("Params",obejct);
}

這樣就可以再controller那邊就可以直接獲取 Attribute 中的值。

但是!這樣有很大的局限性,例如: 我已經(jīng)寫好了大多數(shù)的controller方法體。這時再改用這種方式傳值。對于開發(fā)人員是一種莫大的痛苦 -_- 于是通過不屑的百度查詢到另一種方法 一一一 改寫HttpServletRequestWrapper方法。為什么是這個方法?因為他實現(xiàn)了 HttpServletRequest 這個接口。也是我們攔截器接收的 request 要求的類型。首先我們先看一張圖。** 注意 filter 和 inteceptor 中間。 **

通過上方這個圖我們可以知道,在 Filter 和 Inteceptor 中間有一層Servlet。而Servlet就是提交request的地方。所以我們要重寫HttpServletRequest方法只能在Servlet之前。也就是filter 中。下面就是直接上代碼了

1.重寫 HttpServletRequest

package com.xqw.kyg.util;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.util.StreamUtils;
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper{
    private byte[] requestBody = null;//用于將流保存下來
    public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        requestBody = StreamUtils.copyToByteArray(request.getInputStream());
    }
    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
        return new ServletInputStream() {
            @Override
            public int read(){
                return bais.read();  // 讀取 requestBody 中的數(shù)據(jù)
            }
            @Override
            public boolean isFinished() {
                return false;
            }
            @Override
            public boolean isReady() {
                return false;
            }
            @Override
            public void setReadListener(ReadListener readListener) { }
        };
    }
    @Override
    public BufferedReader getReader() throws IOException{
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}

2.編寫Filter

package com.xqw.kyg.filter;
import com.xqw.kyg.util.MyHttpServletRequestWrapper;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Component
public class HttpServletRequestReplacedFilter implements Filter {
    @Override
    public void destroy() {}
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
        if(request instanceof HttpServletRequest) {
            requestWrapper = new MyHttpServletRequestWrapper((HttpServletRequest) request);
        }
        if(requestWrapper == null) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }
    @Override
    public void init(FilterConfig arg0) throws ServletException {}
}

到此代碼編寫就完成了。你現(xiàn)在可以在 過濾器 中讀取inputstream數(shù)據(jù)controller中也可以獲取到了。其實代碼并不是特別困難。主要是出現(xiàn)BUG能及時的想到原因,和提供解決方案。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • java多線程學習筆記之自定義線程池

    java多線程學習筆記之自定義線程池

    本篇文章主要介紹了java多線程學習筆記之自定義線程池 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 詳解JavaFX桌面應用開發(fā)-Group(容器組)

    詳解JavaFX桌面應用開發(fā)-Group(容器組)

    這篇文章主要介紹了JavaFX桌面應用開發(fā)-Group(容器組),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • java中List去除重復數(shù)據(jù)的5種方式總結(jié)

    java中List去除重復數(shù)據(jù)的5種方式總結(jié)

    這篇文章主要給大家總結(jié)介紹了關于java中List去除重復數(shù)據(jù)的5種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • Eclipse安裝Free marker插件教程

    Eclipse安裝Free marker插件教程

    這篇文章主要為大家詳細介紹了Eclipse安裝Free marker插件教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 詳解Spring數(shù)據(jù)緩存注解@Cacheable、@CachePut、@CacheEvict

    詳解Spring數(shù)據(jù)緩存注解@Cacheable、@CachePut、@CacheEvict

    這篇文章主要介紹了詳解Spring數(shù)據(jù)緩存注解@Cacheable、CachePut、@CacheEvict,當以一組參數(shù)第一次調(diào)用某個方法時,返回值會被保存在緩存中,如果這個方法再次以相同的參數(shù)進行調(diào)用時,這個返回值會從緩存中查詢獲取,需要的朋友可以參考下
    2023-07-07
  • Java獲取文件的類型和擴展名的實現(xiàn)方法

    Java獲取文件的類型和擴展名的實現(xiàn)方法

    這篇文章主要介紹了Java獲取文件的類型和擴展名的實現(xiàn)方法的相關資料,需要的朋友可以參考下
    2017-02-02
  • SpringCloud HystrixDashboard服務監(jiān)控詳解

    SpringCloud HystrixDashboard服務監(jiān)控詳解

    Hystrix Dashboard 是Spring Cloud中查看Hystrix實例執(zhí)行情況的一種儀表盤組件,支持查看單個實例和查看集群實例,本文將對其服務監(jiān)控學習
    2022-11-11
  • Java中的線程安全問題詳細解析

    Java中的線程安全問題詳細解析

    這篇文章主要介紹了Java中的線程安全問題詳細解析,線程安全是如果有多個線程在同時運行,而這些線程可能會同時運行這段代碼,程序每次運行結(jié)果和單線程運行的結(jié)果是一樣的,而且其他的變量的值也和預期的是一樣的,此時我們就稱之為是線程安全的,需要的朋友可以參考下
    2023-11-11
  • Java異常處理機制深入理解

    Java異常處理機制深入理解

    如果某個方法不能按照正常的途徑完成任務,就可以通過另一種路徑退出方法。在這種情況下會拋出一個封裝了錯誤信息的對象。此時,這個方法會立刻退出同時不返回任何值。另外,調(diào)用這個方法的其他代碼也無法繼續(xù)執(zhí)行,異常處理機制會將代碼執(zhí)行交給異常處理器
    2022-01-01
  • springboot接口如何多次獲取request中的body內(nèi)容

    springboot接口如何多次獲取request中的body內(nèi)容

    這篇文章主要介紹了springboot接口多次獲取request中的body內(nèi)容的過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06

最新評論