validation参数校验

  • bean validation和hibernate validator参数校验
    • 常用注解
    • 1.导入依赖
    • 2.测试
    • 3.自定义消息模板
    • 4.分组校验
    • 5.级联校验
    • 6.自定义注解
    • 7.快速校验
    • 8.非bean入参校验
      • 9.与SpringBoot整合
    • 10.统一异常处理

bean validation和hibernate validator参数校验

常用注解

@Null(groups={Add.class}) 参数必须为null,group设置分组,默认为default
@NotNull 参数不为null
@NotEmpty 参数不为null ,"",集合不为空
@NotBlank 参数不为null, "", " ",只能作用字符串类型
@AssertFalse 被注释的元素必须是false
@AssertTrue 被注释的元素必须是true
@Min(value) 被注释的元素必须为一个数字  >=
@Max(value) 被注释的元素必须为一个数字 <=
@DecimalMin("value")  >=
@DecimalMax("value") <=
@NegativeOrZero <=0
@Range(min,max) 被注释的元素大小必须在指定的范围内
@Size(min ,max) 被注释的元素大小必须在指定的范围内
@Email 被注释的元素必须是电子邮箱地址
@Past 被注释的元素必须是一个过去的日期
@PastOrPresent  被注释的元素必须是一个过去的时间
@Future 被注释的元素必须是一个将来的日期
@Pattern(regexp = "1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\\d{8}$")  被注释的元素必须是符合指定的正则表达式
@URL 被注释的元素必须是链接地址
备注:参数校验只有!= null的时候才生效

1.导入依赖

        <!--引入hibernate-validator,beanvalidator--><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>6.0.18.Final</version></dependency><!--el规范和tomcat的实现,用于解析message里面的表达式--><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-el</artifactId><version>9.0.29</version></dependency>

2.测试

