解决 request中getReader()和getInputStream()只能调用一次

java 专栏收录该内容
16 篇文章 0 订阅

最近在做请求鉴权的时候拦截器中需要获取post请求参数,所以获取了多次request中的数据so 总结一下,顺便避免大家踩坑。

总结为:
1.最好继承rHttpServletRequestWrapper重写request
2.通过工具方法获取post数据,一定要传入重写的request而不是原生的
如果:
在这里插入图片描述
上图中的get请求获取参数这里不做解释,很好理解,直接获取即可。而post请求这里提供了一个方法,用来获取post请求参数以JSONObject返回,这里用到的JSONObject为fastjson包中,大家自己导入依赖即可,代码自取如下:

/**
     * 获取post请求参数以JSONObject返回
     * @param wrapper
     * @return JSONObject
     */
    private JSONObject getPostParm(BodyReaderHttpServletRequestWrapper wrapper) {

        StringBuffer jb = new StringBuffer();
        String line = null;
        try {
            BufferedReader reader = wrapper.getReader();
            while ((line = reader.readLine()) != null) {
                jb.append(line);
            }
            JSONObject jsonObject= JSONObject.parseObject(jb.toString());//转化成json对象
            return jsonObject;
        } catch (Exception e) {
            throw new RuntimeException("Error parsing JSON request string ",e);
        }
    }

这里传入的是一个BodyReaderHttpServletRequestWrapper,就是先将RequestBody保存为一个byte数组,然后通过Servlet自带的HttpServletRequestWrapper类覆盖getReader()和getInputStream()方法,使流从保存的byte数组读取。然后最重要的在Filter中将ServletRequest替换为BodyReaderHttpServletRequestWrapper,代码如下:一定要记得替换,不然还是会出现request读取二次的问题

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {


    private final byte[] body;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        BufferedReader reader = request.getReader();

        body = readBytes(request.getReader(), "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 boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {

            }

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }

    /**
     * 通过BufferedReader和字符编码集转换成byte数组
     * @param br
     * @param encoding
     * @return
     * @throws IOException
     */
    private byte[] readBytes(BufferedReader br,String encoding) throws IOException{
        String str = null,retStr="";
        while ((str = br.readLine()) != null) {
            retStr += str;
        }
        if (StringUtils.isNotBlank(retStr)) {
            return retStr.getBytes(Charset.forName(encoding));
        }
        return null;
    }

}
  • 1
    点赞
  • 5
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 5 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

迷路的外星人

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值