基本思想也比较简单,就是基于反射来实现对模型中参数的校验
定义注解
/**
* @Author: feifei
* @Date: 2023/02/13/10:44 上午
* @Description:
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface ValidateFei {
/**
* 小数位数 >0
*/
int digit() default 0;
/**
* @see {@link BigDecimal} Number舍入模式ROUND_*
*/
int round() default BigDecimal.ROUND_HALF_UP;
/**
* null时设置默认值
*/
String defValue() default "null";
/**
* 是否可以为空
*/
boolean nullable() default true;
/**
* 自定义异常说明
*
* @return
*/
String nullableDesc() default "";
/**
* 最大长度
*/
int maxLength() default 0;
String maxLengthDesc() default "";
/**
* 最小长度
*/
int minLength() default 0;
String minLengthDesc() default "";
/**
* 中文最大长度
*/
int maxChineseLenghth() default 0;
String maxChineseLenghthDesc() default "";
/**
* 中文最小长度
*/
int minChineseLength() default 0;
String minChineseLengthDesc() default "";
/**
* Number 金额不为0
*/
boolean notZero() default false;
String notZeroDesc() default "";
/**
* @see {@link RegexTypeEnum} 提供几种常用的正则验证
*/
RegexTypeEnum regexType() default RegexTypeEnum.NONE;
String regexTypeDesc() default "";
/**
* 自定义正则验证
*/
String regexExpression() default "";
String regexExpressionDesc() default "";
/**
* 参数或者字段描述,这样能够显示友好的异常信息
*/
String description() default "";
/**
* 集合非空
*/
boolean notEmpty() default false;
/**
* 对象非null
*/
boolean notNull() default false;
/**
* 字符串非空
*/
boolean notBlank() default false;
}
同时附上基本正则校验规则的枚举
public enum RegexTypeEnum {
NONE,
SPECIAL_CHAR,
CHINESE,
EMAIL,
IP,
NUMBER,
PHONE_NUMBER;
private RegexTypeEnum() {
}
}
定义校验工具类
/**
* @Author: feifei
* @Date: 2023/02/13/10:44 上午
* @Description:
*/
public class ValidateFeiUtils {
/**
*
* @param object 要被校验的对象
* @throws Exception
*/
public static void valid(Object object) throws Exception {
// 获取object的类型
Class<? extends Object> clazz = object.getClass();
// 获取该类型声明的成员
Field[] fields = clazz.getDeclaredFields();
//循环遍历对象中的属性
for (Field field : fields) {
// 获取对象的成员的注解信息
ValidateFei validator = field.getAnnotation(ValidateFei.class);
if (validator == null) {
continue;
}
if (!field.isAccessible()) {
field.setAccessible(true);
}
Object value = field.get(object);
validField(value, validator, field, object);
}
}
private static void validField(Object value, ValidateFei validator, Field field, Object object) throws Exception {
/*************注解解析工作开始******************/
setAmountDigit(value, validator, field, object);
setDefaultValue(value, validator, field, object);
String description;
if (StringUtil.isBlank(validator.description())) {
description = field.getName();
} else {
description = validator.description();
}
validateNullable(description, value, validator);
validateNotEmpty(description,value,validator);
validateNotNull(description,value,validator);
validateNotBlank(description,value,validator);
validateNotZero(description, value, validator);
validateLength(description, value, validator);
validateRegexType(description, value, validator);
validateRegexExpression(description, value, validator);
/*************注解解析工作结束******************/
}
private static void setAmountDigit(Object value, ValidateFei validator, Field field, Object object) throws IllegalAccessException {
if (value != null && validator.digit() > 0 && value instanceof BigDecimal) {
field.set(object, ((BigDecimal) value).setScale(validator.digit(), validator.round()));
}
}
private static void setDefaultValue(Object value, ValidateFei validator, Field field, Object object) throws ParseException, IllegalAccessException {
if (value == null && !"null".equals(validator.defValue())) {
// 获取POJO中属性为null的默认值
Object defaultValue = getDefaultValue(field.getType(), validator.defValue());
if (defaultValue != null) {
field.set(object, defaultValue);
}
}
}
private static Object getDefaultValue(Class<?> type, String value) throws ParseException {
if (type == Long.class) {
return Long.valueOf(value);
}
if (type == Byte.class) {
return Byte.valueOf(value);
}
if (type == BigDecimal.class) {
return new BigDecimal(value);
}
if (type == Date.class) {
return DateUtil.parse(value);
}
if (type == String.class) {
return value;
}
return null;
}
private static void validateNullable(String description, Object value, ValidateFei validator) {
if (validator.nullable()) {
return;
}
if (StringUtils.isNotBlank(validator.nullableDesc())) {
description = validator.nullableDesc();
} else {
description = description + "不能为空";
}
if(value instanceof java.util.List &&
CollectionUtils.isEmpty((Collection<?>) value)){
throw new IllegalArgumentException(description);
}
if (value == null) {
throw new IllegalArgumentException(description);
}
if (value instanceof String && StringUtils.isBlank(value.toString())) {
throw new IllegalArgumentException(description);
}
}
private static void validateNotEmpty(String description, Object value, ValidateFei validator){
if (!validator.notEmpty()) {
return;
}
if (StringUtils.isNotBlank(validator.description())) {
description = validator.description();
} else {
description = description + "不能为空";
}
if (value == null) {
throw new IllegalArgumentException(description);
}
if(value instanceof Collection && CollectionUtils.isEmpty((Collection<?>) value)){
throw new IllegalArgumentException(description);
}
}
private static void validateNotNull(String description, Object value, ValidateFei validator){
if (!validator.notNull()) {
return;
}
if (StringUtils.isNotBlank(validator.description())) {
description = validator.description();
} else {
description = description + "不能为空";
}
if (value == null) {
throw new IllegalArgumentException(description);
}
}
private static void validateNotBlank(String description, Object value, ValidateFei validator){
if (!validator.notBlank()) {
return;
}
if (StringUtils.isNotBlank(validator.description())) {
description = validator.description();
} else {
description = description + "不能为空";
}
if (value == null) {
throw new IllegalArgumentException(description);
}
if(value instanceof String && StringUtils.isBlank((String) value)){
throw new IllegalArgumentException(description);
}
}
private static void validateNotZero(String description, Object value, ValidateFei validator) {
if (!validator.notZero()) {
return;
}
if (value instanceof Number) {
if (((Number) value).doubleValue() == 0) {
if (StringUtils.isNotBlank(validator.notZeroDesc())) {
throw new IllegalArgumentException(validator.notZeroDesc());
}
throw new IllegalArgumentException(description + "不能为0");
}
}
}
private static void validateLength(String description, Object value, ValidateFei validator) {
if (value != null && validator.maxLength() != 0 && value.toString().length() > validator.maxLength()) {
if (StringUtils.isNotBlank(validator.maxLengthDesc())) {
throw new IllegalArgumentException(validator.maxLengthDesc());
}
throw new IllegalArgumentException(description + "长度不能超过" + validator.maxLength());
}
if (value != null && validator.maxChineseLenghth() != 0 && ChineseCheckUtil.getChineseLength(value.toString()) > validator.maxChineseLenghth()) {
if (StringUtils.isNotBlank(validator.maxChineseLenghthDesc())) {
throw new IllegalArgumentException(validator.maxChineseLenghthDesc());
}
throw new IllegalArgumentException(description + "中文长度不能超过" + validator.maxChineseLenghth());
}
if (value != null && validator.minLength() != 0 && value.toString().length() < validator.minLength()) {
if (StringUtils.isNotBlank(validator.minLengthDesc())) {
throw new IllegalArgumentException(validator.minLengthDesc());
}
throw new IllegalArgumentException(description + "长度不能小于" + validator.minLength());
}
if (value != null && validator.minChineseLength() != 0 && ChineseCheckUtil.getChineseLength(value.toString()) < validator.minChineseLength()) {
if (StringUtils.isNotBlank(validator.minChineseLengthDesc())) {
throw new IllegalArgumentException(validator.minChineseLengthDesc());
}
throw new IllegalArgumentException(description + "中文长度不能小于" + validator.minChineseLength());
}
}
private static void validateRegexType(String description, Object value, ValidateFei validator) {
if (value == null || validator.regexType() == RegexTypeEnum.NONE) {
return;
}
switch (validator.regexType()) {
case NONE:
break;
case SPECIAL_CHAR:
if (RegexUtils.hasSpecialChar(value.toString())) {
if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
throw new IllegalArgumentException(validator.regexTypeDesc());
}
throw new IllegalArgumentException(description + "不能含有特殊字符");
}
break;
case CHINESE:
if (RegexUtils.isChinese2(value.toString())) {
if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
throw new IllegalArgumentException(validator.regexTypeDesc());
}
throw new IllegalArgumentException(description + "不能含有中文字符");
}
break;
case EMAIL:
if (!RegexUtils.isEmail(value.toString())) {
if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
throw new IllegalArgumentException(validator.regexTypeDesc());
}
throw new IllegalArgumentException(description + "地址格式不正确");
}
break;
case IP:
if (!RegexUtils.isIp(value.toString())) {
if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
throw new IllegalArgumentException(validator.regexTypeDesc());
}
throw new IllegalArgumentException(description + "地址格式不正确");
}
break;
case NUMBER:
if (!RegexUtils.isNumber(value.toString())) {
if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
throw new IllegalArgumentException(validator.regexTypeDesc());
}
throw new IllegalArgumentException(description + "不是数字");
}
break;
case PHONE_NUMBER:
if (!RegexUtils.isPhoneNumber(value.toString())) {
if (StringUtils.isNotBlank(validator.regexTypeDesc())) {
throw new IllegalArgumentException(validator.regexTypeDesc());
}
throw new IllegalArgumentException(description + "格式不正确");
}
break;
default:
break;
}
}
private static void validateRegexExpression(String description, Object value, ValidateFei validator) {
if (StringUtil.isBlank(validator.regexExpression())) {
return;
}
if (value != null && !value.toString().matches(validator.regexExpression())) {
if (StringUtils.isNotBlank(validator.regexExpressionDesc())) {
throw new IllegalArgumentException(validator.regexExpressionDesc());
}
throw new IllegalArgumentException(description + "格式不正确");
}
}
}
基本测试
测试的model定义
/**
* @Author: feifei
* @Date: 2023/02/13/11:00 上午
* @Description:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestModel {
@ValidateFei(notEmpty = true,description = "姓名集合")
private List<String> nameList;
@ValidateFei(regexType = RegexTypeEnum.PHONE_NUMBER,description = "手机号码")
private String number;
}
测试的main方法
/**
* @Author: feifei
* @Date: 2023/02/13/11:02 上午
* @Description:
*/
public class Test {
public static void main(String[] args) throws Exception {
TestModel testModel = new TestModel();
testModel.setNumber("13279930454");
ValidateFeiUtils.valid(testModel);
}
}
至此结束,同样的可以自己添加适合自己业务需求的校验规则