1.定义实体类
@Data
public class UserInfo{
@NotBlank
private String name;
}
2.编写工具类
public class UserInfo{//声明validator,线程安全的:所有的方法都可以使用这个对象,而不会产生线程安全的问题private static Validator validator;//初始化默认的validator对象static {validator = Validation.buildDefaultValidatorFactory().getValidator();}//校验public static List<String> valid(UserInfo userInfo,Class<?>... groups){//如果被校验对象userInfo没有检验通过,则set里面就有校验信息,返回出去Set<ConstraintViolation<UserInfo>> set = validator.validate(userInfo,groups);List<String> list = set.stream().map(v -> "属性:" + v.getPropertyPath() + ",属性值是:" + v.getInvalidValue()+ ",校验不通过的提示信息:" + v.getMessage()+",消息模板:"+v.getMessageTemplate()).collect(Collectors.toList());return list;}
}
3.测试
public class ValidationTest {public static void main(String[] args) {UserInfo info = new UserInfo();info.setName("名字");}
List<String> valid1 = ValidationUtil.valid(info);
System.out.println(valid1);
返回结果:
[属性:name,属性值是:null,校验不通过的提示信息:不能为空,消息模板:{javax.validation.constraints.NotBlank.message}]

3.自定义消息模板

@NotBlank(message = "姓名不能为空!!")
private String name;
返回结果:
[属性:name,属性值是:null,校验不通过的提示信息:姓名不能为空!!,消息模板:姓名不能为空!!]

4.分组校验

1.定义实体类
public class UserInfo{//标记接口 新增,修改,删除public interface Add extends Default {}public interface Update extends Default{}public interface Delete extends Default{}//默认组default,指定分组@Null(groups = {Add.class}) //只适用于新增@NotNull(groups = {Update.class,Delete.class})//只适用于修改/删除private Long id;@NotBlank(message = "姓名不能为空!!")private String name;}
2.编写工具类//校验,要检验的对象,检验分组public static List<String> valid(UserInfo userInfo,Class<?>... groups){//如果被校验对象userInfo没有检验通过,则2set里面就有校验信息,返回出去Set<ConstraintViolation<UserInfo>> set = validator.validate(userInfo,groups);List<String> list = set.stream().map(v -> "属性:" + v.getPropertyPath() + ",属性值是:" + v.getInvalidValue()+ ",校验不通过的提示信息:" + v.getMessage()+",消息模板:"+v.getMessageTemplate()).collect(Collectors.toList());return list;}
3.测试
public class ValidationTest {public static void main(String[] args) {UserInfo info = new UserInfo();info.setName("名字");}
List<String> valid1 = ValidationUtil.valid(info,UserInfo.Add.class);
List<String> valid2 = ValidationUtil.valid(info,UserInfo.Update.class);
System.out.println(valid1);
System.out.println(valid2);
//结果
valid1[]
valid1[属性:id,属性值是:null,校验不通过的提示信息:不能为null,消息模板:{javax.validation.constraints.NotNull.message}]

5.级联校验

1.编写实体类
public class UserInfo{@NotBlank(message = "姓名不能为空!!")private String name;@Valid //被引用对象加上@valid注解,才可以完成级联校验private Grade grade;}
public class Grade {@NotBlankprivate String id;
}
2.工具类同上
3.测试
public class ValidationTest {public static void main(String[] args) {UserInfo info = new UserInfo();info.setName("名字");//添加gradeGrade grade = new Grade();//grade.setId("123");info.setGrade(grade);}//结果valid1[属性:grade.id,属性值是:null,校验不通过的提示信息:不能为空,消息模板:{javax.validation.constraints.NotBlank.message}]

6.自定义注解

status的必须为1000/1001/1002

1.编写实体类
public class UserInfo{
@NotBlank(message = "姓名不能为空!!")private String name;@UserStatusprivate Integer status;
}
2.1编写注解要校验的规则-继承ConstraintValidator<UserStatus,Integer>,绑定要校验的约束注解UserStatus,类型
public class UserStatusValidator implements ConstraintValidator<UserStatus,Integer> {@Overridepublic void initialize(UserStatus constraintAnnotation) {}@Overridepublic boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {if (value == null){//没有值,不校验return true;}//设置要求之Set<Integer> set = new HashSet<>();set.add(1000);set.add(1001);set.add(1002);return set.contains(value);}
}
2.2编写注解声明类
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {UserStatusValidator.class})//说明当前注解要被谁来完成校验工作
@Documented
public @interface UserStatus {String message() default "{userStatus必须是1000/1001/1002}";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}
3.测试
public class ValidationTest {public static void main(String[] args) {UserInfo info = new UserInfo();info.setName("名字");info.setStatus(200);List<String> valid1 = ValidationUtil.valid(info);System.out.println("valid1"+valid1);}//结果valid1[属性:status,属性值是:200,校验不通过的提示信息:{userStatus必须是1000/1001/1002},消息模板:{userStatus必须是1000/1001/1002}, 属性:grade,属性值是:null,校验不通过的提示信息:不能为空,消息模板:{org.hibernate.validator.constraints.NotEmpty.message}]

7.快速校验

1.实体类 同上
2.工具类
public class ValidationUtil {//配置快速失败private static Validator validFailFast;static {validFailFast = Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory().getValidator();//.failFast(true),快速失败}public static<T> List<String> validNotBean(T object, Method method, Object[] parameterValues, Class<?>... groups){Set<ConstraintViolation<T>> set = executables.validateParameters(object, method, parameterValues, groups);List<String> list = set.stream().map(v -> "属性:" + v.getPropertyPath() + ",属性值是:" + v.getInvalidValue()+ ",校验不通过的提示信息:" + v.getMessage()+",消息模板:"+v.getMessageTemplate()).collect(Collectors.toList());return list;}3.测试类同上调用:  List<String> valid = ValidationUtil.validFailFast(info,UserInfo.Add.class);效果:当有错误时,直接返回第一个错误,不再校验其他错误。

8.非bean入参校验

请求参数和返回值并不是一个bean

1.编写要校验的方法/*** 方法非bean类型的入参校验* 1.方法参数前加注解* 2.执行入参校验,真正有用的话可以使用aop编程思想来使用*/public String getByName(@NotBlank String name){//执行入参校验//当前线程的堆栈,第一个元素就是当前所在方法的名字StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[1];String methodName = stackTraceElement.getMethodName();Method method = null;try{method = this.getClass().getDeclaredMethod(methodName, String.class);}catch (Exception e) {e.printStackTrace();}List<String> strings = ValidationUtil.validNotBean(this, method, new Object[]{name});//打印校验结果System.out.println("校验结果:" + strings);return "ok";}
2.工具类编写
public class ValidationUtil {private static ExecutableValidator executables;static {validator = Validation.buildDefaultValidatorFactory().getValidator();//校验入参或返回值的executables = validator.forExecutables();}public static<T> List<String> validNotBean(T object, Method method, Object[] parameterValues, Class<?>... groups){//校验方法参数 validateParametersSet<ConstraintViolation<T>> set = executables.validateParameters(object, method, parameterValues, groups);List<String> list = set.stream().map(v -> "属性:" + v.getPropertyPath() + ",属性值是:" + v.getInvalidValue()+ ",校验不通过的提示信息:" + v.getMessage()+",消息模板:"+v.getMessageTemplate()).collect(Collectors.toList());return list;}
}
3.测试
method.getByName("");
返回结果
校验结果:[属性:getByName.arg0,属性值是:,校验不通过的提示信息:不能为空,消息模板:{javax.validation.constraints.NotBlank.message}]

9.与SpringBoot整合

1.编程式校验

直接使用工具类校验@GetMapping("/addUser")public String getByName(UserInfo userInfo){List<String> valid = ValidationUtil.valid(userInfo);if (valid.size()>0){System.out.println(valid);return "校验不成功";}else {return "添加成功!";}}
访问:http:8080/addUser
结果:校验不成功  控制台打印报错

2.声明式校验

 @GetMapping("/addUser2")public String getByName2(@Valid UserInfo userInfo){return "添加成功";}
结果:页面直接报错将校验结果封装到BindingResult,不会页面上报错@GetMapping("/addUser2")public String getByName2(@Valid UserInfo userInfo, BindingResult result){if(result.hasErrors()){//判断是否有不满足约束的List<ObjectError> errors = result.getAllErrors();for (ObjectError error : errors) {//打印错误信息System.out.println(error.getObjectName()+"::"+error.getDefaultMessage());}//获取没通过校验的字段详情List<FieldError> fieldErrorList = result.getFieldErrors();for (FieldError fieldError : fieldErrorList) {System.out.println(fieldError.getField() + "::" + fieldError.getDefaultMessage() + ",当前没有通过校验规则的值是:" + fieldError.getRejectedValue());}};return "添加成功";}

3.@Validated 实现分组校验

 @GetMapping("/addUser3")public String getByName3(@Validated(value = {UserInfo.Add.class}) UserInfo userInfo, BindingResult result){if(result.hasErrors()){//判断是否有不满足约束的List<ObjectError> errors = result.getAllErrors();for (ObjectError error : errors) {System.out.println(error.getObjectName()+"::"+error.getDefaultMessage());}//获取没通过校验的字段详情List<FieldError> fieldErrorList = result.getFieldErrors();for (FieldError fieldError : fieldErrorList) {System.out.println(fieldError.getField() + "::" + fieldError.getDefaultMessage() + ",当前没有通过校验规则的值是:" + fieldError.getRejectedValue());}};return "添加成功";}

@Validated方法参数校验

@Validated//表示整个类都启用校验,如果碰到入参含有bean validation注解的话就会自动校验@GetMapping("/getByName")public String getByName(@NotBlank String name){return name;}

10.统一异常处理

不写BindingResult result
方式一:添加一个方法,使用@ExceptionHandler(BindException.class)标记,处理当前controller里抛出的xx异常

@ExceptionHandler(BindException.class)
public String handleEx(BindException e){List<FieldError> fieldErrors = e.getFieldErrors();StringBuilder builder = new StringBuilder();for (FieldError fieldError : fieldErrors) {builder.append("属性:").append(fieldError.getField()).append("校验不通过的原因:").append(fieldError.getDefaultMessage()).append(";;");}return builder.toString();}

方式二:编写统一的异常处理方式

@ControllerAdvice
public class RoadControllerAdvice {/***@Validated 写在方法上的时候会报这个异常*/@ExceptionHandler(BindException.class)@ResponseBodypublic String handleEx(BindException e){List<FieldError> fieldErrors = e.getFieldErrors();StringBuilder builder = new StringBuilder("RoadControllerAdvice里的:");for (FieldError fieldError : fieldErrors) {builder.append("属性:").append(fieldError.getField()).append("校验不通过的原因:").append(fieldError.getDefaultMessage()).append(";;");}return builder.toString();}/*** @Validated 写在类上的时候会报这个异常*/@ExceptionHandler(ConstraintViolationException.class)@ResponseBodypublic List<String> handleEx(ConstraintViolationException e){Set<ConstraintViolation<?>> fieldErrors = e.getConstraintViolations();StringBuilder builder = new StringBuilder("RoadControllerAdvice里的:");List<String> list = fieldErrors.stream().map(v -> "属性:" + v.getPropertyPath() + ",属性值是:" + v.getInvalidValue()+ ",校验不通过的提示信息:" + v.getMessage()+",消息模板:"+v.getMessageTemplate()).collect(Collectors.toList());return list;}/*** 处理所有异常信息*/@ExceptionHandler(Exception.class)@ResponseBodypublic String handleEx(Exception e){return e.getMessage();}
}

代码:https://gitee.com/suisui9857/simpleCode/tree/master/validation

Java代码简洁-validation参数校验相关推荐

  1. Java代码简洁之道

    Java如何把代码写的简洁? 其实这是一个熟练的过程,有的代码在编写的时候有很多方法你没有见过,所以你只能按照一般写法来做,这也就是经验不足!或者有的时候你没有熟练掌握面向对象的思想,所以无法从全局出 ...

  2. jmeter 使用BeanShell编写java代码提取请求参数

    之前在用jmeter写接口测试的时候,我想尽量把参数都设置成可变修改的,现在的大多数请求都会带上时间戳,于是,我用了两种方式提取可变的时间戳参数 1.直接在jmeter的GUI中,编写获取时间戳的方法 ...

  3. java validation_java bean validation 参数验证

    一.前言 在后台开发过程中,对参数的校验成为开发环境不可缺少的一个环节.比如参数不能为null,email那么必须符合email的格式,如果手动进行if判断或者写正则表达式判断无意开发效率太慢,在时间 ...

  4. java 代码实现身份证合法性校验(全国所有地方)

    很多地方可能都会用到对身份证要进行判断校验的功能,这个是之前在网上看到的,具体的网址都忘了,现在项目完成了,有时间把其整理下,方便自己和大家日后使用!(直接复制粘贴即可) package org.as ...

  5. 通过 Java 代码获取 JVM 参数

    一 点睛 Java 提供了 java.lang.management 包用于监视和管理 Java 虚拟机和 Java 运行时中的其他组件,它允许本地或远程监控和管理运行的 Java 虚拟机. 其中 M ...

  6. java代码传中文参数乱码

    原因: idea编码设置的问题 解决方法: 在idea右下角可以设置编码,设置成utf-8就好了

  7. java 实现批量注册---实现类层(含入参参数校验)

    /*** 批量注册** @param file* @return*/@Transactional@Overridepublic Result batchRegistOrganUserByTemplat ...

  8. struts2教程(5)--请求参数校验

    一.请求参数校验介绍 校验的分类 :客户端数据校验 和服务器端数据校验 客户端数据校验 ,通过JavaScript完成校验 (改善用户体验,使用户减少出错 ) 服务器数据校验 ,使用框架内置校验功能( ...

  9. 参数校验之Hibernate-validator的基本使用

    Hibernate-validator是对validation-api的再次封装,在开发过程中是经常使用到(spring boot里面的spring-boot-starter-web是默认应用了Hib ...

最新文章

  1. 【原】高清显示屏原理及设计方案
  2. linux lz4 lzo,Linux六大压缩算法横评:Ubuntu 19.10最终选择LZ4
  3. java 010_Java笔记-day010-[String类]
  4. Git停止跟踪rm -r --cached与ignore区别
  5. Java堆、栈、内存分析
  6. js-array自增长方式
  7. ModelSim入门教程和两个典型例子
  8. Mac 上使用vim 快捷键
  9. 【UV打印机】PrintExp打印软件教程(七)-高级模式(其它)
  10. 大数据平台整体架构设计方案(PPT)
  11. 将网页转换成pdf文档的方法
  12. 揭秘3D游戏模型贴图师
  13. 手动制作满足SARscape要求的_dem数据
  14. 单图像超分辨率重建示例代码解析
  15. php工作心得简50字,50字简短个人工作总结
  16. CAD门窗lisp_CAD高版本窗体阵列LISP_高版本CAD如何显示阵列窗口?
  17. 论Flutter开发如何改善套娃地狱问题
  18. 国外著名大学(计算机,通信及电子方面学院)
  19. windows副本不是正版怎么解决_怎么才能创作出打动人的内容?解决别人的问题,而不是自己的问题...
  20. Java 8 新特性|Collectors.joining() 详解

热门文章

  1. 微信PC端不显示头像和表情怎么解决
  2. mysql 怎么同时删除两张表的数据库,mysql怎样删除多个表格数据库数据_数据库
  3. 纪录大华的智能回调需要用到的事件列表
  4. Java简单知识点小结
  5. F5 Networks:应用交付的“4G”挑战
  6. CGAL例程:地理信息系统----点云数据生成DSM、DTM、等高线和数据分类
  7. 图像搜索引擎 - 原理篇
  8. 如何查找重复文件并快速删除,电脑查重复文件的方法
  9. HTML网页调用 网易云 音乐播放器代码
  10. zk - zookeeper主节点、从节点、客户端三者之间的交互