JSR303校验使用以及如何自定义校验注解

一,JSR303

JSR303是Java为Bean数据合法性校验提供给的标准框架,已经包含在 JavaEE6.0中,JSR303通过在Bean 属性中标注类似 @NotNull @Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean进行验证。

二,JSR303常用注解

注解作用
@Null被注解的元素必须为null
@NotNull被注解的元素必须不为null
@NotBlank用于String类型参数校验,检查字符串不能为null且trim()之后的size>0。
@NotEmpty被注解的字符串的值必须非空
@AssortTrue被注解的元素必须为true
@AssortFalse被注解的元素必须为false
@Min(value)被注解的元素必须是一个数字,其值必须小于等于指定的最小值
@Max(value)被注解的元素必须是一个数字,其值必须大于等于指定的最大值
@Size(max,min)被注解的元素的大小必须在指定的范围内
@Digits(integer,fraction)被注解的元素必须是一个数字,其值必须在可接受范围内
@Past被注解元素必须是一个过去的日期
@Future被注解元素必须是一个将来的日期
@Pattern(value)被注解的元素必须符合指定的正则表达式
@Email被注解的元素必须是电子邮箱地址
@Length被注解的字符串的大小必须在指定的范围内
@Range被注解的元素必须在合适的范围内

三,如何使用这些注解进行校验

1.引入

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>2.7.16</version>
        </dependency>

2.在实体类的成员属性上标注上注解

package com.wufeng.gulimall.product.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import org.hibernate.validator.constraints.URL;

import javax.validation.constraints.*;


@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 品牌id
	 */
	@TableId
	private Long brandId;
	/**
	 * 品牌名
	 */
	@NotBlank(message = "品牌名必须提交")
	private String name;
	/**
	 * 品牌logo地址
	 */
	@URL(message = "logo必须是一个url格式的地址")
	private String logo;
	/**
	 * 介绍
	 */
	private String descript;
	/**
	 * 显示状态[0-不显示;1-显示]
	 */
	private Integer showStatus;
	/**
	 * 检索首字母
	 */
	@NotNull
	@Pattern(regexp = "^[A-Za-z]$", message = "检索首字母必须为字母")
	private String firstLetter;
	/**
	 * 排序
	 */
	@NotNull
	@Min(value = 0, message = "排序必须大于等于0")
	private Integer sort;

}

3.Controller中的方法上添加注解@Valid注解

	@RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand/*, BindingResult result*/){

//        //数据校验不通过
//        if (result.hasErrors()) {
//            HashMap<String, String> map = new HashMap<>();
//            //1.获取校验的错误结果
//            result.getFieldErrors().forEach((item)->{
//
//                //2.获取错误的属性名字
//                String field = item.getField();
//                String message = item.getDefaultMessage();
//                map.put(field,message);
//
//            });
//            return R.error(400,"提交的数据不合法").put("data",map);
//        }

		brandService.save(brand);
        return R.ok();
    }

四,分组校验

1.编写分组标识接口

public interface AddGroup {
}
public interface UpdateGroup{
}

2.实体类中的注解添加分组属性

package com.wufeng.gulimall.product.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;
import java.util.Date;

import com.wufeng.common.valid.AddGroup;
import com.wufeng.common.valid.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.URL;

import javax.validation.constraints.*;

@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 品牌id
	 */
	@Null(message = "新增不能指定品牌id",groups = {UpdateGroup.class})
	@NotNull(message = "修改必须指定品牌id",groups = {AddGroup.class})
	@TableId
	private Long brandId;
	/**
	 * 品牌名
	 */
	@NotBlank(message = "品牌名必须提交",groups = {AddGroup.class,UpdateGroup.class})
	private String name;
	/**
	 * 品牌logo地址
	 */
	@URL(message = "logo必须是一个url格式的地址")
	private String logo;
	/**
	 * 介绍
	 */
	private String descript;
	/**
	 * 显示状态[0-不显示;1-显示]
	 */
	private Integer showStatus;
	/**
	 * 检索首字母
	 */
	@NotNull
	@Pattern(regexp = "^[A-Za-z]$", message = "检索首字母必须为字母")
	private String firstLetter;
	/**
	 * 排序
	 */
	@NotNull
	@Min(value = 0, message = "排序必须大于等于0")
	private Integer sort;

}

3.在Controller的方法中标注@Validated注解并添加使用的分组

    @RequestMapping("/save")
    //@RequiresPermissions("product:brand:save")
    public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand/*, BindingResult result*/){

//        //数据校验不通过
//        if (result.hasErrors()) {
//            HashMap<String, String> map = new HashMap<>();
//            //1.获取校验的错误结果
//            result.getFieldErrors().forEach((item)->{
//
//                //2.获取错误的属性名字
//                String field = item.getField();
//                String message = item.getDefaultMessage();
//                map.put(field,message);
//
//            });
//            return R.error(400,"提交的数据不合法").put("data",map);
//        }

		brandService.save(brand);
        return R.ok();
    }

这时,如果调用的是save这个方法,会校验BrandEntity实体中标注了该AddGroup.class组的注解的成员属性,没有AddGroup.class这个属性的校验注解不生效。

五,自定义校验注解

1.编写一个自定义校验注解

@Constraint(
      validatedBy = {}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ListValue {

  //校验出错后,message去ValidationMessages.properties文件里取com.wufeng.common.valid.ListValue.message这个值
  String message() default "{com.wufeng.common.valid.ListValue.message}";

  //支持分组校验
  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};

  //自己定义的属性
  int[] vals() default {};
}

2.编写一个自定义校验器

//必须实现ConstraintValidator接口,第一个泛型是你的校验注解,第二个泛型需要校验的属性的类型
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {

     private Set<Integer> set = new HashSet<>();
 
     //初始化方法,写你自己的逻辑
     @Override
     public void initialize(ListValue constraintAnnotation) {
     	//获取注解中定义的vals的值,添加到set中
         int[] vals = constraintAnnotation.vals();
         for (int val : vals) {
             set.add(val);
         }
     }
 
     //校验方法,false校验信息有误,写你自己的逻辑
     @Override
     public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
     	//校验的值是否是set中的值,是-true,否-false
         return set.contains(value);
     }
}

3.关联自定义校验器和自定义校验注解,在自定义注解中关联自定义校验器(可以有多个)

@Constraint(
 	//关联校验器,校验器是ListValueConstraintValidator.class这个类,可以写多个校验类
     validatedBy = {ListValueConstraintValidator.class}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ListValue {

     //校验出错后,message去ValidationMessages.properties文件里取com.wufeng.common.valid.ListValue.message这个值
     String message() default "{com.wufeng.common.valid.ListValue.message}";
 
     //支持分组校验
     Class<?>[] groups() default {};
 
     Class<? extends Payload>[] payload() default {};
 
     //自己定义的属性
     int[] vals() default {};
}

4.ValidationMessages.properties中配置message信息

也可以不配置该文件,但是需要在使用注解时带上message属性

com.wufeng.common.valid.ListValue.message=Must be a value within the specified range

在这里插入图片描述

5.在实体类中使用自定义注解(在实体类中的需要校验的属性上使用该注解)

  @ListValue(vals = {0,1},groups = {AddGroup.class})
  private Integer showStatus;

6.测试方法

    /**
     * 保存
     */
    @RequestMapping("/save")
    public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand){

		brandService.save(brand);
        return R.ok();
    }

7.测试效果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值