Java.lang.IllegalStateException: невозможно (переслать | sendRedirect | создать сеанс) после того, как ответ был получен

Этот метод выбрасывает

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);
    }

Ответы

Ответ 1

Распространенным заблуждением среди начинающих является то, что они думают, что вызов 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();
}

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

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 пропускает ресурсы. Исправьте это также. Подсказки см. также Как часто должны быть закрыты Connection, Statement и ResultSet в JDBC?

Ответ 2

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

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

Ответ 3

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

Изменить: Еще одна помощь в диагностировании проблемы...

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

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

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

  • выводить данные в выходной поток или
  • сделал еще один переадресованный запрос.

Удачи!

Ответ 4

Это потому, что ваш сервлет пытается получить доступ к объекту запроса, который больше не существует. Оператор servlet forward или include не останавливает выполнение блока метода. Он продолжается до конца блока метода или первого оператора возврата, как и любой другой 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 после каждого переадресации() или поместить каждый форвард() в if... else block

Ответ 5

Я удалил

        super.service(req, res);

Тогда это сработало хорошо для меня

Ответ 6

Bump...

У меня была такая же ошибка. Я заметил, что я вызывал 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

Ответ 7

Вам следует добавить инструкцию return во время пересылки или перенаправления потока.

Пример:

если forwardind,

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

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

    response.sendRedirect(roundTripURI);
    return;

Ответ 8

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

return null;

Это сломает текущую область.