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

使用ServletInputStream在攔截器或過(guò)濾器中應(yīng)用后重寫(xiě)

 更新時(shí)間:2021年10月26日 11:08:35   作者:閆-先生  
這篇文章主要介紹了使用ServletInputStream在攔截器或過(guò)濾器中應(yīng)用后重寫(xiě),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

ServletInputStream在攔截器或過(guò)濾器應(yīng)用后重寫(xiě)

ServletInputStream inputStream = super.getInputStream();
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
    reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));
    String line = "";
    while ((line = reader.readLine()) != null) {
          sb.append(line);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (servletInputStream != null) {
       try {
           servletInputStream.close();
       } catch (IOException e) {
           e.printStackTrace();
       }
    }
    if (reader != null) {
         try {
              reader.close();
         } catch (IOException e) {
              e.printStackTrace();
         }
    }
}
//使用ServletInputStream中數(shù)據(jù)的代碼
byte[] bytes = sb.getBytes("UTF-8");
final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
return new ServletInputStream() {
       @Override
       public boolean isFinished() {
               return false;
       }
 
        @Override
        public boolean isReady() {
               return false;
        }
 
        @Override
        public void setReadListener(ReadListener readListener) {
 
        }
 
        @Override
        public int read() throws IOException {
               return bais.read();
        }
};

在攔截器種使用了request.getInputStream()或者getReader()

導(dǎo)致在controller中無(wú)法獲取請(qǐng)求參數(shù)

問(wèn)題描述

在攔截器種使用了request.getInputStream()或者getReader(),然后在controller接口種使用了@requestbody ,導(dǎo)致controller中無(wú)法獲取入?yún)ⅲ瑘?bào)錯(cuò):HttpMessageNotReadableException: Required request body is missing:

原因分析

ServletRequest中g(shù)etReader()和getInputStream()只能調(diào)用一次。而又由于@RequestBody注解獲取輸出參數(shù)的方式也是根據(jù)流的方式獲取的。所以我們前面使用流獲取后,后面的@RequestBody就獲取不到對(duì)應(yīng)的輸入流了。

為什么取不到輸入流了???因?yàn)榱鲗?duì)應(yīng)的是數(shù)據(jù),數(shù)據(jù)放在內(nèi)存中,有的是部分放在內(nèi)存中。

read 一次標(biāo)記一次當(dāng)前位置(mark position),第二次read就從標(biāo)記位置繼續(xù)讀(從內(nèi)存中copy)數(shù)據(jù)。

所以這就是為什么讀了一次第二次是空了。 怎么讓它不為空呢?只要inputstream 中的pos 變成0就可以重寫(xiě)讀取當(dāng)前內(nèi)存中的數(shù)據(jù)。

javaAPI中有一個(gè)方法public void reset() 這個(gè)方法就是可以重置pos為起始位置,但是不是所有的IO讀取流都可以調(diào)用該方法!ServletInputStream是不能調(diào)用reset方法,這就導(dǎo)致了只能調(diào)用一次getInputStream()。

如何處理

重寫(xiě)HttpServletRequestWrapper把request保存下來(lái),然后通過(guò)過(guò)濾器把保存下來(lái)的request再填充進(jìn)去,這樣就可以多次讀取request了。

第一步:定義過(guò)濾器

 
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
 
@WebFilter(urlPatterns = "/*", filterName = "channelFilter")
public class ChannelFilter implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}
 
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {
		ServletRequest requestWrapper = null;
		if (servletRequest instanceof HttpServletRequest) {
			requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
		}
		if (requestWrapper == null) {
			filterChain.doFilter(servletRequest, servletResponse);
		} else {
			System.out.println("進(jìn)入了過(guò)濾器。。。。。");
			filterChain.doFilter(requestWrapper, servletResponse);
		}
	}
 
	@Override
	public void destroy() {
	}
}

第二步:重寫(xiě)RequestWrapper類(lèi)

 
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
 
public class RequestWrapper extends HttpServletRequestWrapper { 
	private final String body; 
	public RequestWrapper(HttpServletRequest request) {
		super(request);
		StringBuilder stringBuilder = new StringBuilder();
		BufferedReader bufferedReader = null;
		InputStream inputStream = null;
		try {
			inputStream = request.getInputStream();
			if (inputStream != null) {
				bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
				char[] charBuffer = new char[128];
				int bytesRead = -1;
				while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
					stringBuilder.append(charBuffer, 0, bytesRead);
				}
			} else {
				stringBuilder.append("");
			}
		} catch (IOException ex) {
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		body = stringBuilder.toString();
	} 
	@Override
	public ServletInputStream getInputStream() throws IOException {
		final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
		ServletInputStream servletInputStream = new ServletInputStream() {
			@Override
			public boolean isFinished() {
				return false;
			}
 
			@Override
			public boolean isReady() {
				return false;
			}
 
			@Override
			public void setReadListener(ReadListener readListener) {
			}
 
			@Override
			public int read() throws IOException {
				return byteArrayInputStream.read();
			}
		};
		return servletInputStream;
	}
 
