问题
  在使用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. 移动负载均衡技术(MBL)

    移动负载均衡技术(MBL)   转至元数据结尾 附件:5 被admin添加,被admin最后更新于四月 27, 2015 转至元数据起始 互联网技术发展到今天,已经进入移动时代,很多在传统CS和BS的 ...

  2. jmeter脚本开发-BeanShell Sampler与Debug Sampler

    BeanShell支持java对象的调用,所以可直接通过BeanShell来调用java接口程序. BeanShell调用java接口例子 1.先编写两个简单的java类 创建java简单工程,并创建 ...

  3. Problem-1001:Sum Problem

    Sum Problem Sample code : #include <stdio.h> int main() { int i,n; int sum; while(scanf(" ...

  4. Scrapy:虎牙爬取,图片存储与数据分析

    第一次爬取虎牙主播数据,有点小激动 1.共批量爬取的101个主播的,包括 头像 主播名字 房间号 房间链接 2.数据规整部分,需要将json数据加载到pandas的Dataframe,只显示的前15个 ...

  5. 用Jmeter测试RabbitMQ

    1.下载AMQP插件 github上面有源码,可以通过ant+ivy在本地进行打包(下载IDEA实践成功) https://github.com/jlavallee/JMeter-Rabbit-AMQ ...

  6. android中几个很有用的的api

    0x0001 public PackageInfo getPackageArchiveInfo (String archiveFilePath, int flags) Since: API Level ...

  7. filebeat.service

    # # filebeat systemd service # [Unit] Description=Filebeat Documentation=https://www.elastic.co/guid ...

  8. ORCAD常见DRC错误

    一下就是网上整理的: https://blog.csdn.net/weixin_39671078/article/details/85344762 https://wenku.baidu.com/vi ...

  9. Closure闭包示例

    var foo = function(){ var cnt = 0; return function(){ return cnt++; }; }; var closure = foo(); conso ...

  10. flex与bison

    flex与bison 中文版 目录: 第一章:flex和bison简介 第二章:使用flex 第三章:使用bison 第四章:分析sql 第五章:flex规范参考 第六章:bison规范参考 第七章: ...