getInputStream() has already been called for this request

  • 使用场景:通过request能获取到一次body中的值,有时候我们需要多次获取body中的值的需求,因此需要对流再次封装再次传递
  1. 例如:在controller中我们通过@RequestBody注解来获取前端传过来的json数据,这里已经使用了一次request来获取body中的值。等我们有需求,在完成这一个controller时,通过aop来记录一下操作记录,则可能会需要再次获取到body中的值
  2. 获取request的参数方法
  •     HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
    

a.重写自定义HttpServletRequestWrapper

public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
    public String _body;

    public MultiReadHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        StringBuffer sBuffer = new StringBuffer();
        BufferedReader bufferedReader = request.getReader();
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            sBuffer.append(line);
        }
        _body = sBuffer.toString();

    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(_body.getBytes());
        return new ServletInputStream() {
            @Override
            public int read() {
                return byteArrayInputStream.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {

            }
        };
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
}

b. 自定义过滤器Filter

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
        if(request instanceof HttpServletRequest) {
            requestWrapper = new MultiReadHttpServletRequest((HttpServletRequest) request);
        }
        //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中。
        // 在chain.doFiler方法中传递新的request对象
        if(requestWrapper == null) {
     
       chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }

    @Override
    public void destroy() {

    }
}

c.在配置文件进行配置

@Configuration
public class MyWebConfig implements WebMvcConfigurer {
    @Bean
    public FilterRegistrationBean filterRegist() {
        FilterRegistrationBean frBean = new FilterRegistrationBean();
        frBean.setFilter(new MyFilter());
        frBean.addUrlPatterns("/*");
        System.out.println("filter");
        return frBean;
    }
}

提醒一下:如果你进行文件导入时使用了MultiPartFile 这个组件来上传文件,还是会报 getInputSteam()has already exists的异常。所以你只需要将上传文件的那个请求进行过滤就可以了

  • 过滤器修改如下:
public class MyFilter implements Filter {

    private  final Set ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>(
            Arrays.asList("/writeExcelToDir")));
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
       
        if(request instanceof HttpServletRequest) {
            HttpServletRequest servletRequest = (HttpServletRequest) request;
            String requestURI = servletRequest.getRequestURI();
            if (ALLOWED_PATHS.contains(requestURI)){
                chain.doFilter(servletRequest,response);
            }else {
                requestWrapper = new MultiReadHttpServletRequest(servletRequest);
                //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中。
                // 在chain.doFiler方法中传递新的request对象
                chain.doFilter(requestWrapper, response);
            }
        }
    }

你可能感兴趣的:(getInputStream() has already been called for this request)