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;
Это сломает текущую область.