news 2026/7/1 12:57:00

@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/7/2 4:30:49

Java面试必看:ConcurrentHashMap并发度解析

文章目录Java面试必看&#xff1a;ConcurrentHashMap并发度解析&#xff1f;场景还原&#xff1a;面试官与我的对话什么是并发度&#xff1f;并发度的核心思想并发度的实现细节1. Segment数组2. 分段锁机制3. 动态调整Segment数量4. 高效的查找机制如何配置合适的并发度&#x…

作者头像 李华
网站建设 2026/7/2 5:12:46

计算机基础小题

第一章 填空题 基于&#xff08;存储程序&#xff09;原理的冯诺依曼计算机&#xff0c;其工作方式的基本特点是&#xff08;按地址访问并顺序执行指令&#xff09;&#xff08;指令&#xff09;和&#xff08;数据&#xff09;都存放在存储器中&#xff0c;&#xff08;控制器…

作者头像 李华
网站建设 2026/6/30 7:30:47

Vite 在项目中的使用分析

## &#x1f4cb; 目录 - [Vite 工作流程](#vite-工作流程) - [开发服务器流程](#开发服务器流程) - [构建流程](#构建流程) - [插件处理流程](#插件处理流程) - [关键配置说明](#关键配置说明) - [依赖关系](#依赖关系) ## Vite 工作流程 ## 开发服务器流程mermaid ## 构建…

作者头像 李华
网站建设 2026/7/1 23:57:27

【计算机毕业设计案例】基于Springboot实现动漫推荐系统的协同过滤算法基于协同过滤算法的动漫推荐系统(程序+文档+讲解+定制)

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

作者头像 李华
网站建设 2026/6/28 22:44:32

手术室调度混乱每天浪费数小时,AI如何成为医院救星

在医疗领域&#xff0c;人工智能和机器人备受关注&#xff0c;但真正让医院损失金钱的问题其实是手术室协调。每天有2到4小时的手术室时间被浪费&#xff0c;这并非因为手术本身&#xff0c;而是因为手术间隙的各种问题&#xff0c;从人工排班和协调混乱到房间周转时间的不确定…

作者头像 李华
网站建设 2026/7/2 2:45:12

激动人心!Spring AI 2.x 发布!史诗级加强!

目录版本概览与重大变更**革命性的技术栈升级**&#x1f4e6; 环境要求与项目配置环境要求依赖配置基础配置 (application.yml)✨ 核心新特性与升级详解1. Redis 史诗级增强&#xff1a;成为AI应用核心存储2. 模型生态全面爆发3. 企业级特性与基础设施&#x1f4bb; 核心API使用…

作者头像 李华