Spring多次request.getReader()解决方法

2023-10-29

Spring多次request.getReader()解决方法

ServletRequestgetReadergetInputStream只能调用一次

开发中遇到一个需求,对http请求进行打点,其中有个字段是请求body

本来想的是写一个拦截器拦截所有请求,读取请求中的body,然后写入MQ

        StringBuilder data = new StringBuilder();
        String line;
        BufferedReader reader;
        reader = request.getReader();
        while (null != (line = reader.readLine())) {
            data.append(line);
        }

然后报错了requesst.getReader只能调用一次,因为@RequestBody中读取过一次,拦截器中在读取一次会报错.

网上有说重写HttpServletRequestWrapper备份

多方查找发现Spring自带了一个对HttpServletRequestWrapper的重写(org.springframework.web.util.ContentCachingRequestWrapper),可以满足需求,记录一下解决方法.

下面demo

编写filter,把request设置成ContentCachingRequestWrapper

import org.springframework.web.filter.GenericFilterBean;
import org.springframework.web.util.ContentCachingRequestWrapper;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class CachingRequestBodyFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        HttpServletRequest currentRequest = (HttpServletRequest) request;
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(currentRequest);
        chain.doFilter(wrappedRequest, response);
    }
}

使filter生效

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<CachingRequestBodyFilter> filterRegistration() {
        FilterRegistrationBean<CachingRequestBodyFilter> registration = new FilterRegistrationBean<>(new CachingRequestBodyFilter());
        registration.setOrder(2);
        return registration;
    }
}

使用

    ContentCachingRequestWrapper wrapper = org.springframework.web.util.WebUtils.getNativeRequest(request,ContentCachingRequestWrapper.class);
    if(Objects.isNull(wrapper)){
        return null;
    }
    String s=new String(wrapper.getContentAsByteArray());

注意

ContentCachingRequestWrapper 只有request调用过getReadergetInputStream时才ContentAsByteArray有数据,
controller没有@RequestBody时使用ContentCachingRequestWrapper是读取不到数据的,
需要直接调用处理

        StringBuilder data = new StringBuilder();
        String line;
        BufferedReader reader;
        reader = request.getReader();
        while (null != (line = reader.readLine())) {
            data.append(line);
        }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring多次request.getReader()解决方法 的相关文章

