java.lang.Исключение IllegalStateException:Невозможно (переслать | отправить перенаправление | создать сеанс) после фиксации ответа
-
22-09-2019 - |
Вопрос
Этот метод выдает
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);
Но вы можете обнаружить, что он генерируется позже в коде, где вы пытаетесь вывести в выходной поток после того, как попытались выполнить пересылку.Если оно исходит из приведенной выше строки, то это означает, что где-то перед этой строкой у вас есть либо:
- выводить данные в выходной поток, или
- предварительно сделал еще одно перенаправление.
Удачи вам!
Это происходит потому, что ваш сервлет пытается получить доступ к объекту запроса, который больше не существует..Оператор 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;
Это нарушит текущую область видимости.