Java类属性字段校验(validation的使用) 您所在的位置:网站首页 校验工具怎么用 Java类属性字段校验(validation的使用)

Java类属性字段校验(validation的使用)

2023-07-26 02:46| 来源: 网络整理| 查看: 265

Java类属性字段校验(validation的使用) 1、需求来源:日常校验需求2、validation介绍2-1、常见的注解2-2、快速入门1、简单校验2、自定义校验注解3、通用的Validtor校验工具类

1、需求来源:日常校验需求

日常开发中,我们时常需要提供可靠的 API 接口,此时对于请求的入参就需要校验,以保证最终数据入库的正确性,这就成了必不可少的活。例如说,用户注册时,会校验手机格式的正确性、邮箱格式的正确性、密码非弱密码等。

但是如果使用 if-else 这种代码去校验, 那么需要校验的地方有很多情况下,代码量就会变的十分臃肿,若是一个类请求参数校验字段又多的化,相信各位小伙伴对不会开心,这么干肯定不合适,代码也不优雅,那么如何解决这个问题呢?

答案就是下面要介绍的 validation

2、validation介绍

validation 技术在Java中运用最早在2009 年,Java 官方提出了 Bean Validation 规范,而后经历了JSR303、JSR349、JSR380 三次标准的更迭,发展到了 2.0 。

Bean Validation 和 我们以前学习过的 JPA 一样,只提供规范,不提供具体的实现。因此实际使用过程,常用的是 hibernate 的校验组件:org.hibernate.hibernate-validator

2-1、常见的注解

通常情况下,在javax.validation.constraints 包下,定义了一系列的约束(constraint)注解,一共 22 个注解,快速略过即可。如下:

空和非空检查

@NotBlank:只能用于字符串不为 null ,并且字符串 .trim() 以后 length 要大于 0 。@NotEmpty:集合对象的元素不为 0 ,即集合不为空 。@NotNull:不能为 null 。@Null:必须为 null 。

数值检查

@DecimalMax(value):被注释的元素必须是一个数字,其值必须小于等于指定的最大值。@DecimalMin(value):被注释的元素必须是一个数字,其值必须大于等于指定的最小值。@Digits(integer, fraction):被注释的元素必须是一个数字,其值必须在可接受的范围内。@Positive:判断正数。@PositiveOrZero:判断正数或 0 。@Max(value):该字段的值只能小于或等于该值。@Min(value):该字段的值只能大于或等于该值。@Negative:判断负数。@NegativeOrZero:判断负数或 0 。

Boolean 值检查

@AssertFalse:被注释的元素必须为 true 。@AssertTrue:被注释的元素必须为 false 。

长度检查

@Size(max, min):检查字段的 size 是否在 min 和 max 之间,可以是字符串、数组、集合、Map 等。

日期检查

@Future:被注释的元素必须是一个将来的日期。@FutureOrPresent:判断日期是否是将来或现在日期。@Past:检查该字段的日期是在过去。@PastOrPresent:判断日期是否是过去或现在日期。

其它检查

@Email:被注释的元素必须是电子邮箱地址。@Pattern(value):被注释的元素必须符合指定的正则表达式。

Hibernate Validator 附加的约束注解,在org.hibernate.validator.constraints 包下,定义了一系列的约束(constraint)注解。常见的如示。

@Range(min=, max=):被注释的元素必须在合适的范围内。@Length(min=, max=):被注释的字符串的大小必须在指定的范围内。@URL(protocol=,host=,port=,regexp=,flags=):被注释的字符串必须是一个有效的 URL 。@SafeHtml:判断提交的 HTML 是否安全。例如说,不能包含 javascript 脚本等等。

其他的就不一一列举了,有感兴趣的小伙伴可以去源码包看看。

@Valid和 @Validated

@Valid 注解,是 Bean Validation 所定义,可以添加在普通方法、构造方法、方法参数、方法返回、成员变量上,表示它们需要进行约束校验。

@Validated 注解,是 Spring Validation 锁定义,可以添加在类、方法参数、普通方法上,表示它们需要进行约束校验。同时,@Validated 有 value 属性,支持分组校验。

对于初学者来说,很容易搞混 @Valid 和 @Validated 注解。

① 声明式校验:Spring Validation 仅对 @Validated 注解,实现声明式校验。

② 分组校验:Bean Validation 提供的 @Valid注解,因为没有分组校验的属性,所以无法提供分组校验。此时,我们只能使用 @Validated 注解。

③ 嵌套校验:相比来说,@Valid注解的地方,多了【成员变量】。这就导致,如果有嵌套对象的时候,只能使用@Valid注解。

2-2、快速入门 在 pom.xml 文件中,引入相关依赖。 org.springframework.boot spring-boot-starter-parent 2.2.1.RELEASE 4.0.0 com.raos validation-demo 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-web org.projectlombok lombok compile org.springframework.boot spring-boot-starter-test test

spring-boot-starter-web 依赖里,已经默认引入 hibernate-validator 依赖,所以本示例使用的是 Hibernate Validator 作为 Bean Validation 的实现框架。

