问题:在使用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. 2、GCC编译器的使用

    GCC编译器是一个非常强大和流行的C编译器,适用于各种Linux发行版.本文解释了一些流行的GCC编译器选项. GCC编译器选项 1.指定输出可执行文件名称 在最基本的形式中,gcc编译器可以用作: ...

  2. spring boot 整合 mybatis 以及原理

    同上一篇文章一样,spring boot 整合 mybatis过程中没有看见SqlSessionFactory,sqlsession(sqlsessionTemplate),就连在spring框架整合 ...

  3. list列表常用操作

    1.创建列表.只要把逗号分隔的不同的数据项使用方括号括起来即可 List = ['wade','james','bosh','haslem'] 2.使用 range() 创建数字列表 numbers ...

  4. Android-Kotlin-抽象类与多态的表现

    选择包名,然后右键: 选择Class类型,会有class:  选择File类型,不会自动有class: 目录结构: 定义描述抽象类 Person人类: package cn.kotlin.kotlin ...

  5. yum安装jdk如何配置JAVA_HOME

    安装Java环境 yum -y install java-1.8.0-openjdk.x86_64 java-1.8.0-openjdk-devel.x86_64 查看安装后的配置 java -ver ...

  6. Windows核心编程:第7章 线程调度、优先级和关联性

    Github https://github.com/gongluck/Windows-Core-Program.git //第7章 线程调度.优先级和关联性.cpp: 定义应用程序的入口点. // # ...

  7. linux shell实现批量关闭局域网中主机端口

    假设局域网中有多台主机,只能开通ssh服务(端口22),如果发现其他服务打开,则全部关闭.通过运行一个shell脚本,完成以上功能.在实际运维中,可以通过puppet等工具更快更好的完成这个功能,所以 ...

  8. PHP 调试工具Xdebug安装配置

    ## PHP 调试工具Xdebug安装配置 一.Xdebug 介绍 Xdebug是一个开源的PHP程序调试工具,可以使用它来调试.跟踪及分析程序运行状态.当然,Xdebug需要结合PHP的编辑工具来打 ...

  9. mysql创建账号及管理权限

    mysql创建账号及管理权限 0.mysql版本8.0.15,服务器版本:RHEL 6.5 1.创建用户名密码 mysql> use mysql; mysql> create user ' ...

  10. Asp.net管线事件(页面请求周期)

    在处理该请求时将由 HttpApplication 类执行以下事件. 希望扩展 HttpApplication 类的开发人员尤其需要注意这些事件. . 对请求进行验证,将检查浏览器发送的信息,并确定其 ...