SpringBoot拦截器执行后,Controller层不执行的问题及解决
作者:努力的雅木茶
请求拦截器中若调用getInputStream()读取流,会导致Controller层无法获取请求体,引发400错误,解决方案:避免在拦截器中读取流,或使用缓存(如将流转为字符串)确保数据可重复使用
问题描述
请求在SpringBoot拦截器中执行后,在Controller层不执行,前端错误码400
原因分析
ServletRequest 中通过流获取参数(getInputStream())只能读取一次,
而@RequestBody注解也是根据流的形式获取参数。
所以拦截器中 request 使用流获取参数后,Controller中获取不到参数
解决方案
// 拦截器中获取请求 RequestWrapper myRequestWrapper = new RequestWrapper(request); String JSONData = myRequestWrapper.getBody();
public class RequestWrapper extends HttpServletRequestWrapper { /** * 存储请求数据 */ private String body; public RequestWrapper(HttpServletRequest request) { super(request); renewBody(request); } /** * 重写getInputStream方法 * @return */ @Override public ServletInputStream getInputStream() { 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() { return byteArrayInputStream.read(); } }; return servletInputStream; } /** * 重写getReader方法 * @return */ @Override public BufferedReader getReader() { return new BufferedReader(new InputStreamReader(this.getInputStream())); } /** * 读取body的值 * @param request */ private void renewBody(HttpServletRequest request) { StringBuilder stringBuilder = new StringBuilder(); BufferedReader bufferedReader = null; try { InputStream 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); } } } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ex) { ex.printStackTrace(); } } } body = stringBuilder.toString(); } public String getBody() { return body; } }
@Component public class HttpServletFilter 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); System.out.println(((RequestWrapper) requestWrapper).getBody()); // do something } if (requestWrapper == null) { filterChain.doFilter(servletRequest, servletResponse); } else { filterChain.doFilter(requestWrapper, servletResponse); } } @Override public void destroy() { } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。