2011-11-25 7 views
13

Estoy utilizando un SimpleMappingExceptionResolver que envía todas las excepciones a una vista donde se representa muy bien. Eso funciona excepto un caso: Si el usuario solicita una página, y luego envía y "Abortar" () no sé exactamente cómo funciona eso, pero noté que si hago clic en un botón de envío de formulario HTTP post muy rápido y con frecuencia el Firefox 7 de alguna manera notifica al servidor que ya no está interesado en el resultado.) Luego el Tomcat 6 se eleva a ClientAbortException cuando se intenta renderizar la página, o se escribe la respuesta http de cualquier tipo.Cómo excluir ClientAbortException de SimpleMappingExceptionResolver

Ahora empiezan los problemas: los SimpleMappingExceptionResolver "atrapa" la excepción y trys para hacerlo muy bien a una página HTML. Esto provoca una excepción de Stream ya cerrada que contamina el archivo de registro. (java.lang.IllegalStateException: getOutputStream() has already been called for this response)

Lo que he hecho para la tarifa, es registrar una página jsp vacía para la "ClientAbortException". Pero siento que esto es un Hack. Por otro lado, creo que este no es un problema tan incongruente, porque lo esperaré en casi todas las aplicaciones de primavera que presenten todas las excepciones. Entonces, ¿alguien tiene experiencia con ese problema, o tiene una idea de una solución no tan 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> 

Respuesta

10

Extender SimpleMappingExceptionResolver, reemplace doResolveException() método, y en caso de que el nombre de excepción es ClientAbortException y response.isCommitted() retorno null en lugar de devolver super.doResolveException().

1

En mi humilde opinión, registrar la vista nothing para el Exception que no desea manejar es manera elegante; en oposición a la sensación de hackeo; como puede tener incluso más de una excepción, no desea/no quiere hacerla en comparación con otras excepciones.

No recomiendo crear una implementación personalizada para HandlerExceptionResolver; ya que puede aumentar los costos de mantenimiento.

1

Para las versiones más recientes de Spring, también puede usar la anotación @ExceptionHandler, posiblemente con @ControllerAdvice (para manejo global).

@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

Para mí esto no funciona. El método nunca se invoca cuando se ejecuta en tomcat ... – membersound

Cuestiones relacionadas