Http Servlet 请求在读取一次后丢失 POST 正文中的参数

编程入门 行业动态 更新时间:2024-10-25 07:32:54
本文介绍了Http Servlet 请求在读取一次后丢失 POST 正文中的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试访问 Java Servlet 过滤器中的两个 http 请求参数,这里没有什么新鲜事,但惊讶地发现这些参数已经被消耗了!因此,它在过滤器链中不再可用.

I'm trying to accessing two http request parameters in a Java Servlet filter, nothing new here, but was surprised to find that the parameters have already been consumed! Because of this, it is not available anymore in the filter chain.

这似乎仅在参数出现在 POST 请求正文(例如,表单提交)中时才会发生.

It seems that this only occurs when the parameters comes in a POST request body (a form submit, for example).

有没有办法读取参数而不消耗它们?

Is there a way to read the parameters and NOT consume them?

到目前为止,我只找到了这个参考:使用 request.getParameter 的 Servlet 过滤器丢失表单数据.

So far I've found only this reference: Servlet Filter using request.getParameter loses Form data.

谢谢!

推荐答案

顺便说一句,解决这个问题的另一种方法是不使用过滤器链,而是构建自己的拦截器组件,也许使用切面,它可以操作在解析的请求正文上.它也可能更有效,因为您只需将请求 InputStream 转换为您自己的模型对象一次.

As an aside, an alternative way to solve this problem is to not use the filter chain and instead build your own interceptor component, perhaps using aspects, which can operate on the parsed request body. It will also likely be more efficient as you are only converting the request InputStream into your own model object once.

但是,我仍然认为想要多次读取请求正文是合理的,特别是当请求通过过滤器链时.我通常会对某些操作使用过滤器链,这些操作希望保留在 HTTP 层,与服务组件分离.

However, I still think it's reasonable to want to read the request body more than once particularly as the request moves through the filter chain. I would typically use filter chains for certain operations that I want to keep at the HTTP layer, decoupled from the service components.

正如 Will Hartung 所建议的那样,我通过扩展 HttpServletRequestWrapper 来实现这一点,使用请求 InputStream 并基本上缓存字节.

As suggested by Will Hartung I achieved this by extending HttpServletRequestWrapper, consuming the request InputStream and essentially caching the bytes.

public class MultiReadHttpServletRequest extends HttpServletRequestWrapper { private ByteArrayOutputStream cachedBytes; public MultiReadHttpServletRequest(HttpServletRequest request) { super(request); } @Override public ServletInputStream getInputStream() throws IOException { if (cachedBytes == null) cacheInputStream(); return new CachedServletInputStream(); } @Override public BufferedReader getReader() throws IOException{ return new BufferedReader(new InputStreamReader(getInputStream())); } private void cacheInputStream() throws IOException { /* Cache the inputstream in order to read it multiple times. For * convenience, I use apachemons IOUtils */ cachedBytes = new ByteArrayOutputStream(); IOUtils.copy(super.getInputStream(), cachedBytes); } /* An inputstream which reads the cached request body */ public class CachedServletInputStream extends ServletInputStream { private ByteArrayInputStream input; public CachedServletInputStream() { /* create a new input stream from the cached request body */ input = new ByteArrayInputStream(cachedBytes.toByteArray()); } @Override public int read() throws IOException { return input.read(); } } }

现在可以通过在原始请求通过过滤器链之前包装原始请求来多次读取请求正文:

Now the request body can be read more than once by wrapping the original request before passing it through the filter chain:

public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { /* wrap the request in order to read the inputstream multiple times */ MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest((HttpServletRequest) request); /* here I read the inputstream and do my thing with it; when I pass the * wrapped request through the filter chain, the rest of the filters, and * request handlers may read the cached inputstream */ doMyThing(multiReadRequest.getInputStream()); //OR anotherUsage(multiReadRequest.getReader()); chain.doFilter(multiReadRequest, response); } }

该解决方案还允许您通过 getParameterXXX 方法多次读取请求正文,因为底层调用是 getInputStream(),它当然会读取缓存的请求 InputStream.

This solution will also allow you to read the request body multiple times via the getParameterXXX methods because the underlying call is getInputStream(), which will of course read the cached request InputStream.

编辑

对于更新版本的 ServletInputStream 接口.您需要提供更多方法的实现,例如 isReady、setReadListener 等.请参阅此 问题,如下面评论中提供的.

For newer version of ServletInputStream interface. You need to provide implementation of few more methods like isReady, setReadListener etc. Refer this question as provided in comment below.

更多推荐

Http Servlet 请求在读取一次后丢失 POST 正文中的参数

本文发布于:2023-10-09 18:41:37,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1476469.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:文中   参数   Http   Servlet   POST

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!