问题:在使用HTTP协议实现应用间接口通信时,服务端读取客户端请求过来的数据,会用到request.getInputStream(),第一次读取的时候可以读取到数据,但是接下来的读取操作都读取不到数据
 
原因
1. 一个InputStream对象在被读取完成后,将无法被再次读取,始终返回-1;
2. InputStream并没有实现reset方法(可以重置首次读取的位置),无法实现重置操作;
 
解决方法(缓存读取到的数据)
1.使用request、session等来缓存读取到的数据,这种方式很容易实现,只要setAttribute和getAttribute就行;
2.使用HttpServletRequestWrapper来包装HttpServletRequest,在MAPIHttpServletRequestWrapper中初始化读取request的InputStream数据,以byte[]形式缓存在其中,然后在Filter中将request转换为包装过的request;代码如下:
public class MAPIHttpServletRequestWrapper extends HttpServletRequestWrapper {

    private final byte[] body; // 报文

    public MAPIHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = StreamUtil.readBytes(request.getInputStream());
    }

    @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();
            }
        };
    }

}
/**
 * @author Perlin.Yao
 * @date 2014年8月22日
 * @version 1.0
 */
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) {
            requestWrapper = new MAPIHttpServletRequestWrapper((HttpServletRequest) request);
        }
        if(requestWrapper == null) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }

}

-----------------------------------------------------------

来源于:http://ayaoxinchao.iteye.com/blog/2110902

HttpServletRequest.getInputStream() 只能读取一次的更多相关文章

  1. Servlet的Request.getInputStream()只能读取一次问题

    Servlet的Request.getInputStream()只能读取一次问题 这个星期公司的项目接口进行改造,公司的接口有的采用了WebService的方式,有的使用的是Http协议+Servle ...

  2. request.getInputStream() 流只能读取一次问题

    问题: 一次开发过程中同事在 sptring interceptor 中获取 request body 中值,以对数据的校验和预处理等操作 .导致之后spring 在读取request body 值做 ...

  3. httpServletRequest中的流只能读取一次的原因

    首先,我们复习一下InputStream read方法的基础知识, java InputStream read方法内部有一个,postion,标志当前流读取到的位置,每读取一次,位置就会移动一次,如果 ...

  4. Request.getInputStrema只能读取一次的分析过程

    1. 我们先来看一下继承关系HttpServletRequest 接口继承ServletRequest接口 public abstract interface  ServletRequest{ pub ...

  5. 解决HttpServletRequest的输入流只能读取一次的问题

    背景 通常对安全性有要求的接口都会对请求参数做一些签名验证,而我们一般会把验签的逻辑统一放到过滤器或拦截器里,这样就不用每个接口都去重复编写验签的逻辑. 在一个项目中会有很多的接口,而不同的接口可能接 ...

  6. 拦截器中,request中getReader()和getInputStream()只能调用一次,构建可重复读取inputStream的request.

    由于 request中getReader()和getInputStream()只能调用一次 在项目中,可能会出现需要针对接口参数进行校验等问题. 因此,针对这问题,给出一下解决方案 实现方法:先将Re ...

  7. 大白话讲解如何解决HttpServletRequest的请求参数只能读取一次的问题

    大家在开发过程中,可能会遇到对请求参数做下处理的场景,比如读取上送的参数中看调用方上送的系统编号是否是白名单里面的(更多的会用request中获取IP地址判断).需要对请求方上送的参数进行大小写转换或 ...

  8. HttpServletRequest.getInputStream()多次读取问题

    转自:https://www.jianshu.com/p/85feeb30c1ed HttpServletRequest.getInputStream()多次读取问题   背景 使用POST方法发送数 ...

  9. 解决SpringMVC拦截器中Request数据只能读取一次的问题

    解决SpringMVC拦截器中Request数据只能读取一次的问题 开发项目中,经常会直接在request中取数据,如Json数据,也经常用到@RequestBody注解,也可以直接通过request ...

随机推荐

  1. request.getScheme() 使用方法

    今天在看代码时,发现程序使用了 request.getScheme() .不明白是什么意思,查了一下.结果整理如下: 1.request.getScheme() 返回当前链接使用的协议:一般应用返回h ...

  2. nutch相关目录说明

    Nutch数据包含3个目录结构,分别是: 1.Crawldb:用于存储Nutch将要检索的url信息,以及检索状态(是否检索.何时检索) 2.Linkdb:用于存储每一个url所包含的超链接信息(包括 ...

  3. spring中的两个数据库事务DataSourceTransactionManager 和 JtaTransactionManager区别

    在spring与数据框架(mybatis或hibernate)容器的配置文件中通常会有 <!-- (事务管理)transaction manager, use JtaTransactionMan ...

  4. I - Dividing Stones

    Description There are N stones, which can be divided into some piles arbitrarily. Let the value of e ...

  5. 火狐浏览器(Firefox)打开EBS form的设置方法

    http://yedward.net/?id=247 客户在使用EBS的时候,很多都是使用IE浏览器打开,但是EBS并不仅仅只是支持IE,对于谷歌浏览器(Chrome).火狐浏览器(Firefox)也 ...

  6. Android-Java控制多线程执行顺序

    功能需求: Thread-0线程:打印 1 2 3 4 5 6 Thread-1线程:打印1 1 2 3 4 5 6 先看一个为实现(功能需求的案例) package android.java; // ...

  7. nips 2016 吴恩达

    一年一度的 NIPS 又来了.今年举办地是笔者最爱的欧洲城市巴塞罗那.阳光沙滩配学术,确实很爽.这次的会议的第一天开场的大部分时间安排给了 tutorial.其中人数爆满的依旧是吴恩达(AndrewN ...

  8. kotlin面向对象-笔记

  9. 使用System.Net.Mail中的SMTP发送邮件(带附件)

    System.Net.Mail 使用简单邮件传输协议SMTP异步发送邮件 想要实现SMTP发送邮件,你需要了解这些类 SmtpClient :使用配置文件设置来初始化 SmtpClient类的新实例. ...

  10. C# 简单反射实现winform左侧树形导航,右侧切换内容

    先看看效果: 核心代码: using System; using System.Collections.Generic; using System.ComponentModel; using Syst ...