news 2026/2/16 9:35:29

@valid的坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
@valid的坑

尝试1

  • 如果需要参数校验,我们就在controller的参数前添加@valid,像下面一样
@RequestBody @Valid List<PlatProjectItemAndVerionVo> itemAndVersionVoList
  • 参数属性上添加注解
@NotBlank(message = "dataType参数不能为空") private String dataType;
  • 这个@valid引入如下
import javax.validation.Valid;

但是根本就不生效,于是同事心生一计,采用自定义注解

尝试2

  • 定义自定义注解
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=CustomFieldValidator.class) public @interface CustomVaildator { String message() default "字段校验失败"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; // 自定义参数 String pattern() default ""; int maxLength() default -1; boolean required() default false; }
  • 定义自定义注解处理类
public class CustomFieldValidator implements ConstraintValidator<CustomVaildator, Object> { private CustomVaildator annotation; @Override public void initialize(CustomVaildator customVaildator) { // 未使用 } @Override public boolean isValid(Object value, ConstraintValidatorContext context) { // 如果字段不是必需的且值为null,则通过校验 if (value == null && !annotation.required()) { return true; } // 如果是必需字段但值为null,则不通过校验 if (value == null && annotation.required()) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("字段不能为空") .addConstraintViolation(); return false; } String stringValue = value.toString(); // 长度校验 if (annotation.maxLength() > 0 && stringValue.length() > annotation.maxLength()) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("字段长度不能超过" + annotation.maxLength()) .addConstraintViolation(); return false; } // 正则表达式校验 if (!annotation.pattern().isEmpty()) { Pattern pattern = Pattern.compile(annotation.pattern()); if (!pattern.matcher(stringValue).matches()) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("字段格式不正确") .addConstraintViolation(); return false; } } return true; } }
  • 参数属性上添加自定义注解
@CustomVaildator(required = true) private String dataType;

依然不生效,于是同事尝试了以下方法

尝试3

  • 定义手动校验类
@Component public class AnnotationBasedValidator { // 缓存正则表达式以提高性能 private final Map<String, Pattern> patternCache = new ConcurrentHashMap<>(); /** * 通过反射扫描对象中带有指定注解的字段并进行校验 */ public <T> List<String> validateByAnnotation(T object) { List<String> errors = new ArrayList<>(); if (object == null) { errors.add("对象不能为空"); return errors; } Field[] fields = object.getClass().getDeclaredFields(); for (Field field : fields) { // 检查是否有自定义注解 if (field.isAnnotationPresent(CustomVaildator.class)) { try { field.setAccessible(true); Object value = field.get(object); CustomVaildator annotation = field.getAnnotation(CustomVaildator.class); String error = validateField(value, annotation, field.getName()); if (error != null) { errors.add(field.getName() + ": " + error); } } catch (IllegalAccessException e) { errors.add("校验字段" + field.getName() + "时发生错误: " + e.getMessage()); } } } return errors; } private String validateField(Object value, CustomVaildator annotation, String fieldName) { // 必填校验 if (annotation.required() && (value == null || (value instanceof String && StringUtils.isBlank((String) value)) || (value instanceof List && ((List<?>) value).isEmpty()))) { if (value instanceof List) { return "列表字段不能为空"; } return "字段不能为空"; } if (value == null) { return null; // 非必填字段为null时直接通过 } // List类型特殊处理 if (value instanceof List) { List<?> listValue = (List<?>) value; if (annotation.required() && listValue.isEmpty()) { return "列表字段不能为空"; } // 可以在这里添加对List元素的进一步校验逻辑 return null; } String stringValue = value.toString(); // 正则表达式校验 if (!annotation.pattern().isEmpty()) { // 使用缓存避免重复编译正则表达式 Pattern pattern = patternCache.computeIfAbsent(annotation.pattern(), Pattern::compile); if (!pattern.matcher(stringValue).matches()) { return "格式不符合要求"; } } return null; } /** * 校验列表中的所有对象 */ public <T> void validateListByAnnotation(List<T> list, String exceptionPrefix) { if (CollectionUtils.isEmpty(list)) { throw new IllegalArgumentException("列表不能为空"); } for (int i = 0; i < list.size(); i++) { T item = list.get(i); List<String> errors = validateByAnnotation(item); if (!errors.isEmpty()) { throw new IllegalArgumentException( String.format("%s列表中第%d个元素校验失败: %s", exceptionPrefix, i + 1, String.join(", ", errors))); } } } }
  • 手动校验
annotationBasedValidator.validateListByAnnotation(platVersionAndItemVoList, "总成学科");

这次终于可以,但是更加的不通用

尝试4

根据同事的解释是,如果参数是单个对象,可以通过框架触发校验,但是如果是数组对象,无法通过框架触发校验。排查后发现同事引入的@valid注解是javax.validation.Valid,更换引入的@valid注解,这次数组对象也可以触发参数校验。

  • 我们在controller的参数前添加@valid,像下面一样
@RequestBody @Valid List<PlatProjectItemAndVerionVo> itemAndVersionVoList
  • 这个@valid引入如下
import jakarta.validation.Valid;
  • 参数属性上添加注解
@NotBlank(message = "dataType参数不能为空") private String dataType;
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/12 1:01:35

《从视觉到听觉:游戏状态信息的屏幕阅读器适配底层逻辑》

某个深夜,为测试一款开放世界作品的边缘场景,我刻意关闭视觉输出,仅依赖屏幕阅读器漫游虚拟大陆,那份突如其来的割裂感至今清晰—角色翻越地形时仅有模糊的方位提示,技能蓄力完成毫无有效反馈,任务目标的进度变化隐没在视觉信息的洪流中,就连拾取道具的提示都显得苍白无…

作者头像 李华
网站建设 2026/2/5 19:30:11

年终述职 PPT 工具横评:效率、质量、模板一次看清

又到年终&#xff0c;职场人又要开始为年终述职 PPT 发愁了。熬夜加班改报告是常有的事&#xff0c;内容框架搭建毫无头绪&#xff0c;设计上也没有灵感&#xff0c;好不容易做好了&#xff0c;不同系统打开还容易出现格式乱码问题。面对这些办公痛点&#xff0c;一款好用的 AI…

作者头像 李华
网站建设 2026/2/7 10:35:40

【计算机毕业设计案例】基于springboot旅游门票信息系统设计与实现基于springboot的旅游网站系统的设计与实现(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/2/8 0:30:36

18、数据库开发技术全面解析

数据库开发技术全面解析 1. 特殊字符与运算符 在数据库操作中,特殊字符和运算符起着关键作用。例如, % 通配符用于模糊匹配, * 字符常用于选择所有列。以下是一些常见特殊字符和运算符的介绍: | 特殊字符/运算符 | 作用 | | ---- | ---- | | % 通配符 | 用于模糊…

作者头像 李华