如何从SimpleMappingExceptionResolver中排除ClientAbortException

时间:2011-11-25 16:27:54

标签: java spring tomcat exception-handling

我正在使用SimpleMappingExceptionResolver,它将所有异常发送到一个很好地呈现它的视图。这有效,除了一个案例: 如果用户请求一个页面,然后发送并“中止”(我不确切知道它是如何工作的,但我注意到如果我非常快地点击一个HTTP帖子表单提交按钮,通常Firefox 7会以某种方式通知它不再对结果感兴趣的服务器。)当一个人试图渲染页面时,Tomcat 6会上升ClientAbortException,或者写出任何类型的http响应。

现在开始麻烦:SimpleMappingExceptionResolver“捕获”异常并尝试将其很好地呈现给html页面。这会导致Stream已经关闭的异常,这会污染日志文件。 (java.lang.IllegalStateException: getOutputStream() has already been called for this response

我所做的就是为“ClientAbortException”注册一个空的jsp页面。但我觉得这是一个哈克。另一方面,我想这不是一个非常不常见的问题,因为我会期望它几乎在每个春季应用程序中呈现所有异常。那么,是否有人有过这个问题的经验,或者想到一个不太苛刻的解决方案?

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

3 个答案:

答案 0 :(得分:10)

扩展SimpleMappingExceptionResolver,覆盖doResolveException()方法,如果异常名称为ClientAbortExceptionresponse.isCommitted()返回null而不是返回super.doResolveException()

答案 1 :(得分:1)

恕我直言,为你不想处理的nothing注册Exception视图是优雅的方式;而不是黑客的感觉;因为与其他例外相比,你不会/不希望呈现多个例外。

我不建议为HandlerExceptionResolver提供自定义实现;因为它可能会增加可维护性成本。

答案 2 :(得分:1)

对于较新版本的Spring,您还可以使用@ExceptionHandler注释,可能使用@ControllerAdvice(用于全局处理)。

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

}