Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to build a request that can read inputStream repeatedly

2025-01-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces the knowledge of "how to build a request that can read inputStream repeatedly". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Build a request that can read inputStream repeatedly

We know that the inputStream of request can only be read once, and multiple reads will report an error, so how can it be read repeatedly? One answer is to increase buffering and record what has been read.

The code is as follows:

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: repeatable read request.getInputStream * / @ Log4j2public 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);}}

Next, you need a corresponding Filter.

The code is as follows:

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}}

Finally, you need to add the configuration of the Filter in web.xml.

InputStream read multiple times in request

When using HTTP protocol to achieve inter-application interface communication, the server will use request.getInputStream () to read the data requested by the client. The data can be read when it is read for the first time, but it can not be read in the next read operation.

Reason

After an InputStream object has been read, it cannot be read again and always returns-1

InputStream does not implement the reset method (which can reset the position read for the first time) and cannot implement the reset operation

Solution (caching read data)

Use request, session, etc., to cache read data, which is easy to implement, as long as setAttribute and getAttribute

Use HttpServletRequestWrapper to wrap HttpServletRequest, initialize reading InputStream data from request, cache it in the form of byte [], and then convert request to wrapped request in Filter

Code

Write a rHttpServletRequestWrapper subclass to process the request data

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;@Slf4jpublic class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {private final byte [] body Public BodyReaderHttpServletRequestWrapper (HttpServletRequest request) throws IOException {super (request); Enumeration e = request.getHeaderNames (); while (e.hasMoreElements ()) {String name = (String) e.nextElement (); String value = request.getHeader (name) Log.debug ("HttpServletRequest header information: {}-{}", 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 getHeaderNames () {return super.getHeaderNames () @ Override public Enumeration getHeaders (String name) {return super.getHeaders (name);}}

Call

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) / / data reading processing / /. / / send the requestWrapper to the following filter filterChain.doFilter (requestWrapper, httpResponse);} "how to build a request that can read inputStream repeatedly" ends here. Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report