validator入门

validator中文文档地址和英文地址

https://docs.jboss.org/hibernate/validator/4.2/reference/zh-CN/html/validator-gettingstarted.html
https://docs.jboss.org/hibernate/validator/6.0/reference/en-US/html_single/#preface

@Service注解为什么不能使用在接口上,而是写在实现类上

接口中只有抽象方法、默认方法、静态方法,不包含构造器,不能实例化。而@Service标注这是一个spring管理的bean,需要实例化,相互矛盾,所以只能在实现类上使用@service注解。

@Validated可以加在接口上,实现类就可以不需要

@Validated
public interface DemoService {
    void demo();

//    注解只需要加载接口上 // 2 <= value <= 10
    void demotwo(@Size(min = 2, max = 10, message = "字段长度必须在2到10之间") String num);
}

自定义hibernate-validator校验

工具类ValidatorUtils

/**
 * hibernate-validator校验工具类
 * 参考文档:http://docs.jboss.org/hibernate/validator/6.0/reference/en-US/html_single/
 *
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0
 */
public class ValidatorUtils {

    private static ResourceBundleMessageSource getMessageSource() {
        ResourceBundleMessageSource bundleMessageSource = new ResourceBundleMessageSource();
        bundleMessageSource.setDefaultEncoding("UTF-8");
        bundleMessageSource.setBasenames("i18n/validation", "i18n/validation_common");
        return bundleMessageSource;
    }

    /**
     * 校验对象
     * @param object        待校验对象
     * @param groups        待校验的组
     * @throws RenException  校验不通过,则报RenException异常
     */
    public static void validateEntity(Object object, Class<?>... groups)
            throws RenException {
        Locale.setDefault(LocaleContextHolder.getLocale());
        Validator validator = Validation.byDefaultProvider().configure().messageInterpolator(
                new ResourceBundleMessageInterpolator(new MessageSourceResourceBundleLocator(getMessageSource())))
                .buildValidatorFactory().getValidator();
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty()) {
        	ConstraintViolation<Object> constraint = constraintViolations.iterator().next();
            throw new RenException(constraint.getMessage());
        }
    }
}
// 自定义资源绑定指定的properties文件
ResourceBundleMessageSource bundleMessageSource = new ResourceBundleMessageSource();
        bundleMessageSource.setDefaultEncoding("UTF-8");
        bundleMessageSource.setBasenames("i18n/validation", "i18n/validation_common");
       

在这里插入图片描述

添加约束

/**
 * 用户管理
 */
@Data
@ApiModel(value = "用户管理")
public class SysUserDTO implements Serializable {
    private static final long serialVersionUID = 1L;

	@ApiModelProperty(value = "id")
	@Null(message="{id.null}", groups = AddGroup.class)
	@NotNull(message="{id.require}", groups = UpdateGroup.class)
	private Long id;

	@ApiModelProperty(value = "用户名", required = true)
	@NotBlank(message="{sysuser.username.require}", groups = DefaultGroup.class)
	private String username;

	@ApiModelProperty(value = "密码")
	@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
	@NotBlank(message="{sysuser.password.require}", groups = AddGroup.class)
	private String password;

	@ApiModelProperty(value = "姓名", required = true)
	@NotBlank(message="{sysuser.realname.require}", groups = DefaultGroup.class)
	private String realName;

	@ApiModelProperty(value = "头像")
	private String headUrl;

	@ApiModelProperty(value = "性别   0:男   1:女    2:保密", required = true)
	@Range(min=0, max=2, message = "{sysuser.gender.range}", groups = DefaultGroup.class)
	private Integer gender;

	@ApiModelProperty(value = "邮箱", required = true)
	@NotBlank(message="{sysuser.email.require}", groups = DefaultGroup.class)
	@Email(message="{sysuser.email.error}", groups = DefaultGroup.class)
	private String email;

	@ApiModelProperty(value = "手机号", required = true)
	@NotBlank(message="{sysuser.mobile.require}", groups = DefaultGroup.class)
	private String mobile;