	@Override
	public BufferedReader getReader() throws IOException {
		return new BufferedReader(new InputStreamReader(this.getInputStream()));
	} 
	public String getBody() {
		return this.body;
	}
}

第三步:在啟動(dòng)類(lèi)中注冊(cè)過(guò)濾器

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

相關(guān)文章

  • spring?boot使用@Async注解解決異步多線(xiàn)程入庫(kù)的問(wèn)題

    spring?boot使用@Async注解解決異步多線(xiàn)程入庫(kù)的問(wèn)題

    最近在寫(xiě)項(xiàng)目是需要添加異步操作來(lái)提高效率,所以下面這篇文章主要給大家介紹了關(guān)于spring?boot使用@Async注解解決異步多線(xiàn)程入庫(kù)問(wèn)題的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • Java如何使用字符流讀寫(xiě)非文本文件

    Java如何使用字符流讀寫(xiě)非文本文件

    這篇文章主要介紹了Java如何使用字符流讀寫(xiě)非文本文件,以Java的字符流讀取文件為例:它只能讀取0-65535之間的字符,可以看出來(lái)字符都是正數(shù),但是二進(jìn)制的byte是可以為負(fù)數(shù)的,需要的朋友可以參考下
    2023-04-04
  • 深入講解SpringBoot Actuator是什么

    深入講解SpringBoot Actuator是什么

    Spring Boot Actuator提供了生產(chǎn)上經(jīng)常用到的功能(如健康檢查,審計(jì),指標(biāo)收集,HTTP跟蹤等),幫助我們監(jiān)控和管理Spring Boot應(yīng)用程序。這些功能都可以通過(guò)JMX或HTTP端點(diǎn)訪(fǎng)問(wèn)
    2023-01-01
  • 一文吃透Spring集成MyBatis

    一文吃透Spring集成MyBatis

    spring能集成很多的框架,是spring一個(gè)優(yōu)勢(shì)功能,通過(guò)集成功能,讓開(kāi)發(fā)人員使用其他框架更方便,本文將給大家詳細(xì)介紹Spring如何集成MyBatis,,需要的朋友可以參考下
    2023-05-05
  • JDK的命令詳解

    JDK的命令詳解

    JDK的命令詳解...
    2006-12-12
  • SpringBoot自定義starter啟動(dòng)器的實(shí)現(xiàn)思路

    SpringBoot自定義starter啟動(dòng)器的實(shí)現(xiàn)思路

    這篇文章主要介紹了SpringBoot如何自定義starter啟動(dòng)器,通過(guò)starter的自定義過(guò)程,能夠加深大家對(duì)SpringBoot自動(dòng)配置原理的理解,需要的朋友可以參考下
    2022-10-10
  • 詳解springboot中各個(gè)版本的redis配置問(wèn)題

    詳解springboot中各個(gè)版本的redis配置問(wèn)題

    這篇文章主要介紹了詳解springboot中各個(gè)版本的redis配置問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • SpringBoot使用TraceId進(jìn)行日志鏈路追蹤的實(shí)現(xiàn)步驟

    SpringBoot使用TraceId進(jìn)行日志鏈路追蹤的實(shí)現(xiàn)步驟

    有時(shí)候一個(gè)業(yè)務(wù)調(diào)用鏈場(chǎng)景,很長(zhǎng),調(diào)了各種各樣的方法,看日志的時(shí)候,各個(gè)接口的日志穿插,確實(shí)讓人頭大,所以為了解決這個(gè)問(wèn)題,本文給大家介紹了SpringBoot使用TraceId進(jìn)行日志鏈路追蹤的實(shí)現(xiàn)步驟,需要的朋友可以參考下
    2024-11-11
  • Android中比較常見(jiàn)的Java super關(guān)鍵字

    Android中比較常見(jiàn)的Java super關(guān)鍵字

    這篇文章主要為大家介紹了Android中比較常見(jiàn)的Java super關(guān)鍵字,具有一定的學(xué)習(xí)參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Java實(shí)現(xiàn)優(yōu)雅的參數(shù)校驗(yàn)方法詳解

    Java實(shí)現(xiàn)優(yōu)雅的參數(shù)校驗(yàn)方法詳解

    這篇文章主要為大家詳細(xì)介紹了Java語(yǔ)言如何實(shí)現(xiàn)優(yōu)雅的參數(shù)校驗(yàn),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定是幫助,需要的可以參考一下
    2022-06-06

最新評(píng)論

宁蒗| 鄂伦春自治旗| 伊金霍洛旗| 阿巴嘎旗| 蒙山县| 盘山县| 观塘区| 前郭尔| 阆中市| 牟定县| 淮滨县| 财经| 大兴区| 巴青县| 桦甸市| 外汇| 石林| 冀州市| 灵山县| 中牟县| 娱乐| 湟源县| 铁岭县| 鹿泉市| 镇安县| 九龙县| 太仓市| 虞城县| 惠水县| 侯马市| 河北省| 濮阳市| 井陉县| 浏阳市| 肃北| 汪清县| 阳高县| 古交市| 龙南县| 石狮市| 嵊州市|