基于javax.validation结合spring的最佳实践
前言
本人先将用到的配置、工具类贴出来,然后一步步告诉大家怎么使用
JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。
注解如下:

Hibernate validator 在JSR303的基础上对校验注解进行了扩展,扩展注解如下:

pom中添加注解
<!--jsr 303-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<!-- hibernate validator-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.0.Final</version>
</dependency>
Spring配置
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
自己的Violation实体
这里使用的Lombok获取get和set,使用的@Getter注解
@AllArgsConstructor 这个注解是lombok中为类提供一个全参的构造方法
package com.alibaba.xianzhi.validator;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* Created by Jackielee on 2017
* @author: lizhilong
* @date: 2017-11-14 18:01:34
*/
@Getter
@AllArgsConstructor
public class Violation implements Serializable {
private static final long serialVersionUID = -1731546219600067986L;
private final String message;
private final Object bean;
private final String property;
private final Object value;
}
封装一个ViolationBuild
后面会说这个类的用法
package com.alibaba.xianzhi.validator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.collections.CollectionUtils;
/**
* @author: lizhilong
* @date: 2017-11-15 11:41:12
*/
@AllArgsConstructor
public class ViolationBuild{
@Getter
private Set<Violation> violations;
public String getMessage() {
List<String> list = new ArrayList<String>();
for (Violation violation : violations) {
list.add(violation.getMessage());
}
return list.size() > 0 ? list.get(0) : "";
}
public static <T> ViolationBuild build(Set<ConstraintViolation<T>> cvs) {
Set<Violation> result = new HashSet<Violation>();
if (CollectionUtils.isNotEmpty(cvs)) {
for (ConstraintViolation cv : cvs) {
result.add(new Violation(cv.getMessage(), cv.getRootBean() == null ? null : cv.getRootBean().toString(),
cv.getPropertyPath() == null ? null : cv.getPropertyPath().toString(),
cv.getInvalidValue()));
}
}
return new ViolationBuild(result);
}
}
用来校验实体,构建并存储校验后的信息ValidatorProvider
package com.alibaba.xianzhi.validator;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author: lizhilong
* @date: 2017-11-15 11:40:59
*/
@AllArgsConstructor
@Getter
public class ValidatorProvider {
private final Validator validator;
public <T> ViolationBuild validate(T object) {
Set<ConstraintViolation<T>> violations;
try {
violations = validator.validate(object);
} catch (IllegalArgumentException iae) {
throw iae;
} catch (ValidationException ve) {
throw ve;
}
return ViolationBuild.build(violations);
}
public <T> ViolationBuild validate(T object, Class<?>... groups) {
Set<ConstraintViolation<T>> violations;
try {
violations = validator.validate(object, groups);
} catch (IllegalArgumentException iae) {
throw iae;
} catch (ValidationException ve) {
throw ve;
}
return ViolationBuild.build(violations);
}
public <T> ViolationBuild validateProperty(T object, String propertyName, Class<?>... groups) {
Set<ConstraintViolation<T>> violations;
try {
violations = validator.validateProperty(object, propertyName, groups);
} catch (IllegalArgumentException iae) {
throw iae;
} catch (ValidationException ve) {
throw ve;
}
return ViolationBuild.build(violations);
}
public <T> ViolationBuild validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups) {
Set<ConstraintViolation<T>> violations;
try {
violations = validator.validateValue(beanType, propertyName, value, groups);
} catch (IllegalArgumentException iae) {
throw iae;
} catch (ValidationException ve) {
throw ve;
}
return ViolationBuild.build(violations);
}
}
BaseService让自己的service继承此类
java不能多继承 所以如果已经继承了别的类,可以将此类注入出来
此类是为了拿到一个单例的ValidatorProvider
package com.alibaba.xianzhi.base.web;
import javax.annotation.Resource;
import javax.validation.Validator;
import com.alibaba.xianzhi.validator.ValidatorProvider;
/**
* BaseService
* @author: lizhilong
* @date: 2017-11-15 11:41:24
*/
public abstract class BaseService {
@Resource
protected Validator validator;
private ValidatorProvider validatorProvider;
protected ValidatorProvider getValidatorProvider() {
if (validatorProvider == null) {
validatorProvider = new ValidatorProvider(validator);
}
return validatorProvider;
}
}
所需校验的实体类
说明:Constants为接口常量
@Getter
@AllArgsConstructor
public class SubmitVO extends BaseVO {
@NotNull(message="厂商不能为空")
private Long companyId;
@Length(min=0, max=100, message="标题请控制在" + Constants.MAX_TITLE + "个字符以内")
@NotNull(message="标题不能为空")
private String title;
@Length(min=0, max=65535, message="修复方案长度不能超过" + Constants.MAX_FIX_ADVICE)
@NotNull(message="修复方案不能为空")
private String fixAdvice;
}
下面就是如何使用
public BaseResponse save(SubmitVO submitVO ) {
/**
* getValidatorProvider()此方法是BaserService中,
* 上面说到本人的service是继承此
* service的所以可以直接用
**/
ValidatorProvider validatorProvider = getValidatorProvider();
/**
* validatorProvider调用validate(Object obj)进行校验
* 返回ViolationBuild
**/
ViolationBuild validateFlaw = validatorProvider.validate(submitVO);
/**
* 此时如果校验有失败的 容器中便会存储信息,ViolationBuild可以通过自己的
* getMessage方法获取信息(此方法可以自己封装成自己想要的样子)
**/
System.out.println(validateFlaw.getMessage());
}
打印结果:标题请控制在100个字符以内
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
Java的外部类为什么不能使用private和protected进行修饰的讲解
今天小编就为大家分享一篇关于Java的外部类为什么不能使用private和protected进行修饰的讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧2019-04-04
Java多线程之readwritelock读写分离的实现代码
这篇文章主要介绍了Java多线程之readwritelock读写分离的相关内容,文中涉及具体实例代码,具有一定参考价值,需要的朋友可以了解下。2017-10-10
Springboot打包代码,反编译后代码混淆方式(防止还原代码)
文章主要介绍了如何对Spring Boot项目进行jar包混淆,以防止反编译还原原始代码,通过在项目中添加proguard.cfg文件并配置Maven插件,可以实现代码混淆,从而增加反编译的难度2024-11-11
Java面试岗常见问题之ArrayList和LinkedList的区别
ArrayList和LinkedList作为我们Java中最常使用的集合类,很多人在被问到他们的区别时,憋了半天仅仅冒出一句:一个是数组一个是链表。这样回答简直让面试官吐血。为了让兄弟们打好基础,我们通过实际的使用测试,好好说一下ArrayList和LinkedList的区别这道经典的面试题2022-01-01
解读HttpServletRequestWrapper处理request数据流多次读取问题
在Java Web开发中,获取HTTP请求参数是常见需求,本文详细讨论了通过POST方式获取参数的两种主要方法:使用request.getParameter()适用于application/x-www-form-urlencoded和multipart/form-data内容类型;而对于application/json类型的数据2024-10-10


最新评论