Проверка параметров запроса является распространенным сценарием, в котором многие начинающие разработчики склонны совершать ошибки или есть много точек улучшения. Наиболее распространенные проблемы в основном проявляются в следующих аспектах:
- Для решения проверки параметров полагайтесь только на интерфейсную структуру, а проверка на стороне сервера отсутствует. Такая ситуация распространена, когда фронт и бэкенд нужно разрабатывать одновременно, хотя нормальное использование программы не будет проблемой, но аномальную работу разработчик игнорирует. Например, обход клиентской программы и прямая имитация клиентского запроса внезапно установит различные ограничения на интерфейс и напрямую затронет различные интерфейсы доступа к данным, что создаст угрозу безопасности нашей системы.
- Интенсивное использование
if/else
Оператор вложен, а логика проверки неясна и сложна для понимания, что не способствует долгосрочному обслуживанию.
Поэтому, в ответ на вышеуказанные проблемы, рекомендуется, чтобы разработка на стороне сервера имела проверку параметров запроса на стороне сервера при реализации интерфейса для обеспечения безопасности данных и стабильной работы системы. В то же время реализация проверки параметров должна быть достаточно элегантной, чтобы соответствовать основным характеристикам легко читаемой и простой в обслуживании логики.
Далее в этом руководстве мы подробно обсудим, как элегантно реализовать проверку параметров запроса на сервере Spring Boot.
JSR-303
Прежде чем мы приступим к практической работе, давайте взглянем на стандартную спецификацию, которую мы будем использовать дальше: JSR-303.
Что такое ЖСР?
JSR — это аббревиатура от Java Specification Requests, что означает предложение спецификации Java. Это официальный запрос в JCP (Java Community Process) о добавлении стандартизированной технической спецификации. Любой может отправить JSR для добавления новых API и сервисов на платформу Java. JSR стал важным стандартом в мире Java.
Какой стандарт определен JSR-303?
JSR-303 — это подспецификация в JAVA EE 6, называемая «Проверка компонентов», а Hibernate Validator — эталонная реализация проверки компонентов.Hibernate Validator обеспечивает реализацию всех встроенных ограничений спецификации JSR 303 в дополнение к некоторым дополнительным ограничение.
Ограничения, встроенные в проверку компонентов
Дополнительные ограничения Hibernate Validator
В соответствии со стандартом JSR-303 мы можем элегантно определить проверку каждого параметра запроса с помощью приведенных выше аннотаций. Подробнее о JSR можно узнать в официальной документации или ссылках [1].
Руки
После понимания JSR-303 давайте попробуем реализовать проверку параметров на основе этой спецификации!
Готов к работе
Читатели могут взять за основу любой проект, созданный с помощью Spring Boot 2.x, который предоставляет RESTful API. также можно использоватьБазовое руководство по Spring Boot 2.x: создание надежной документации API с помощью Swagger2Экспериментальный проект, построенный вchapter2-2
Каталог для получения:
- Гитхаб:GitHub.com/first87112/sp…
- Гостиница:git ee.com/brother space/S…
Конечно, вы также можете построить еще один в качестве обзора на основе предыдущей статьи, и в этом нет никакой проблемы.
Быстрый старт
Сначала рассмотрим простой пример, например: поле определения не может бытьNull
. Всего два шага
первый шаг: Добавить Для проверки на поле@NotNull
Примечания, как показано ниже:
@Data
@ApiModel(description="用户实体")
public class User {
@ApiModelProperty("用户编号")
private Long id;
@NotNull
@ApiModelProperty("用户姓名")
private String name;
@NotNull
@ApiModelProperty("用户年龄")
private Integer age;
}
второй шаг: добавить перед объектом параметра, который необходимо проверить.@Valid
Примечания, как показано ниже:
@PostMapping("/")
@ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
public String postUser(@Valid @RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
После завершения вышеуказанной настройки запустите приложение и получите к нему доступ с помощью POST-запроса.localhost:8080/users/
Интерфейс, корпус использует пустой объект,{}
. Вы можете инициировать инструменты тестирования, такие как Postman, или запускать их с помощью CURL, например:
curl -X POST \
http://localhost:8080/users/ \
-H 'Content-Type: application/json' \
-H 'Postman-Token: 72745d04-caa5-44a1-be84-ba9c115f4dfb' \
-H 'cache-control: no-cache' \
-d '{
}'
Неудивительно, что вы можете получить следующие результаты:
{
"timestamp": "2019-10-05T05:45:19.221+0000",
"status": 400,
"error": "Bad Request",
"errors": [
{
"codes": [
"NotNull.user.age",
"NotNull.age",
"NotNull.java.lang.Integer",
"NotNull"
],
"arguments": [
{
"codes": [
"user.age",
"age"
],
"arguments": null,
"defaultMessage": "age",
"code": "age"
}
],
"defaultMessage": "不能为null",
"objectName": "user",
"field": "age",
"rejectedValue": null,
"bindingFailure": false,
"code": "NotNull"
},
{
"codes": [
"NotNull.user.name",
"NotNull.name",
"NotNull.java.lang.String",
"NotNull"
],
"arguments": [
{
"codes": [
"user.name",
"name"
],
"arguments": null,
"defaultMessage": "name",
"code": "name"
}
],
"defaultMessage": "不能为null",
"objectName": "user",
"field": "name",
"rejectedValue": null,
"bindingFailure": false,
"code": "NotNull"
}
],
"message": "Validation failed for object='user'. Error count: 2",
"path": "/users/"
}
Значение каждого параметра возвращаемого содержимого следующее:
-
timestamp
: время запроса -
status
: Код состояния, возвращаемый HTTP, здесь возвращает 400, то есть: неверный запрос, неправильный запрос, обычно 400, если проверка параметра не удалась. -
error
: Описание ошибки, возвращенное HTTP, которое соответствует описанию ошибки статуса 400: Неверный запрос. -
errors
: Конкретной причиной ошибки является тип массива; проверка ошибок, поскольку могут быть ошибки множества полей, таких как определенные здесь, поскольку два параметра не могутNull
, поэтому есть две записи об ошибках -
message
: сводное сообщение об ошибке. Это легко понять из возвращенного содержимого. Причина ошибки здесь в том, что проверка объекта пользователя не удалась, а количество ошибок равно2
, а конкретное сообщение об ошибке определено вышеerrors
в массиве -
path
: путь запроса
Получив нормализованное сообщение об ошибке, вызывающая сторона запроса может легко проанализировать его и принять соответствующие меры для завершения собственной бизнес-логики.
попробуйте другие проверки
После завершения вышеуказанного примера мы также можем добавить некоторые правила валидации, такие как: Проверка длины строки, проверка размера, проверка, проверка ли струнного формата по электронной почте. Здесь мы должны определить некоторые комплексные определения проверки, такие как:
@Data
@ApiModel(description="用户实体")
public class User {
@ApiModelProperty("用户编号")
private Long id;
@NotNull
@Size(min = 2, max = 5)
@ApiModelProperty("用户姓名")
private String name;
@NotNull
@Max(100)
@Min(10)
@ApiModelProperty("用户年龄")
private Integer age;
@NotNull
@Email
@ApiModelProperty("用户邮箱")
private String email;
}
Инициировать может пойтиname
,age
,email
Запросы, не прошедшие проверку, например:
curl -X POST \
http://localhost:8080/users/ \
-H 'Content-Type: application/json' \
-H 'Postman-Token: 114db0f0-bdce-4ba5-baf6-01e5104a68a3' \
-H 'cache-control: no-cache' \
-d '{
"name": "abcdefg",
"age": 8,
"email": "aaaa"
}'
Мы получим следующий возврат ошибки:
{
"timestamp": "2019-10-05T06:24:30.518+0000",
"status": 400,
"error": "Bad Request",
"errors": [
{
"codes": [
"Size.user.name",
"Size.name",
"Size.java.lang.String",
"Size"
],
"arguments": [
{
"codes": [
"user.name",
"name"
],
"arguments": null,
"defaultMessage": "name",
"code": "name"
},
5,
2
],
"defaultMessage": "个数必须在2和5之间",
"objectName": "user",
"field": "name",
"rejectedValue": "abcdefg",
"bindingFailure": false,
"code": "Size"
},
{
"codes": [
"Min.user.age",
"Min.age",
"Min.java.lang.Integer",
"Min"
],
"arguments": [
{
"codes": [
"user.age",
"age"
],
"arguments": null,
"defaultMessage": "age",
"code": "age"
},
10
],
"defaultMessage": "最小不能小于10",
"objectName": "user",
"field": "age",
"rejectedValue": 8,
"bindingFailure": false,
"code": "Min"
},
{
"codes": [
"Email.user.email",
"Email.email",
"Email.java.lang.String",
"Email"
],
"arguments": [
{
"codes": [
"user.email",
"email"
],
"arguments": null,
"defaultMessage": "email",
"code": "email"
},
[],
{
"defaultMessage": ".*",
"codes": [
".*"
],
"arguments": null
}
],
"defaultMessage": "不是一个合法的电子邮件地址",
"objectName": "user",
"field": "email",
"rejectedValue": "aaaa",
"bindingFailure": false,
"code": "Email"
}
],
"message": "Validation failed for object='user'. Error count: 3",
"path": "/users/"
}
отerrors
В различных ошибках в массиве вы знаете каждое полеdefaultMessage
Вы можете увидеть очень четкое описание ошибки.
Воплощено в документации Swagger
Некоторые читатели могут спросить, так много всего настроено в моем интерфейсе. В предыдущем туториале разве не учили автоматически генерировать документы, так как описать логику проверки параметров?
Здесь есть два случая: сам Swagger имеет некоторую поддержку JSR-303, но поддержка не такая полная, и она не распространяется на все аннотации.
Например, аннотации, которые мы использовали выше, могут быть сгенерированы автоматически, запустить наш экспериментальный проект выше, а затем посетитьhttp://localhost:8080/swagger-ui.html
,существуетModels
Нет, мы можем видеть что-то вроде изображения ниже:
в:name
иage
По сравнению с описанием документа в предыдущем руководстве, в этом поле содержится больше пояснений по поводу проверки; иemail
Поле не отражает соответствующие инструкции по проверке. В настоящее время Swagger поддерживает следующие аннотации:@NotNull
,@Max
,@Min
,@Size
,@Pattern
. В реальном процессе разработки нам нужно иметь дело с ситуацией.Для ветки Swagger, созданной автоматически, ее можно сгенерировать с помощью встроенной поддержки.Если некоторые поля не могут быть сгенерированы, вы можете@ApiModelProperty
В описании аннотации он добавляет соответствующие инструкции по проверке для удобства просмотра пользователем.
Дополнительно: Возможно, у вас есть эти вопросы
Когда появляется сообщение об ошибке при проверке параметра запроса, можно ли изменить формат ошибки?
Ответ положительный. Информация об ошибках здесь фактически организована и возвращается механизмом обработки исключений Spring Boot.В следующих руководствах мы подробно расскажем о том, как Spring Boot обрабатывает возвраты исключений единообразно и как мы можем определить время возврата исключений.
spring-boot-starter-validation
Это необходимо?
Некоторые читатели спрашивали раньше и видели, что было написано и представлено много руководств.spring-boot-starter-validation
Зависит от этого зависимого? (В этой статье не представлено в этой статье)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
На самом деле, просто присмотритесьspring-boot-starter-validation
Зависимость в основном заключается в том, чтобы представить что, а затем судить в соответствии с версией Spring Boot, которую вы используете в настоящее время. По факту,spring-boot-starter-validation
Зависимость в основном состоит в том, чтобы ввести следующие зависимости:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.14.Final</version>
<scope>compile</scope>
</dependency>
Мы можем увидеть, существует ли он в зависимостях текущего проекта, и можем судить, нужно ли дополнительное введение. В Spring Boot версии 2.1 это все еще было включено вspring-boot-starter-web
В зависимостях дополнительное введение не требуется, поэтому в этой статье вы не найдете этого шага.
пример кода
Полный проект этой статьи можно посмотреть на следующем складеchapter2-3
содержание:
- Гитхаб:GitHub.com/first87112/sp…
- Гостиница:git ee.com/brother space/S…
Если вы считаете, что эта статья хороша, добро пожаловатьStarПоддержите, ваше внимание - движущая сила моего упорства!
использованная литература
- [1] https://www.jianshu.com/p/554533f88370
- [2] http://blog.didispace.com/spring-boot-starter-swagger-1.3.0/
Эта статья была впервые опубликована на:блог Brother space.com/spring-boot…
Добро пожаловать, чтобы обратить внимание на мой общедоступный номер: Programmer DD, получить эксклюзивные учебные ресурсы и ежедневный толчок галантерейных товаров. Если вам интересен мой рекомендуемый контент, вы также можете подписаться на мой блог:didispace.com