解决request.getParameter() 、 request.getInputStream()和request.getReader()只能使用一次的问题

springmvc 专栏收录该内容
4 篇文章 0 订阅
问题:在使用SpringMVC拦截器获取POST请求中的JSON信息的时候,使用request.getReader()方法获取JSON信息后,POST请求就不往下走了,
 
原因
1. 一个Reader对象在被读取完成后,将无法被再次读取,始终返回-1;
2. POST也是一种流,所以使用Reader方法后,POST请求返回true也不往下走了
 
解决方案:使用HttpServletRequestWrapper来包装HttpServletRequest,在BodyReaderHttpServletRequestWrapper中初始化读取request的Reader数据,以byte[]形式缓存在其中,然后在Filter中将request转换为包装过的request;代码如下:
public class HttpServletRequestReplacedFilter implements Filter {  
    @Override  
    public void destroy() {  
  
    }  
  
    @Override  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
  
        ServletRequest requestWrapper = null;  
        if (request instanceof HttpServletRequest) {  
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;  
            System.out.println(httpServletRequest.getContentType());
            System.out.println(httpServletRequest.getContextPath());
            System.out.println(httpServletRequest.getRemoteHost());
            System.out.println(httpServletRequest.getMethod());
            if ("POST".equals(httpServletRequest.getMethod().toUpperCase())  
                    ) {  
            	//&& httpServletRequest.getContentType().equalsIgnoreCase(  
           // "application/json")
                requestWrapper = new BodyReaderHttpServletRequestWrapper(  
                        (HttpServletRequest) request);  
            }  
        }  
  
        if (requestWrapper == null) {  
            chain.doFilter(request, response);  
        } else {  
            chain.doFilter(requestWrapper, response);   
        }  
    }  
  
    @Override  
    public void init(FilterConfig arg0) throws ServletException {  
  
    }  
  
}  
public class BodyReaderHttpServletRequestWrapper extends  
        HttpServletRequestWrapper {  
      
    private final byte[] body;  
  
    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {  
        super(request);  
        Enumeration e = request.getHeaderNames()   ;    
         while(e.hasMoreElements()){    
             String name = (String) e.nextElement();    
             String value = request.getHeader(name);    
                 
         }    
        body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));  
    }  
  
    @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 String getHeader(String name) {  
        return super.getHeader(name);  
    }  
  
    @Override  
    public Enumeration<String> getHeaderNames() {  
        return super.getHeaderNames();  
    }  
  
    @Override  
    public Enumeration<String> getHeaders(String name) {  
        return super.getHeaders(name);  
    }  
      
}
public class HttpHelper {  
    /** 
     * 获取请求Body 
     * 
     * @param request 
     * @return 
     */  
    public static String getBodyString(ServletRequest request) {  
        StringBuilder sb = new StringBuilder();  
        InputStream inputStream = null;  
        BufferedReader reader = null;  
        try {  
            inputStream = 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();  
    }  
}  
web.xml配置文件
	<filter>  
	    <filter-name>HttpServletRequestReplacedFilter</filter-name>  
	    <filter-class>com.xxx.xxx.xxx.xxx.util.HttpServletRequestReplacedFilter</filter-class>  
<!-- 	    <init-param>   -->
<!-- 	        <param-name>encoding</param-name>   -->
<!-- 	        <param-value>utf-8</param-value>   -->
<!-- 	    </init-param>   -->
	</filter>  
	<filter-mapping>  
	    <filter-name>HttpServletRequestReplacedFilter</filter-name>  
	    <url-pattern>/*</url-pattern>  
	</filter-mapping>  
<!--     <filter-mapping>   -->
<!--         <filter-name>CORS</filter-name>   -->
<!--         <url-pattern>/*</url-pattern>   -->
<!--    </filter-mapping> -->


这样运行的时候就会先走Filter再走springmvc的拦截器了,就可以多次读取了
 
  • 5
    点赞
  • 7
    评论
  • 2
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 7 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页

打赏作者

Sampson丶

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值