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

如何構(gòu)建可重復(fù)讀取inputStream的request

 更新時(shí)間:2022年03月15日 11:30:43   作者:bjo2008cn  
這篇文章主要介紹了如何構(gòu)建可重復(fù)讀取inputStream的request,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

構(gòu)建可重復(fù)讀取inputStream的request

我們知道,request的inputStream只能被讀取一次,多次讀取將報(bào)錯(cuò),那么如何才能重復(fù)讀取呢?答案之一是:增加緩沖,記錄已讀取的內(nèi)容。

代碼如下所示:

import lombok.extern.log4j.Log4j2;
import org.springframework.mock.web.DelegatingServletInputStream;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
/**
?* request wrapper: 可重復(fù)讀取request.getInputStream
?*/
@Log4j2
public class RepeatedlyReadRequestWrapper extends HttpServletRequestWrapper {
? ? private static final int BUFFER_START_POSITION = 0;
? ? private static final int CHAR_BUFFER_LENGTH = 1024;
? ? /**
? ? ?* input stream 的buffer
? ? ?*/
? ? private final String body;
? ? /**
? ? ?* @param request {@link javax.servlet.http.HttpServletRequest} object.
? ? ?*/
? ? public RepeatedlyReadRequestWrapper(HttpServletRequest request) {
? ? ? ? super(request);
? ? ? ? StringBuilder stringBuilder = new StringBuilder();
? ? ? ? InputStream inputStream = null;
? ? ? ? try {
? ? ? ? ? ? inputStream = request.getInputStream();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? log.error("Error reading the request body…", e);
? ? ? ? }
? ? ? ? if (inputStream != null) {
? ? ? ? ? ? try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
? ? ? ? ? ? ? ? char[] charBuffer = new char[CHAR_BUFFER_LENGTH];
? ? ? ? ? ? ? ? int bytesRead;
? ? ? ? ? ? ? ? while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
? ? ? ? ? ? ? ? ? ? stringBuilder.append(charBuffer, BUFFER_START_POSITION, bytesRead);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? log.error("Fail to read input stream",e);
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? stringBuilder.append("");
? ? ? ? }
? ? ? ? body = stringBuilder.toString();
? ? }
? ? @Override
? ? public ServletInputStream getInputStream() throws IOException {
? ? ? ? final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
? ? ? ? return new DelegatingServletInputStream(byteArrayInputStream);
? ? }
}

接下來,需要一個(gè)對(duì)應(yīng)的Filter.

代碼如下所示:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class RepeatlyReadFilter implements Filter {
? ? @Override
? ? public void init(FilterConfig filterConfig) throws ServletException {
? ? ? ? //Do nothing
? ? }
? ? @Override
? ? public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
? ? ? ? if (request instanceof HttpServletRequest) {
? ? ? ? ? ? request = new RepeatedlyReadRequestWrapper((HttpServletRequest) request);
? ? ? ? }
? ? ? ? chain.doFilter(request, response);
? ? }
? ? @Override
? ? public void destroy() {
? ? ? ? //Do nothing
? ? }
}

最后,需要在web.xml中,增加該Filter的配置(略)。 

request中inputStream多次讀取

在使用HTTP協(xié)議實(shí)現(xiàn)應(yīng)用間接口通信時(shí),服務(wù)端讀取客戶端請(qǐng)求過來的數(shù)據(jù),會(huì)用到request.getInputStream(),第一次讀取的時(shí)候可以讀取到數(shù)據(jù),但是接下來的讀取操作都讀取不到數(shù)據(jù)。

原因

一個(gè)InputStream對(duì)象在被讀取完成后,將無法被再次讀取,始終返回-1;

InputStream并沒有實(shí)現(xiàn)reset方法(可以重置首次讀取的位置),無法實(shí)現(xiàn)重置操作;

解決方法(緩存讀取到的數(shù)據(jù))

使用request、session等來緩存讀取到的數(shù)據(jù),這種方式很容易實(shí)現(xiàn),只要setAttribute和getAttribute就行;

使用HttpServletRequestWrapper來包裝HttpServletRequest,在中初始化讀取request的InputStream數(shù)據(jù),以byte[]形式緩存在其中,然后在Filter中將request轉(zhuǎn)換為包裝過的request;

代碼

