Статьи

RESTful Обработка ошибок с помощью Spring

Этот пост иллюстрирует способ, которым обработка исключений может быть реализована для веб-сервисов RESTful в Spring таким образом, что проблемы обработки исключений отделены от логики приложения.

Используя аннотацию @ControllerAdvice мы можем создать глобальный вспомогательный класс для всех контроллеров. Добавляя методы, которые мы аннотируем как @ExceptionHandler и @ResponseStatus мы можем указать, какой тип исключения сопоставляется с каким статусом ответа HTTP. Например, наше пользовательское NotFoundException может быть сопоставлено с HTTP-ответом 404 Not Found , или все исключения, которые не были обнаружены в другом месте, приведут к HTTP-состоянию 500 Внутренняя ошибка сервера путем перехвата java.lang.Exception , или IllegalArgumentException может привести к 400 Bad Запрос или … ну, я уверен, что вы поняли основную идею.

При необходимости вы также можете отправить клиенту более подробную информацию, добавив @ResponseBody в список.

Ниже приведен очень ограниченный пример для начала.

GeneralRestExceptionHandler

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package it.jdev.examples.spring.rest.exceptions;
 
import java.lang.invoke.MethodHandles;
import org.slf4j.*;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.ServletWebRequest;
 
@ControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE)
public class GeneralRestExceptionHandler {
 
    private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(CustomNotFoundException.class)
    public void handleNotFoundException(final Exception exception) {
        logException(exception);
    }
 
    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ExceptionHandler(CustomForbiddenException.class)
    public void handleForbiddenException(final Exception exception) {
        logException(exception);
    }
 
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler({ CustomException.class, Exception.class })
    public void handleGeneralException(final Exception exception) {
        logException(exception);
    }
 
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public void handleGeneralException(final Exception exception) {
        logException(exception);
    }
 
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({ CustomBadRequestException.class, IllegalArgumentException.class })
    @ResponseBody
    public String handleBadRequestException(final Exception exception) {
        logException(exception);
        return exception.getMessage();
    }
 
    // Add more exception handling as needed…
    // …
 
    private void logException(final Exception exception) {
        // ...
    }
 
}