2015-04-27 8 views
7

Mam projekt Spring MVC, w którym używam porady kontrolera do obsługi błędów generowanych w kontrolerach. Jednak chcę również wyświetlać ładną stronę błędu, jeśli wystąpi błąd w plikach JSP (nawet jeśli tak naprawdę nie powinno się zdarzyć!). Dlatego dodałem następujące do mojego projektu web.xml pliku:Strona błędu JSP dołączona do poprzedniego wyjścia

<error-page> 
    <error-code>500</error-code> 
    <location>/WEB-INF/views/application/error/view-error.jsp</location> 
</error-page> 

<error-page> 
    <exception-type>java.lang.Exception</exception-type> 
    <location>/WEB-INF/views/application/error/view-error.jsp</location> 
</error-page> 

Gdybym wywołać błąd w JSTL celowo zawartość view-error.jsp jest renderowany w porządku. Jednak treść jest dołączona dołączona do wyjścia pliku JSP, w którym wystąpił błąd. Na przykład, jeśli wystąpi błąd w ciągu display-users.jsp w linii 50, wynikiem jest, że wyjście, które zostało wygenerowane przed wystąpieniem błędu (linia 1-50) jest poprzedzone treścią w view-error.jsp.

Jest to bardzo niepożądane, ponieważ generuje wyglądającą stronę błędu. A ponieważ nie mogę stwierdzić, gdzie zostanie zgłoszony wyjątek (gdybym mógł, naprawiłbym błąd), to, co widzi użytkownik, najprawdopodobniej będzie źle wyglądać.

Chyba dlatego, że dane wyjściowe znajdują się już w buforze i mogły już zostać wysłane do klienta? Czy jest jakiś sposób, żeby to naprawić, czy może alternatywne podejście? Dzięki!

Odpowiedz

1

To jest problem z dużym JSP generującym duży HTML, z kodem skryptowym java wymieszanym wszędzie. Po zapisaniu wystarczającej ilości danych serwer zatwierdza nagłówki (wysyła je do klienta) i wysyła początek strony. W tym momencie nie można już przywrócić niczego, aby odzyskać dane, które zostały już odebrane (i ewentualnie wyświetlone) przez przeglądarkę.

Jest to jeden z powodów, dla których scriplet nie jest zalecany, a jeśli naprawdę potrzebujesz umieścić inteligencję na stronie JSP, powinna znajdować się na początku strony, zanim cokolwiek zostanie wysłane do przeglądarki. Ale najlepiej, wszystko powinno zostać wcześniej obliczone w serwletach i przygotowane dane umieszczone w atrybutach żądania. W ten sposób strona JSP powinna zawierać tylko proste znaczniki warunkowe lub pętli, a także wyjście HTML i odtwarzanie atrybutów żądań. Wszystko to z niewielkim ryzykiem wygenerowania wyjątku.

+0

Program operacyjny nie oznacza, że ​​korzysta ze skryptletów. Wszystko o czym wspomniał to JSTL, więc może to być proste ' GriffeyDog

+0

@GriffeyDog Masz rację, moja odpowiedź jest prawdopodobnie zbyt ogólna. Ale błędy w '' lub '

+0

Masz rację, jednak nie używam skryptletów. Używam wyłącznie JSTL. Większość tego, co dzieje się w moich plikach JSP, to przeglądanie danych, a także proste sprawdzanie warunkowe - wszystko za pomocą JSTL. Niestety, niektóre strony JSP mają nieco bardziej skomplikowane rzeczy, a obecnie refaktoryzacja nie ma priorytetu. Dlatego chciałbym mieć tę "siatkę bezpieczeństwa". Rozmiar całej strony bez błędów wynosi 9 KB, a nawet jeśli wywołuję błąd w górnej części, nadal tak się dzieje, więc nie sądzę, że jest to spowodowane ilością HTML. Dziękuję za Twoją odpowiedź! – Andy0708

1

Wygląda na to, że OutputStream z HttpServletResponse jest zapisywany przed zakończeniem renderowania przez enitre JSP.

To najlepiej powinno być kontrolowane przez właściwość "autoflush". https://tomcat.apache.org/tomcat-5.5-doc/jspapi/javax/servlet/jsp/JspWriter.html

Ale na wszelki wypadek nie jest rozwiązywalne przez że:

Można przechwycić wszystko, co napisane na HttpServletResponse stosując podejście HttpServletResponseWrapper.

Generalnie chodzi o to, że tworzy się filtr, a ten filtr przekaże "Wrapper odpowiedzi" do poniższych warstw. Ten Wrapper odpowiedzi zawiera odwołanie do rzeczywistej instancji Response. Wszystko, co zostanie zapisane w odpowiedzi, może zostać zmanipulowane przez opakowanie odpowiedzi, a następnie wysłane do prawdziwej instancji odpowiedzi.

W twoim przypadku możesz dodać wszystkie dane do StringBuilder, a gdy następnie kontrolki powrócą do Filtra, Filtr może wydrukować cały StringBuilder do rzeczywistego OutputStream Response.

Oto przykład przechwytujący cokolwiek Serwlety itp.napisać, a następnie wysyła wersję tego zgzipowanego do przeglądarki:

http://tutorials.jenkov.com/java-servlets/gzip-servlet-filter.html

+0

Lub .. można zrobić view-error.jsp podjąć pewne działania, jeśli odpowiedź została już zatwierdzona. http://docs.oracle.com/javaee/5/api/javax/servlet/ServletResponse.html#isCommitted%28%29 Może wykonać JavaScript w przeglądarce, aby go przekierować do strony błędu – Mecon

+0

Dziękuję bardzo za odpowiedź - zaglądnę w to! – Andy0708

0

tam, zrobić to. Oto szybkie i brudne obejście, dopóki nie można przeprojektować.

1) Umieść cały kod JSTL, który generuje dane wyjściowe na nowej stronie JSP - nazwijmy go display-users-view.jsp (wywołaj to, co chcesz).

2) Importuj display-users-view.jsp ze strony display-users.jsp poprzez < c: import >, ale upewnij się, że zrzucisz zawartość do var (!). np:

<c:import url="display-users-view.jsp" var="output"/> 

3) Jako ostatni krok na wyświetlaczu-users.jsp, wyjście do zrzutu ekranu z prostym:

${output} 

Teraz, gdy błąd zostanie zgłoszony przed $ { output} .. nie szkodzi, nie fauluje, ponieważ nic nie wyświetliło się do przeglądarki. Jeśli nie wystąpi błąd, $ {output} zrzuci kod HTML wygenerowany w display-users-view.jsp.

Uwaga, przy użyciu c: import nie trzeba przekazywać żadnych znaków zapytania lub formularzy, które zostały przesłane do display-users.jsp, ponieważ nadal będą dostępne w twoim display-users-view.jsp.

+0

Jest to rzeczywiście trochę brudne rozwiązanie, ale jest to całkiem logiczne. Będę o tym pamiętać, jeśli nie znajdę bardziej "czystego" rozwiązania. :-) Dziękuję za odpowiedź, doceniam to! – Andy0708

+0

Inną rzeczą, którą powinieneś rozważyć, jest to, że c: forloop może wygenerować tonę białych znaków, co powoduje przedwczesne zatwierdzanie bufora. Czasami potrzebujesz tylko c: forloop generujący tonę danych, ale nie resztę JSTL, aby zapobiec wykonaniu bufora. – alfreema

Powiązane problemy