2010-09-01 15 views
9

Ho un ErrorFilter che estende la molla GenericFilterBean. Voglio mostrare una pagina di errore decorata con piastrelle se si verifica un errore.Impostazione nome vista nel filtro primavera

C'è un modo per impostare un nome di vista dal filtro?

<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> 

Questa è la configurazione nel web.xml e il metodo doFilter nel errorfilter è la seguente:

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); 
    } 
} 

L'ErrorPage corrente non è decorato con piastrelle, quindi voglio decorare con normale intestazione e piè di pagina e chiama tale nome vista dal filtro.

È possibile?

Edit: Fondamentalmente vogliamo essere in grado di fare qualcosa di simile al controller metodo cioè ritorno "nome di vista";

già provato:

  • httpResponse.sendRedirect ("errorPageView"); non funziona, reindirizza a http://server/fooerrorPageView
  • request.getRequestDispatcher ("errorPageView"). Inoltro (richiesta, risposta); fa, inoltre, non, simile come sopra (senza reindirizzamento HTTP, ma dà lo stesso "senza tale errore pagina" contenuti)

risposta

0

Ci deve essere un modo per farlo con Spring MVC, ma suppongo che è un redirect abbastanza.

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. non prendere un errore!

+0

_sendRedirect_ reindirizzerà il browser del client all'URL specificato, ignorando qualsiasi risoluzione del nome di visualizzazione. –

1

Penso che questo non sia possibile, perché questo è un filtro servlet, che verrebbe applicato dopo l'applicazione del servlet mapper della richiesta di primavera. quindi, in pratica, il servlet di mapper della richiesta pensa che sia finito e restituisce la richiesta al contenitore del servlet.

i nomi di vista funzionano solo DENTRO di primavera - fuori dalla primavera, nel contenitore della servlet, dovrete parlare di URL, non vedere i nomi.

un reindirizzamento a URL specifico funzionerebbe. per questo, devi essere consapevole delle differenze tra un reindirizzamento e un avanti.

un redirect manda la seguente intestazione al client:

Località: http://server/new/location

insieme al codice di stato 301 (redirect permanente, per lasciare il cliente sapere che può memorizzare nella cache queste informazioni) o 307 (reindirizzamento temporaneo, per dire al cliente che dovrebbe chiedere nuovamente la prossima volta, perché il reindirizzamento potrebbe cambiare)

l'inoltro sul dispatcher di richiesta riproduce sostanzialmente una nuova richiesta ed è possibile inviare la richiesta a QUALSIASI servlet nello stesso contenitore. questo significa, bisogna prendere anche il percorso contesto in considerazione, vale a dire la risposta @iimuhin dato:

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

è in realtà la strada giusta da percorrere. è possibile (dovrebbe) aggiungere la registrazione per vedere cosa succede realmente e quali percorsi sono effettivamente utilizzati.

anche - è necessario essere consapevoli del buffering. la risposta di una servlet viene solitamente memorizzata nel buffer e nulla viene inviato al client fino a quando il buffer non è pieno o l'intera elaborazione non è terminata.

quando viene lavato, le intestazioni vengono scritte per prime. questo significa che cambiare le intestazioni DOPO che la risposta è stata scaricata non è possibile, perché sono già state inviate.

questo è il motivo per cui i servlet possono forzare lo scarico, ma di solito non dovrebbero.

nel tuo caso, si consiglia di aumentare la dimensione del buffer sulla risposta:

response.setBufferSize(int size) 

prima di chiamare chain.doFilter() per evitare vampate di calore precoce.

+0

Grazie mille per la spiegazione dettagliata in merito. +1 per menzionare la differenza tra reindirizzamento e inoltro. – yuva

1

Perché non si utilizza il meccanismo di gestione degli errori della molla? qui il buon post su di esso (con esempi) - https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

A parte questo, non sono sicuro se c'è un modo pulito per farlo. Altri suggerimenti potrebbero essere una chiamata alla vostra applicazione per ottenere la risposta della pagina di errore e l'output di risposta sostitutivo con quello (in tal caso dovrete anche usare la risposta HTTP "bufferizzata" per essere sicuri che il flusso non sia ancora scaricato) o fare un reindirizza all'URL dell'errore.

+0

Il tuo suggerimento funziona se l'interrogante vuole mostrare la pagina di errore dal controller. Quello che vuole è costruire una pagina di errore all'interno del filtro servlet che è prima che la richiesta passi al controller. Quindi, Exception Handling non può funzionare qui. Il secondo suggerimento vale comunque la pena di essere notato. – yuva

+1

grazie per la vostra risposta e valutazione, ma perché pensate che il filtro servlet non sia in grado di catturare l'eccezione generata nel controller a molla o dopo l'esecuzione del controller a molla (in altre parole su un percorso dopo l'esecuzione del controller)? – Maks

+0

l'intero punto della mia risposta è stato: - utilizzare la funzionalità sring se è possibile - se (per qualsiasi motivo) non è in grado di usarlo, il reindirizzamento o l'analisi di risposta (nel filtro) è ancora un'opzione. Ma questo può funzionare solo se la risposta non è ancora stata commessa. Ha senso? – Maks

1

Il filtro arriva prima della primavera. I bean Spring possono essere iniettati in Filter usando il meccanismo ApplicationContextAware, ma formare una vista MVC Spring significa che devi avere a disposizione l'intero framework MVC primaverile nel tuo Filtro. Penso che questo non sia possibile e dovrai inoltrare la richiesta utilizzando RequestDispatcher non a una vista di primavera ma alla tua vista personalizzata.

0

Basta controllare l'URL di reindirizzamento. sei in grado di accedere alla pagina con l'url.

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); 
} 
Problemi correlati