Ta metoda rzuca
java.lang.IllegalStateException: nie można przekazać dalej po zatwierdzeniu odpowiedzi
i nie jestem w stanie dostrzec problemu. Jakaś pomoc?
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);
}
servlets
response
illegalstateexception
forward
requestdispatcher
sansknwoledge
źródło
źródło
Odpowiedzi:
Powszechnym nieporozumieniem wśród początkujących jest to, że myślą, że wywołanie a
forward()
,sendRedirect()
lub wsendError()
magiczny sposób zakończyło się i „wyskoczyło” z bloku metody, ignorując tym samym pozostałość kodu. Na przykład:Tak więc w rzeczywistości nie jest to prawdą. Z pewnością nie zachowują się inaczej niż jakiekolwiek inne metody Java (spodziewaj się
System#exit()
oczywiście). KiedysomeCondition
w powyższym przykładzie jesttrue
i dzwoniszforward()
po tym samym żądaniu / odpowiedzisendRedirect()
lubsendError()
z tą samą odpowiedzią, istnieje duża szansa , że otrzymasz wyjątek:Jeśli
if
instrukcja wywołuje a,forward()
a następnie wywołujeszsendRedirect()
lubsendError()
, zostanie zgłoszony poniższy wyjątek:Aby to naprawić, musisz
return;
później dodać oświadczenie... lub wprowadzić inny blok.
Aby usunąć główną przyczynę w kodzie, po prostu wyszukaj dowolną linię, która wywołuje a
forward()
,sendRedirect()
lubsendError()
bez wychodzenia z bloku metody lub pomijania pozostałej części kodu. Może to znajdować się w tym samym serwlecie przed określoną linią kodu, ale także w dowolnym aplecie lub filtrze, który został wywołany przed określonym serwletem.W przypadku
sendError()
, jeśli jedynym celem jest ustawienie statusu odpowiedzi, użyjsetStatus()
zamiast tego.Inną prawdopodobną przyczyną jest to, że serwlet zapisuje w odpowiedzi, podczas gdy
forward()
zostanie wywołane a, lub zostało wywołane tą samą metodą.W większości serwerów rozmiar bufora odpowiedzi domyślnie wynosi 2 KB, więc jeśli napiszesz do niego więcej niż 2 KB, zostanie on
forward()
zatwierdzony i zakończy się niepowodzeniem w ten sam sposób:Rozwiązanie jest oczywiste, po prostu nie pisz odpowiedzi w serwlecie. Za to odpowiada strona JSP. Po prostu ustawiasz atrybut żądania w ten sposób,
request.setAttribute("data", "some string")
a następnie drukujesz go w JSP w ten sposób${data}
. Zobacz również naszą stronę wiki serwletów, aby dowiedzieć się, jak używać serwletów we właściwy sposób.Inną prawdopodobną przyczyną jest to, że serwlet zapisuje pobranie pliku do odpowiedzi, po czym
forward()
wywoływana jest np . A.Nie jest to technicznie możliwe. Musisz usunąć
forward()
połączenie. Użytkownik końcowy pozostanie na aktualnie otwartej stronie. Jeśli faktycznie zamierzasz zmienić stronę po pobraniu pliku, musisz przenieść logikę pobierania plików na ładowanie strony docelowej.Jeszcze inną prawdopodobną przyczyną jest to, że
forward()
,sendRedirect()
lubsendError()
metody są wywoływane za pomocą kodu Java osadzone w pliku JSP w postaci starej drodze<% scriptlets %>
, praktyki, która została oficjalnie zniechęca od 2001 roku . Na przykład:Problem polega na tym, że JSP wewnętrznie zapisuje tekst szablonu (tj. Kod HTML)
out.write("<!DOCTYPE html> ... etc ...")
natychmiast po jego napotkaniu. Jest to zatem zasadniczo ten sam problem, co wyjaśniono w poprzedniej sekcji.Rozwiązanie jest oczywiste, po prostu nie pisz kodu Java w pliku JSP. Za to odpowiada normalna klasa Javy, taka jak serwlet lub filtr. Zobacz także naszą stronę wiki serwletów, aby dowiedzieć się, jak używać serwletów we właściwy sposób.
Zobacz też:
Twój kod JDBC, niezwiązany z konkretnym problemem, przecieka zasoby. Napraw to również. Aby uzyskać wskazówki, zobacz także Jak często należy zamykać Connection, Statement i ResultSet w JDBC?
źródło
break;
? Oznaczałoby to, że kod znajdował się w jakiejś pętlifor
lubwhile
pętli, w którejforward()
był wywoływany wielokrotnie podczas pętli (co jest zatem niepoprawne, powinieneś wywołać przekierowanie tylko raz PO pętli - lub pozbyć się pętli, ponieważ najwyraźniej nie jest potrzebna) .forward()
wywołanie, podczas gdy nie powinno tego robić. JSF, który znam, robi to również, chyba że wyraźnie zadzwoniszFacesContext#responseComplete()
. To pokrewne pytanie (które znalazłem przy użyciu słów kluczowych „grails zapobiegają renderowaniu odpowiedzi”) może być pomocne: stackoverflow.com/questions/5708654/ ...forward()
połączenie, podczas gdy nie powinien tego robić. Rozwiązanie jest funkcjonalnie oczywiste: powiedz mu, żeby tego nie robił. Nie miał mianowicie pojęcia, że programowo przejąłeś zadanie, które miał wykonać Grails: obsługę odpowiedzi. Technicznie nie mam pojęcia, jak to powiedzieć Grailsowi. Ale wiem, że wiele innych frameworków MVC obsługuje to (poinstruowane, aby same nie obsługiwały odpowiedzi), takich jak JSF, Spring MVC, Wicket itp. Byłbym zaskoczony, gdyby było to niemożliwe w Grails.nawet dodanie instrukcji return wywołuje ten wyjątek, dla którego jedynym rozwiązaniem jest ten kod:
źródło
Zwykle pojawia się ten błąd po wykonaniu przekierowania, a następnie próbie wyprowadzenia większej ilości danych do strumienia wyjściowego. W przypadkach, w których widziałem to w przeszłości, często jest to jeden z filtrów, który próbuje przekierować stronę, a następnie nadal przekazuje ją do serwletu. Nie widzę od razu nic złego w serwlecie, więc możesz spróbować rzucić okiem na wszystkie filtry, które masz na miejscu.
Edycja : dodatkowa pomoc w diagnozowaniu problemu…
Pierwszym krokiem do zdiagnozowania tego problemu jest ustalenie, gdzie dokładnie jest zgłaszany wyjątek. Zakładamy, że jest rzucany przez linę
Ale może się okazać, że jest on wyrzucany później w kodzie, w którym próbujesz wyprowadzić do strumienia wyjściowego po próbie wykonania operacji do przodu. Jeśli pochodzi z powyższej linii, oznacza to, że gdzieś przed tą linią masz albo:
Powodzenia!
źródło
Dzieje się tak, ponieważ aplet próbuje uzyskać dostęp do obiektu żądania, który już nie istnieje. Instrukcja forward lub include serwletu nie zatrzymuje wykonywania bloku metody. Kontynuuje do końca bloku metody lub pierwszej instrukcji powrotu, tak jak każda inna metoda Java.
Najlepszym sposobem rozwiązania tego problemu jest po prostu ustawienie strony (na której ma zostać przekazane żądanie) dynamicznie zgodnie z logiką. To jest:
i wykonaj naprzód tylko raz w ostatniej linii ...
możesz również rozwiązać ten problem, używając instrukcji return po każdym forward () lub wstawiając każdą forward () w bloku if ... else
źródło
usunąłem
Wtedy działało dobrze dla mnie
źródło
Guz...
Po prostu miałem ten sam błąd. Zauważyłem, że wywoływałem
super.doPost(request, response);
podczas zastępowaniadoPost()
metody, a także jawnie wywoływałem konstruktora nadklasyJak tylko skomentowałem oświadczenie
super.doPost(request, response);
od wewnątrzdoPost()
, zadziałało idealnie ...Nie trzeba dodawać, że muszę ponownie przeczytać
super()
najlepsze praktyki: sźródło
Należy dodać instrukcję return podczas przekazywania lub przekierowywania przepływu.
Przykład:
jeśli forwardind,
jeśli przekierowujesz,
źródło
Po metodzie powrotu do przodu możesz po prostu zrobić to:
Spowoduje to przerwanie obecnego zakresu.
źródło