java.lang.Исключение IllegalStateException:Невозможно (переслать | отправить перенаправление | создать сеанс) после фиксации ответа

StackOverflow https://stackoverflow.com/questions/2123514

Вопрос

Этот метод выдает

java.lang.Исключение IllegalStateException:Не удается переслать после того, как ответ был зафиксирован

и я не в состоянии определить проблему.Какая-нибудь помощь?

    int noOfRows = Integer.parseInt(request.getParameter("noOfRows"));
    String chkboxVal = "";
    // String FormatId=null;
    Vector vRow = new Vector();
    Vector vRow1 = new Vector();
    String GroupId = "";
    String GroupDesc = "";
    for (int i = 0; i < noOfRows; i++) {
        if ((request.getParameter("chk_select" + i)) == null) {
            chkboxVal = "notticked";
        } else {
            chkboxVal = request.getParameter("chk_select" + i);
            if (chkboxVal.equals("ticked")) {
                fwdurl = "true";
                Statement st1 = con.createStatement();
                GroupId = request.getParameter("GroupId" + i);
                GroupDesc = request.getParameter("GroupDesc" + i);
                ResultSet rs1 = st1
                        .executeQuery("select FileId,Description from cs2k_Files "
                                + " where FileId like 'M%' and co_code = "
                                + ccode);
                ResultSetMetaData rsm = rs1.getMetaData();
                int cCount = rsm.getColumnCount();

                while (rs1.next()) {
                    Vector vCol1 = new Vector();
                    for (int j = 1; j <= cCount; j++) {
                        vCol1.addElement(rs1.getObject(j));
                    }
                    vRow.addElement(vCol1);
                }
                rs1 = st1
                        .executeQuery("select FileId,NotAllowed from cs2kGroupSub "
                                + " where FileId like 'M%' and GroupId = '"
                                + GroupId + "'" + " and co_code = " + ccode);
                rsm = rs1.getMetaData();
                cCount = rsm.getColumnCount();

                while (rs1.next()) {
                    Vector vCol2 = new Vector();
                    for (int j = 1; j <= cCount; j++) {
                        vCol2.addElement(rs1.getObject(j));
                    }
                    vRow1.addElement(vCol2);
                }

                // throw new Exception("test");

                break;
            }
        }
    }
    if (fwdurl.equals("true")) {
        // throw new Exception("test");
        // response.sendRedirect("cs2k_GroupCopiedUpdt.jsp") ;
        request.setAttribute("GroupId", GroupId);
        request.setAttribute("GroupDesc", GroupDesc);
        request.setAttribute("vRow", vRow);
        request.setAttribute("vRow1", vRow1);
        getServletConfig().getServletContext().getRequestDispatcher(
                "/GroupCopiedUpdt.jsp").forward(request, response);
    }
Это было полезно?

Решение

Распространенное недоразумение среди начинающих заключается в том, что они думают, что вызов forward(), sendRedirect(), или sendError() волшебным образом завершился бы и "выпрыгнул" из блока метода, тем самым игнорируя остаток кода.Например:

protected void doPost() {
    if (someCondition) {
        sendRedirect();
    }
    forward(); // This is STILL invoked when someCondition is true!
}