1、简单校验 编写实体类(这里以常用的用户注册为场景) @Data public class SysUser { private Long userId; /** * 账号 */ @NotBlank(message = "用户名不能为空") @Size(min = 6, message = "用户名长度不能小于6个字符") private String username; /** * 密码 */ @NotEmpty(message = "密码不能为空") @Size(min = 8, message = "密码长度不能小于8个字符") private String password; /** * 手机号 */ @NotBlank(message = "手机号不能为空") @Size(min = 11, max = 11, message = "手机号长度不对") private String mobile; } 编写前端控制器 @RestController @RequestMapping("/user") public class SysUserController { @PostMapping("/add") public R addUser(@RequestBody @Valid SysUser sysUser) { System.out.println("走到这里说明校验成功"); System.out.println(sysUser); return R.ok(R.SUCCESS_MSG); } } 编写前端响应封装实体 public class R extends HashMap { private static final long serialVersionUID = 1L; public static final String SUCCESS_MSG = "操作成功!"; public static final String FAIL_MSG = "操作失败!"; public R() { this.put((String) "code", 0); } public static R error() { return error(500, "未知异常,请联系管理员"); } public static R error(String msg) { return error(500, msg); } public static R error(int code, String msg) { R r = new R(); r.put((String) "code", code); r.put((String) "msg", msg); return r; } public static R ok(String msg) { R r = new R(); r.put((String) "msg", msg); return r; } public static R ok(Object object) { R r = new R(); r.put("result", object); return r; } public static R ok(int code, String msg) { R r = new R(); r.put((String) "code", code); r.put((String) "msg", msg); return r; } public static R ok(Map map) { R r = new R(); r.putAll(map); return r; } public static R ok() { return new R(); } public R put(String key, Object value) { super.put(key, value); return this; } } 编写自定义异常(用于后续业务抛出异常错误) public class RRException extends RuntimeException { private static final long serialVersionUID = 1L; private String msg; private int code = 500; public RRException(String msg) { super(msg); this.msg = msg; } public RRException(String msg, Throwable e) { super(msg, e); this.msg = msg; } public RRException(String msg, int code) { super(msg); this.msg = msg; this.code = code; } public RRException(String msg, int code, Throwable e) { super(msg, e); this.msg = msg; this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } }

当访问/user/add这个post接口时,如果参数不符合Model中定义的话,程序中就回抛出400异常状态码,并提示错误信息,如下所示。

{ "timestamp": "2021-05-20T01:08:28.831+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "Size.sysUser.mobile", "Size.mobile", "Size.java.lang.String", "Size" ], "arguments": [ { "codes": [ "sysUser.mobile", "mobile" ], "arguments": null, "defaultMessage": "mobile", "code": "mobile" }, 11, 11 ], "defaultMessage": "手机号长度不对", "objectName": "sysUser", "field": "mobile", "rejectedValue": "155833013", "bindingFailure": false, "code": "Size" } ], "message": "Validation failed for object='sysUser'. Error count: 1", "path": "/user/add" } 2、自定义校验注解

虽然 JSR303 和 Hibernate Validtor 已经提供了很多校验注解,但是当面对复杂参数校验时,还是不能满足我们的要求,这时候我们就需要 自定义校验注解。

下面以“List数组中不能含有null元素”为实例自定义校验注解 1、注解定义如示。

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD}) @Retention(RUNTIME) @Documented @Constraint(validatedBy = ListNotHaveNullValidatorImpl.class)//此处指定了注解的实现类 public @interface ListNotHaveNull { /** * 添加value属性,可以作为校验时的条件,若不需要,可去掉此处定义 */ int value() default 0; String message() default "List集合中不能含有null元素"; Class[] groups() default {}; Class[] payload() default {}; /** * 定义List,为了让Bean的一个属性上可以添加多套规则 */ @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Documented @interface List { ListNotHaveNull[] value(); } }

2、编写自定义校验实现类

@Service public class ListNotHaveNullValidatorImpl implements ConstraintValidator { private int value; @Override public void initialize(ListNotHaveNull constraintAnnotation) { //传入value 值,可以在校验中使用 this.value = constraintAnnotation.value(); } public boolean isValid(List list, ConstraintValidatorContext constraintValidatorContext) { for (Object object : list) { if (object == null) { //如果List集合中含有Null元素,校验失败 return false; } else if (object instanceof String) { String value = object.toString(); if (value.trim().length() == 0){ return false; } } } return true; } }

3、model中添加注解:

@Data public class SysRole { private Long roleId; @NotBlank(message = "角色名不能为空") private String name; @NotEmpty(message = "资源列表不能为空") @ListNotHaveNull(message = "List 中不能含有null元素") @Valid private List paths; }

4、编写前端控制器

@PostMapping("/addRole") public R addRole(@RequestBody @Valid SysRole sysRole) { System.out.println("走到这里说明校验成功"); System.out.println(sysRole); return R.ok(R.SUCCESS_MSG); }

使用方法同 “简单校验”,在在需要校验的Model上面加上@Valid即可。

3、通用的Validtor校验工具类 public class ValidatorUtils { private ValidatorUtils() { } private static Validator validator; static { validator = Validation.buildDefaultValidatorFactory().getValidator(); } /** * 校验对象 * * @param object 待校验对象 * @param groups 待校验的组 * @throws RRException 校验不通过,则报RRException异常 */ public static void validateEntity(Object object, Class... groups) throws RRException { Set constraintViolations = validator.validate(object, groups); if (!constraintViolations.isEmpty()) { Iterator iterator = constraintViolations.iterator(); StringBuilder msg = new StringBuilder(); while (iterator.hasNext()) { ConstraintViolation constraint = iterator.next(); msg.append(constraint.getMessage()).append(','); } throw new RRException(msg.toString().substring(0,msg.toString().lastIndexOf(','))); } } }

使用方式,在接收到前端传递的参数后,使用ValidatorUtils.validateEntity(【参数名】);即可校验,支持分组校验,分组需要定义分组接口。 以上待续。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有