2010-09-01 10 views
9

Ich habe eine ErrorFilter, die die Feder erweitert GenericFilterBean. Ich möchte eine Fehlerseite anzeigen, die mit Kacheln versehen ist, wenn ein Fehler auftritt.Einstellung Ansicht Name im Frühjahr Filter

Gibt es eine Möglichkeit, einen Ansichtsnamen aus dem Filter zu setzen?

<filter> 
    <filter-name>errorFilter</filter-name> 
    <filter-class>com.abc.filter.ErrorFilter</filter-class> 
    <init-param> 
     <param-name>errorPage</param-name> 
     <param-value>/jsp/errorpage.jsp</param-value> 
    </init-param> 
</filter> 

Dies ist die Konfiguration in web.xml und die doFilter Methode in errorfilter ist die folgende:

public void doFilter(ServletRequest req, ServletResponse resp, 
     FilterChain chain) throws IOException, ServletException { 

    HttpServletRequest httpReq = (HttpServletRequest) req; 
    StringBuffer reqUrl = httpReq.getRequestURL(); 
    try { 
     chain.doFilter(req, resp); 
    } catch (Exception ex) { 
     String requestRepresentation = createRequestRepresentation(req); 
     errorService.handleException(reqUrl.toString(), ex, requestRepresentation); 
     req.getRequestDispatcher(
       getFilterConfig().getInitParameter("errorPage")).forward(req, resp); 
    } catch (Error er) { 
     errorService.handleError(reqUrl.toString(), er); 
     req.getRequestDispatcher(
       getFilterConfig().getInitParameter("errorPage")).forward(req, resp); 
    } 
} 

Die aktuelle Errorpage nicht mit Kacheln dekoriert, so will ich es dekorieren mit normalen Kopf- und Fußzeile und rufen Sie diesen Ansichtsnamen aus dem Filter.

Ist es möglich?

Edit: Grundsätzlich wollen wir in der Lage sein, etwas zu tun, ähnlich wie Controller-Methode heißt return „Viewname“;

bereits versucht:

  • httpResponse.sendRedirect ("errorPageView"); funktioniert nicht, leitet es um http://server/fooerrorPageView
  • request.getRequestDispatcher ("errorPageView"). Forward (Anforderung, Antwort); auch nicht ähnlich, wie oben (ohne HTTP-Umleitung, sondern gibt die gleiche „keine solche Seitenfehler“ content)

Antwort

0

Es muss einen Weg geben, um es mit Spring MVC zu tun, aber ich denke, eine Umleitung ist genug.

try { 
    chain.doFilter(req, resp); 
} catch (Exception ex) { 
    if (response.isCommitted()) { 
     log(ex); // at least a part of the response is already sent to the client, you can't do much about it 
    } else { 
     session.setAttribute("last.exception", ex); 
     response.sendRedirect(request.getContextPath() + getFilterConfig().getInitParameter("errorPage")); 
    } 
} 

P.S. Fange keinen Fehler!

+0

_sendRedirect_ leitet den Client-Browser einfach zur angegebenen URL um, wobei die Auflösung des Ansichtsnamens umgangen wird. –

1

Ich denke, das ist nicht möglich, weil dies ein Servlet-Filter ist, der nach dem Einsatz des Spring-Request-Mapper-Servlets angewendet würde. Das Anforderungszuordnerservlet denkt also im Grunde, dass es beendet ist, und übergibt die Anforderung zurück an den Servletcontainer.

Ansicht Namen funktionieren nur INNERHALB der Feder - außerhalb des Frühlings, im Servlet Container, müssen Sie über URLs sprechen, nicht Namen anzeigen.

eine Weiterleitung an spezifische URL würde funktionieren. Dazu müssen Sie sich der Unterschiede zwischen einer Weiterleitung und einer Weiterleitung bewusst sein.

eine Umleitung sendet folgende Header an den Client:

Ort: http://server/new/location

zusammen mit dem Statuscode 301 (dauerhafte Umleitung der Client zu informieren, dass er diese Informationen zwischenzuspeichern kann) oder 307 (vorübergehende Umleitung, um dem Kunden mitzuteilen, dass er das nächste Mal erneut fragen sollte, weil sich die Weiterleitung ändern könnte)

