• 关于自定义 HttpServletRequestWrapper 后续读不到参数的问题


    我遇到一个老代码,里面有个自定义Filter ,里面通过自定义 HttpServletRequestWrapper 实现请求数据的可复读。我看到网上有不少优秀的解决方案,例如可以搜下关键字:

    BodyReaderHttpServletRequestWrapper

    大部分搜索结果思路都是一样的:

     copy(inputstream), 转成 ByteArrayInputStream 缓存在 BodyReaderHttpServletRequestWrapper 的成员变量中。只不过方案们描述的都是基于一个前提:请求参数是 json 格式的,也就是说仅支持 application/json 的请求。如果传 form/data 就挂了。

    优化思路也很简单:加上重写 getParameterValues 方法就行了。

    package com.org.zm;
    
    import org.apache.commons.collections.MapUtils;
    import org.springframework.util.StreamUtils;
    
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.ServletRequest;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.io.*;
    import java.nio.charset.Charset;
    import java.util.Map;
    
    public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
        private final byte[] body;
        private Map parameterMap;
    
    
        @Override
        public String[] getParameterValues(String name) {
            if(MapUtils.isNotEmpty(parameterMap)) {
                return parameterMap.get(name);
            }
            return null;
        }
    
        public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
            super(request);
            parameterMap = request.getParameterMap();
            body = StreamUtils.copyToByteArray(request.getInputStream());
        }
    
        public String getBodyString(){
            return new String(body,Charset.forName("UTF-8"));
        }
    
        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream()));
        }
    
        @Override
        public ServletInputStream getInputStream() throws IOException {
    
            final ByteArrayInputStream bais = new ByteArrayInputStream(body);
    
            return new ServletInputStream() {
    
                @Override
                public int read() throws IOException {
                    return bais.read();
                }
    
                @Override
                public boolean isFinished() {
                    return false;
                }
    
                @Override
                public boolean isReady() {
                    return false;
                }
    
                @Override
                public void setReadListener(ReadListener readListener) {
    
                }
            };
        }
    }

    重要:该方案支持 json 数据的缓存 ,也支持了 formdata 的数据缓存,还有文件类型的还没支持,如果涉及到文件接口的话,还需要再扩展

  • 相关阅读:
    06 数据操纵之数据更新与删除 | OushuDB 数据库使用入门
    强强联手,NVIDIA 与 Ampere Computing 重磅推出云原生服务器平台
    ROS1余ROS2共存的一键安装(全)
    01创建型设计模式——单例模式
    JS教程之使用 ElectronJS 桌面应用程序打印贴纸/标签
    一篇打通,pytest自动化测试框架详细,从0到1精通实战(一)
    科学计算与仿真-高斯牛顿法的非线性最小二乘问题简单介绍与应用
    短视频矩阵系统源码(搭建)
    MySQL---three 多表查询与事务的操作
    Maven 指定 Java 编译版本
  • 原文地址:https://blog.csdn.net/weixin_38989369/article/details/126487136