当前位置: 移动技术网 > IT编程>开发语言>Java > JSR303数据校验:springBoot校验前段数据是否合法

JSR303数据校验:springBoot校验前段数据是否合法

2020年08月10日  | 移动技术网IT编程  | 我要评论
JSR303校验JSR303校验添加依赖第一步: 给Bean添加校验注解:javax.validation.constraints,并定义自己的message提示第二步:开启校验功能分组校验(多场景的复杂校验)自定义校验编写一个自定义的校验注解创建ValidationMessages.properties 配置文件自定义校验器JSR303校验添加依赖 <!-- 字段校验一般用在实体类上 --> <!-- https://mvnrepository.com



JSR303校验

添加依赖

 <!-- 字段校验一般用在实体类上 --> <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.5.Final</version> </dependency> 

JSR 提供的校验注解:

@Null 被的注解元素必须为 null @NotNull 被注解的元素必须不为 null @AssertTrue 被注解的元素必须为 true @AssertFalse 被注解的元素必须为 false @Min(value) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值 @Max(value) 被注解的元素必须是一个数字,其值必须小于等于指定的最大值 @DecimalMin(value) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值 @DecimalMax(value) 被注解的元素必须是一个数字,其值必须小于等于指定的最大值 @Size(max=, min=) 被注解的元素的大小必须在指定的范围内   集合或数组 集合或数组的大小是否在指定范围内 @Digits (integer, fraction) 被注解的元素必须是一个数字,验证是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。 @Past 被注解的元素必须是一个过去的日期 @Future 被注解的元素必须是一个将来的日期 @Pattern(regex=,flag=) 被注解的元素必须符合指定的正则表达式 

Hibernate Validator 提供的校验注解:

@Email 被注释的元素必须是电子邮箱地址 @Length(min=,max=) 被注解的值大小必须在指定的范围内 @NotEmpty 被注解的字符串的必须非空 @Range(min=,max=,message=) 验证该值必须在合适的范围内 

第一步: 给Bean添加校验注解:javax.validation.constraints,并定义自己的message提示

@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("pms_brand") @ApiModel(value = "Brand对象}", description = "品牌") public class BrandEntity implements Serializable { private static final long serialVersionUID = 1L; /**
     * 品牌id
     */ @NotNull(message = "修改必须指定品牌id", groups = {UpdateGroup.class}) @Null(message = "新增不能指定id", groups = {AddGroup.class}) @TableId private Long brandId; * 介绍 */ private String descript; /**
     * 显示状态[0-不显示;1-显示]
     */ @NotNull(groups = {AddGroup.class, UpdateGroup.class}) @ListValue(value = {1, 0}, groups = {AddGroup.class, UpdateGroup.class}) //这里用了自定义校验功能,配合全文看 private Integer showStatus; /**
     * 检索首字母
     */ @NotEmpty(groups = {AddGroup.class}) @Pattern(regexp = "^[a-zA-Z]$", message = "检索首字母必须是一个字母", groups = {AddGroup.class, UpdateGroup.class}) private String firstLetter; /**
     * 排序
     */ @NotNull(groups = {AddGroup.class}) @Min(value = 0, message = "排序必须大于等于0", groups = {AddGroup.class, UpdateGroup.class}) private Integer sort; } 

第二步:开启校验功能

首先了解下:
关于@Valid和@Validated的区别联系

首先了解下:
关于@Valid和@Validated的区别联系

  • @Valid: javax.validation, 是javax,也是就是jsr303中定义的规范注解
  • @Validated: org.springframework.validation.annotation, 是spring自己封装的注解。参数校验失败抛出 org.springframework.validation.BindException 异常。
@Validated` 是 `@Valid` 的一个变种,扩展了 `@Valid` 的功能,支持 `group分组校验` 的写法,所以为了校验统一,尽量使用 `@Validated 
 /**
     * 保存
     * 如果不需要分组校验 就开启校验功能`@Valid` 如果bean添加了分组就不校验
     * @Validated({AddGroup.class})如果我们添加了分组校验 那么就要带上分组的class 
     * @Validated 对没添加分组的生效
     */ @RequestMapping("/save") public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand) { brandService.save(brand); return R.ok(); } 

分组校验(多场景的复杂校验)

  1. @NotBlank(message = “品牌名必须提交”,groups = {AddGroup.class,UpdateGroup.class})给校验注解标注什么情况需要进行校验
  2. @Validated({AddGroup.class})
  3. 默认没有指定分组的校验注解@NotBlank,在分组校验情况@Validated({AddGroup.class})下不生效,只会在@Validated生效;

**创建分组接口 **

package com.initialize.common.valid; public interface AddGroup { } 

自定义校验