	@ApiModelProperty(value = "部门ID", required = true)
	@NotNull(message="{sysuser.deptId.require}", groups = DefaultGroup.class)
	private Long deptId;

	@ApiModelProperty(value = "超级管理员   0:否   1:是")
	@Range(min=0, max=1, message = "{sysuser.superadmin.range}", groups = DefaultGroup.class)
	private Integer superAdmin;

	@ApiModelProperty(value = "状态  0:停用    1:正常", required = true)
	@Range(min=0, max=1, message = "{sysuser.status.range}", groups = DefaultGroup.class)
	private Integer status;

	@ApiModelProperty(value = "备注")
	private String remark;

	@ApiModelProperty(value = "创建时间")
	@JsonProperty(access = JsonProperty.Access.READ_ONLY)
	@JsonFormat(pattern = DateUtils.DATE_TIME_PATTERN)
	private Date createDate;

	@ApiModelProperty(value = "角色ID列表")
	private List<Long> roleIdList;

	@ApiModelProperty(value = "岗位ID列表")
	private List<Long> postIdList;

	@ApiModelProperty(value = "部门名称")
	private String deptName;

}

校验约束

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();

Car car = new Car(null, "DD-AB-123", 4);

Set<ConstraintViolation<Object>> constraintViolations = validator.validate(car);
// validator.validate(car, DefaultGroup.class);

if (!constraintViolations.isEmpty()) {
	ConstraintViolation<Object> constraint = constraintViolations.iterator().next();
    throw new RenException(constraint.getMessage());
}
// validate()方法会返回一个set的ConstraintViolation的实例的集合, 我们可以通过遍历它来查看有哪些验证错误, 如果一个对象没有校验出问题的话,那么validate() 会返回一个空的set对象
assertEquals(1, constraintViolations.size());
assertEquals("may not be null", constraintViolations.iterator().next().getMessage());


在这里插入图片描述

Controller使用

新增和修改都需要校验对象数据使用 ValidatorUtils.validateEntity校验工具,如果是校验单个值使用AssertUtils.isArrayEmpty断言工具

@RestController
@RequestMapping("post")
@Api(tags="岗位管理")
public class SysPostController {
    @Autowired
    private SysPostService sysPostService;
    
	@PostMapping
    @ApiOperation("保存")
    @LogOperation("保存")
    @PreAuthorize("hasAuthority('sys:post:save')")
    public Result save(@RequestBody SysPostDTO dto){
        //效验数据
        ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);

        sysPostService.save(dto);

        return new Result();
    }
}

	@PutMapping
    @ApiOperation("修改")
    @LogOperation("修改")
    @PreAuthorize("hasAuthority('sys:post:update')")
    public Result update(@RequestBody SysPostDTO dto){
        //效验数据
        ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);

        sysPostService.update(dto);

        return new Result();
    }
    
	@DeleteMapping
    @ApiOperation("删除")
    @LogOperation("删除")
    @PreAuthorize("hasAuthority('sys:post:delete')")
    public Result delete(@RequestBody Long[] ids){
        //效验数据
        AssertUtils.isArrayEmpty(ids, "id");

        sysPostService.delete(ids);

        return new Result();
    }

添加约束的常见取舍

@NotNull

@NotNull 常用在数据类型为Long,Integer的基础数据类型上,可以配合@Size、@Max、@Min对数值进行大小的控制

主键和数字校验

@ApiModelProperty(value = "编号")
@NotNull(message = "编号不能为空")
@JsonFormat(shape = Shape.STRING)
private Long id;

@ApiModelProperty(value = "价格")
@NotNull(message = "价格不能为空")
@Min(value = 100, message = "价格不能低于100")
@Max(value = 5000, message = "价格不能超过5000")
private Integer price;

@ApiModelProperty(value = "数量")
@NotNull(message = "数量不能为空")
@Size(min = 10, max = 50, message = "数量必须不低于10不超过50")
private Integer num;

@NotEmpty 数组集合校验

@NotEmpty 常用在集合类和数组类型上,也可以配合@Size进行大小的控制。

