Методы обработки ошибок, когда Spring Boot предоставляет интерфейсы RESTful

Spring Boot

В процессе разработки микросервисов с Spring Boot мы будем использовать интерфейсы, предоставленные другими, а также разработаем интерфейсы для использования другими.В настоящее время взаимодействие между приложениями микросервисов должно иметь определенные спецификации.

  • Основываясь на протоколе rpc, у нас обычно есть две идеи: (1) приложение, предоставляющее сервис, единообразно оборачивает исключение, а затем взаимодействует с кодом ошибки; (2) приложение, предоставляющее сервис, выдает исключение во время выполнения и выдает пользовательский бизнес-код. Exception, вызывающая сторона службы обрабатывает исключение с помощью перехвата исключения.

  • Основанный на протоколе HTTP, наиболее популярным является протокол RESTful. Поставщик услуг будет обрабатывать все исключения самостоятельно, а возвращаемый результат будет объединен с кодом состояния HTTP. В этой статье мы будем использовать пример, чтобы проиллюстрировать обработка ошибок интерфейса RESTful.Как это сделать.

Сначала нам нужно создать простой контроллер, код выглядит следующим образом:

@RestController
class GreetingController {

    @RequestMapping("/greet")
    String sayHello(@RequestParam("name") String name) {
        if (name == null || name.isEmpty()) {
            throw new IllegalArgumentException("The 'name' parameter must not be null or empty");
        }
        return String.format("Hello %s!", name);
    }
}

Запрос клиента через http -httpieПреимущества этого инструмента перед curl для отправки HTTP-запросов: информация о возвращаемом значении имеет подсветку синтаксиса, а возвращаемая строка JSON автоматически форматируется. Для запуска сервера используйте командуhttp http://127.0.0.1:8080/greet?name=duqiИнициируйте запрос, и результат будет следующим:

HTTP/1.1 200 OK
Content-Length: 11
Content-Type: text/plain;charset=UTF-8
Date: Sat, 05 Dec 2015 05:45:03 GMT
Server: Apache-Coyote/1.1
X-Application-Context: application

Теперь мы делаем неправильный запрос, @RequestParam должен получить параметры в URL, если этот параметр не указан, произойдет ошибка. Итак, мы отправляем командуhttp http://127.0.0.1:8080, чтобы увидеть, как это получается.

HTTP/1.1 400 Bad Request
Connection: close
Content-Type: application/json;charset=UTF-8
Date: Sat, 05 Dec 2015 05:54:06 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
X-Application-Context: application

{
    "error": "Bad Request",
    "exception": "org.springframework.web.bind.MissingServletRequestParameterException",
    "message": "Required String parameter 'name' is not present",
    "path": "/greet",
    "status": 400,
    "timestamp": 1449294846060
}

Как видите, поскольку параметр name не указан, сервер возвращает код состояния 400: Bad Request. Содержимое тела ответа следующее:

  • ошибка: сообщение об ошибке;
  • исключение: тип исключения, MissingServletRequestParameterExeption, как следует из названия, указывающий, что параметр запроса отсутствует;
  • сообщение: описание исключения
  • path: Показать запрошенный URL-адрес;
  • статус: указывает возвращенный код ошибки
  • timestamp: Отметка времени, когда произошла ошибка, вызовите System.currentMills().

Что, если мы дадим параметр имени, но не присвоим ему значение? отправить командуhttp http:127.0.0.1:8080/greet?name, возвращаемое значение сервера выглядит следующим образом:

HTTP/1.1 500 Internal Server Error
Connection: close
Content-Type: application/json;charset=UTF-8
Date: Sat, 05 Dec 2015 06:01:24 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
X-Application-Context: application

{
    "error": "Internal Server Error",
    "exception": "java.lang.IllegalArgumentException",
    "message": "The 'name' parameter must not be null or empty",
    "path": "/greet",
    "status": 500,
    "timestamp": 1449295284160
}