Die Weiterleitung auf der Anfrage Dispatcher imitiert im Grunde eine neue Anfrage, und Sie können die Anfrage an JEDES Servlet im selben Container senden. Dies bedeutet, müssen Sie auch den Kontextpfad in Betracht ziehen, um die Antwort Bedeutung @iimuhin gab:

response.sendRedirect(
     request.getContextPath() + 
     getFilterConfig().getInitParameter("errorPage")); 

tatsächlich den richtigen Weg zu gehen. Sie können (sollten) eine Protokollierung hinzufügen, um zu sehen, was tatsächlich passiert und welche Pfade tatsächlich verwendet werden.

auch - Sie müssen sich der Pufferung bewusst sein. Eine Servlet-Antwort wird normalerweise gepuffert, und nichts wird an den Client gesendet, bis entweder der Puffer voll ist oder die gesamte Verarbeitung abgeschlossen ist.

Wenn es geleert wird, werden die Header zuerst geschrieben. Das bedeutet, dass das Ändern der Header nach dem Löschen der Antwort nicht möglich ist, da sie bereits gesendet wurden.

Dies ist der Grund, warum Servlets Spülen erzwingen können, aber normalerweise nicht.

in Ihrem Fall, können Sie die Puffergröße auf die Antwort zu erhöhen:

response.setBufferSize(int size) 

vor chain.doFilter() aufrufen vorzeitige Spülung zu vermeiden.

+0

Vielen Dank für die ausführliche Erklärung zu diesem Thema. +1 für die Erwähnung des Unterschieds zwischen Redirect und Forward. – yuva

1

Warum verwenden Sie nicht den Fehlerbehandlungsmechanismus von spring? hier der gute Beitrag darüber (mit Beispielen) - https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

Ansonsten nicht sicher, ob es eine saubere Art und Weise, dies zu tun ist. Andere Vorschläge könnten einen Aufruf an Ihre Anwendung machen, um eine Fehlerseitenantwort zu erhalten und die Antwortausgabe mit dieser zu ersetzen (in diesem Fall müssen Sie auch eine "gepufferte" HTTP-Antwort verwenden, um sicher zu sein, dass der Stream noch nicht geleert wurde) oder make a Weiterleitung an die Fehler-URL.

+0

Ihr Vorschlag funktioniert, wenn der Fragesteller eine Fehlerseite vom Controller anzeigen möchte. Was er will, ist eine Fehlerseite innerhalb des Servlet-Filters aufzubauen, die bevor die Anfrage an die Steuerung geht. Daher kann die Ausnahmebehandlung hier nicht funktionieren. Ihr zweiter Vorschlag ist jedoch erwähnenswert. – yuva

+1

Vielen Dank für Ihre Antwort und Bewertung, aber warum glauben Sie, dass der Servlet-Filter nicht in der Lage ist, in Spring Controller geworfene Ausnahme oder nach Feder-Controller-Ausführung (mit anderen Worten auf eine Rückfahrt nach der Controller-Ausführung) zu fangen? – Maks

+0

der ganze Punkt meiner Antwort war: - Verwenden Sie sring-Funktionalität, wenn Sie können - wenn Sie (aus welchen Gründen auch immer) nicht in der Lage ist, es zu verwenden, ist Redirect oder Response-Analyse (im Filter) immer noch eine Option. Aber das funktioniert möglicherweise nur, wenn die Antwort noch nicht festgelegt ist. Macht es Sinn? – Maks

1

Filter kommt vor dem Frühling. Spring-Beans können mithilfe des ApplicationContextAware-Mechanismus in den Filter eingefügt werden. Wenn Sie jedoch eine Spring-MVC-Ansicht erstellen, müssen Sie das gesamte Feder-MVC-Framework in Ihrem Filter verwenden. Ich denke, das ist nicht möglich, und Sie müssen die Anfrage mit RequestDispatcher nicht an eine Spring View, sondern an Ihre eigene benutzerdefinierte Ansicht weiterleiten.

0

Überprüfen Sie einfach Ihre Weiterleitungs-URL. Sie können auf die Seite mit der URL zugreifen.

public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) 
     throws IOException { 
    String redirectUrl = request.getContextPath() + url; 
    redirectUrl = response.encodeRedirectURL(redirectUrl); 

    if (logger.isDebugEnabled()) { 
     logger.debug("Redirecting to '" + redirectUrl + "'"); 
    } 

    response.sendRedirect(redirectUrl); 
}