主页 > 软件开发  > 

Whatis`HttpServletRequestWrapper`does?


HttpServletRequestWrapper 是 Java 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 IOException { 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 */ @Override public 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" */ @Override public String getCharacterEncoding() { // 调用父类的getCharacterEncoding方法获取字符编码 String encoding = super.getCharacterEncoding(); // 如果字符编码为空,则默认为utf-8 return encoding == null ? "utf-8" : encoding; } /** * 重写父类或接口中的getReader方法,提供一个BufferedReader对象。 * * @return 返回一个根据请求体内容和字符编码方式创建的BufferedReader对象 */ @Override public BufferedReader getReader() { // 如果输入流尚未初始化,则使用请求体内容创建一个新的ByteArrayInputStream if (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) { // 若遇到不支持的字符编码异常,捕获并抛出一个包含详细错误信息的RuntimeException throw new RuntimeException("Unsupported encoding: " + characterEncoding, e); } } // 返回已经创建好的BufferedReader对象 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) { // 留给子类实现 } }; } } // 返回已初始化的 servletInputStream return this.servletInputStream; } }

[Ref] StreamIUtils 共通方法最佳实践

标签:

Whatis`HttpServletRequestWrapper`does?由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Whatis`HttpServletRequestWrapper`does?