java.lang.IllegalStateException: невозможно (переслать | sendRedirect | создать сеанс) после того, как ответ был зафиксирован - PullRequest
88 голосов
/ 23 января 2010

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

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

Ответы [ 8 ]

230 голосов
/ 24 января 2010

Распространенным заблуждением среди начинающих является то, что они думают, что вызов 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}. См. Также нашу вики-страницу Servlets , чтобы узнать, как правильно использовать Servlets.

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


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

19 голосов
/ 23 февраля 2013

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

if(!response.isCommitted())
// Place another redirection
6 голосов
/ 23 января 2010

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

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

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

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

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

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

Удачи!

2 голосов
/ 12 августа 2016

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

2 голосов
/ 14 августа 2015

я удалил

        super.service(req, res);

Тогда у меня все заработало

2 голосов
/ 20 ноября 2014

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

1 голос
/ 19 августа 2012

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

Пример:

если переадресация,

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

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

    response.sendRedirect(roundTripURI);
    return;
0 голосов
/ 26 мая 2018

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

return null;

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

...