问题:在使用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. 【python-ini】python读写ini文件

    [python-ini]python读写ini文件 本文实例讲述了Python读写ini文件的方法.分享给大家供大家参考.具体如下: 比如有一个文件update.ini,里面有这些内容:   1 2 ...

  2. 22个值得收藏的Android开源代码——cool

    转自http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1020/1808.html 本文介绍了android开发者中比较热门的开源代 ...

  3. express package.json解析

    教程:http://www.tuicool.com/articles/vuiyIz

  4. 微擎开启性能优化里面的性能优化memcache内存优化及数据库读写分离

    http://www.mitusky.com/forum.php?mod=viewthread&tid=3135 [微擎 安装使用] 微擎开启性能优化里面的性能优化memcache内存优化及数 ...

  5. 有关VS报错Files的值XXX

    从网上下载了一个实例来学习,但是运行的时候报错:Files的值(后面跟一堆符号,看不懂), 环境:安装了易赛通加密软件(估计可能跟这个加密软件有关系了) 解决方案:找到程序根目录的obj/Debug/ ...

  6. [LintCode] Permutations II

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  7. sql server rdl report 如何用动态sql

    我做rdl report 一般用存储过程,可是今天遇到个问题,需要用动态sql,rdl report数据集不能绑定字段 查了一下谷歌,解决如下: declare @CarrierList table ...

  8. dialog里屏蔽ESC和回车

    重载PreTranslateMessage,在return之前加一句判断,只要是按下ESC和回车的消息,就直接置之不理即可,代码如下: if( pMsg->message == WM_KEYDO ...

  9. 类库中使用WPF 资源文件

    1.类库的 后缀.csproj文件,第一个<PropertyGroup>中加入下面代码 <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-b ...

  10. 添加vscode自定义代码块

    以vue为例 一.打开vscode>文件>首选项>用户代码片段>vue.json二.编写代码块 其中一行一句:$1是占位符,就是你可以输入的地方."http get& ...