当前位置: 首页 > news >正文

使用HttpServletRequestWrapper解决web项目request数据流无法重复读取的问题

在做web项目开发时,我们有时候需要做一些前置的拦截判断处理,比如非法参数校验,防攻击拦截,统一日志处理等,而请求参数如果是form表单提交还好处理;对于json这种输入流的数据就会有问题,统一处理如果读取了数据流就会将流进行关闭,这就会导致接下来的业务处理无法读取数据流。为了解决这个问题,需要将request中的输入流包装为可以重复读取的数据流,具体的操作如下:
自定义一个类继承HttpServletRequestWrapper,并实现它里面的相关方法:

import cn.hutool.core.io.IoUtil;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;/*** @Author xingo* @Date 2024/1/26*/
public class RepeatableReadRequestWrapper extends HttpServletRequestWrapper {private final byte[] body;public RepeatableReadRequestWrapper(HttpServletRequest request) throws IOException {super(request);request.setCharacterEncoding("UTF-8");body = IoUtil.readBytes(request.getInputStream());}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bis = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic int read() throws IOException {return bis.read();}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}};}}

封装成这个类就是为了解决需要重复读取输入流的地方就使用这个包装类替换原有的request对象。再定义一个过滤器用于模拟统一处理请求参数,下面就简单模拟在参数中取用户名的过滤器:

