在Spring应用程序中处理异常的位置 [英] Where to handle Exceptions in Spring Applications

查看:97
本文介绍了在Spring应用程序中处理异常的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我还在学习Spring。我有一个应用程序设置,我正在尝试理解Spring中的异常处理。

I'm still learning Spring. I have an Application set upped and i'm trying to understand exception handling in Spring.

我正在使用 @ControllerAdvice 处理异常。在我的应用程序中,有几个层,如服务控制器模型存储库。我应该在哪个层处理异常?或者我应该在每个层中处理异常吗?

I'm using @ControllerAdvice to handle exceptions. In my application there are few layers such as Services, Controllers, Models and Repositories. In which Layer should i be handling my exceptions? Or should i be handling exception in each layer as appropriate?

推荐答案

这是在Spring中启动异常处理的好方法:

This is a good way to start your Exception handling in Spring:

步骤1 - 创建一个特定的DefaultExceptionHandler类,并使用 @ControllerAdvice 注释对其进行注释。在此处理程序类中,您有不同的方法,同时捕获预期意外异常,这些异常使用 @ExceptionHandler 注释进行注释:

Step 1 - Create a specific DefaultExceptionHandler class, and annotate it using the @ControllerAdvice annotation. In this handler class, you have different methods, catching both expected and unexpected exceptions, which are annotated using the @ExceptionHandler annotation:

@ControllerAdvice("com.stackoverflow.example")
@SuppressWarnings("WeakerAccess")
public class DefaultExceptionHandler extends ResponseEntityExceptionHandler {

    private final Logger log = LoggerFactory.getLogger("DefaultExceptionHandler");

    private final MessageSourceAccessor messageSource;

    @Autowired
    public DefaultExceptionHandler(MessageSourceAccessor messageSource) {
        Assert.notNull(messageSource, "messageSource must not be null");
        this.messageSource = messageSource;
     }

      @ExceptionHandler(ApplicationSpecificException.class)
      public ResponseEntity<Object> handleApplicationSpecificException(ApplicationSpecificExceptionex) {
         final Error error = buildError(ex);
         return handleExceptionInternal(ex, ex.getHttpStatus(), error);
      }

       @ExceptionHandler(Exception.class)
       public ResponseEntity<Object> handleException(Exception ex) {
           final Error error = buildError(ex);
           return handleExceptionInternal(ex, HttpStatus.INTERNAL_SERVER_ERROR, error);
    }
}

第2步 - 创建一个特定于应用程序的异常(ApplicationSpecificException类),用于预期的异常,并在任何级别抛出此异常,它将被Spring接收:

Step 2 - Create an application specific exception (ApplicationSpecificException class) used for expected exceptions and throw this exception on any level and it will get picked up by Spring:

public class ApplicationSpecificException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    private final ExceptionType exceptionType;

    public ApplicationSpecificException(ExceptionType exceptionType, Object... messageArguments) {
        super(MessageFormat.format(exceptionType.getMessage(), messageArguments));
        this.exceptionType = exceptionType;
    }

    public ApplicationSpecificException(ExceptionType exceptionType, final Throwable cause, Object... messageArguments) {
        super(MessageFormat.format(exceptionType.getMessage(), messageArguments), cause);
        this.exceptionType = exceptionType;
    }

    public HttpStatus getHttpStatus() {
        return exceptionType.getStatus();
    }

    public ExceptionType getExceptionType() {
        return exceptionType;
    }
}

ExceptionType为枚举:

With ExceptionType being an enum:

public enum ExceptionType {

    HTTP_INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "An internal server error occurred.");
    //you can specify your own exception types...

    private HttpStatus status;
    private String message;

    ExceptionType(HttpStatus status, String message) {
        this.status = status;
        this.message = message;
    }

    public HttpStatus getStatus() {
        return status;
    }

    public String getMessage() {
        return message;
    }
}

第3步 - 最后,创建了一个ExceptionFactory类。这允许您在应用程序日志中自动记录异常:

Step 3 - Finally, created an ExceptionFactory class. This allows you to automatically log the exception in your application logs:

public class ExceptionFactory {

    private static final Logger LOG = LoggerFactory.getLogger(ExceptionFactory.class);

    public static ApplicationSpecificException create(final Throwable cause, final ExceptionType exceptionType, final Object... messageArguments) {
        LOG.error(MessageFormat.format(exceptionType.getMessage(), messageArguments), cause);
        return new ApplicationSpecificException (exceptionType, cause, messageArguments);
    }

    public static ApplicationSpecificException create(final ExceptionType exceptionType, final Object... messageArguments) {
        LOG.error(MessageFormat.format(exceptionType.getMessage(), messageArguments));
        return new TerminologyServerException(exceptionType, messageArguments);
    }
}

第4步 - 在您可以在应用程序中的任何位置抛出异常,这将在应用程序日志中记录异常。由于Spring @ControllerAdvice注释,DefaultExceptionHandler抛出并拾取此异常:

Step 4 - At any place in your application, you can now throw an exception, and this will log the exception in the application logs. This exception is thrown and picked up by the DefaultExceptionHandler thanks to the Spring @ControllerAdvice annotation:

throw ExceptionFactory.create(ExceptionType.INTERNAL_SERVER_ERROR);

像这样,您可以将异常处理流程作为一个跨领域的问题来应对。不会将内部服务器错误传播给最终用户,并且DefaultExceptionHandler会处理预期和意外异常。异常被分配了一个HTTP错误代码和错误消息,它将返回给客户端。

Like this you cope with the Exception handling process as a cross-cutting concern. No internal server errors will be propagated to the end user, and both expected and unexpected exceptions are handled by the DefaultExceptionHandler. The exception is assigned a certain HTTP error code and error message, which will be returned to the client.

这篇关于在Spring应用程序中处理异常的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