post请求体内容无法重复获取

post请求体内容无法重复获取

为什么会无法重复读取呢?

以tomcat为例,在进行请求体读取时实际底层调用的是org.apache.catalina.connector.Request的getInputStream()方法,而该方法返回的是CoyoteInputStream输入流

public ServletInputStream getInputStream() throws IOException {

    if (usingReader) {
        throw new IllegalStateException(sm.getString("coyoteRequest.getInputStream.ise"));
    }

    usingInputStream = true;
    if (inputStream == null) {
        inputStream = new CoyoteInputStream(inputBuffer);
    }
    return inputStream;

}

在使用CoyoteInputStream进行读取时

public int read(byte[] b, int off, int len) throws IOException {
  // 如果流关闭,则抛出异常
    if (closed) {
        throw new IOException(sm.getString("inputBuffer.streamClosed"));
    }
// 如果已经读完了,则返回-1
    if (checkByteBufferEof()) {
        return -1;
    }
    int n = Math.min(len, bb.remaining());
    bb.get(b, off, n);
    return n;
}

而流读取完毕都会进行close,这个流close之后,close状态就置为了true,所以导致流无法进行二次读取

那么如何解决呢?将tomcat的Request类进行重新实现吗?代价太大了,sun公司当初在设计的时候就已经提供了解决方法,对于请求和响应,sun公司提供了包装类,可以HttpServletRequestWrapper类包装原始的request对象,实现了HttpServletRequest接口的所有方法,内部调用了所包装的request对象的对应方法;相应的也有HttpServletResponseWrapper类来包装原始的response对象继承HttpServletRequestWrapper来进行方法重写,可以使用HttpServletResponseWrapper和HttpServletRequestWrapper来进行定制响应和请求

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
  // 存储请求体
    private byte[] body;

    private HttpServletRequest orgRequest;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        this.orgRequest = request;
        body = HttpHelper.getBody(request);
    }

    public HttpServletRequest getOrgRequest() {
        return this.orgRequest;
    }

  // 重写读取,从存储的字节数组中读
    @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();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }
}

https://zhhll.icu/2020/javaweb/问题/6.post请求体内容无法重复获取/

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/716806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CVE-2016-5195 复现记录

文章目录 poc前置知识页表与缺页异常/proc/self/mem的写入流程madvise 漏洞点修复 Dirty COW脏牛漏洞是一个非常有名的Linux竞争条件漏洞,虽然早在2016年就已经被修复,但它依然影响着众多古老版本的Linux发行版,如果需要了解Linux的COW&#…

Redis7 实现持久化的三种方式

1、概述 1.1、Redis持久化的重要性 数据恢复:Redis是一个内存数据库,如果系统或服务宕机,内存中的数据将会丢失。Redis的持久化机制可以把数据保存到磁盘上,以便在系统重启后恢复数据。这是Redis持久化最基本也是最重要的功能。…

JCL中IEFBR14和COND

JCL中IEFBR14和COND ​ COND CODE,就是反映JCL中STEP运行状态的参数,JCL正常终了的COND CODE 是0000,另外笔者在执行某些工具JCL时候,比方说简单一个COMPARE吧,可能会出现0012、0004或者0016,0001&#xf…

JSON与Object等的相互转换

JSON与Object的转换 // 将 Object 对象转换为 String 类型 String jsonString = JSON.toJSONString(body);// 将 String 或 byte[] 转换为 JSONObject 类型 JSONObject jsonObject = JSONObject.parseObject(jsonString); // 根据键key获取 JSONObject 中的某一个键值对的值 S…

数据结构:栈和队列的实现附上源代码(C语言版)