随机推荐

  • Flink1.11内存机制之进程内存及TaskManager内存

    问题导读 1 如何配置 Flink 进程的内存 2 如何配置总内存 3 如何配置 TaskManager 内存 4 如何配置堆内存和托管内存 Apache Flink 基于 JVM 的高效处理能力 依赖于其对各组件内存用量的细致掌控 考虑到
  • C++11中的右值引用及move语义编程

    C 11中的右值引用及move语义编程 C 0x中加入了右值引用 和move函数 右值引用出现之前我们只能用const引用来关联临时对象 右值 造孽的VS可以用非const引用关联临时对象 请忽略VS 所以我们不能修临时对象的内容 右值引用
  • 迪杰斯特拉 (Dijkstra)算法求最短路径问题

    目录 算法介绍 应用实例 算法步骤 代码实现 算法介绍 迪杰斯特拉 Dijkstra 算法是典型最短路径算法 用于计算一个结点到其他结点的最短路径 它的主要特点是以起始点为中心向外层层扩展 广度优先搜索思想 直到扩展到终点为止 应用实例 算
  • 基于SpringBoot和协同过滤算法的体育商城系统的实现

    最近帮小伙伴做了个基于SpringBoot和协同过滤算法的体育商城系统 文章目录 一 SpingBoot介绍 二 协同过滤算法介绍 三 系统功能需求 四 系统功能演示 五 系统核心代码演示 一 SpingBoot介绍 现如今后台开源框架主流
  • CSS3之border-sizing属性功能get!

    今天在进行文本框样式编写的过程中遇到一个问题 当我将input元素的宽度定义为 width 100 之后 如果再增加 padding 或者 border 则文本框会溢出父容器 是向外扩张的 解决方法 加入box sizing border
  • 管道/消息队列/共享内存

    管道通信 PIPE 管道通信方式的中间介质是文件 通常称这种文件为管道文件 两个进程利用管道文件进行通信时 一个进程为写进程 另一个进程为读进程 写进程通过写端 发送端 往管道文件中写入信息 读进程通过读端 接收端 从管道文件中读取信息 两
  • json.dumps()和json.loads()、json.dump()和json.load()的区分

    1 json dumps 和json loads 是json格式处理函数 1 json dumps 函数是将一个Python数据类型列表进行json格式 字符串格式 的编码 可以这么理解 json dumps 函数是将字典转化为字符串 js
  • 生成随机色多种方法

    方法一 颜色随机 0 9 a f function getColor var str var arr 0 1 2 3 4 5 6 7 8 9 a b c d e f for var i 0 i lt 6 i str arr Math flo
  • oracle自定义存储过程:删除表(无论表是否存在)和检测表是否存在

    oracle删除表 如果表不存在 就报错 在跑大型脚本 脚本长且耗时的时候 比较麻烦 一般希望的是点开始然后脚本运行到结束 不可能一直盯着屏幕等弹出提示手工点掉 mysql就很好有drop table if not exist功能 CREA
  • 前端获取北京时间_js获取标准北京时间

    JS如何获取北京时间JS如何获取网络时间 因为本地时间可以修改 所以需要获取网络服务器的要获取服务器时间 一般是在页面提交后 在后台获龋 如果用js获取服务器时间 可以通过ajax方式 Node js中怎么获取北京时间 即构造了一个日期 获
  • dubbo-admin的编译安装

    1 美图 1 dubbo admin源码下载 Github地址 https github com apache incubator dubbo 注意 master和2 6 x分支上是没有dubbo admin模块的 源码clone到本地之后
  • HJ32 密码截取(模块化编程)(重点关注)

    描述 Catcher是MCA国的情报员 他工作时发现敌国会用一些对称的密码进行通信 比如像这些ABBA ABA A 123321 但是他们有时会在开始或结束时加入一些无关的字符以防止别国破解 比如进行下列变化 ABBA gt 12ABBA
  • tftp的配置

    首先配置tftp 配置过程如下 首先需要安装tftpd的相关软件包 sudo apt get install xinetd tftpd tftp 设置xinetd的tftp服务 具体为在 etc xinetd d 目录下创建一个tftp文件
  • Angular使用Promise解决多个异步回调问题

    Promise的基本用法 var p1 new Promise resolve reject gt setTimeout resolve 1000 done p1 then data gt console log data done ang
  • 配置文件jdk和hadoop和scala和spark

    bashrc profile java验证java version export JAVA HOME usr lib jvm java export JRE HOME JAVA HOME jre export CLASSPATH JAVA
  • rsync常见问题及解决办法(亲测)

    错误一 password file must not be other accessible continuing without password file Password rsync客户端路径是否写错 权限设置不对 需要再次输入密码
  • python数据结构与算法篇:排序

    1 冒泡排序 英语 Bubble Sort 它重复地遍历要排序的数列 一次比较两个元素 如果他们的顺序错误就把他们交换过来 遍历数列的工作是重复地进行直到没有再需要交换 也就是说该数列已经排序完成 这个算法的名字由来是因为越小的元素会经由交
  • Linux下压缩文件夹命令

    tar zcvf 打包后生成的文件名全路径 要打包的目录 例子 把 xahot文件夹打包后生成一个 home xahot tar gz的文件 tar zcvf home xahot tar gz xahot zip 压缩方法 压缩当前的文件
  • 【ISO】Windows10系统ISO镜像怎么从微软官网下载?

    要自己安装正版系统 第一步就是要下载到正确的系统镜像 下载的方法很多 可以通过搜索 网盘 网站或者论坛等下载 但那都不是最正宗 最纯粹的的 通过这些渠道下载 偶尔 难免也会遇到些心术不正的人给你夹带点私货 从微软官网下载Windows10系
  • Spring多次request.getReader()解决方法

    Spring多次request getReader 解决方法 ServletRequest的getReader和getInputStream只能调用一次 开发中遇到一个需求 对http请求进行打点 其中有个字段是请求body 本来想的是写一