千家信息网

怎么解决在controller中无法二次读取的问题

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容介绍了"怎么解决在controller中无法二次读取的问题"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能
千家信息网最后更新 2026年11月03日怎么解决在controller中无法二次读取的问题

本篇内容介绍了"怎么解决在controller中无法二次读取的问题"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

目录
  • 拦截器中读取request参数,在controller中无法二次读取

    • 新建类

    • 添加过滤器

  • 使用拦截器时,controller中不能再次获取body中的参数

    • 解决办法

      • 1、获取body信息

      • 2、重新写入

      • 3、注册过滤器

拦截器中读取request参数,在controller中无法二次读取

新建类

package com.ouyeelbuy.mc.common.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;    }}

添加过滤器

package com.ouyeelbuy.mc.common.filter;import com.ouyeelbuy.mc.common.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数据流只能读取一次的问题 */@Componentpublic 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信息
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: 复制输入流
* * @param inputStream * @return
*/ 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、重新写入
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、注册过滤器
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// 注册过滤器注解@ServletComponentScanpublic class WebPlatformApplication {    public static void main(String[] args) {        SpringApplication.run(WebPlatformApplication.class);    }}

"怎么解决在controller中无法二次读取的问题"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0