目录 前言 1.栈 1.1 栈的概念及结构 1.2 栈的底层数据结构选择 1.2 数据结构设计代码(栈的实现) 1.3 接口函数实现代码 (1)初始化栈 (2)销毁栈 (3)压栈 (4&…

金三银四求职攻略:如何在面试中脱颖而出

随着春天的脚步渐近,对于众多程序员来说,一年中最繁忙、最重要的时期也随之而来。金三银四,即三月和四月,被广大程序员视为求职的黄金时段。在这段时间里,各大公司纷纷开放招聘,求职者们则通过一场又一场的…

初阶数据结构之---栈和队列(C语言)

引言 在顺序表和链表那篇博客中提到过,栈和队列也属于线性表 线性表: 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构。线性表在逻辑上是线性结构,也就是说是连…

xxl-job--02--可视化界面各功能详细介绍

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 可视化界面1 新增执行器2.新增任务**执行器**:**任务描述**:**路由策略**:**Cron**:cron表达式**运行模式**JobHandl…

01.18 校招 实习 内推 面经

绿*泡*泡VX: neituijunsir 交流*裙 ,内推/实习/校招汇总表格 1、校招 | 中国航天科工四院四部2024春季校园招聘 校招 | 中国航天科工四院四部2024春季校园招聘 2、阿里集团24届秋招「空缺岗位」大盘点 校招 | 阿里集团24届校招补录大盘点&#xff0…

全量知识系统问题及SmartChat给出的答复 之15 币圈生态链

Q40. 今天聊聊关于币圈和币圈生态方面,尤其是在建立和保护各种币圈生态链的问题。 主要包括各种主体、 各种权益 和 各种币及其币圈的 分类,包括 概念、关系和 链接和断链的判断根据等等, 是否有一个比较清晰的体系结构呢? 因为现…

java Springboot vue 健身房系统,简单练手项目

该项目主要分为管理员和会员模块 管理员具有:会员管理,器材管理,员工管理,健身课程管理 会员模块,可以在线报名健身课程,查看自己课程 采用VUE前端开发和springboot后端开发,极简代码编写,没…

融资项目——登录接口的开发

1. 首先创建登录与用户信息VO类。 Data ApiModel(description "登陆对象") public class LoginVO {ApiModelProperty("手机号")private String mobile;ApiModelProperty("密码")private String password;ApiModelProperty("用户类型"…

蓝桥每日一题 (差分)3月3号

//3279改变数组元素 自己做TLE&#xff1a;奈何想不出怎么用差分 #include<bits/stdc.h> using namespace std; //3279 改变数组元素&#xff08;超时&#xff09; const int N2e510; vector<int>a; int t,n; int main() {cin>>t;while(t--){cin>>n;…

ubuntu20.04安装docker及运行

ubuntu20.04安装docker及运行 ubuntu环境版本 Ubuntu Focal 20.04 (LTS) 查看系统版本 rootubuntu20043:~# cat /proc/version Linux version 5.15.0-78-generic (builddlcy02-amd64-008) (gcc (Ubuntu 11.3.0-1ubuntu1~22.04.1) 11.3.0, GNU ld (GNU Binutils for Ubuntu) …

Vue(黑马学习笔记)

Vue概述 通过我们学习的htmlcssjs已经能够开发美观的页面了&#xff0c;但是开发的效率还有待提高&#xff0c;那么如何提高呢&#xff1f;我们先来分析下页面的组成。一个完整的html页面包括了视图和数据&#xff0c;数据是通过请求从后台获取的那么意味着我们需要将后台获取…

通过XML调用CAPL脚本进行测试(新手向)

目录 0 引言 1 XML简介 2 通过XML调用CAPL脚本 0 引言 纪念一下今天这个特殊日子&#xff0c;四年出现一次的29号。 在CANoe中做自动化测试常用的编程方法有CAPL和XML两种&#xff0c;二者各有各的特色&#xff0c;对于CAPL来说新手肯定是更熟悉一些&#xff0c;因为说到在C…

使用Go Validator在Go应用中有效验证数据

作为一名开发者&#xff0c;确保Go应用中处理的数据是有效和准确的非常重要。Go Validator是一个开源的数据验证库&#xff0c;为Go结构体提供强大且易于使用的数据验证功能。本篇文章将介绍Go Validator库的主要特点以及如何在Go应用中使用它来有效验证数据。 什么是Go Valid…

Vue开发实例(五)修改项目入口页面布局

修改项目入口 一、创建新入口二、分析代码&#xff0c;修改入口三、搭建项目主页面布局1、Container 布局容器介绍2、创建布局3、布局器铺满屏幕4、创建Header页面5、加入Aside、Main和Footer模块 一、创建新入口 创建新的入口&#xff0c;取消原来的HelloWorld入口 参考代码…

剑指offer刷题记录Day2 07.数组中重复的数字 ---> 11.旋转数组的最小数字

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1、重建二叉树①代码实现&#xff08;带注释&am…

【重温设计模式】职责链模式及其Java示例

职责链模式的介绍 在开发过程中&#xff0c;我们经常会遇到这样的问题&#xff1a;一个请求需要经过多个对象的处理&#xff0c;但是我们并不知道具体由哪个对象来处理&#xff0c;或者说&#xff0c;我们希望由接收到请求的对象自己去决定如何处理或者是将请求传递给下一个对…