解决Filter中request.getInputStream()后Controller中读取不到的流的问题
程序员文章站
2022-02-16 11:56:01
...
最近一直在研究Spring MVC写App接口的框架的东西、其实的都搞得差不多咯、最后要做一个Filter、然后在Filter中主要验证一下请求有没有被篡改、校验请求是否合法、自己实现了Spring的OncePerRequestFilter来验证、由于很久没有写Java EE相关的东西了
都忘了getInputStream()只有读一次、验证之后一直提示400 Bad Request The request sent by the client was syntactically incorrect、最后又通过HandlerInterceptorAdapter去处理、发现还是这个错误、后来查了很多很多资料才回忆起来
原来流只能读一次、 读了就没有了、为了后面的代码还能够取得流、 我们应该还需要将其写出去才行、然后又是一番网上的资料查阅、最后用HttpServletRequestWrapper搞出来了、必须笔记一下、分享给更多朋友
BodyReaderHttpServletRequestWrapper.java
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { private final byte[] body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); 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 int read() throws IOException { return bais.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } }
HttpHelper.java
/** * 获取请求Body * * @param request * @return */ public static String getBodyString(ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); }
Filter.Java
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 防止流读取一次后就没有了, 所以需要将流继续写出去 ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request); String json = HttpHelper.getBodyString(requestWrapper); System.out.println(json); filterChain.doFilter(requestWrapper, response); }
最后需要注意的是在doFilter的时候、request参数一定要传我们自定义的才行、不然又会出问题的
推荐阅读
-
安装Python后IDA中找不到Python模块的问题解决
-
本来规整的csv数据通过pandas读取后变得不规整的原因以及如何解决(CSV文件中读取时数据分割问题)
-
安装Python后IDA中找不到Python模块的问题解决
-
解决使用maven将项目打包成jar包后运行在linux系统中无法读取jar包中文件的问题
-
HttpServletRequestWrapper使用:解决HttpServletRequest只能读取一次流后无法获取的问题,封装request.getInputStream()
-
解决Filter中request.getInputStream()后Controller中读取不到的流的问题