import com.fasterxml.jackson.databind.JsonNode;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.util.Objects;/*** @Author xingo* @Date 2024/1/26*/
@Order(value = Ordered.LOWEST_PRECEDENCE - 1)
@Component
@WebFilter(filterName = "paramsFilter", urlPatterns = "/*")
public class CheckParamsFilter implements Filter {private ServletContext context;static final String checkKey = "userName";@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);context = filterConfig.getServletContext();}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;ServletRequest requestWrapper = null;String userName = null;String contentType = request.getContentType();if(contentType != null && contentType.contains(MediaType.APPLICATION_JSON_VALUE)) {try {// 对于需要读取输入流的先对request进行包装处理,这样后续再次需要读取数据流时就可以正常读到requestWrapper = new RepeatableReadRequestWrapper(request);JsonNode jsonNode = JacksonUtils.getObjectMapper().readTree(requestWrapper.getInputStream());if(jsonNode.get(checkKey) != null) {userName = jsonNode.get(checkKey).asText();}} catch (Exception e) {e.printStackTrace();}} else {try {if(request.getParameter(checkKey) != null) {userName = request.getParameter(checkKey);}} catch (Exception e) {e.printStackTrace();}}if(userName != null) {// 这里判断用户名检查成功就放行、否则就返回失败信息,在放行处理时需要判断是否需要传递包装requestif(this.check(userName)) {chain.doFilter(Objects.requireNonNullElse(requestWrapper, servletRequest), servletResponse);}servletResponse.setContentType("application/json; charset=utf-8");servletResponse.getWriter().print(JacksonUtils.toJSONString(ApiResult.fail(400, "信息验证失败")));return;}chain.doFilter(Objects.requireNonNullElse(requestWrapper, servletRequest), servletResponse);}@Overridepublic void destroy() {Filter.super.destroy();}private boolean check(String userName) {return "admin".equals(userName);}
}

相关文章:

使用HttpServletRequestWrapper解决web项目request数据流无法重复读取的问题

在做web项目开发时,我们有时候需要做一些前置的拦截判断处理,比如非法参数校验,防攻击拦截,统一日志处理等,而请求参数如果是form表单提交还好处理;对于json这种输入流的数据就会有问题,统一处理…...

从CNN ,LSTM 到Transformer的综述

前情提要:文本大量参照了以下的博客,本文创作的初衷是为了分享博主自己的学习和理解。对于刚开始接触NLP的同学来说,可以结合唐宇迪老师的B站视频【【NLP精华版教程】强推!不愧是的最完整的NLP教程和学习路线图从原理构成开始学&a…...

Git学习笔记:1 基础命令详解

文章目录 Git基础命令详解: Git基础命令详解: git commit 用法:git commit -m "commit message"功能:将暂存区(stage)中的所有更改提交到本地仓库的当前分支,同时提供一个简短的提交信…...

【服务器】安装宝塔面板

目录 🌺【前言】 🌼【前提】连接服务器 🌷方式一 使用工具登录服务器如Xshell 🌷方式二 阿里云直接连接 🌼 1. 安装宝塔 🌷获取安装脚本 方式一 使用下面提供的脚本安装 方式二 使用官网提供的脚本…...

开源模型应用落地-业务优化篇(一)

一、前言 通过参与“开源模型应用落地-业务整合系列篇”的学习,我们已经成功建立了基本的业务流程。然而,这只是迈出了万里长征的第一步。现在我们要对整个项目进行优化,以提高效率。我们计划利用线程池来加快处理速度,使用redis来实现排队需求,以及通过多级环境来减轻负载…...

【遥感专题系列】影像信息提取之——基于专家知识的决策树分类

可以将多源数据用于影像分类当中,这就是专家知识的决策树分类器,本专题以ENVI中Decision Tree为例来叙述这一分类器。 本专题包括以下内容: 专家知识分类器概述知识(规则)定义ENVI中Decision Tree的使用 概述 基于知…...

lqb日志08

一只小蒟蒻备考蓝桥杯的日志 文章目录 笔记坐标相遇判断工作调度问题(抽象时间轴绘制) 刷题心得小结 笔记 坐标相遇判断 我是小懒虫,碰了一下运气,开了个“恰当”的数(7000)如果,7000次还不能…...

SAP EXCEL上传如何实现指定读取某一个sheet页(ALSM_EXCEL_TO_INTERNAL_TABLE)

如何读取指定的EXCEL sheet 页签,比如要读取下图中第二个输出sheet页签 具体实现方法如下: 拷贝标准的函数ALSM_EXCEL_TO_INTERNAL_TABLE封装成一个自定义函数ZCALSM_EXCEL_TO_INTERNAL_TABLE 在自定义函数导入参数页签新增一个参数SHEET_NAME 在源代码…...

奇怪问题说 - 测试篇

文章目录 1.什么是软件测试2.软件测试和开发的区别3.软件测试的发展:4.软件测试岗位5.软件测试在不同类型公司的定位6.一个优秀的软件测试人员具备的素质6.1综合能力6.2掌握自动化测试技术6.3优秀的测试用例设计能力6.4探索性思维6.5有责任感和一定的压力 7.软件测试…...

中国新能源汽车持续跑出发展“加速度”,比亚迪迎来向上突破

2023年已经过去,对于汽车圈而言,2023年是中国车市的分水岭,在这一年,中国汽车工业70年以来首次进入全球序列,自主品牌强势霸榜,销量首次超过合资车。要知道,这是自大众于1984年进入中国市场成立…...

chatGPT辅助写硕士毕业论文

一、写作顺序 1.标题、研究问题、研究方法 2.文献综述(占比1/5-1/6) 3.论证章节 4.结论、不足、启示 5.处理图表、参考文献的格式 6.绪论或引言 7.摘要、关键词 8.查重、装订 http://【硕士毕业论文写不下去,多亏听了张博士的论文写…...

搭建nginx图片服务器

(1)将图片存储于/home/data/images目录; (2)配置nginx.conf user nginx; worker_processes 4;error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;events {worker_connections 10000; }ht…...

大数据学习之Flink算子、了解DataStream API(基础篇一)

DataStream API (基础篇) 注: 本文只涉及DataStream 原因:随着大数据和流式计算需求的增长,处理实时数据流变得越来越重要。因此,DataStream由于其处理实时数据流的特性和能力,逐渐替代了DataSe…...

js中字符串string,遍历json/Object【匹配url、邮箱、电话,版本号,千位分割,判断回文】

目录 正则 合法的URL 邮箱、电话 字符串方法 千位分割:num.slice(render, len).match(/\d{3}/g).join(,) 版本号比较 判断回文 json/Object 遍历 自身属性 for...inhasOwnProperty(key) Object.获取数组(obj):Object.keys,Object…...

字符串和C预处理器

本文参考C Primer Plus第四章学习 文章目录 常量和预处理器const限定符 1. 常量和预处理器 有时,在程序中要使用常量。例如,可以这样计算圆的周长: circumference 3.14159 * diameter; 这里,常量3.14159 代表著名的常量 pi(π)。…...

Ultraleap 3Di新建项目之给所有的Joint挂载物体

工程文件 Ultraleap 3Di给所有的Joint挂载物体 前期准备 参考上一期文章,进行正确配置 Ultraleap 3Di配置以及在 Unity 中使用 Ultraleap 3Di手部跟踪 新建项目 初始项目如下: 新建Create Empty 将新建的Create Empty,重命名为LeapPro…...

关于session每次请求都会改变的问题

这几天在部署一个前后端分离的项目,使用docker进行部署,在本地测试没有一点问题没有,前脚刚把后端部署到服务器,后脚测试就出现了问题!查看控制台报错提示跨域错误?但是对于静态资源请求,包括登…...

【leetcode题解C++】150.逆波兰表达式求值 and 239.滑动窗口最大值 and 347.前k个高频元素

150.逆波兰表达式求值 给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意: 有效的算符为 、-、* 和 / 。每个操作数(运算对象)都可以是一个整数…...

【计网·湖科大·思科】实验三 总线型以太网的特性、集线器和交换机的区别、交换机的自学习算法

🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要&…...

API设计模式:REST、GraphQL、gRPC与tRPC全面解析

一、引言 在现代Web和微服务架构中,API(应用程序编程接口)的设计和实现方式至关重要。本文将探讨四种流行的API设计模式:REST(Representational State Transfer)、GraphQL、gRPC以及新兴的tRPC。每种模式都…...

终极指南:Windows平台APK安装器如何让安卓应用无缝运行

终极指南:Windows平台APK安装器如何让安卓应用无缝运行 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 在Windows电脑上运行安卓应用曾经是一个技术难题&am…...

Agent OS:AI智能体开发的操作系统级解决方案

1. 项目概述:一个为AI智能体而生的操作系统最近在AI智能体开发圈子里,一个名为“Agent OS”的项目热度持续攀升。它来自Rivet.dev团队,定位非常清晰:一个专为构建、运行和管理AI智能体而设计的操作系统。如果你正在尝试将大语言模…...

单元体幕墙计算方法研究

单元体幕墙计算方法研究 一、单元板块计算 选择隔离的单个单元进行计算,不需要考虑周边单元的影响。 单元之间的相互影响,来自于左右立柱的变形不一致,在截面选择上反应的就是左右立柱的截面参数的不同。 所以,单元间的相互影响,可以通过控制左右立柱截面参数的相近而进…...

如何在Mac上轻松导出微信聊天记录:WeChatExporter完整指南

如何在Mac上轻松导出微信聊天记录:WeChatExporter完整指南 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾因误删重要微信聊天记录而焦虑&#xff1f…...

AICoverGen终极指南:5分钟用AI制作专业级翻唱歌曲

AICoverGen终极指南:5分钟用AI制作专业级翻唱歌曲 【免费下载链接】AICoverGen A WebUI to create song covers with any RVC v2 trained AI voice from YouTube videos or audio files. 项目地址: https://gitcode.com/gh_mirrors/ai/AICoverGen 想不想让AI…...

Seraphine:英雄联盟智能BP助手与战绩查询工具完整指南

Seraphine:英雄联盟智能BP助手与战绩查询工具完整指南 【免费下载链接】Seraphine 英雄联盟战绩查询工具 项目地址: https://gitcode.com/gh_mirrors/se/Seraphine 在英雄联盟的对局中,BP(禁选英雄)阶段往往是决定胜负的关…...

构建轻量级LLM工具集:模块化设计、多模型集成与本地化部署实践

1. 项目概述:一个面向日常的轻量级LLM工具集最近在GitHub上闲逛,发现了一个挺有意思的项目,叫“Daily-LLM”。光看名字,你可能会觉得这又是一个庞大的、需要海量算力才能跑起来的“大模型”项目。但点进去仔细研究后,我…...

5分钟免费获取:开源鼠标连点器MouseClick完整使用指南

5分钟免费获取:开源鼠标连点器MouseClick完整使用指南 【免费下载链接】MouseClick 🖱️ MouseClick 🖱️ 是一款功能强大的鼠标连点器和管理工具,采用 QT Widget 开发 ,具备跨平台兼容性 。软件界面美观 ,…...

基于Groq LPU与React技术栈构建极速AI聊天应用实战

1. 项目概述:当极速推理遇上聊天应用最近在折腾AI应用开发的朋友,估计都绕不开一个词:推理速度。模型能力再强,如果生成一句话要等上十几秒,用户体验就无从谈起。正是在这种背景下,我注意到了unclecode/gro…...

基于 Next.js 的无头电商架构实战:从 Vercel Commerce 看现代全栈开发

1. 项目概述:一个面向未来的全栈电商起点如果你最近在琢磨着用 Next.js 搞一个电商网站,或者想找一个现代、开箱即用的全栈电商模板来启动项目,那你大概率已经听说过vercel/commerce这个仓库了。它不是某个具体的电商平台,而是一个…...