欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

如何解决getReader()hasalreadybeencalledforthisrequest问题,

来源: javaer 分享于  点击 36205 次 点评:201

如何解决getReader()hasalreadybeencalledforthisrequest问题,


目录
  • 解决getReader() has already been called for this request
    • 原因是
    • 重写  HttpServletRequestWrapper
    • Filter 使用
  • 总结

    解决getReader() has already been called for this request

    在 Filter 中对 request 中的 body 进行参数签名校验

    会报如下错误:

    getReader() has already been called for this request

    原因是

    request.getReader() 和 request.getInputStream() 都是只能调用一次

    并且 getReader() 方法底层也是调用 getInputStream() 来实现的.

    所以我们要使用 HttpServletRequestWrapper 来实现自定义的 CustomHttpServletRequestWrapper, 把 body 保存在 CustomHttpServletRequestWrapper 中, 并且重写 getInputStream() 方法

    重写  HttpServletRequestWrapper

    package com.fosung.pb.village.config;
     
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
     
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.nio.charset.StandardCharsets;
     
    public class MyRequestWrapper extends HttpServletRequestWrapper {
     
        private byte[] body;
        public MyRequestWrapper(HttpServletRequest request) throws IOException {
            super(request);
            if(ServletFileUpload.isMultipartContent(request)){
                return;
            }
            StringBuilder sb = new StringBuilder();
            String line;
            BufferedReader reader = request.getReader();
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            String body = sb.toString();
            this.body = body.getBytes(StandardCharsets.UTF_8);
        }
        public String getBody() {
            return new String(this.body , StandardCharsets.UTF_8) ;
        }
        @Override
        public ServletInputStream getInputStream() {
            final ByteArrayInputStream bais = new ByteArrayInputStream(body);
            return 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 bais.read();
                }
            };
        }
        @Override
        public BufferedReader getReader(){
            return new BufferedReader(new InputStreamReader(this.getInputStream()));
        }
    }

    Filter 使用

    package com.fosung.pb.village.config;
     
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
     
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
     
    /**
     * @author lanx
     * @date 2022/4/11
     */
    @Slf4j
    @Component
    @WebFilter(filterName = "AntiSqlInjectionfilter", urlPatterns = "/*")
    public class AntiSqlInjectionfilter implements Filter {
     
        public void destroy() {
            // TODO Auto-generated method stub
        }
     
        public void init(FilterConfig arg0) throws ServletException {
            // TODO Auto-generated method stub
        }
     
     
        public void doFilter(ServletRequest request, ServletResponse response,
                             FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse res = (HttpServletResponse) response;
            MyRequestWrapper myRequestWrapper = null;
            // 获取请求body
            try {
                myRequestWrapper = new MyRequestWrapper(req);
            } catch (IOException e) {
                log.error("get request body exception", e);
                throw new RuntimeException(e);
            }
     
            if ("POST".equalsIgnoreCase(req.getMethod())) {
                String param = myRequestWrapper.getBody();
                chain.doFilter(myRequestWrapper, response);
            } else {
                chain.doFilter(myRequestWrapper, response);
            }
        }
        
    }

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持3672js教程。

    您可能感兴趣的文章:
    • 解决异常处理问题:getReader() has already been called for this
    • 解决java启动时报线程占用报错:Exception in thread “Thread-14“ java.net.BindException: Address already in use: bind
    • 如何解决Mybatis--java.lang.IllegalArgumentException: Result Maps collection already contains value for X
    • SVN出现提示org.apache.subversion.javahl.ClientException: Attempted to lock an already-locked dir解决方案
    • 启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099的解决办法
    相关栏目:

    用户点评