В Spring можно иметь обработчик исключений для всех и комментировать некоторые исключения с указанным c http статусом? - PullRequest
1 голос
/ 26 февраля 2020

В моем приложении Spring у меня есть обработчик универсальных исключений в моем контроллере отдыха:

@ExceptionHandler(Exception.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public String otherExceptions(Exception e) {
    return "Internal Server Error";
}

Однако некоторые исключения снабжены указанным c http кодом состояния:

@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
public class UserNotAuthenticatedException extends RuntimeException {
}

К сожалению, аннотированные исключения также обрабатываются обработчиком исключений в контроллере. Можно ли как-то сказать Spring, чтобы обрабатывать их, возвращая код состояния, с которым они помечены?

Ответы [ 4 ]

1 голос
/ 26 февраля 2020

Вы смешиваете два способа обработки исключения, но есть обходной путь для этого.

@ExceptionHandler(Exception.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public String otherExceptions(Exception e) throws Exception {
    if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
      throw e;

    return "Internal Server Error";
}

В этом случае, если исключение помечено ResponseStatus, вы перебрасываете исключение и позволяете рамки обрабатывать его.

0 голосов
/ 26 февраля 2020

Ниже одно решение, которое вы можете попробовать

@ControllerAdvice
public class SampleExceptionHandler extends ResponseEntityExceptionHandler {

@ExceptionHandler(Exception.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public String otherExceptions(Exception e) {
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
  throw e;

return "Internal Server Error";

}

}

0 голосов
/ 26 февраля 2020

Вы можете использовать @ControllerAdvice для обработки пользовательских исключений, например, для исключения UserNotAuthenticatedException:

1) Создать универсальное c исключение

 public abstract class GenericException extends RuntimeException {

    public GenericException (String messageKey) {
        super(messageKey);
    }

    public GenericException (String messageKey, Throwable cause) {
        super(messageKey, cause);
    }

    private static final long serialVersionUID = 1L;

    public abstract HttpStatus getHttpStatus();
}

2) Создать спецификацию c исключение с вашей аннотацией:

 @ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotAuthenticatedException   extends GenericException  {

    private static final long serialVersionUID = 1L;

    public UserNotAuthenticatedException  () {
        super(ExceptionKeys.RESOURCE_NOT_FOUND_EXCEPTION);
    }

    public UserNotAuthenticatedException  (Throwable cause) {
        super(ExceptionKeys.RESOURCE_NOT_FOUND_EXCEPTION, cause);
    }

    public UserNotAuthenticatedException  (String messageKey) {
        super(messageKey);
    }

    public UserNotAuthenticatedException  (String messageKey, Throwable cause) {
        super(messageKey, cause);
    }

    @Override
    public HttpStatus getHttpStatus() {
        return HttpStatus.NOT_FOUND;
    }
}

3) Создайте ошибку DTO:

@Data
public class ErrorDto {

    private int code;

    private String message;

    private String additionalData;

    public ErrorDto(String message, int code) {
        super();
        this.message = message;
        this.code = code;
    }

    public ErrorDto(String message, String additionalData) {
        super();
        this.message = message;
        this.additionalData = additionalData;
    }

    public ErrorDto() {
    }

}

4) Затем создайте глобальный обработчик исключений для сопоставления вашего исключения со статусом:

@ControllerAdvice
@RestController
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {


    @ExceptionHandler({GenericException  .class})
    public ResponseEntity<ErrorDto> handlePortalExceptions(final GenericException   pex) {
        log.error("{} [{}]", pex.getClass().getName(), pex.getMessage());
        log.error(pex.getMessage(), pex);
        final ErrorDto errorDetails = new ErrorDto(pex.getMessage(), pex.getHttpStatus().value());
        errorDetails.setAdditionalData(pex.getCause() != null ? pex.getCause().getLocalizedMessage() : pex.getLocalizedMessage());
        return new ResponseEntity<>(errorDetails, pex.getHttpStatus());
    }


    @ExceptionHandler({Exception.class})
    public ResponseEntity<Object> handleAllExceptions(final Exception ex, WebRequest request) {
        log.error("{} detected [{}]", ex.getClass().getName(), ex.getMessage());
        log.error(ex.getMessage(), ex);
        final ErrorDto errorDetails = new ErrorDto(ExceptionKeys.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR.value());
        errorDetails.setAdditionalData(ex.getCause() != null ? ex.getCause().getLocalizedMessage() : ex.getLocalizedMessage());
        return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
    }

}
0 голосов
/ 26 февраля 2020
@ExceptionHandler(UserNotAuthenticatedException.class)
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
public String otherExceptions(Exception e) {
    return "Internal Server Error";
}

Создайте @ExceptionHandler для каждого отдельного необходимого вам класса исключения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...