编写一个自定义的校验注解

import com.initialize.common.valid.validator.ListValueConstraintValidator; import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; /**
 * 自定义的校验注解 和 自定义的校验器 是一对多的
 * 
 * 
 * 
 * 
 */ @Documented//记录注解 @Constraint(validatedBy = {ListValueConstraintValidator.class})//绑定自定义的校验器 @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})//注解可以加在什么地方 @Retention(RUNTIME)//表示运行时一直保留 public @interface ListValue { String message() default "{com.initialize.common.valid.annotation.ListValue.message}"; Class<?>[] groups() default {};//分组 Class<? extends Payload>[] payload() default {}; int[] value() default {};//可以输入int类型的数组值 } 

创建ValidationMessages.properties 配置文件

设置默认提示信息,这个文件名不是随便起的,是和自带的配置文件名一样,可全局搜索 ValidationMessages.properties可以发现有一个自带的额消息提示配置文件

com.initialize.common.valid.annotation.ListValue.message=必须提交指定的值 

自定义校验器

import com.initialize.common.valid.annotation.ListValue; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.HashSet; import java.util.Set; /**
 * @program: gulimall
 * @description: 自定义校验器
 * @author: Mr.Lu
 * @create: 2020-08-04 23:13
 **/ /**
 * 在自定义注解中 @Constraint(validatedBy = {}) 里面的ConstraintValidator其实是个接口 所以我们要实现这个接口
 * 接口的两个范型 第一个  指定注解  第二个  校验什么类型
 */ public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> { //将值设置进去方便下面的拍断校验方法 private Set<Integer> set = new HashSet<>(); /**
     * 初始化方法 会将ListValue标注的详细信息返回给我们
     *
     * @param constraintAnnotation 通过它拿值
     */ @Override public void initialize(ListValue constraintAnnotation) { int[] value = constraintAnnotation.value();//通过ListValue拿到value值 for (int val : value) { set.add(val); } } /**
     * 判断是否校验成功
     *
     * @param value   需要校验的值 就是给这个属性复的值
     * @param context 整个校验的上下文信息
     * @return
     */ @Override public boolean isValid(Integer value, ConstraintValidatorContext context) { //判读值是否在集合中 不包含返回false return set.contains(value); } } 

当我们校验失败的时候 我们统一交给全局异常处理器处理

import com.initialize.common.response.R; import com.initialize.common.response.ResultCode; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; /**
 * @program: gulimall
 * @description: 全局异常处理
 * @author: Mr.Lu
 * @create: 2020-08-04 20:31
 **/ @Slf4j @RestControllerAdvice(basePackages = "com.initialize.gulimall.product.controller") public class ExceptionControllerAdvice { /**
     * 参数错误异常
     */ @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class}) public R handleVaildException(HttpServletRequest request, Exception e) { //判断异常是否是MethodArgumentNotValidException if (e instanceof MethodArgumentNotValidException) { //将异常转为MethodArgumentNotValidException MethodArgumentNotValidException validException = (MethodArgumentNotValidException) e; //通过异常获取所有返回验证失败的结果 BindingResult bindingResult = validException.getBindingResult(); HashMap<String, String> errorMap = new HashMap<>(); //判断是否有错 if (bindingResult.hasErrors()) { log.info("### 请求参数错误: \t|对象名| \t\t\t|字段| \t\t\t|错误消息|"); //去除所以字段错误并且遍历处理 bindingResult.getFieldErrors().forEach((fieldError) -> { errorMap.put(fieldError.getField(), fieldError.getDefaultMessage()); log.error("### 请求参数错误: \t{} \t\t{} \t\t{}", fieldError.getObjectName(), fieldError.getField(), fieldError.getDefaultMessage()); }); log.error("### 请求路径RequestURL:{} ###", request.getRequestURL()); return R.error(10001, "参数无效").put("data", errorMap); } } else if (e instanceof BindException) { BindException bindException = (BindException) e; if (bindException.hasErrors()) { log.error("### 请求参数错误: {}", bindException.getAllErrors()); log.error("### 请求路径RequestURL:{} ###", request.getRequestURL()); } } return R.error(10001, "参数无效"); } /**
     * 处理所有不可知的异常
     */ @ExceptionHandler(Exception.class) public R handleOtherException(HttpServletRequest request, Exception e) { //打印异常堆栈信息 e.printStackTrace(); // 打印异常信息 log.error("### 不可知的异常:{} ###", e.getMessage()); log.error("### 请求路径RequestURL:{} ###", request.getRequestURL()); return R.error(4444, "系统繁忙,请稍后重试"); } } 

本文地址:https://blog.csdn.net/qq_46126559/article/details/107888606

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网