news 2026/5/9 4:14:31

@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/5/1 1:30:40

4 倍扩容 + 700 + 流程图极速展示!ProDB×TDengine 赋能泰州石化

小T导读&#xff1a;中海油泰州石化原有 AspenTech InfoPlus.21 实时数据库系统建设至今已有十余年&#xff0c;随着企业的逐步发展&#xff0c;原有采集点数已达上限&#xff0c;相关应用取数效率下降&#xff0c;限制了企业新需求的增长&#xff0c;借助该国产化项目汉中诺 P…

作者头像 李华
网站建设 2026/5/2 20:00:37

【电动汽车响应率】考虑的是针对电动汽车充放电调度问题,由于放电奖励不同导致部分车主不愿参与放电,设计出响应率计算方法附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码及仿真咨询…

作者头像 李华
网站建设 2026/5/1 10:55:05

从数据瓶颈到ROAS飙升21%!Skygo牵手热力引擎,按下游戏增长快进键

在游戏行业全球化竞争日趋激烈的市场环境下&#xff0c;如何依托高效的移动营销合作伙伴&#xff08;MMP&#xff09;破解数据短板、优化广告投放效能&#xff0c;不仅是必修课&#xff0c;更是游戏厂商实现规模化增长的破局关键。越南游戏开发与发行公司 Skygo&#xff0c;凭借…

作者头像 李华
网站建设 2026/5/3 18:38:20

需求接口人与研发接口人的职责分别是什么

需求接口人与研发接口人是连接“业务价值”与“技术实现”的两个核心枢纽。需求接口人&#xff08;通常是产品经理或业务分析师&#xff09;的核心职责是“定义”&#xff0c;即明确“做什么”和“为什么做”&#xff0c;他们对业务价值、需求优先级和用户体验负责。研发接口人…

作者头像 李华
网站建设 2026/5/1 14:35:01

基于大数据的短视频用户兴趣分析的设计与实现(程序+文档+讲解)

课题介绍在短视频平台精细化运营、个性化推荐需求下&#xff0c;传统用户兴趣分析存在 “维度单一、实时性差、精准度不足” 的痛点&#xff0c;基于大数据技术构建的短视频用户兴趣分析体系&#xff0c;整合用户行为数据、内容交互数据、环境数据等多源信息&#xff0c;实现用…

作者头像 李华
网站建设 2026/5/2 15:57:55

【最新2023】各省地区生产总值GDP 人均生产总值(人均GDP) 地区生产总值指数的 省级省份

【最新2023】各省地区生产总值GDP 人均生产总值(人均GDP) 地区生产总值指数的 省级省份 时间范围1999-2023年 人均生产总值指数(人均GDP指数) 包括一下: 人均生产总值(人均GDP) 各省地区生产总值GDP 人均生产总值指数(人均GDP指数) 地区生产总值指数 见图 说明:人均生产总值指…

作者头像 李华