使用hibernate validate做参数校验
1.为什么使用hibernate validate
在开发http接口的时候,参数校验是必须有的一个环节,当参数校验较少的时候,一般是直接按照校验条件做校验,校验不通过,返回错误信息。比如以下校验用户名不为空的校验:
if (userName == null || "".equals(userName)) {
response.setCode(10001);
response.setMessage("用户名不能为空!");
return response;
}
但是当接口参数很多,并且参数校验很负责的时候,如果继续使用这种校验的方式,校验代码会非常多,并且难以维护。那么在这种情况下可以考虑使用hibernate validate做参数校验。
2.hibernate validate简介
hibernate validate是基于注解来实现的参数校验框架,并且有很好的扩展性,使用者可以通过自定义约束条件来实现自定义的校验条件。以下为添加注解的一个小例子:
public class Car {
@NotNull
private String manufacturer;
@NotNull
@Size(min = 2, max = 14)
private String licensePlate;
@Min(2)
private int seatCount;
}
2.1 springboot项目做基本校验
新建springboot项目,并且在项目中添加hibernate validate依赖,在springboot2.0版本中的spring-boot-starter-web已经包含了此jar包,不需要再重复添加,但是在spring-boot-starter-web2.0以上版本中不包含此jar包,需要手动添加,依赖信息如下:
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
添加Validator的bean配置,配置内容如下:
@Configuration
public class ValidatorConfiguration {
@Bean
public Validator validator(){
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.addProperty( "hibernate.validator.fail_fast", "true" )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
return validator;
}
}
Validator的实现必须是线程安全的,因此可以配置了bean之后,在全项目中使用,并且能多次使用.
创建对象:
public class Company {
@NotBlank(message = "商品名称不能为空")
private String name;
@Size(min = 2, max = 10, message = "税号长度必须在2到10位之前")
private String taxNum;
@Min(13)
@Pattern(regexp = "[+-]?[0-9.]+$", message = "手机号码只能是数字")
private String phoneNum;
public String getName() {
return name;
}
....(相关get和set方法)
}
运行以下测试类:
@SpringBootTest
class HibernateValidateDemoApplicationTests {
@Autowired
protected Validator validator;
@Test
void contextLoads() {
Company company = buildCompany();
Set<ConstraintViolation<Company>> validResultSet = validator.validate(company);
for (ConstraintViolation<Company> validResult : validResultSet) {
System.out.println(validResult.getMessage());
}
}
private Company buildCompany() {
Company company = new Company();
company.setName("中国石化(浙江石油分公司)");
company.setTaxNum("123123123123");
company.setPhoneNum("13333333333");
return company;
}
}
输出结果为:税号长度必须在2到10位之前
以上例子中的注解比较简单,通过添加
@NotBlank(message = "商品名称不能为空")
@Size(min = 2, max = 10, message = "税号长度必须在2到10位之前")
@Min(13)
@Pattern(regexp = "[+-]?[0-9.]+$", message = "手机号码只能是数字") 通过正则表达式校验字符窜
来做一些字符串非空、长度的校验.常用的校验注解有以下几种:
注解 |
校验规则 |
---|---|
AssertFalse、AssertTrue |
判断值是否为false或者true |
DecimalMax、DecimalMin |
必须为数字,并且值小于最大值、大于最小值 |
Digits |
必须是数字 |
必须是邮箱 |
|
Max、Min、NotBlank、NotEmpty、Size |
最大最小长度校验 |
Negative、NegativeOrZero |
数值校验 |
Pattern |
正则表达式校验 |
2.2 自定义校验规则
除了上面框架提供的校验规则, 我们也可以自定义校验规则,比如当我们要校验字符个数的时候,可以使用一下自定义规则。
首先定义注解:
@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CharacterValidator.class)
@Documented
public @interface CharLength {
int min() default 0;
int max() default Integer.MAX_VALUE;
String message() default "{org.hibernate.validator.constraints.Length.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
定义此注解对应的校验实现类:
public class CharacterValidator implements ConstraintValidator<CharLength, String> {
private static final Log log = LoggerFactory.make(MethodHandles.lookup());
private int min;
private int max;
@Override
public void initialize(CharLength constraintAnnotation) {
min = constraintAnnotation.min();
max = constraintAnnotation.max();
validateParameters();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
//为具体的校验规则
if ( value == null ) {
return true;
}
int length = CharUtil.getStringLength(value);
return length >= min && length <= max;
}
private void validateParameters() {
if ( min < 0 ) {
throw log.getMinCannotBeNegativeException();
}
if ( max < 0 ) {
throw log.getMaxCannotBeNegativeException();
}
if ( max < min ) {
throw log.getLengthCannotBeNegativeException();
}
}
}
定义完成之后,对Company的定义修改如下:
@NotBlank(message = "公司名称不能为空")
@CharLength(max = 12, message = "公司名称不能超过12个字符")
private String name;
再次运行测试用例,输出内容如下:公司名称不能超过12个字符
2.3 使用@ScriptAssert校验参数
但是当我们的校验规则更加复杂的时候,只是用注解可能不能完成我们的需求,这个时候就可以使用@ScriptAssert注解来实现运行方法的方式来实现复杂校验。
在Company类上添加以下注解:
@ScriptAssert(lang = "javascript", script = "com.zjut.hibernate.validate.business.CompanyValidateScript.checkCombineLength(_this.name,_this.taxNum, 30)",
message = "名称和税号不能超过30位")
并定义校验方法:
public static boolean checkCombineLength(int maxLength, String... params) {
int length = 0;
for (String param : params) {
if (StringUtils.isEmpty(param)) {
continue;
}
length += CharUtil.getStringLength(param);
}
return length <= maxLength;
}
除此之外,hibernater validate还支持分组校验、校验集合等功能,具体可参考官方文档:
http://hibernate.org/validator/
- 基于MongoDB GridFS的图片存储
- css3 过渡和2d变换——回顾
- Microsoft 防跨站点脚本库AntiXSS Library v4.2.1
- Compilify——让你在浏览器中编译.NET代码
- Python进阶-面向对象
- WCF RESTful服务的Google Protocol Buffers超媒体类型
- 使用CoreOs,Docker和Nirmata部署微服务类型的应用
- .NET 4 上的REST 框架
- 结合游戏开发与人工智能研究,游戏大厂 Ubisoft 成立AI研发部门
- Quartz.NET的管理工具
- Python-执行系统命令
- css3 UI 修饰——回顾
- Windows Phone 7实战 第一天 设计启动页面和应用程序图标
- css3响应式布局设计——回顾
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- redis常用操作,redis操作键值,redis安全设置
- redis介绍,redis安装,redis持久化,redis数据类型
- AJAX的post请求与上传文件
- memcached的一些简单使用
- nosql介绍,memrcached介绍,安装memcached,查看memcachedq状态
- 如何在IDEA2017创建Maven的Web工程
- JSP上传文件与导出Excel表
- 关于CentOS中tomcat的8005端口启动不起来的解决办法
- 安装ansible以及简单使用
- 设计模式之职责链
- 转录组分析 | 使用SAMtools将SAM文件转换为BAM文件、排序、建立索引
- Matlab系列之那些数学函数(讨论功能已加入)
- 简单使用saltstack
- CentOS7下搭建postfix邮箱服务器并实现extmail的web访问
- 安装saltstack