@ApiModelProperty(value = "材料保存列表", required = true)
@NotEmpty(message = "存货清单列表不能为空")
@Size(min = 1, message = "至少需要一条数据")
private List<MaterialAcceptanceItemsSaveVo> itemsSaveList;

@NotBlank 字符串校验

@NotBlank 只用于String数据类型上,可以和@Len配合使用限制字符长度。

@ApiModelProperty(value = "供应商", required = true)
@NotBlank(message = "供应商不能为空")
@Len(min = 1, max = 500)
private String provider;

@ApiModelProperty(value = "发票号", required = true)
@Len(min = 0, max = 250)
private String invoiceNo;

BigDecimal数据类型校验

Long数据类型防止精度丢失,添加注解:@JsonFormat(shape = Shape.STRING)
BigDecimal数据类型的限制注解使用:@DecimalMin、@DecimalMax、@Digits

@ApiModelProperty(value = "报账总金额")
@DecimalMin(value = "0", inclusive = false, message = "报账总金额必须大于0")
@Digits(integer = 10, fraction = 2, message = "报账总金额 最大长度:10,允许精度:2")
private BigDecimal financeMoney;

status值校验

// @Pattern(regexp = "^[0,1]{1}$",message = "帐号启用状态:0->禁用;1->启用")
@Range(min=0, max=1,message = "帐号启用状态:0->禁用;1->启用")
@NotNull(message = "帐号启用状态不能为空")
@ApiModelProperty(value = "帐号启用状态:0->禁用;1->启用")
private Integer status;

@正则匹配

@ApiModelProperty(value = "是否有符号位 Y:有 N:无")
@Pattern(regexp = "^[YN]{1}$", message = "是否有符号位 Y:有 N:无",  groups = DefaultGroup.class)
private String sign;

@Null 被注解的元素必须为 null
@NotNull 被注解的元素必须不为 null
@AssertTrue 被注解的元素必须为 true
@AssertFalse 被注解的元素必须为 false
@Min(value) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注解的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注解的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注解的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注解的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注解的元素必须是一个过去的日期
@Future 被注解的元素必须是一个将来的日期
@Pattern(value) 被注解的元素必须符合指定的正则表达式
Hibernate Validator 扩展注解
@Email 被注解的元素必须是电子邮箱地址
@Length 被注解的字符串的大小必须在指定的范围内
@NotEmpty 被注解的字符串的必须非空
@Range 被注解的元素必须在合适的范围内

javax.validation 和 Hibernate-Validator区别

参考: https://www.ngui.cc/el/1183725.html?action=onClick
javax.validation

自定校验

@Data
@ApiModel(value = "测量参数的构型")
public class MeasureQarTypeDTO {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "构型名称")
    private String qarType;
    private Integer qarTypeId;
    @ApiModelProperty(value = "基础参数路径可以有型号")
    private List<String> paths;
    private List<Integer> ids;
}

import javax.validation.constraints.NotNull;
import java.util.List;

@Data
@ApiModel(value = "测量参数的构型")
public class MeasureQarTypeDTO {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "构型名称")
    @NotNull(message = "qarType cannot be null") // 非空校验
    private String qarType;

    private Integer qarTypeId;

    @ApiModelProperty(value = "基础参数路径可以有型号")
    @NotNull(message = "paths cannot be null") // 非空校验
    private List<String> paths; // 注意:这里仅校验paths本身不能为null,如果需要校验paths中的元素也不能为null,则需要自定义校验注解或方法

    private List<Integer> ids;
}

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = NotEmptyListValidator.class)
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmptyList {
    String message() default "{NotEmptyList.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        NotEmptyList[] value();
    }
}

class NotEmptyListValidator implements ConstraintValidator<NotEmptyList, List<?>> {
    @Override
    public boolean isValid(List<?> list, ConstraintValidatorContext context) {
        if (list == null) return true; // 或者根据需求处理null情况
        for (Object element : list) {
            if (element == null || "".equals(element)) {
                return false;
            }
        }
        return true;
    }
}
@ApiModelProperty(value = "基础参数路径可以有型号")
@NotEmptyList(message = "Each path in paths cannot be empty")
private List<String> paths;


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值