編寫rHttpServletRequestWrapper子類,用來處理請(qǐng)求數(shù)據(jù)

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Enumeration;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper
{
	private final byte[] body;
	public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException
	{
		super(request);
		Enumeration<String> e = request.getHeaderNames();
		while (e.hasMoreElements())
		{
			String name = (String) e.nextElement();
			String value = request.getHeader(name);
			log.debug("HttpServletRequest頭信息:{}-{}", name, value);
		}
		body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
	}
	@Override
	public BufferedReader getReader() throws IOException
	{
		return new BufferedReader(new InputStreamReader(getInputStream()));
	}
	@Override
	public ServletInputStream getInputStream() throws IOException
	{
		final ByteArrayInputStream bais = new ByteArrayInputStream(body);
		return new ServletInputStream(){
			@Override
			public boolean isFinished()
			{
				return false;
			}
			@Override
			public boolean isReady()
			{
				return false;
			}
			@Override
			public void setReadListener(ReadListener listener)
			{
				
			}
			@Override
			public int read() throws IOException
			{
				return bais.read();
			}
			
		};
		
	}
	@Override
	public String getHeader(String name)
	{
		return super.getHeader(name);
	}
	@Override
	public Enumeration<String> getHeaderNames()
	{
		return super.getHeaderNames();
	}
	@Override
	public Enumeration<String> getHeaders(String name)
	{
		return super.getHeaders(name);
	}
}

調(diào)用

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
	{
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;
		
		ServletRequest requestWrapper = null;
		requestWrapper = new BodyReaderHttpServletRequestWrapper(httpRequest);
		
		//數(shù)據(jù)讀取處理
		//...
		//將requestWrapper專遞給后面的過濾器
		filterChain.doFilter(requestWrapper, httpResponse);
	}

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

相關(guān)文章

  • 關(guān)于java方法區(qū)詳解

    關(guān)于java方法區(qū)詳解

    這篇文章主要介紹了關(guān)于java方法區(qū)的使用解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • jpa?EntityManager?復(fù)雜查詢實(shí)例

    jpa?EntityManager?復(fù)雜查詢實(shí)例

    這篇文章主要介紹了jpa?EntityManager?復(fù)雜查詢實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 通過web控制當(dāng)前的SpringBoot程序重新啟動(dòng)

    通過web控制當(dāng)前的SpringBoot程序重新啟動(dòng)

    本文主要給大家介紹了如何通過web控制當(dāng)前的SpringBoot程序重新啟動(dòng),文章給出了詳細(xì)的代碼示例供大家參考,對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-11-11
  • 為何HashSet中使用PRESENT而不是null作為value

    為何HashSet中使用PRESENT而不是null作為value

    這篇文章主要介紹了為何HashSet中使用PRESENT而不是null作為value,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Java OpenCV4.0.0實(shí)現(xiàn)實(shí)時(shí)人臉識(shí)別

    Java OpenCV4.0.0實(shí)現(xiàn)實(shí)時(shí)人臉識(shí)別

    這篇文章主要為大家詳細(xì)介紹了Java OpenCV4.0.0實(shí)現(xiàn)實(shí)時(shí)人臉識(shí)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • springcloud部署提示 找不到url的解決

    springcloud部署提示 找不到url的解決

    這篇文章主要介紹了springcloud部署提示 找不到url的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
    2022-01-01
  • 解決@Transaction注解導(dǎo)致動(dòng)態(tài)切換更改數(shù)據(jù)庫失效問題

    解決@Transaction注解導(dǎo)致動(dòng)態(tài)切換更改數(shù)據(jù)庫失效問題

    這篇文章主要介紹了解決@Transaction注解導(dǎo)致動(dòng)態(tài)切換更改數(shù)據(jù)庫失效問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 將Maven鏡像源更改為阿里鏡像的操作步驟

    將Maven鏡像源更改為阿里鏡像的操作步驟

    在軟件開發(fā)中,Maven是一個(gè)流行的項(xiàng)目管理工具,它允許你從Maven中央倉庫下載所需的依賴包,然而,由于地理位置或網(wǎng)絡(luò)狀況的差異,從默認(rèn)的Maven中央倉庫下載依賴包的速度可能會(huì)較慢,所
    2025-01-01
  • springboot的@Value中#和$區(qū)別詳解

    springboot的@Value中#和$區(qū)別詳解

    這篇文章主要介紹了springboot的@Value中#和$區(qū)別詳解,@Value注解的作用主要可以給屬性直接賦值、也可以讀取配置文件中的值給屬性賦值,需要的朋友可以參考下
    2023-11-11
  • Java連接MYSQL數(shù)據(jù)庫的詳細(xì)步驟

    Java連接MYSQL數(shù)據(jù)庫的詳細(xì)步驟

    這篇文章主要為大家介紹了Java連接MYSQL數(shù)據(jù)庫的詳細(xì)步驟,感興趣的小伙伴們可以參考一下
    2016-05-05

最新評(píng)論

上栗县| 晋宁县| 宝鸡市| 南木林县| 金溪县| 平泉县| 博白县| 文水县| 枣庄市| 鸡西市| 周至县| 棋牌| 胶州市| 巴里| 志丹县| 平阴县| 新化县| 句容市| 威海市| 全州县| 白银市| 靖安县| 依安县| 厦门市| 尤溪县| 托克托县| 汕尾市| 兰溪市| 深泽县| 依安县| 兰州市| 泰顺县| 神木县| 南充市| 九龙坡区| 巫溪县| 内乡县| 乐安县| 屏东市| 东港市| 赣州市|