解决 HttpServletRequest 流数据不可重复读

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决 HttpServletRequest 流数据不可重复读相关的知识,希望对你有一定的参考价值。

参考技术A

甲方客户的生产系统,有安全风险预警和安全事件快速溯源要求,需要做一套日志管理规范。

要求我们接入的系统,要对用户登录、注册、密码修改等重要场景,严格按照提供的格式,输出相应的日志。

后续通过filebeat对接,收集我们系统上的日志信息。

简单来说,就是应用系统,处理接口请求时,统一打印相应日志。

成熟且常见的日志统一打印方案,就是使用 AOP 技术,自定义注解,在切面上使用环绕通知@Around,拦截请求,获取Controller类上方法的入参、出参即可。

奈何业务场景使用到的接口,以前的人在实现的时候,使用了如下方式:

把传参直接丢在 HttpServletRequest 中。

返回参数,又是采用 HttpServletResponse 输出。

不像平时熟练的做法,把具体入参和出参,用对象封装,直接放在方法上即可。

因为上面的做法,导致我们在拦截器中,想提前拦截请求获取传参,使用 request.getParameter() 等方法时,能拿到参数。 但是在具体接口业务流程中,再使用request.getParameter() 等方法,传入参数就获取不到了。

因为流只能被读一次

因此就抛出一个问题:Request 和 Response 怎么重复读取?

使用request.getParameter() 等方法,最终会调用getInputStream方法。

需要重写HttpServletRequestWrapper包装类,在调用getInputStream方法时,将流数据同时写到缓存。

后面想获取参数,直接读取缓存数据即可。

这样就可以实现Request的内容多次读取。

自定义类 ContentCachingRequestWrapper

自定义类 ContentCachingResponseWrapper

拦截器 LogFilter 使用上面封装的包装类,即可获取传参。

注意:启动类要加上注解@ServletComponentScan识别上面注入的Filter。

具体业务接口,原来的逻辑保持不变,仍然可以获取到入参。

以上是关于解决 HttpServletRequest 流数据不可重复读的主要内容,如果未能解决你的问题,请参考以下文章

解决HttpServletRequest的输入流只能读取一次的问题

解决HttpServletRequest的输入流只能读取一次的问题

java HttpServletRequest 重复流读取

解决HttpServletRequest的输入流只能读取一次的问题(转)

为啥 HttpServletRequest 输入流为空?

HttpServletRequest参数只能获取一次的解决方案(参数拦截器 + 拦截器的注册)