Сравнивая приведенное выше, можно увидеть, что на этот раз возвращается код ошибки 500, что указывает на внутреннюю ошибку сервера, а возвращаемый тип исключения — java.lang.IllegalArgumentException, что указывает на то, что параметр недействителен. Внутренняя ошибка сервера означает, что сервер выдал исключение и не обработал его. Мы предпочитаем, чтобы API возвращал 400, чтобы сообщить вызывающей стороне, что пошло не так. Как этого добиться? Просто используйте аннотацию @ExceptionHandler.

Добавьте следующую функцию-обработчик в контроллер GreetingController, чтобы перехватить исключение этого контроллера.

@ExceptionHandler
void handleIllegalArgumentException(IllegalArgumentException e, 
                        HttpServletResponse response) throws IOException {    
      response.sendError(HttpStatus.BAD_REQUEST.value());
}

отправить команду еще разhttp http:127.0.0.1:8080/greet?name, возвращается следующий результат:

HTTP/1.1 400 Bad Request
Connection: close
Content-Type: application/json;charset=UTF-8
Date: Sat, 05 Dec 2015 06:08:50 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
X-Application-Context: application

{
    "error": "Bad Request",
    "exception": "java.lang.IllegalArgumentException",
    "message": "The 'name' parameter must not be null or empty",
    "path": "/greet",
    "status": 400,
    "timestamp": 1449295729978
}

Это означает, что мы поймали исключение IllegalArgumentException на стороне сервера и установили код возврата ответа 400. Если вы хотите одинаково обрабатывать несколько исключений, приведенный выше код обработки исключений можно изменить следующим образом (параметры передаются в @ExceptionHandler):

@ExceptionHandler({IllegalArgumentException.class, NullPointerException.class})
void handleIllegalArgumentException(HttpServletResponse response) throws IOException {
    response.sendError(HttpStatus.BAD_REQUEST.value());
}

Теперь этот код обработки исключений добавляется к текущему контроллеру, поэтому он обрабатывает только ответ, принадлежащий этому контроллеру.Если мы создадим новый класс, украсим его аннотацией @ControllerAdvice и определим приведенный выше код обработки исключений в этом классе, то он будет отвечать за обработку всех запросов.

После Spring Boot 1.2.0 также поддерживается изменение соответствующего сообщения в ответе, если соответствующая информация сообщения передается в функцию sendError, например:

@ExceptionHandler({IllegalArgumentException.class, NullPointerException.class})
void handleIllegalArgumentException(HttpServletResponse response) throws IOException {
    response.sendError(HttpStatus.BAD_REQUEST.value(), 
         "Please try again and with a non empty string as 'name'");
}

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

HTTP/1.1 400 Bad Request
Connection: close
Content-Type: application/json;charset=UTF-8
Date: Sat, 05 Dec 2015 06:21:05 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
X-Application-Context: application

{
    "error": "Bad Request",
    "exception": "java.lang.IllegalArgumentException",
    "message": "Please try again and with a non empty string as 'name'",
    "path": "/greet",
    "status": 400,
    "timestamp": 1449296465060
}

Если вы хотите проверить параметры запроса, вы можете использовать JSR-303 Bean Validation API и обратиться кSpring Validation. Также есть пример проверки ввода формы на spring.ioValidating Form Input.

использованная литература

  1. Инструменты для имитации запросов GET/POST
  2. Spring Boot Error Response

Весенняя загрузка серии 1.x

  1. Автоматическая настройка Spring Boot, Command-line-Runner
  2. Понимание автоматической настройки Spring Boot
  3. Использование аннотации Spring Boot @PropertySource при интеграции Redis
  4. Как настроить преобразователи HTTP-сообщений в проектах Spring Boot
  5. Spring Boot интегрирует Mongodb для обеспечения интерфейса Restful.
  6. Сфера фасоли весной
  7. Использование шаблона диспетчера событий в проекте Spring Boot

В этом выпуске основное внимание уделяется таким темам, как серверные технологии, устранение неполадок и оптимизация JVM, вопросы на собеседованиях по Java, личностный рост и самоуправление, а читателям предлагается опыт работы и роста передовых разработчиков. .

javaadu