In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-09 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article focuses on "how to solve a series of problems caused by reading ServletInputStream many times". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Now let the editor take you to learn how to solve a series of problems caused by reading ServletInputStream many times.
Catalogue
Problems caused by reading ServletInputStream multiple times
Because the transmission mode between the server and app is JSON
So I wrote the following filter to let ServletInputStream read it many times.
Solution: solve it yourself
ServletInputStream repeat read problem
Directly paste the code, personal test can be used.
Problems caused by reading ServletInputStream multiple times because the transfer mode between the server and the app is JSON
The format is as follows
{head:nullbody:nulltoken:xxxxxxxxxxxxxxxxxxxxx}
So I want to write an interceptor or filter on the server to read token first to verify my identity. But if you pre-intercept, the parameter controller in springMVC will not be able to read it, causing the parameter of the @ RequestBody annotation to not work.
The reason is that ServletInputStream has been read once in the front interceptor and can no longer be read in the following ArgumentHandler, so the data cannot be obtained and the value cannot be assigned.
So I wrote the following filter to let ServletInputStream read it many times.
Write a request first.
Public class MyHttpRequest extends HttpServletRequestWrapper {private static Logger log=Logger.getLogger (MyHttpRequest.class); private byte [] bytes; / * @ param request {@ link javax.servlet.http.HttpServletRequest} object. * @ throws IOException * / public MyHttpRequest (HttpServletRequest request) throws IOException {super (request); bytes= IOUtils.toByteArray (request.getInputStream ());} @ Override public ServletInputStream getInputStream () throws IOException {final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream (bytes); return new DelegatingServletInputStream (byteArrayInputStream);} @ Override public BufferedReader getReader () throws IOException {return new BufferedReader (new InputStreamReader (getInputStream ());}
The above content is read out first, and then put into a byte [], and then you can create a new stream about Byte [] every time you get the stream.
Then write another filter.
Public class MyFilter implements Filter {@ Override public void destroy () {} @ Override public void doFilter (ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {HttpServletRequest request= (HttpServletRequest) req; MyHttpRequest myrequest=new MyHttpRequest (request); chain.doFilter (myrequest, res);} @ Override public void init (FilterConfig arg0) throws ServletException {}}
In the web.xml configuration, try the effect, very good. Can be read multiple times.
But I'll go.
Things like request.getParamter don't work again at the request of post.
The reason is that the request we rewrote is the default call to the parent class's super.getparamter method, and super.getparamter depends on super.getInputStream, but in the constructor in our rewritten request, the first sentence of the old request is injected into the super, and then the next sentence reads the stream of the old request, resulting in an empty stream when we call super.getparameter.
Solution: solve package com.hrhs.jyj.filter; import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.util.ArrayList;import java.util.Enumeration;import java.util.HashMap;import java.util.List;import java.util.Map; import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper; import org.apache.commons.io.IOUtils by yourself Import org.apache.log4j.Logger;import org.springframework.mock.web.DelegatingServletInputStream; public class MyHttpRequest extends HttpServletRequestWrapper {private static Logger log = Logger.getLogger (MyHttpRequest.class); private byte [] bytes; private String body; private Map map; private int readMap=0; private String queryString; / * @ param request * {@ link javax.servlet.http.HttpServletRequest} object. * @ throws IOException * / public MyHttpRequest (HttpServletRequest request) throws IOException {super (request); bytes = IOUtils.toByteArray (request.getInputStream ()); queryString = request.getQueryString ();} @ Override public ServletInputStream getInputStream () throws IOException {final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream (bytes); return new DelegatingServletInputStream (byteArrayInputStream);} @ Override public BufferedReader getReader () throws IOException {return new BufferedReader (new InputStreamReader (getInputStream ());} @ Override public String getParameter (String name) {log.info ("gone getParameter") Return super.getParameter (name);} @ Override public Map getParameterMap () {log.info ("gone getParameterMap"); return super.getParameterMap ();} @ Override public Enumeration getParameterNames () {log.info ("gone getParameterNames"); return super.getParameterNames ();} / / rewrite this one for the time being. Others can also modify @ Override public String [] getParameterValues (String name) {log.info ("gone getParameterValues"); try {Map nameVals = doParameter () List list = nameVals.get (name); if (listings invalid nullpercent list.size () > 0) {return list.toArray (new String [] {});} catch (UnsupportedEncodingException e) {e.printStackTrace ();} return new String [] {} } / / the map public Map doParameter () throws UnsupportedEncodingException {if (readMap==0) {/ / here combines the parameters in post with the address bar parameters, and then parses body = new String (bytes, getCharacterEncoding ()) + "&" + queryString; String [] nameVals = body.split ("&"); map = new HashMap (); for (String nameVal: nameVals) {String name = nameVal.split ("=") [0] String val = nameVal.split ("=") [1]; if (map.containsKey (name)) {List vals = map.get (name); vals.add (val); map.put (name, vals);} else {List vals = new ArrayList (); vals.add (val); map.put (name, vals);} readMap=1;} return map;}} ServletInputStream repeat read problem
Originally intended to implement tomcat's acess_log print post request parameters. To complain, the tomcat function is several blocks away from nginx. I found a way on the Internet and realized it with tomcat's filter.
However, when writing filter, I found the problem of repeated reading of ServletInputStream.
Find several methods on the Internet, none of which can be used directly. Synthesize the information on the Internet, according to their own understanding, finally can run perfectly.
Directly paste the code, personal test can be used.
The first step is to write a BufferHttpServletRequestWrapper class to copy the HttpServletRequest request.
Import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader; import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper; public class BufferHttpServletRequestWrapper extends HttpServletRequestWrapper {private final byte [] body; public BufferHttpServletRequestWrapper (HttpServletRequest request) throws IOException {super (request); InputStream is = request.getInputStream (); ByteArrayOutputStream baos = new ByteArrayOutputStream () Byte buff [] = new byte [1024]; int read; while ((read = is.read (buff)) > 0) {baos.write (buff, 0, read);} body = baos.toByteArray ();} @ 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 int read () throws IOException {return bais.read ();};}
Then the filter implementation is as follows:
Import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest; / * Servlet Filter implementation class PostDataDumperFilter * / public class PostDataDumperFilter implements Filter {private FilterConfig filterConfig = null; / * Default constructor. * / public PostDataDumperFilter () {/ / TODO Auto-generated constructor stub} / * * @ see Filter#destroy () * / public void destroy () {this.filterConfig = null;} / * * @ see Filter#doFilter (ServletRequest, ServletResponse, FilterChain) * / public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {if (filterConfig = = null) return; / / backup HttpServletRequest ServletRequest requestWrapper = null If (request instanceof HttpServletRequest) {requestWrapper = new BufferHttpServletRequestWrapper ((HttpServletRequest) request);} / / usage flow InputStream reader = requestWrapper.getInputStream (); ByteArrayOutputStream byteOutput = new ByteArrayOutputStream; int I = 0; byte [] b = new byte [100]; while ((I = reader.read (b))! =-1) {byteOutput.write (b, 0, I) } request.setAttribute ("post", new String (byteOutput.toByteArray (); / / pass the request along the filter chain if (null = = requestWrapper) {chain.doFilter (request, response);} else {chain.doFilter (requestWrapper, response);}} / * * @ see Filter#init (FilterConfig) * / public void init (FilterConfig fConfig) throws ServletException {this.filterConfig = fConfig }} at this point, I believe you have a deeper understanding of "how to solve a series of problems caused by reading ServletInputStream many times". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.