如何确定异常是否是ClientAbortException

时间:2017-02-07 15:56:40

标签: java spring maven tomcat exception-handling

当用户取消托管在Tomcat应用程序服务器上的Web应用程序上的请求时,我得到以下异常,并通过Maven处理依赖关系管理:

ClientAbortException:  java.net.SocketException: Connection reset
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:406)
    at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480)
    at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:366)
    at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:431)
    at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:419)
    at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:91)
    ...

我有一个Spring @ControllerAdvice类来处理所有异常,并发送电子邮件。

@ExceptionHandler(value = Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResponseEntity defaultErrorHandler(final HttpServletRequest request, final Principal principal, final Exception e) {

    //send email with details of error

    return ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}

但是,如果是ClientAbortException,我不想发送电子邮件。

我想做这样的事情:

if (!(e instanceof ClientAbortException)) {
    //send email with details of error
}

ClientAbortException似乎不在我的类路径中,因为它是tomcat服务器级lib中包含的异常。

我可以查看是否e instance of SocketException,但我可能会错过我关心的其他SocketException。我的下一个想法是:

e instanceof SocketException && e.getMessage().contains("Connection reset")

但似乎应该有一种更简单的方法来做到这一点。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我看一下java doc,ClientAbortException是IOException的子代,所以你不能使用SocketException的实例。

在我的tomcat版本中,抛出异常的代码是:

if (cnt > 0) {
        // real write to the adapter
        outputChunk.setBytes(buf, off, cnt);
        try {
            coyoteResponse.doWrite(outputChunk);
        } catch (IOException e) {
            // An IOException on a write is almost always due to
            // the remote client aborting the request.  Wrap this
            // so that it can be handled better by the error dispatcher.
            throw new ClientAbortException(e);
        }
    }

我认为您只需为您的客户端中止异常创建一个新的异常处理程序。不要在不同的例外中使用实例。

@ExceptionHandler(value = ClientAbortException.class)
public ResponseEntity<ErrorResponse> handleClientAbort(Exception ex, HttpServletRequest req) {
    //YOUR HANDLER IMPLEMENTATION

}

您可以使用@Order注释来配置precedence of exceptions