很多时候我们都需对api的参数进行规则检验,校验,如不能为空,长度限制,电话号码等等。一般我都使用validation的@Valid注解,再在相应的参数上加上如@NotBlank之类的注解来实现校验,但是在一些特殊的场景下@Valid注解不会生效,也就不会对参数校验,比如service接口我需要校验,所以基于validation封装了如下工具类。其中用到的EmptyChecker工具类见: java常用判空工具类_百块富翁的博客-CSDN博客_java判空工具类
import com.alibaba.fastjson.JSON;
import org.hibernate.validator.HibernateValidator;
import javax.validation.*;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
/**
* @ClassName 自定义参数校验器
* @Description 在service层Validator的@Valid注解无法生效,使用以下方法可以对Validation的相关注解生效,如@NotNull
* 如果对象内包含对象,下层对象仍需校验,请使用 @Valid 标识
* 注意:目前不支持内部类
* @Author miss you BUG
* @Date 2021/8/12 16:11
* @Email rkj01135525@cainiao.com
*/
public class ValidUtil {
//初始化检查器。
static ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
.configure()
.failFast(false)
.buildValidatorFactory();
static Validator validator = validatorFactory.getValidator();
public static void validChecker(Object object) {
List<LinkedHashMap<String, Object>> result = new ArrayList<>();
serviceValid(object, result);
if (EmptyChecker.notEmpty(result)) {
throw new RuntimeException(JSON.toJSONString(result));
}
}
private static void serviceValid(Object object, List<LinkedHashMap<String, Object>> result) {
try {
LinkedHashMap<String, Object> msg = new LinkedHashMap<>();
//检查object
Set<ConstraintViolation<Object>> set = validator.validate(object);
List<String> list = new ArrayList<>();
//循环set,获取检查结果
for (ConstraintViolation<Object> voset : set) {
list.add("key:" + voset.getPropertyPath() + ", errMsg:" + voset.getMessage() + ";");
}
Class classInfo = object.getClass();
if (EmptyChecker.notEmpty(list)) {
msg.put("className", classInfo.getName());
msg.put("errMsg", list);
result.add(msg);
}
Field[] fields = classInfo.getDeclaredFields();//Object是已经被赋值的对象实例
for (Field field : fields) {
Type genericFieldType = field.getGenericType();
Valid valid = field.getAnnotation(Valid.class);
//如果存在这个注解
if (EmptyChecker.notEmpty(valid)) {
//如果是List
if (genericFieldType instanceof ParameterizedType) {
//打开私有访问
field.setAccessible(true);
//获取属性值
Object value = field.get(object);
if (EmptyChecker.isEmpty(value)) {
LinkedHashMap<String, Object> msg1 = new LinkedHashMap<>();
msg1.put("className", field.getName());
msg1.put("errMsg", "不能为空!");
result.add(msg1);
continue;
}
Collection cloneable = (Collection) value;
//拿到List的值
for (Object obj : cloneable) {
serviceValid(obj, result);
}
} else {//获取属性值
//打开私有访问
field.setAccessible(true);
Object value = field.get(object);
serviceValid(value, result);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用方法:在参数上还是一样的使用@NotNull之类的注解,在服务中手动的调用工具类方法把需校验的参数传进去。
eg:
@Data
public class User{
@NotNull
private Integer id;
@NotBlank
private String name;
//下层对象需校验需使用@Valid注解
@Valid
private Order order
}
@Data
public class Order{
@NotNull
private Long id;
@NotBlank
private String code;
}
public class TsetServiceImpl{
public boolean validTest(User user){
//参数校验
ValidUtil.validChecker(user);
return true;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!