В процессе разработки микросервисов с 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.x
- Автоматическая настройка Spring Boot, Command-line-Runner
- Понимание автоматической настройки Spring Boot
- Использование аннотации Spring Boot @PropertySource при интеграции Redis
- Как настроить преобразователи HTTP-сообщений в проектах Spring Boot
- Spring Boot интегрирует Mongodb для обеспечения интерфейса Restful.
- Сфера фасоли весной
- Использование шаблона диспетчера событий в проекте Spring Boot
В этом выпуске основное внимание уделяется таким темам, как серверные технологии, устранение неполадок и оптимизация JVM, вопросы на собеседованиях по Java, личностный рост и самоуправление, а читателям предлагается опыт работы и роста передовых разработчиков. .