参考

1. 什么是JSR-303

JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是Hibernate Validator。

此实现与 Hibernate ORM 没有任何关系

JSR-303 用于对 Java Bean 中的字段的值进行验证。

Spring MVC 3.x 之中也大力支持 JSR-303,可以在控制器中对表单提交的数据方便地验证。

JSR-303官网

2. JSR-303内置校验规则

3. SpringBoot整合JSR-303

3.1 导入依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

3.2 在类的属性上加上相应校验注解

@NotNull(message="名字不能为空")
private String userName; @Max(value=120,message="年龄最大不能查过120")
private int age; @Email(message="邮箱格式错误")
private String email;

3.3 实现校验

在Controller的处理方法的参数前,加@Valid注解,出错后,错误信息会放置在 Errors或BindingResult 的对象参数中

@RequestMapping("/login")
public String testValid(@Valid User user, BindingResult result){
if (result.hasErrors()){
List<ObjectError> errorList = result.getAllErrors();
for(ObjectError error : errorList){
System.out.println(error.getDefaultMessage());
}
}
return "test";
}

3.4 通过全局统一异常替换BindingResult写法

给controller后的需要校验的bean后加一个BindingResult类就可以获得校验的结果,但是相对麻烦,每次都要写BindingResult。在大项目中一般使用统一异常处理校验结果,返回json格式,如下所示

//后端校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public RtnResult handValidException(MethodArgumentNotValidException e){
BindingResult bindingResult = e.getBindingResult();
Map<String, Object> map = new HashMap<>();
bindingResult.getFieldErrors().forEach(fieldError -> {
map.put(fieldError.getField(),fieldError.getDefaultMessage());
});
return RtnResult.fail(map);
}

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

分组校验应用场景:添加和更新需要不同的校验规则时

3.5.1 先创建添加和更新的接口,该接口仅仅是多场景的一个标识,接口内容为空即可。
public interface AddGroup {
} public interface UpdateGroup {
}
3.5.2 在 @NotBlank(message = “密码不能为空”) 后加上groups 用于表示给校验注解标注什么情况下需要校验(添加/更新)
//AddGroup.class是添加的标识组,可以有多个
@NotBlank(message = "密码不能为空", groups = {AddGroup.class})
private String password; @NotBlank(message = "姓名不能为空", groups = {AddGroup.class,UpdateGroup.class})
private String name;
3.5.3 替换controller层原来的@Valid注解,使用mvc提供的@Validated注解,否则不生效
//添加用户   @Validated指定哪个操作使用校验
@PostMapping("/addUser")
public RtnResult addUser(@Validated(AddGroup.class) @RequestBody ClaimUser claimUser){
return claimUserService.addUser(claimUser);
}

如果使用分组校验,校验注解没有使用groups,则校验不生效,一定要使用groups!!

4. 自定义校验注解

当给出的校验规则不能满足需求,可以通过自定义校验来实现,如某个字段只能为0或1。

举例场景:当显示和隐藏的属性showStatus只能时0或1,需要自定义校验注解和自定义校验器

4.1 导入依赖

<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>

4.2 编写自定义校验注解

PS:可以参考JSR-303原本的校验

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME) //运行环境
@Repeatable(List.class)
@Documented
@Constraint(validatedBy = { }) // 指定自定义校验器,可以适配多个校验器,一个注解完成多种校验
public @interface NotNull {
String message() default "{javax.validation.constraints.NotNull.message}"; // 校验失败的提示信息
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
int[] vals() default {}; //标注在属性上的vals={0,1} }

4.3 编写自定义校验注解

//自定义校验器 必须实现ConstraintValidator
//ConstraintValidator中的 泛型1:绑定的泛型注解 泛型2:校验的数据类型
public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> { private Set<Integer> set = new HashSet<>(); //初始化方法,获取在Entity类的属性上标注的符合条件的Integer的值:{0,1}
@Override
public void initialize(ListValue constraintAnnotation) {
int[] vals = constraintAnnotation.vals();
for (int val : vals) {
set.add(val);
}
} //判断是否校验成功方法
//integer:传进来的值
//判断依据:看integer是否在初始化方法的数组中
@Override
public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
if (set.contains(integer)) {
return true;
}
return false;
}
}

4.4 在需要校验的属性上添加自定义注解

@ListValue(vals={0,1},message = "开关状态只能是0或1")
private Integer showStatus;

4.5 自定义参数校验(这边以校验手机号为例)

  1. 编写注解类
//说明该注解将被包含在javadoc中
@Documented
// 注解的作用目标 类上、方法上、属性上
@Target({ElementType.FIELD, ElementType.PARAMETER})
// 注解的保留位置  
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {IsMobileValidator.class }) // 与约束注解关联的验证器
public @interface IsMobile { boolean required() default true; String message() default "手机号不正确"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; }
  1. 编写校验规则
public class IsMobileValidator implements ConstraintValidator<IsMobile, String> {
private boolean required; /**
* 重写initialize方法获取注解实例
* @param ca
*/
@Override
public void initialize(IsMobile ca) {
// 重注解实例中获信息
required = ca.required();
} @Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// value就是要校验的数据了
if (value != null && required) {
// 手机号校验规则
System.out.println(value);
String regexp= "^(((\\+\\d{2}-)?0\\d{2,3}-\\d{7,8})|((\\+\\d{2}-)?(\\d{2,3}-)?([1][3,4,5,7,8][0-9]\\d{8})))$";
boolean matches = Pattern.matches(regexp, value);
System.out.println(matches);
return matches;
}
return false;
}
}
  1. 使用自定义校验注解
    /**
* 手机号
*/
@IsMobile(message = "用户手机号不正确")
private String tel;

最新文章

  1. 在Ubuntu13.04中配置Jexus+Mono3.2运行Asp.Net Mvc 4站点 (二)
  2. Linux下命令行安装配置android sdk
  3. 自然语言19.1_Lemmatizing with NLTK(单词变体还原)
  4. SymmetricDS 数据库双向同步开源软件入门
  5. Eclipse中10个最有用的快捷键组合(转)
  6. 可运行jar包生成步骤和jar包的生成
  7. Redis 二:入门基本篇
  8. css中居中的居中方法
  9. Swift - 使用UIImagePickerController从相册选择照片并展示
  10. C#使用文件监控对象FileSystemWatcher 实现数据同步
  11. 201521123098 《Java程序设计》第12周学习总结
  12. c#中的格式输出
  13. Xml文档规则
  14. 【vue】vue全家桶
  15. sqlserver 存储过程 自定义函数 游标???
  16. [Git] Git操作命令
  17. 例子:动能并不是特别强(2-3)后,下M5的同时,也是恢复期到期的前一天
  18. (转)Maven学习总结(三)——使用Maven构建项目
  19. lufylegend:动画
  20. Android自定义View创建流程

热门文章

  1. linux服务开机自启动&amp;注册系统服务
  2. /etc/hosts导致的问题
  3. 【Mysql】[Err] 1153 - Got a packet bigger than 'max_allowed_packet' bytes
  4. apiAutoTest: 接口自动化测试的数据清洗(备份/恢复)处理方案
  5. 十一、UART&amp;TTY驱动
  6. 在HTML中改变input标签中的内容
  7. MySQL 中的临时表
  8. cookie加密 当浏览器全面禁用三方 Cookie
  9. Uber如何解决2000多个微服务带来的复杂性问题?
  10. SpringCloud配置刷新机制的简单分析[nacos为例子]