#12解决request中getReader()和getInputStream()只能调用一次的问题

目录

1、背景

2、解决方案

2.1、自定义HttpServletRequestWrapper

2.2、JsonRequestHeaderParamsHelper

2.3、HttpServletRequestReplacedFilter

2.4、使用


1、背景

当前系统Content-Type为application/json,参数接收方式采用@RequestBody和@RequestParam,但Interceptor拦截器和Aspect切面中存在再次调用request获取其中请求参数或者请求头等操作,导致报错getReader()和getInputStream()只能调用一次(getInputStream() has already been called for this request)。

2、解决方案

2.1、自定义HttpServletRequestWrapper

由于请求信息存储在流中,只能调用一次,因此将其存储到字节数组中,保证之后调用getReader()和getInputStream()均通过body数组来获取数据。

public class BodyReaderHttpServletRequestWrapper extends
HttpServletRequestWrapper {private final byte[] body;public BodyReaderHttpServletRequestWrapper(HttpServletRequest request)throws IOException {super(request);body = JsonRequestHeaderParamsHelper.bufferReaderToString(request.getReader()).getBytes();}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() {return byteArrayInputStream.read();}};}
}

2.2、JsonRequestHeaderParamsHelper

@Slf4j
public class JsonRequestHeaderParamsHelper {public static JSONObject parseHeader(ServletRequest request) throws IOException {return JSON.parseObject(bufferReaderToString(request.getReader()));}public static String bufferReaderToString(BufferedReader reader) throws IOException {StringBuilder sb = new StringBuilder();try  {char[] buff = new char[1024];int len;while ((len = reader.read(buff)) != -1) {sb.append(buff, 0, len);}} catch (IOException e) {log.error("bufferReaderToString error", e);}return sb.toString();}
}

2.3、HttpServletRequestReplacedFilter

通过Order(0)使其最优先加载,保证所有请求都先将request替换为自定义的。

此处的init()和destroy()方法不要使用super.init(),务必清空idea自动生成的内容。

@Slf4j
@Order(value = 0)
@WebFilter(filterName = "httpServletRequestReplacedFilter", urlPatterns = "/*")
public class HttpServletRequestReplacedFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {log.info("进入HttpServletRequestReplacedFilter");ServletRequest requestWrapper = null;if(request instanceof HttpServletRequest) {requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);}if(null == requestWrapper) {chain.doFilter(request, response);} else {chain.doFilter(requestWrapper, response);}}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {}
}

2.4、使用

之后就可以愉快地使用request.getParameter,@RequestBody等等了。

附上get和post手动获取请求参数的方法:

        if("GET".equals(request.getMethod())|| "DELETE".equals(request.getMethod())) {JSONObject jsonObject = JSONObject.fromObject(request.getParameterMap());params=jsonObject.toString();log.info("get请求参数为:{}", params);}else {com.alibaba.fastjson.JSONObject jsonObject =JsonRequestHeaderParamsHelper.parseHeader(request);params=jsonObject.toJSONString();log.info("post请求参数为:{}",params);}

如果对你有帮助,点赞、收藏、关注是我更新的动力!

往期精彩:

#11vue3中使用el-dialog展示与关闭交由父组件控制的写法-CSDN博客文章浏览阅读1k次,点赞40次,收藏28次。vue3中使用elementplus的el-dialog展示与关闭交由父组件控制的写法,分两种方法,使用difineExpose或者defineEmits实现https://blog.csdn.net/weixin_42718399/article/details/136155379?spm=1001.2014.3001.5501#10外部网页跳转vue3+SpringMVC解码GBK编码的参数-CSDN博客文章浏览阅读2.2k次,点赞64次,收藏18次。外部网页跳转vue3页面解码GBK编码的参数问题(包括乱码、解码失败、无法进入页面、URI malformed等问题)https://blog.csdn.net/weixin_42718399/article/details/135995885?spm=1001.2014.3001.5501#6解析@PreAuthorize以及其中的Spel-CSDN博客文章浏览阅读1.2k次,点赞41次,收藏18次。#6解析@PreAuthorize以及其中的Spel _@preauthorizehttps://blog.csdn.net/weixin_42718399/article/details/135558235?spm=1001.2014.3001.5501#2Vite+Vue3+SpringMVC前后端分离 解决跨域问题和session每次请求不一致问题_vue3前后端分离跨域问题-CSDN博客文章浏览阅读1.1k次,点赞37次,收藏15次。Vite+Vue3+SpringMVC前后端分离通过vite/nginx解决跨域问题和session一致性问题_vue3前后端分离跨域问题https://blog.csdn.net/weixin_42718399/article/details/135388463?spm=1001.2014.3001.5501

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

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

相关文章

平时积累的FPGA知识点(10)

平时在FPGA群聊等积累的FPGA知识点,第10期: 41 ZYNQ系列芯片的PL中使用PS端送过来的时钟,这些时钟名字是自动生成的吗? 解释:是的。PS端设置的是ps_clk,用report_clocks查出来的时钟名变成了clk_fpga_0&a…

Linux篇:进程

一. 前置知识 1.1冯诺依曼体系结构 我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系 为什么计算机要采用冯诺依曼体系呢? 在计算机出现之前有很多人都提出过计算机体系结构,但最…

时序数据库TimescaleDB,实战部署全攻略

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…

C++ Primer 笔记(总结,摘要,概括)——第5章 语句

