использовать фон
В настоящее время в проекте проверка параметров выполняется на внешнем интерфейсе, в то время как внутренний интерфейс имеет дело только с бизнес-логикой, но этот метод не является разумным, обход страницы для выполнения http-запросов напрямую, будут системные исключения и риск грязных данных, поэтому рекомендуемое использованиеBean Validationна основеJSR 303 - Bean ValidationПлатформа проверки параметров выполняет проверку параметров, проверку формата и проверку дополнительного диапазона параметров во внутреннем интерфейсе, что позволяет не только избежать большинства системных исключений, вызванных отсутствующими параметрами, но и на этапе совместной отладки интерфейса. Повысьте эффективность совместного исследования и сократите время, затрачиваемое студентами переднего и заднего плана на устранение проблем во время совместного исследования.
Hibernate ValidatorЯвляется эталонной реализацией Bean Validation. Hibernate Validator обеспечивает реализацию всех встроенных ограничений спецификации JSR 303 и теперь обновлен доBean Validation 2.0 / JSR - 380, в дополнение к некоторым дополнительным ограничениям.Hibernate не является ORM для Hibernate
Например, ограничение (ограничение, ограничение) в Bean Validation, аннотация Bean Validation находится под javax.validation.constraints
ограничение | ограничение |
---|---|
@Null | Аннотированный элемент должен быть нулевым |
@NotNull | Аннотированный элемент не должен быть нулевым |
@AssertTrue | Аннотированный элемент должен быть истинным |
@AssertFalse | Аннотированный элемент должен быть ложным |
@Min(value) | Аннотированный элемент должен быть числом, значение которого должно быть больше или равно указанному минимальному значению. |
@Max(value) | Аннотированный элемент должен быть числом, значение которого должно быть меньше или равно указанному максимальному значению. |
@DecimalMin(value) | Аннотированный элемент должен быть числом, значение которого должно быть больше или равно указанному минимальному значению. |
@DecimalMax(value) | Аннотированный элемент должен быть числом, значение которого должно быть меньше или равно указанному максимальному значению. |
@Size(max, min) | Размер аннотируемого элемента должен быть в пределах указанного диапазона. |
@Digits (integer, fraction) | Аннотируемый элемент должен быть числом, и его значение должно быть в допустимом диапазоне. |
@Past | Аннотированный элемент должен быть датой в прошлом |
@Future | Аннотированный элемент должен быть датой в будущем |
@Pattern(value) | Аннотированный элемент должен соответствовать указанному регулярному выражению. |
Дополнительное ограничение Hibernate Validator / Hibernate Validator — лучшая реализация JSR-303, спецификация обновлена до JSR
ограничение | ограничение |
---|---|
Аннотированный элемент должен быть адресом электронной почты. | |
@Length | Размер аннотированной строки должен быть в пределах указанного диапазона. |
@NotEmpty | Аннотированная строка должна быть непустой. |
@Range | Аннотируемый элемент должен находиться в соответствующей области |
инструкции
Bean Validation встроен после JDK 1.6+, имя пакета — javax.validation.constraints.
Hibernate Validator должен представить пакет jar с именем org.hibernate.validator.constraints.
POM.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.1.Final</version>
</dependency>
класс сущности
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import java.util.Date;
public class ValidationDemo {
private String id;
@Length(min = 2, max = 6, message = "用户名长度要求在{min}-{max}之间")
@NotNull(message = "用户名不可为空")
private String userName;
@Email(message = "邮箱格式错误")
private String email;
@Past(message = "出生日期错误")
private Date birthDay;
@Min(value = 18, message = "年龄错误")
@Max(value = 80, message = "年龄错误")
private Integer age;
@Range(min = 0, max = 1, message = "性别选择错误")
private Integer sex;
}
Сравнительный @Valid и Validated, в соответствии с фактическим спросом необходимо выбрать
@Valid: нет функции группировки, ее можно использовать для методов, конструкторов, параметров метода и свойств членов (полей).Если проверяемый класс pojo также содержит объекты, подлежащие проверке, вам необходимо аннотировать @ на объекте, чтобы быть проверено действительным, чтобы проверить свойства члена в объекте, который нужно проверить
@Validated : предоставляет функцию группировки, которую можно использовать для типов, методов и параметров методов в соответствии с различными группами во время проверки параметров. Но не для свойств члена (поля).
Controller
-- @Valid 表示对该实体进行校验
-- BindingResult 则保存对参数的校验结果
@RequestMapping(value = "validation", method = RequestMethod.POST)
public JsonResult validation(@Valid @RequestBody ValidationDemo demo, BindingResult result) {
JsonResult jsonResult = new JsonResult();
if (result.hasErrors()) {
result.getAllErrors().forEach(err -> {
jsonResult.setCode(ApiConstants.JsonResult.FAIL);
jsonResult.setMsg(err.getDefaultMessage());
});
}
return jsonResult;
}
RequestBody
{
"age": 19,
"birthDay": "2019-04-14T09:05:39.604Z",
"email": "string",
"id": "string",
"sex": 0,
"userName": "string"
}
Response
{
"code": 1,
"msg": "邮箱格式错误",
"total": 0,
"totalpage": 0
}
Видно, что проверка параметров вступила в силу, так как электронная почта не соответствует правилам проверки @Email. Конкретные правила проверки см. в реализации @Email EmailValidator.java.
В сообщении об ошибке userName есть {min} - {max}?
RequestBody
{
"age": 19,
"birthDay": "2019-04-14T09:05:39.604Z",
"email": "string",
"id": "string",
"sex": 0,
"userName": ""
}
Response
{
"code": 1,
"msg": "用户名长度要求在2-6之间",
"total": 0,
"totalpage": 0
}
Hibernate Validator получает значения свойств min и max, определенных в @length через выражения EL
В приведенном выше Контроллере необходимо добавить BindingResult в параметры интерфейса для получения результата проверки.Каждому BindingResult соответствует @Valid один к одному.Если @Valid несколько, то для сохранения проверки требуется один BindResult результат результат теста
Расширенное использование, единая обработка результатов проверки и возврат к внешнему интерфейсу
В ResponseEntityExceptionHandler (строка 162) вызывается MethodArgumentNotValidException, если проверка не пройдена.
MethodArgumentNotValidException 描述:
Exception to be thrown when validation on an argument annotated with {@code @Valid} fails.
当使用@Valid注解的参数验证失败是抛出异常
Итак, обработайте MethodArgumentNotValidException в BaseController.
Controller
-- 对接口进行简化,通过异常捕获的方式对校验结果返回给前端
@RequestMapping(value = "validation", method = RequestMethod.POST)
public JsonResult validation(@Valid @RequestBody ValidationDemo demo) {
return null;
}
BaseController
if (e instanceof MethodArgumentNotValidException) {
res.setCode(ApiConstants.JsonResult.FAIL);
res.setMsg(JSONArray.toJSONString(((MethodArgumentNotValidException) e).getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.toList())));
}
Response
{
"code": 1,
"msg": "[\"年龄错误\",\"邮箱格式错误\"]",
"total": 0,
"totalpage": 0
}
Проверка пакетов
В реальном использовании возможно, что у нас есть несколько правил проверки для атрибута.В настоящее время нам нужно использовать групповую проверку.
Модернизированный объект
public class ValidationDemo {
private String id;
@Length(min = 2, max = 6, message = "用户名长度要求在{min}-{max}之间")
@NotNull(message = "用户名不可为空")
private String userName;
// 表示分组为Adult时使用该校验规则
@Email(message = "邮箱格式错误")
@NotBlank(message = "邮箱不可为空", groups = {ValidationDemo.Adult.class})
private String email;
@Past(message = "出生日期错误")
private Date birthDay;
@Min(value = 18, message = "年龄错误")
@Max(value = 80, message = "年龄错误")
private Integer age;
@Range(min = 0, max = 1, message = "性别选择错误")
private Integer sex;
// 添加两个分组
public interface Adult {
}
public interface Minor {
}
}
пройти тест
// 这里将分组设置为Minor,目的是不校验邮箱字段
@RequestMapping(value = "validation", method = RequestMethod.POST)
public JsonResult validation(@Validated({ValidationDemo.Adult.class}) @RequestBody ValidationDemo demo) {
return null;
}
RequestBody:
{
"age": 0,
"birthDay": "2019-04-14T10:39:08.501Z",
"email": "",
"id": "string",
"sex": 0,
"userName": "string"
}
Response:
{
"code": 1,
"msg": "[\"邮箱不可为空\"]",
"total": 0,
"totalpage": 0
}
Что, если в интерфейсе используется второстепенная группировка?
RequestBody:
{
"age": 0,
"birthDay": "2019-04-14T10:39:08.501Z",
"email": "",
"id": "string",
"sex": 0,
"userName": "string"
}
Response:
{
"code": 0,
"data": [
{}
],
"extra": "string",
"msg": "string",
"result": {},
"total": 0,
"totalpage": 0
}
Подсказки о том, что почтовый ящик не может быть пустым, нет, видно, что групповая проверка вступила в силу.
пользовательские правила проверки
Например, создайте собственную проверку формата даты
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = {DateFormatByPatternValidator.class})
public @interface DateFormatByPattern {
String pattern() default "yyyy-MM-dd HH:mm";
//默认错误消息
String message() default "日期格式错误";
//分组
Class<?>[] groups() default {};
//负载
Class<? extends Payload>[] payload() default {};
}
При этом создайте соответствующий валидатор
public class DateFormatByPatternValidator implements ConstraintValidator<DateFormatByPattern, String> {
private DateFormatByPattern dateFormatByPattern;
@Override
public void initialize(DateFormatByPattern constraintAnnotation) {
dateFormatByPattern = constraintAnnotation;
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
//假如参数为空的话,返回true,如果要对参数值进行非空校验的话,通过@NotNull来校验,这样与日期格式校验解耦
if (StringUtils.isNotBlank(value)) {
String pattern = dateFormatByPattern.pattern();
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
try {
dateFormat.parse(value);
} catch (ParseException e) {
return false;
}
}
return true;
}
}
Модернизированный объект
//使用自定义规则校验前端参数
@DateFormatByPattern(pattern = "yyyy-MM-dd")
//因为同时用到了分组校验,所以在stringDate上添加@Valid,使校验生效
@Valid
private String stringDate;
пройти тест
RequestBody:
{
"age": 0,
"birthDay": "2019-04-15T08:23:21.683Z",
"email": "",
"id": "string",
"sex": 0,
"stringDate": "string",
"userName": "string"
}
Response:
{
"code": 1,
"msg": "[\"日期格式错误\",\"邮箱不可为空\",\"年龄错误\"]",
"total": 0,
"totalpage": 0
}
Видно, что пользовательская проверка вступила в силу.
Справочная документация
Проверка пользовательской аннотации Hibernate Validation
Пользовательские аннотации валидатора
Интегрированная проверка компонентов SpringMVC 1.0 (JSR-303)