сброс HttpRequest после вызова request.getReader()

Есть ли способ вызвать метод getReader() для HttpRequest, а затем «сбросить» запрос, чтобы другие вызовы getReader() не вызывали java.lang.IllegalStateException?


person Noam Nevo    schedule 12.06.2011    source источник
comment
Я смущен этим вопросом. API не позволяет вызывать getInputStream и getReader по одному и тому же запросу. Вы хотите избежать этого сценария? Или вы пытаетесь получить несколько читателей для одного и того же объекта запроса?   -  person Vineet Reynolds    schedule 12.06.2011
comment
@Vineet Я пытаюсь извлечь тело запроса и зарегистрировать его, а затем передать запрос следующим обработчикам (в моем случае пружинным компонентам) и позволить им работать как обычно. Я хочу избежать сценария, который вы описали.   -  person Noam Nevo    schedule 12.06.2011
comment
Вы пытались использовать HttpServletRequestWrapper? Насколько мне известно, было бы сложно (или невозможно) сбросить маркер в объектах потока или чтения. Возможно, вы могли бы извлечь запрос, заполнить объект-оболочку и передать его вниз по течению. Это чисто теоретическая концепция; вам, возможно, придется попробовать, чтобы увидеть, работает ли это.   -  person Vineet Reynolds    schedule 12.06.2011
comment
Нет, это объект J2EE?   -  person Noam Nevo    schedule 12.06.2011
comment
Да, это часть Servlet API.   -  person Vineet Reynolds    schedule 12.06.2011


Ответы (2)


Простой ответ: «Нет».

Поток нельзя сбросить, и нет метода API, который позволил бы вам снова открыть его. (И не без оснований. Инфраструктуре сервлета потребуется сохранить копию входных данных на всякий случай, если сервлет решит повторно открыть поток. Это было бы неоправданными накладными расходами.)

Если вы хотите сделать что-то подобное, вам нужно будет написать свой код, чтобы сохранить собственную копию данных. Если вы реализуете это в фильтре (или клапане Tomcat), вы можете создать HttpServletRequestWrapper, чтобы скрыть тот факт, что вы уже прочитали данные .... как это было предложено @Vineet.

person Stephen C    schedule 12.06.2011

Как говорили другие люди, нет, я не думаю, что есть способ сбросить запрос.

Я был в той же ситуации, когда хотел записать содержимое запроса в ServletFilter, прежде чем двигаться дальше. Вот сообщение на форуме, которое помогло мне понять, как создайте HttpServletRequestWrapper, как говорил Стивен С. Это сохранит данные, чтобы вы могли вызывать 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();
    }
}
person bmeding    schedule 12.06.2011
comment
это решение вызовет проблемы с составными запросами. Не знаю почему именно, но они уже не работают. - person Salvatorelab; 02.12.2014
comment
Навскидку, я не уверен, почему составные запросы не будут работать. Если вы посмотрите ссылку на сообщение на форуме из ответа, кто-то еще обновил код, чтобы исправить проблему, связанную с загрузкой файлов. Не помешает взглянуть на то, что они изменили, чтобы увидеть, исправлены ли также составные запросы. - person bmeding; 02.12.2014
comment
прикольно, проверю! - person Salvatorelab; 03.12.2014