What is `HttpServletRequestWrapper` does?

HttpServletRequestWrapperJava Servlet API 中的一个类,作为 HttpServletRequest 接口的包装器(Decorator)实现。

该类设计为装饰者模式(Decorator Pattern)的一部分,允许开发人员通过包装现有的 HttpServletRequest对象来定制或修改请求行为。比如:
过滤或修改请求参数
转换请求体数据
添加或删除请求头信息
实现请求级的安全控制,如防止 XSS(跨站脚本攻击)或 SQL 注入等安全风险
修改请求URI或其他请求属性

样例

import com.zhangziwa.practisesvr.utils.stream.StreamIUtils;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.text.StringEscapeUtils;import java.io.*;public class FilterHttpServletRequest extends HttpServletRequestWrapper {private final byte[] body;private ByteArrayInputStream byteArrayInputStream;private ServletInputStream servletInputStream;private BufferedReader bufferedReader;public FilterHttpServletRequest(HttpServletRequest request) throws Exception {super(request);body = StreamIUtils.readStream2Bytes(request.getInputStream());byteArrayInputStream = new ByteArrayInputStream(body);}public String getBody() throws UnsupportedEncodingException {String characterEncoding = this.getCharacterEncoding();return new String(body, characterEncoding);}/*** 覆盖父类方法,实现获取参数时自动对参数值进行XSS攻击过滤。** @param name 参数名* @return 如果参数存在,则返回经过HTML转义的、已过滤XSS攻击的参数值;若参数不存在,则返回null*/@Overridepublic String getParameter(String name) {String value = super.getParameter(name);if (value != null) {// 对请求参数值进行XSS过滤return StringEscapeUtils.escapeHtml4(value);}return null;}/*** 重写父类的getCharacterEncoding方法,获取请求的字符编码。* 若当前请求的字符编码未设置或为空,则默认返回"utf-8"作为字符编码。** @return 请求的字符编码,若原编码为空则返回"utf-8"*/@Overridepublic String getCharacterEncoding() {// 调用父类的getCharacterEncoding方法获取字符编码String encoding = super.getCharacterEncoding();// 如果字符编码为空,则默认为utf-8return encoding == null ? "utf-8" : encoding;}/*** 重写父类或接口中的getReader方法,提供一个BufferedReader对象。** @return 返回一个根据请求体内容和字符编码方式创建的BufferedReader对象*/@Overridepublic BufferedReader getReader() {// 如果输入流尚未初始化,则使用请求体内容创建一个新的ByteArrayInputStreamif (byteArrayInputStream == null) {byteArrayInputStream = new ByteArrayInputStream(body);}// 如果BufferedReader还未创建,则进行以下逻辑:if (bufferedReader == null) {// 获取当前请求的字符编码方式String characterEncoding = getCharacterEncoding();try {// 使用获取到的字符编码方式以及已有的ByteArrayInputStream创建一个InputStreamReader对象// 并在此基础上封装一个BufferedReader对象以提高读取效率bufferedReader = new BufferedReader(new InputStreamReader(byteArrayInputStream, characterEncoding));} catch (UnsupportedEncodingException e) {// 若遇到不支持的字符编码异常,捕获并抛出一个包含详细错误信息的RuntimeExceptionthrow new RuntimeException("Unsupported encoding: " + characterEncoding, e);}}// 返回已经创建好的BufferedReader对象return bufferedReader;}/*** 重写父类的 getInputStream 方法,提供一个自定义的 ServletInputStream 实例,* 该实例从内部的 byteArrayInputStream 中读取数据,并支持监听器模式。** @return 自定义的 ServletInputStream 实例,用于读取请求体数据*/@Overridepublic ServletInputStream getInputStream() {// 确保 servletInputStream 的初始化在多线程环境下是安全的if (servletInputStream == null) {synchronized (this) {// 创建并初始化一个 ServletInputStream 子类实例servletInputStream = new ServletInputStream() {/*** 从内部的 byteArrayInputStream 中读取下一个字节数据** @return 下一个可读字节,如果已到达流末尾则返回 -1* @throws IOException 如果发生输入/输出错误*/@Overridepublic int read() throws IOException {return byteArrayInputStream.read();}/*** 判断是否已经读取完所有数据,即 byteArrayInputStream 是否还有可用数据** @return 如果没有更多数据可供读取,则返回 true;否则返回 false*/public boolean isFinished() {return byteArrayInputStream.available() == 0;}/*** 指示此输入流是否准备好进行读取操作** @return 始终返回 true,表示此输入流始终处于就绪状态*/public boolean isReady() {return true;}/*** 设置 ReadListener 监听器,用于异步读取数据。此处未实现具体逻辑。** @param readListener 用于处理数据读取事件的 ReadListener 实例*/@Overridepublic void setReadListener(ReadListener readListener) {// 留给子类实现}};}}// 返回已初始化的 servletInputStreamreturn this.servletInputStream;}
}

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

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

相关文章

【DP】53.最大子数组和

题目 法1&#xff1a;DP class Solution {public int maxSubArray(int[] nums) {if (nums null || nums.length 0) {return 0;}int n nums.length, res nums[0];int[] dp new int[n];dp[0] nums[0];for (int i 1; i < nums.length; i) {dp[i] Math.max(nums[i], d…

Orchestrator源码解读4-计划内切换

计划内切换 Graceful master promotion 通常因为升级&#xff0c;服务器为何等原因&#xff0c;需要按照计划将主库迁移到其他实例的情况。 计划内切换的拓扑结构改变的流程如下&#xff1a; orchestrator自己选或用户自己指定一个从库实例为新主库orchestrator将其他从库ch…

【江科大STM32合集】day2按键控制LED光敏传感器控制峰鸣器

【STM32合集】day2按键控制LED&光敏传感器控制峰鸣器 电路基础c语言基础main.ckey.c结果 实现一个键开关灯实验结果避坑 电路基础 运算放大器-在江科大51单片机b站视频&#xff08;AD/DA&#xff09;复习 原理&#xff1a;两个极端 同相输入端电压 》反相输入端 电压输出最…

【leetcode题解C++】707.设计链表

你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则还需要属性 prev 以指示链表中的上一个节点…

Git_01_push失败之解决办法

从本地服务器向云端服务器提交代码的过程中&#xff0c;碰到了以下问题&#xff1a; 提示账号没有push权限 rootlocalhost:~/repo/$ git push qnx HEAD:refs/for/develop Counting objects: 29, done. Delta compression using up to 32 threads. Compressing objects: 100% …

如何利用小程序介绍公司品牌形象?

企业小程序的建设对于现代企业来说已经成为了一项必不可少的工作。随着移动互联网的快速发展&#xff0c;越来越多的职场人士和创业老板希望通过小程序来提升企业形象&#xff0c;增强与用户的互动&#xff0c;实现更好的商业效果。在这个过程中&#xff0c;使用第三方制作平台…

排序算法-冒泡排序(含C语言代码示例)

一、算法介绍 冒泡排序是一种简单的排序算法&#xff0c;其核心思想是重复地遍历待排序列表&#xff0c;比较并交换相邻元素&#xff0c;使得较大的元素逐渐“冒泡”到列表的末尾&#xff0c;而较小的元素则逐渐上浮至列表的前端。该算法的名字源于类比元素的移动过程&#xff…

Java零基础教学文档第五篇:jQuery

今日新篇章 【jQuery】 【主要内容】 jQuery简介 jQuery安装 jQuery语法 jQuery选择器 jQuery事件处理 jQueryDOM操作 jQuery元素遍历 jQuery过滤 jQuery其它方法 【学习目标】 1.jQuery简介 1.1 jQuery简介 jQuery 库可以通过一行简单的标记被添加到网页中。 1.…

vue使用el-input监听不了回车事件解决方法

无法监听回车事件 <el-input v-model"password" type"password" placeholder"密码" keyup.enter"onLogin"></el-input> 在keyup.enter后加上’.native’ <el-input v-model"password" type"password…

国内镜像:极速下载编译WebRTC源码(For Android/Linux/IOS)(二十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

C语言实现双向循环链表

1.mj版本的双向循环链表(虚拟头节点) #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define ELEMENT_NOT_FOUND -1 // 设置一个节点类 typedef struct Node {// 数据域int data;// 指针域struct Node* pre;struct Node* next; }Node; // 初…

Vue学习笔记5-- nextTick | Vue封装的过渡与动画

一、nextTick(tick-工作&#xff0c;起作用&#xff1b;下次起作用&#xff09; 语法&#xff1a; this.$nextTick(回调函数&#xff09;作用&#xff1a;在下一次DOM更新结束后执行其指定的回调。什么时候用&#xff1a;当改变数据后&#xff0c;要基于更新后的新DOM进行某些…

Linux修改文件名的三种方法分享

在Linux系统中&#xff0c;修改文件名是日常工作中常见的操作之一。无论是批量重命名文件还是修改单个文件名&#xff0c;掌握合适的方法可以提高工作效率。本文将分享三种常用的Linux修改文件名的方法&#xff0c;帮助您轻松应对文件管理任务。 方法一&#xff1a;使用mv命令 …

面试百问:Redis常见的故障以及发生场景

作为一个测试同学&#xff0c;被测系统架构中有使用到redis吗&#xff1f;对redis常见的故障有了解吗&#xff1f;又是如何进行测试的呢&#xff1f; 针对常见的redis面试问题&#xff0c;怎样才算一个高质量的回答呢&#xff0c;回答思路一般包括 问题的类型是什么&#xff…

快速入门Java NIO(Not I/O)的网络通信框架--Netty

Netty 入门 了解netty前需要对nio有一定认识,该笔记基础来自bilinbili黑马,在此基础上自己学习的笔记,添加了一些自己的理解 了解java 非阻塞io编程 1. 概述 1.1 Netty 是什么&#xff1f; Netty is an asynchronous event-driven network application framework for rapid …

编程笔记 html5cssjs 039 CSS背景示例

编程笔记 html5&css&js 039 CSS背景示例 一、html二、css小结 网页上只有三个水平并列大小相同的的DIV&#xff0c;大小为300p*200,如何使用CSS让它们整体水平和垂直都居中&#xff0c;并使用不同的背景色&#xff1f; 一、html 要在网页上实现三个水平并列且大小相同…

Intellij idea安装easy code后无法打开问题

先把C:\Program Files\JetBrains\IntelliJ IDEA 2021.1.1\plugins\platform-images移除&#xff0c;得以打开idea&#xff0c;然后卸载easy code。 我的intellij idea原本有一个EasyCodeMybatisCodeHelperPro插件&#xff0c;用得好地地&#xff0c;结果有天傻傻的安装了另一个…

Flink启动Yarn Session报错:Couldn‘t deploy Yarn session cluster

Flink版本&#xff1a;1.1.3 启动Yarn Session的语句&#xff1a;bin/yarn-session.sh -nm test -d 报错截图如下&#xff1a; 仅通过ERROR信息只能知道是yarn session集群未能正常启动&#xff0c;因此继续向下查找&#xff1a; 找到报错信息的Caused by部分&#xff1a; 报…

test-03-test case generate 测试用例生成 Randoop 介绍

拓展阅读 junit5 系列 基于 junit5 实现 junitperf 源码分析 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息) Junit performance rely on junit5 and jdk8.(java 性能测试框架。性能测试。压测。测试报告生成。) 拓展阅读 自动生成测试用例 Rand…

springboot 项目访问静态资源遇到的问题,WebMvcConfigurer和WebMvcConfigurationSupport

之前发过通过继承WebMvcConfigurationSupport来访问静态资源的文章——img标签访问静态资源&#xff0c;代码如下 Configuration public class LocalPathWebMvcConfigurer extends WebMvcConfigurationSupport {/*** 在springboot项目中&#xff0c;允许浏览器访问指定本地文件…