Таким образом, на самом деле это неправда.Они, конечно, ведут себя не иначе, чем любые другие методы Java (ожидайте от System#exit() конечно).Когда в someCondition в приведенном выше примере это true и ты таким образом призываешь forward() после sendRedirect() или sendError() по одному и тому же запросу / ответу, тогда вероятность равна большой что вы получите исключение:

java.lang.Исключение IllegalStateException:Не удается переслать после того, как ответ был зафиксирован

Если в if оператор вызывает forward() и ты после этого звонишь sendRedirect() или sendError(), тогда будет сгенерировано приведенное ниже исключение:

java.lang.Исключение IllegalStateException:Не удается вызвать sendRedirect() после того, как ответ был зафиксирован

Чтобы исправить это, вам нужно либо добавить return; последующее заявление

protected void doPost() {
    if (someCondition) {
        sendRedirect();
        return;
    }
    forward();
}

...или ввести блок else.

protected void doPost() {
    if (someCondition) {
        sendRedirect();
    } else {
        forward();
    }
}

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

В случае sendError(), если ваша единственная цель - установить статус ответа, используйте setStatus() вместо этого.


Другая вероятная причина заключается в том, что сервлет записывает ответ, в то время как forward() будет вызван или был вызван тем же самым методом.

protected void doPost() {
    out.write("some string");
    // ... 
    forward(); // Fail!
}

Размер буфера ответов по умолчанию на большинстве серверов равен 2 КБ, поэтому, если вы запишете в него более 2 КБ, то он будет зафиксирован и forward() потерпит неудачу таким же образом:

java.lang.Исключение IllegalStateException:Не удается переслать после того, как ответ был зафиксирован

Решение очевидно, просто не записывайте ответ в сервлет.Это входит в обязанности JSP.Вы просто устанавливаете атрибут запроса следующим образом request.setAttribute("data", "some string") а затем распечатайте его в JSP вот так ${data}.Смотрите также вики-страница наших сервлетов чтобы узнать, как правильно использовать сервлеты.


Еще одна вероятная причина заключается в том, что forward(), sendRedirect() или sendError() методы вызываются с помощью Java-кода, встроенного в JSP-файл по старинке <% scriptlets %>, практика , которая была официально не рекомендуется с 2001 года.Например:

<!DOCTYPE html>
<html lang="en">
    <head>
        ... 
    </head>
    <body>
        ...

        <% sendRedirect(); %>

        ...
    </body>
</html>

Проблема здесь в том, что JSP внутренне немедленно записывает текст шаблона (т.е.HTML-код) через out.write("<!DOCTYPE html> ... etc ...") как только с этим столкнетесь.Таким образом, это, по сути, та же проблема, что и описанная в предыдущем разделе.

Решение очевидно, просто не записывайте Java-код в JSP-файл.За это отвечает обычный Java-класс, такой как сервлет или Фильтр.Смотрите также вики-страница наших сервлетов чтобы узнать, как правильно использовать сервлеты.


Смотрите также:


Не связанный что касается вашей конкретной проблемы, то ваш код JDBC приводит к утечке ресурсов.Исправьте и это тоже.Дополнительные подсказки см. также Как часто следует закрывать соединение, оператор и результирующий набор в JDBC?

Другие советы

даже добавление оператора return приводит к возникновению этого исключения, единственным решением для которого является этот код:

if(!response.isCommitted())
// Place another redirection

Обычно вы видите эту ошибку после того, как уже выполнили перенаправление, а затем пытаетесь вывести еще какие-то данные в выходной поток.В тех случаях, когда я видел это в прошлом, часто это один из фильтров, который пытается перенаправить страницу, а затем все равно перенаправляет ее на сервлет.Я не могу сразу заметить ничего плохого в сервлете, поэтому вы, возможно, захотите попробовать взглянуть на любые фильтры, которые у вас есть.

Редактировать:Еще немного помощи в диагностике проблемы…

Первым шагом к диагностике этой проблемы является точное определение того, где генерируется исключение.Мы предполагаем, что он выбрасывается линией

getServletConfig().getServletContext()
                  .getRequestDispatcher("/GroupCopiedUpdt.jsp")
                  .forward(request, response);

Но вы можете обнаружить, что он генерируется позже в коде, где вы пытаетесь вывести в выходной поток после того, как попытались выполнить пересылку.Если оно исходит из приведенной выше строки, то это означает, что где-то перед этой строкой у вас есть либо:

  1. выводить данные в выходной поток, или
  2. предварительно сделал еще одно перенаправление.

Удачи вам!

Это происходит потому, что ваш сервлет пытается получить доступ к объекту запроса, который больше не существует..Оператор forward или include сервлета не останавливает выполнение блока метода.Он продолжается до конца блока метода или первого оператора return точно так же, как и любой другой метод java.

Лучший способ решить эту проблему - просто динамически настроить страницу (на которую вы предполагаете переслать запрос) в соответствии с вашей логикой.Это:

protected void doPost(request , response){
String returnPage="default.jsp";
if(condition1){
 returnPage="page1.jsp";
}
if(condition2){
   returnPage="page2.jsp";
}
request.getRequestDispatcher(returnPage).forward(request,response); //at last line
}

и сделайте переадресацию только один раз в последней строке...

вы также можете исправить эту проблему, используя оператор return после каждого forward() или помещая каждый forward() в блок if ...else

Я удалил

        super.service(req, res);

Тогда у меня это прекрасно сработало

Удар...

У меня только что была такая же ошибка.Я заметил , что я вызывал super.doPost(request, response); при переопределении doPost() метод, а также явный вызов конструктора суперкласса

    public ScheduleServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

Как только я прокомментировал super.doPost(request, response); изнутри doPost() утверждение, что это сработало отлично...

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //super.doPost(request, response);
        // More code here...

}

Излишне говорить, что мне нужно перечитать дальше super() лучшие практики :p

Вы должны добавить Возврат оператор, пока вы пересылаете или перенаправляете поток.

Пример:

если в прямом направлении,

    request.getRequestDispatcher("/abs.jsp").forward(request, response);
    return;

если перенаправление,

    response.sendRedirect(roundTripURI);
    return;

После метода return forward вы можете просто сделать это:

return null;

Это нарушит текущую область видимости.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top