2011-11-25 15 views
13

Sto usando un SimpleMappingExceptionResolver che invia tutte le eccezioni a una vista in cui è ben rappresentato. Funziona tranne un caso: Se l'utente richiede una pagina e quindi invia e "Abort" (non so esattamente come funziona, ma ho notato che se faccio clic su un modulo di invio del modulo HTTP invio molto veloce e spesso il Firefox 7 in qualche modo notifica al server che non è più interessato al risultato:) Quindi il Tomcat 6 sale a ClientAbortException quando si tenta di eseguire il rendering della pagina o si scrive la risposta http in qualsiasi tipo.Come escludere ClientAbortException da SimpleMappingExceptionResolver

Ora iniziano i problemi: i SimpleMappingExceptionResolver "catture" l'eccezione e trys per renderlo ben ad una pagina html. Ciò provoca quindi un'eccezione Stream già chiusa che inquina il file di registro. (java.lang.IllegalStateException: getOutputStream() has already been called for this response)

Quello che ho fatto in questo modo, è registrare una pagina jsp vuota per "ClientAbortException". Ma sento che questo è un Hack. D'altra parte credo che questo non sia un problema così poco comune, perché lo aspetterò in quasi tutte le applicazioni di primavera che rendono tutte le eccezioni. Quindi qualcuno ha esperienza con quel problema o ha un'idea di una soluzione non così hacky?

<bean 
    class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" 
    p:defaultErrorView="uncaughtException"> 
    <property name="exceptionMappings"> 
     <props> 
      <prop key=".MissingServletRequestParameterException"> 
       resourceNotFound 
      </prop> 
      <prop key=".ClientAbortException">nothing</prop> 
     </props> 
    </property> 
</bean> 

risposta

10

Estendere SimpleMappingExceptionResolver, override doResolveException() metodo, e nel caso in cui il nome dell'eccezione è ClientAbortException e response.isCommitted() ritorno null invece di ritornare super.doResolveException().

1

IMHO, la registrazione della vista nothing per il Exception che non si desidera gestire è elegante; al contrario del sentimento di hack; poiché puoi avere anche più di un'eccezione che non vuoi/non vuoi rendere rispetto ad altre eccezioni.

Non suggerirò di venire con un'implementazione personalizzata per HandlerExceptionResolver; in quanto potrebbe aumentare i costi di manutenibilità.

1

Per le versioni più recenti di Spring, è anche possibile utilizzare l'annotazione @ExceptionHandler, possibilmente con @ControllerAdvice (per la gestione globale).

@ControllerAdvice 
public class GlobalDefaultExceptionHandler { 
    private final Logger logger = LoggerFactory.getLogger(getClass()); 

    @ExceptionHandler(ClientAbortException.class) 
    public void clientAbortExceptionHandler(HttpServletRequest request, ClientAbortException e) { 
     // This usually means the browser closed or disconnected or 
     // something. We can't do anything. To avoid excessive stack traces 
     // in log, just print a simple message and return null 
     String username = "<NONE>"; 
     Principal principal = request.getUserPrincipal(); 
     if (principal != null) { 
      username = principal.getName(); 
     } 
     logger.warn("ClientAbortException: username={},remoteAddr={},userAgent={},requestedURL={}", username, 
       request.getRemoteAddr(), request.getHeader("User-Agent"), request.getRequestURL()); 
    } 

} 
+1

Per me questo non funziona. Il metodo non viene mai richiamato durante l'esecuzione in tomcat ... – membersound

Problemi correlati