使用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/
使用hibernate validate做参数校验的更多相关文章
- 寻找写代码感觉(十六)之 集成Validation做参数校验
写在前面 今天是大年初五了... 不知不觉,又要上班了,美好的假期只剩一天了,有点不舍呢! 也不知道为什么,总感觉像在做梦一样,像没睡醒一样,并不是因为眼睛小,更多应该是自寻烦恼,想得多罢了. 参数校 ...
- 如何在 Spring/Spring Boot 中做参数校验?你需要了解的都在这里!
本文为作者原创,如需转载请在文首著名地址,公众号转载请申请开白. springboot-guide : 适合新手入门以及有经验的开发人员查阅的 Spring Boot 教程(业余时间维护中,欢迎一起维 ...
- 如何在 Spring/Spring Boot 中做参数校验
数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据. 本文结合自己在项目 ...
- 如何优雅的做参数校验-JSR330
前言: 本文不是讲@Validate.@Valid是如何使用的.区别是什么,想看这些内容的请换篇文章. 背景: 当前端传过来的参数是进行对称性加密.base64加密等处理后过的参数时,在control ...
- hibernate validation 手动参数校验 不经过spring
/** * 校验工具类 * @author wdmcygah * */ public class ValidationUtils { private static Validator validato ...
- spring mvc +@Valid +@RequestBody 来做参数校验返回400,并且不显示具体message 如何解决
参考文档: https://www.oschina.net/question/115867_2282711 谢谢原作者
- Spring Validation最佳实践及其实现原理,参数校验没那么简单!
之前也写过一篇关于Spring Validation使用的文章,不过自我感觉还是浮于表面,本次打算彻底搞懂Spring Validation.本文会详细介绍Spring Validation各种场景下 ...
- eggjs的参数校验模块egg-validate的使用和进一步定制化升级
简单讲一下这个egg-validate egg-validate是基于parameter的. 安装 npm install --save egg-validate 启用 // config/plugi ...
- 全栈项目|小书架|服务器开发-Koa2 参数校验处理
为什么需要做参数校验 在开发中,无论是App开发还是服务器接口开发, 我们无法去预测用户传入的数据,因此参数(数据)校验是开发中不可或缺的一环. 例如像App的注册登录表单提交页面,就要做好多层的判断 ...
随机推荐
- 四维DP之方格取数
题目描述 传送门 设有N*N的方格图(N<=20,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例): 某人从图的左上角的A(1,1) 点出发,可以向下行走,也可 ...
- Tomcat 架构原理解析到架构设计借鉴
Tomcat 发展这么多年,已经比较成熟稳定.在如今『追新求快』的时代,Tomcat 作为 Java Web 开发必备的工具似乎变成了『熟悉的陌生人』,难道说如今就没有必要深入学习它了么?学习它我们又 ...
- spring-boot 应用 报错 No qualifying bean of type XXXXX.***Mapper
报错类型 NoSuchBeanDefinitionException.No qualifying bean of type XXXXX.***Mapper 报错信息详情 Caused by: org ...
- python 爬虫由于网络或代理不能用导致的问题处理方法
平时在爬取某些网页的时候,可能是由于网络不好或者代理池中的代理不能用导致请求失败.此时有们需要重复多次去请求,python中有现成的,相应的包供我们使用: 我们可以利用retry模块进行多次请求,如果 ...
- windows python的多进程
最近打比赛,apply操作极慢,队友使用了线程池,用多核开辟多线程跑,加速. 在阿里平台上,都没问题. 我是win10系统+jupyter notebook 多线程那个模块运行,会显示一直运行,p.c ...
- Burp Suite Sequencer Modules - 定序器模块
Sequencer 主要用于处理和分析Tokens 目标网站:http://testaspnet.vulnweb.com/ (1)通过代理,拦截数据流. (2)Send to Sequencer,然后 ...
- vue : async / await 的应用
比如有组数据是很多页面都要用的,我想把它写在一个js文件里作为公共方法. public.js import axios from 'axios'; axios.defaults.headers.pos ...
- 代码Verify简介
序 对于开发者而言,编译代码和提交代码是必不可少的流程,同一个需求反复提交的情况也时常出现,那么怎么避免这种情况,且保证代码的质量,这就是Verify CI的目标.Verify表示认证验证的意思,结合 ...
- 题解 洛谷 P3210 【[HNOI2010]取石头游戏】
考虑到先手和后手都使用最优策略,所以可以像对抗搜索一样,设 \(val\) 为先手收益减去后手收益的值.那么先手想让 \(val\) 尽可能大,后手想让 \(val\) 尽可能小. 继续分析题目性质, ...
- Ubuntu Server 19.04配置静态IP
这个/etc/netplan下默认有个文件50-cloud-init.yaml,直接修改它就行了 sudo vim /etc/netplan/50-cloud-init.yaml 网口名字enp0s3 ...