数据校验
数据校验
element前端自定义校验规则
-
:rules="dataRule" 绑定数据校验规则方法
-
firstLetter: [ { validator: (rule, value, callback) => { if (value == "") { callback(new Error("首字母必须填写不能为空")); } else if (!/^[a-zA-Z]$/.test(value)) { callback(new Error("首字母必须a-z或者A-Z之间")); } else { callback(); } }, trigger: 'blur' } ],
-
firstLetter
是prop属性值validator
自定义校验规则trigger
出发时间rule
当前自定义校验规则对象callback
回调函数
后端数据校验
使用JSR303规则进行校验
什么是jsr 303
-
jsr303 常用注解
以上是
bean validation
自带的注解hibernate validation
在上面的基础上增加了一些注解
简单校验
-
引入pom依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
-
在需要进行数据校验的类中添加注解,例如:
package com.cui.gulimall.modules.product.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotEmpty; import java.io.Serializable; import java.util.Date; /** * 品牌 * * @author cui cui@gmail.com * @since 1.0.0 2022-05-25 */ @Data @ApiModel(value = "品牌") public class BrandDTO implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "品牌id") private Long brandId; @ApiModelProperty(value = "品牌名") @NotEmpty private String name; @ApiModelProperty(value = "品牌logo地址") private String logo; @ApiModelProperty(value = "介绍") private String descript; @ApiModelProperty(value = "显示状态[0-不显示;1-显示]") private Integer showStatus; @ApiModelProperty(value = "检索首字母") private String firstLetter; @ApiModelProperty(value = "排序") private Integer sort; }
-
在controller层中添加
@Validated
注解或者@Valid
开启数据校验@PostMapping("save") @ApiOperation("保存") @LogOperation("保存") public Result save(@Validated @RequestBody BrandDTO dto, BindingResult bindingResult) { System.out.println(ObjectUtils.isEmpty(bindingResult)); if (bindingResult.hasErrors()) { List<FieldError> fieldErrors = bindingResult.getFieldErrors(); System.out.println(fieldErrors.isEmpty()); return new Result().error("数据校验失败"); } //效验数据 ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); brandService.save(dto); return new Result(); }
-
BindingResult
封装了数据校验结果等信息hasErrors
获得数据校验结果 如果校验失败返回false -
在进行数据校验的时候一定要看清参数位置写的是哪个类不然就会像我这个虎比一样找半天没注意参数位置
分组校验
-
列入:当我们添加数据时不需要上传用户id但是当我们修改数据时需要根据用户id修改,所以需要有两组不同的校验规则
-
每一个校验注解都含有这三个属性
String message() default "{javax.validation.constraints.NotEmpty.message}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { };
其中groups为分组的属性, 类型为
Class<?>[]
没有什么特殊意义所以只需要定义几个接口来区分不同分组的校验规则 -
数据接收类代码
package com.cui.gulimall.modules.product.dto; import com.cui.gulimall.modules.product.check.AddCheck; import com.cui.gulimall.modules.product.check.ModifyCheck; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.hibernate.validator.constraints.URL; import javax.validation.constraints.*; import java.io.Serializable; import java.util.Date; /** * 品牌 * * @author cui cui@gmail.com * @since 1.0.0 2022-05-25 */ @Data @ApiModel(value = "品牌") public class BrandDTO implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "品牌id") @NotNull(message = "id不能为空",groups = {ModifyCheck.class}) @Null(message = "新增品牌id不能指定",groups = {AddCheck.class}) private Long brandId; @ApiModelProperty(value = "品牌名") @NotEmpty(message = "品牌名称不能为空",groups = {AddCheck.class,ModifyCheck.class}) private String name; @ApiModelProperty(value = "品牌logo地址") @URL(message = "logo地址不能为空" ,groups = {AddCheck.class,ModifyCheck.class}) private String logo; @ApiModelProperty(value = "介绍") private String descript; @ApiModelProperty(value = "显示状态[0-不显示;1-显示]") @NotNull(groups = {AddCheck.class},message = "显示状态不能为空") @Min(value = 0,groups = {AddCheck.class,ModifyCheck.class},message = "该数据只能为0或1") @Max(value = 1,groups = {AddCheck.class,ModifyCheck.class},message = "该数据只能为0或1") private Integer showStatus; @ApiModelProperty(value = "检索首字母") @Pattern(regexp = "^[a-zA-Z]$",message = "必须是一个字母",groups = {AddCheck.class, ModifyCheck.class}) private String firstLetter; @ApiModelProperty(value = "排序") @Min(value = 0,message = "排序数字必须大于0",groups = {AddCheck.class, ModifyCheck.class}) private Integer sort; }
-
控制层代码
@PostMapping("save") @ApiOperation("保存") @LogOperation("保存") public Result save(@Validated(AddCheck.class) @RequestBody BrandDTO dto, BindingResult bindingResult) { System.out.println(ObjectUtils.isEmpty(bindingResult)); if (bindingResult.hasErrors()) { List<FieldError> fieldErrors = bindingResult.getFieldErrors(); Map<String, Object> map = new HashMap<>(); fieldErrors.forEach(fieldError -> { map.put(fieldError.getField(), fieldError.getDefaultMessage()); }); return new Result().error(map); } //效验数据 ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class); brandService.save(dto); return new Result(); }
-
嵌套校验:就是在一个类中需要包含另一个类,而另一个类也需要校验. 需要在那个类的属性也需要校验 只需在那个嵌套的类属性上添加
@Valid
如果不添加则不会校验 -
全局异常处理
package com.cui.gulimall.modules.product.ex; import com.cui.gulimall.common.utils.Result; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.validation.BindException; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import java.util.stream.Collectors; /** * @author 崔令雨 * @date 2022/6/2 11:07 * @Version 1.0 */ @RestControllerAdvice @Slf4j public class GlobalExceptionHandl { @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class, ConstraintViolationException.class}) public Result abnormalDataValidation(Exception e) { log.info("进入全局异常处理"); if (e instanceof MethodArgumentNotValidException) { MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e; return new Result().error(HttpStatus.BAD_REQUEST.value(), exception .getBindingResult() .getAllErrors() .stream() .map(ObjectError::getDefaultMessage) .collect(Collectors.joining(";"))); } if (e instanceof ConstraintViolationException) { ConstraintViolationException exception = (ConstraintViolationException) e; return new Result().error(HttpStatus.BAD_REQUEST.value(), exception.getConstraintViolations() .stream() .map(ConstraintViolation::getMessage) .collect(Collectors.joining(";"))); } if (e instanceof BindException) { BindException bindException = (BindException) e; return new Result().error(HttpStatus.BAD_REQUEST.value(), bindException.getAllErrors() .stream() .map(ObjectError::getDefaultMessage) .collect(Collectors.joining(";"))); } return new Result(); } @ExceptionHandler(RuntimeException.class) public Result exceptionHandler(Exception e) { return new Result().error(e.getMessage()); } }
自定义校验
-
创建自定义注解
package com.cui.gulimall.modules.product.validator; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * @author 崔令雨 * @date 2022/6/2 11:33 * @Version 1.0 */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) @Repeatable(EnumString.List.class) @Documented @Constraint(validatedBy = EnumStringValidator.class)//标明由哪个类执行校验逻辑 public @interface EnumString { String message() default "value not in enum values."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; /** * @return date must in this value array */ String[] value(); /** * Defines several {@link EnumString} annotations on the same element. * * @see EnumString */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) @Retention(RUNTIME) @Documented @interface List { EnumString[] value(); } }
-
创建自定义校验类
package com.cui.gulimall.modules.product.validator; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.Arrays; import java.util.List; /** * @author 崔令雨 * @date 2022/6/2 11:35 * @Version 1.0 */ public class EnumStringValidator implements ConstraintValidator<EnumString, String> { private List<String> list; @Override public void initialize(EnumString constraintAnnotation) { list = Arrays.asList(constraintAnnotation.value()); } @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (value == null) { return false; } return list.contains(value); } }
-
在属性上添加校验属性
@ApiModelProperty(value = "显示状态[0-不显示;1-显示]") @EnumString(value = {"1", "0"}, message = "显示状态只能为0或1", groups = AddCheck.class) private Integer showStatus;
作者:01cui
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.