java 调用 request.getReader() 后重置 HttpRequest

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6322462/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:21:43  来源:igfitidea点击:

resetting a HttpRequest after calling request.getReader()

javajakarta-eehttprequest

提问by Noam Nevo

Is there a way to call the getReader()method on a HttpRequestand then "reset" the request so other calls to getReader()will not throw java.lang.IllegalStateException?

有没有办法在 a 上调​​用该getReader()方法HttpRequest然后“重置”请求,以便其他调用getReader()不会抛出java.lang.IllegalStateException

采纳答案by Stephen C

The simple answer is "No".

简单回答是不”。

The stream is not resettable and there's no API method that will allow you to reopen it. (And for good reason. It would require the servlet infrastructure to keep a copy of the input just in casethe servlet decided to reopen the stream. That would be an unwarranted overhead.)

该流不可重置,并且没有允许您重新打开它的 API 方法。(并且有充分的理由。它需要 servlet 基础结构保留输入的副本,以防万一servlet 决定重新打开流。这将是无根据的开销。)

If you want to do this kind of thing, you will need to write your code to keep its own copy of the data. If you are implementing this in a Filter (or a Tomcat Valve) then you could create a HttpServletRequestWrapperto hide the fact that you've already read the data .... as suggested by @Vineet.

如果你想做这种事情,你需要编写代码来保留自己的数据副本。如果您在过滤器(或 Tomcat Valve)中实现这一点,那么您可以创建一个HttpServletRequestWrapper来隐藏您已经读取数据的事实......正如@Vineet所建议的那样。

回答by bmeding

Like other people have said, No I don't think there is a way to reset the request.

就像其他人所说的那样,不,我认为没有办法重置请求。

I have been in the same situation of wanting to log the content of the request in a ServletFilter before moving on. Here is a forum postthat helped me figure out how to create a HttpServletRequestWrapperlike Stephen C was talking about. That will store the data so you can call getReader()and getInputStream()multiple times.

在继续之前,我一直希望在 ServletFilter 中记录请求的内容。这是一个论坛帖子,它帮助我弄清楚如何创建HttpServletRequestWrapper像 Stephen C 所说的那样。这将存储数据,以便您可以多次调用getReader()和调用getInputStream()

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class MyRequestWrapper extends HttpServletRequestWrapper {

    private HttpServletRequest original;
    private byte[] reqBytes;
    private boolean firstTime = true;

    public MyRequestWrapper(HttpServletRequest request) {
        super(request);
        original = request;
    }

    @Override
    public BufferedReader getReader() throws IOException{

        if(firstTime)
            firstTime();

        InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(reqBytes));
        return new BufferedReader(isr);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        if(firstTime)
            firstTime();

        ServletInputStream sis = new ServletInputStream() {
            private int i;

            @Override
            public int read() throws IOException {
                byte b;
                if(reqBytes.length > i)
                    b = reqBytes[i++];
                else
                    b = -1;

                return b;
            }
        };

        return sis;
    }

    private void firstTime() throws IOException{
        firstTime = false;
        StringBuffer buffer = new StringBuffer();
        BufferedReader reader = original.getReader();
        String line;
        while((line = reader.readLine()) != null){
            buffer.append(line);
        }
        reqBytes = buffer.toString().getBytes();
    }
}