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

web.xml配置文件

  

<filter>  
    <filter-name>requestFilter</filter-name>  
    <filter-class>com.ulinkpay.mapi.common.web.HttpServletRequestReplacedFilter</filter-class>  
</filter>  
      
<filter-mapping>  
    <filter-name>requestFilter</filter-name>  
    <url-pattern>*.action</url-pattern>  
</filter-mapping>  

解决 request.getInputStream() 只能获取一次body的问题的更多相关文章

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

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

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

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

  3. 图片上传利用request.getInputStream()获取文件流时遇到的问题

    图片上传功能是我们web里面经常用到的,获得的方式也有很多种,这里我用的是request.getInputStream()获取文件流的方式.想要获取文件流有两种方式,附上代码 int length = ...

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

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

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

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

  6. 获取【请求体】数据的3种方式(精)(文末代码) request.getInputStream() request.getInputStream() request.getReader()

    application/x- www-form-urlencoded是Post请求默认的请求体内容类型,也是form表单默认的类型.Servlet API规范中对该类型的请求内容提供了request. ...

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

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

  8. Springboot框架中request.getInputStream()获取不到上传的文件流

    Springboot框架中用下面的代码,使用request.getInputStream()获取不到上传的文件流 @PostMapping("/upload_img") publi ...

  9. 自定义HttpReqeust,解决request请求参数只能拿一次就失效的问题

    定义一个过滤器并实现如下方法 @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResp ...

随机推荐

  1. iOS 核心动画 Core Animation浅谈

    代码地址如下:http://www.demodashi.com/demo/11603.html 前记 关于实现一个iOS动画,如果简单的,我们可以直接调用UIView的代码块来实现,虽然使用UIVie ...

  2. LoadRunner+Java接口性能测试

    想必各位小伙伴们会对LR还可以调用java感到好奇,之前我也这么一直认为LR只支持C语言.其实LR脚本支持的语言有:C.Java.Visual Basic.VbScript.JavaScript,只不 ...

  3. c#枚举的描述和值

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; usin ...

  4. Html Table用JS导出excel格式问题 导出EXCEL后单元格里的000412341234会变成412341234 7-14 会变成 2018-7-14(7月14) 自定义格式 web利用table表格生成excel格式问题 js导出excel增加表头、mso-number-format定义数据格式 数字输出格式转换 mso-number-format:"\@"

    Html Table用JS导出excel格式问题 我在网上找的JS把HTML Tabel导出成EXCEL.但是如果Table里的数字内容为0开的的导成Excel后会自动删除0,我想以text的格式写入 ...

  5. Visual Studio提示“无法启动IIS Express Web服务器”或者“无法连接Web服务器IIS Express ”的解决方法

    解决办法:找到程序根目录,删除隐藏的.vs文件夹即可. 问题原因:一般是项目拷贝或者系统设置变更所造成的.

  6. rabbitmqctl 报错

    RabbitMQ 安装成功后,cmd dos命令进入RabbitMQ的安装路径,如 E:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.10\sb ...

  7. 【CODEFORCES】 C. Captain Marmot

    C. Captain Marmot time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  8. C++ Primer Plus的若干收获--(二)

    哎,真是不想吐槽考驾照的艰辛历程了.跑到大西郊,顶着大太阳,一天就能摸上个十几分钟二十分钟的车,简直不要太坑爹,这两天真是做的我屁股疼的不行. .. 今天果断不去了.仅仅可惜我的大阿根廷啊,坚持到最后 ...

  9. VC驿站黑客编程(关机,重新启动,注销)

    此程序在VS2013下编译通过,假设换到编译器,大家能够稍作改动使用 #include<Windows.h> #include<tchar.h> #include"r ...

  10. oracle 数据查询

    1,读取从今天到1个月前之间的数据select * from tablewhere column between add_months(sysdate, -1) and sysdate;