HttpServletRequestWrapper
是 Java Servlet API
中的一个类,作为 HttpServletRequest
接口的包装器(Decorator)实现。
该类设计为装饰者模式(Decorator Pattern
)的一部分,允许开发人员通过包装现有的 HttpServletRequest
对象来定制或修改请求行为。比如:
1、过滤或修改请求参数
2、添加或删除请求头信息
3、实现请求级的安全控制,如防止 XSS(跨站脚本攻击)或 SQL 注入等安全风险
4、转换请求体数据
5、修改请求URI或其他请求属性
样例:获取requestBody的内容
2、添加或删除请求头信息
3、实现请求级的安全控制,如防止 XSS(跨站脚本攻击)或 SQL 注入等安全风险
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 FilterHttpRequestBodyWrapper extends HttpServletRequestWrapper {
private final byte[] bodyByteArr; // 字节数组
private final ByteArrayInputStream byteArrayInputStream; // 从字节数组读取数据的输入流
private BufferedReader bufferedReader; // getReader()
private ServletInputStream servletInputStream; // getInputStream()
public FilterHttpRequestBodyWrapper(HttpServletRequest request) throws IOException {
super(request);
bodyByteArr = StreamIUtils.readStream2Bytes(request.getInputStream());
byteArrayInputStream = new ByteArrayInputStream(bodyByteArr);
}
public String getBodyByteArr() throws UnsupportedEncodingException {
return new String(bodyByteArr, getCharacterEncoding());
}
/**
* 覆盖父类方法,实现获取参数时自动对参数值进行XSS攻击过滤。
*
* @param name 参数名
* @return 如果参数存在,则返回经过HTML转义的、已过滤XSS攻击的参数值;若参数不存在,则返回null
*/
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value != null) {
// 使用StringEscapeUtils.escapeHtml4对请求参数进行XSS攻击过滤
return StringEscapeUtils.escapeHtml4(value);
}
return null;
}
/**
* 重写父类的getCharacterEncoding方法,获取请求的字符编码。
* 若当前请求的字符编码未设置或为空,则默认返回"utf-8"作为字符编码。
*
* @return 请求的字符编码,若原编码为空则返回"utf-8"
*/
@Override
public String getCharacterEncoding() {
String encoding = super.getCharacterEncoding();
return encoding == null ? "utf-8" : encoding;
}
/**
* 重写父类或接口中的getReader方法,提供一个BufferedReader对象。
*
* @return 返回一个根据请求体内容和字符编码方式创建的BufferedReader对象
*/
@Override
public BufferedReader getReader() {
if (bufferedReader == null) {
try {
// 封装一个BufferedReader对象以提高读取效率
bufferedReader = new BufferedReader(new InputStreamReader(byteArrayInputStream, getCharacterEncoding()));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Unsupported encoding: ", e);
}
}
return bufferedReader;
}
/**
* 重写父类的 getInputStream 方法,提供一个自定义的 ServletInputStream 实例,
* 该实例从内部的 byteArrayInputStream 中读取数据,并支持监听器模式。
*
* @return 自定义的 ServletInputStream 实例,用于读取请求体数据
*/
@Override
public ServletInputStream getInputStream() {
// 确保 servletInputStream 的初始化在多线程环境下是安全的
if (servletInputStream == null) {
synchronized (this) {
// 创建并初始化一个 ServletInputStream 子类实例
servletInputStream = new ServletInputStream() {
/**
* 从内部的 byteArrayInputStream 中读取下一个字节数据
*
* @return 下一个可读字节,如果已到达流末尾则返回 -1
* @throws IOException 如果发生输入/输出错误
*/
@Override
public 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 实例
*/
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
return servletInputStream;
}
}
# 使用
FilterHttpRequestBodyWrapper filterHttpRequest = new FilterHttpRequestBodyWrapper(httpRequest);
String body = filterHttpRequest.getBodyByteArr();
filterHttpRequest.setAttribute("requestBodyData", body);
# 继续执行filter链
chain.doFilter(filterHttpRequest, response);
样例:获取requestBody的内容
4、转换请求体数据文章来源:https://www.toymoban.com/news/detail-799461.html
import com.zhangziwa.practisesvr.model.Student;
import com.zhangziwa.practisesvr.utils.JsonUtils;
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;
/**
* StudentParamHttpRequestWrapper 是一个自定义的 HttpServletRequest 包装类,它继承或实现 HttpRequestWrapper 类,
* 主要用于在处理 HTTP 请求时对学生的特定参数进行封装和预处理。此类允许开发者方便地获取、验证以及修改请求中的学生相关参数,
* 提供了一种集中管理与学生信息相关的请求参数的方式。
* 它主要用于解决以下问题:
* 1. 对请求参数的统一管理和验证,例如检查学号(studentId)、姓名(name)等字段的有效性。
* 2. 在过滤器、拦截器或控制器中便捷地访问和操作学生相关信息,无需重复解析原始请求参数。
* 注意:此包装类的具体实现可能需要根据实际项目需求来调整。
*/
public class StudentParamHttpRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public StudentParamHttpRequestWrapper(HttpServletRequest request, Student vo) {
super(request);
this.body = JsonUtils.toJson(vo);
}
@Override
public String getCharacterEncoding() {
String encoding = super.getCharacterEncoding();
return encoding == null ? "utf-8" : encoding;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes(getCharacterEncoding()));
return new ServletInputStream() {
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
# 使用
StudentParamHttpRequestWrapper filterHttpRequest = new StudentParamHttpRequestWrapper(httpRequest, new Student());
chain.doFilter(filterHttpRequest, response);
[Ref] StreamIUtils 共通方法最佳实践文章来源地址https://www.toymoban.com/news/detail-799461.html
到了这里,关于What is `HttpServletRequestWrapper` does?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!