拦截器中读取request参数,在controller中无法二次读取
新建类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
package com.ouyeelbuy.mc测试数据mon.base; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*;
/** * @author robin.zhang * @date $ * @description 解决在request的数据流只能读取一次的问题 */ 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; } } |
添加过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package com.ouyeelbuy.mc测试数据mon.filter; import com.ouyeelbuy.mc测试数据mon.base.RequestWrapper; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException;
/** * @author robin.zhang * @date $ * @description 解决request数据流只能读取一次的问题 */ @Component public class RequestFilter 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 { filterChain.doFilter(requestWrapper, servletResponse); } }
@Override public void destroy() { } } |
然后注册这个过滤器到spring容器中,问题解决!
使用拦截器时,controller中不能再次获取body中的参数
报错信息: 从报错信息可以看出,io流已经关闭。这是由于拦截器读取了body中的参数信息,导致controller不能再次读取。
I/O error while reading input message; nested exception is java.io.IOException: Stream closed
解决办法
在拦截器读取到body信息后,再次将内容写入
1、获取body信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; import java.nio.charset.Charset;
/** * 保存流 */ public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { private final byte [] body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) { super (request); String sessionStream = getBodyString(request); body = sessionStream.getBytes(Charset.forName( "UTF-8" )); }
/** * 获取请求Body * * @param request * @return */ public String getBodyString( final ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null ; BufferedReader reader = null ; try { inputStream = cloneInputStream(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(); }
/** * Description: 复制输入流</br> * * @param inputStream * @return</br> */ public InputStream cloneInputStream(ServletInputStream inputStream) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte [] buffer = new byte [ 1024 ]; int len; try { while ((len = inputStream.read(buffer)) > - 1 ) { byteArrayOutputStream.write(buffer, 0 , len); } byteArrayOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); return byteArrayInputStream; }
@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) { } }; } } |
2、重新写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import org.springframework.core.annotation.Order; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; // 表示执行过滤顺序,值越小,越先执行 @Order ( 1 ) // 配置需要过滤的地址 @WebFilter (filterName = "bodyReaderFilter" , urlPatterns = "/*" ) public class BodyReaderFilter implements Filter {
@Override public void init(FilterConfig filterConfig) throws ServletException { // System.out.println("--------------过滤器初始化------------"); }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // System.out.println("--------------执行过滤操作------------");
// 防止流读取一次后就没有了, 所以需要将流继续写出去 HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest); filterChain.doFilter(requestWrapper, servletResponse); }
@Override public void destroy() { // System.out.println("--------------过滤器销毁------------"); } } |
3、注册过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication @EnableFeignClients @EnableDiscoveryClient // 注册过滤器注解 @ServletComponentScan public class WebPlatformApplication { public static void main(String[] args) { SpringApplication.run(WebPlatformApplication. class ); } } |
添加完成后,运行正常!
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
原文链接:https://blog.csdn.net/bai120552717/article/details/98062171
查看更多关于在拦截器中读取request参数,解决在controller中无法二次读取的问题的详细内容...