目录 5.1 简单语句 5.2 语句作用域 5.3 条件语句 5.3.1 if语句 5.3.2 switch语句 5.4 迭代语句 5.4.1 while语句 5.4.2 传统的for语句 5.4.3 范围for语句 5.4.4 do while语句 5.5 跳转语句 5.5.1 break语句 5.5.2 continue语句 5.5.3 goto语句 5.6 try语句块和异常处理 5…

2024华北医院信息网络大会第二轮更新通知

大会背景 近年来,我国医疗行业信息化取得了飞跃式的发展,医疗信息化对医疗行业有着重要的支撑作用。2021年国家卫健委、中医药管理局联合印发《公立医院高质量发展促进行动(2021-2025年)》,提出重点建设“三位一体”智…

【青龙】快速搭建青龙面板,部署属于你自己的应用!

青龙面板是一个支持 Python3、JavaScript、Shell、Typescript 的定时任务管理平台。 废话不多说,直接开始。 这里使用一台 雨云 的云服务器作为演示。雨云注册地址:https://www.rainyun.com/ 优惠码:lz932 使用优惠码注册后绑定微信可获得8折…

【Chrono Engine学习总结】4-vehicle-4.3-两个vehicle碰撞测试

由于Chrono的官方教程在一些细节方面解释的并不清楚,自己做了一些尝试,做学习总结。 今天突发奇想,想试一下,是否可以实现两个vehicle的碰撞? 1、两辆vehicle的仿真 官方提供了demo_VEH_TwoCars这个demo&#xff0c…

C++入门04 函数的参数传递、引用类型与重载

图源:文心一言 听课笔记简单整理,供小伙伴们参考,包含以下内容“🐋3.11 引用类型、🐋3.14 内联函数、🐋3.15 默认参数值、🐋3.16 函数重载、🐋3.17 C系统函数”~🥝&…

LabVIEW多通道压力传感器实时动态检测

LabVIEW多通道压力传感器实时动态检测 介绍了一种基于LabVIEW的多通道压力传感器实时动态检测系统,解决压阻式压力传感器温度补偿过程的复杂度,提高测量的准确性。通过自动轮询检测方法,结合硬件检测模型和多通道检测系统设计,本…

集合框架之List集合

目录 ​编辑 一、什么是UML 二、集合框架 三、List集合 1.特点 2.遍历方式 3.删除 4.优化 四、迭代器原理 五、泛型 六、装拆箱 七、ArrayList、LinkedList和Vector的区别 ArrayList和Vector的区别 LinkedList和Vector的区别 一、什么是UML UML(Unif…

基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法)

基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法) 写上篇文章时测试过程比较乱,写的时候有些地方有点失误,所以重新写了这篇 本文内容均在RGB-D环境下进行程序测试 本文涉及到的动态特征点剔除速度均是以https://cvg.cit.tum.de/data/datasets/rgbd-dat…

编写程序,实现shell功能——项目训练——day08

c c今天做了一个实战项目训练,编写一个程序,实现shell功能,我们称之为minishell。 主要是利用Linux中IO接口实现,实现的功能有: 1.ls ls -a ls -l cd cp mv pwd c…

软件License授权原理

软件License授权原理 你知道License是如何防止别人破解的吗?本文将介绍License的生成原理,理解了License的授权原理你不但可以防止别人破解你的License,你甚至可以研究别人的License找到它们的漏洞。喜欢本文的朋友建议收藏关注,…

【Linux】进程状态

进程状态 进程状态的简要介绍运行状态进程排队 阻塞状态挂起状态Linux中的进程状态 进程状态的简要介绍 进程状态指的是一个操作系统中正在运行的进程当前所处的状态。根据不同的操作系统,进程状态可能会有一些细微的差别,但最主要的是以下三种状态 运行…

Java——方法的使用

目录 一.方法的概念及使用 1 什么是方法(method) 2.方法定义 3 方法调用的执行过程 4 实参和形参的关系(重要) 5.没有返回值的方法 二.方法重载 1.为什么需要方法重载 2.方法重载概念 3.方法签名 三.递归 1.递归的概念 2.递归执行过程分析 3. 递归练习 一.方法的…

猫头虎分享已解决Bug || 容器编排问题:OrchestrationFailure, ContainerManagementError

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …

【Python】【VS Code】VS Code中python.json和setting.json文件配置说明

目录 1. python.json配置 2. setting.json配置 3. 解决中文乱码 4. 实现效果 1. python.json配置 python.json 获取步骤:文件 -> 首选项 -> 配置用户代码片段 -> python 此为VS Code的头文件设置,复制以下内容到 python.json {"HEADER…

个人做抖店如何能够快速起店?掌握好技巧是关键!建议收藏!

大家好,我是电商小布。 相信我们每个朋友在店铺开通后,最关心的事情就是小店成功起店了。 那么个人做抖店想要快速起店,该怎么来进行操作呢? 接下来,小布重点给大家说三点: 首先来说一下小店的主体类型…

dell r740服务器黄灯闪烁维修现场解决

1:首先看一下这款DELL非常主力的PowerEdge R740服务器长啥样,不得不说就外观来说自从IBM抛弃System X系列服务器后,也就戴尔这个外观看的比较顺眼。 图一:是DELL R740前视图(这款是8盘机型) 图二&#xff…

QT 数据库的增加操作和画图 Win

第一步、先配置CMakeLists.txt 在CMakeLists.txt中添加 find_package(Qt6 REQUIRED COMPONENTS Sql) find_package(Qt6 REQUIRED COMPONENTS Charts)target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Sql) target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Charts)避…