@Validated // 标注这个,方法中的 @Min、@Max 和 自定义校验 @ValidExcelFile、@FileSize 等才会生效(Spring 默认不对 @PathVariable 进行校验,需 @Validated 激活)

代码:

/**
 * 资金信息控制器
 * <p>提供资金信息的增删改查、附件管理、导入导出等 RESTful API。</p>
 */
@RestController
@RequestMapping("/capital/infos")
@Slf4j
@RequiredArgsConstructor
@Validated // 标注这个,方法中的 @Min、@Max 和 自定义校验 @ValidExcelFile、@FileSize 等才会生效(Spring 默认不对 @PathVariable 进行校验,需 @Validated 激活)
public class CapitalInfoController {

    private final CapitalInfoService capitalInfoService;

    /**
     * 导入数据(Excel 文件)
     * <p>支持 .xls 和 .xlsx 格式。</p>
     *
     * @param uploadFile 上传的 Excel 文件
     * @param request    HttpServletRequest 对象,用于记录请求 URI
     * @return 操作结果 {@link Result}&lt;{@link Void}&gt;
     */
    @PostMapping("/import")
    @Debounce(keyType = Debounce.KeyType.USER, value = 0) // value=0 表示使用配置值
    public Result<Void> importData(
            @RequestParam("uploadFile")
            @NotNull
            @ValidExcelFile
            @FileSize(max = 1024 * 1024, message = "Excel文件大小不能超过1MB")
            MultipartFile uploadFile,
            HttpServletRequest request) {

        String endpoint = request.getRequestURI();
        String method = "importData";

        log.info("【资金信息】导入数据,{},{},uploadFile={}", endpoint, method, uploadFile);

        capitalInfoService.importData(uploadFile);

        return Result.success();
    }
}

对自定义注解的要求:要求有 groups() 和 payload() 方法

src/main/java/com/weiyu/annotation/ValidExcelFile.java

package com.weiyu.annotation;

import com.weiyu.validation.ExcelFileValidator;
import jakarta.validation.Constraint;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Excel文件校验注解
 */
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ExcelFileValidator.class)
public @interface ValidExcelFile {

    String message() default "请确保是有效的Excel文件(.xls 或 .xlsx 格式)";

    /**
     * groups() – 校验分组
     * <p>
     *     - 作用:允许对同一个字段在不同场景下应用不同的校验规则。
     * </p>
     * <p>
     *     - 使用场景:例如在新增时 capitalName 字段必须不为空,但更新时允许为空。通过定义分组(如 CreateGroup、UpdateGroup),可以在不同操作时激活不同的校验规则。
     * </p>
     * <p>
     *     - 默认行为:如果不指定分组,则属于默认分组 Default.class。
     * </p>
     */
    Class<?>[] groups() default {};

    /**
     * payload() – 载荷
     * <p>
     *     - 作用:用于传递附加的元数据,例如错误严重级别(Payload 可以携带自定义信息)。
     * </p>
     * <p>
     *     - 使用场景:当校验失败时,可以通过 payload 携带一些额外信息,供上层处理(如国际化、错误分类)。
     * </p>
     * <p>
     *     - 实际使用:在大多数项目中并不常用,但规范要求必须存在。通常保持空数组即可。
     * </p>
     */
    Class<? extends jakarta.validation.Payload>[] payload() default {};
}

当你在 CapitalInfoController 类上添加 @Validated 后,Spring 会启用方法参数校验,从而扫描到所有自定义约束注解(如 @ValidExcelFile@FileSize@FileType)。如果这些注解缺少 Bean Validation 规范要求的 groups() 和 payload() 方法,就会抛出 ConstraintDefinitionException。之前由于没有 @Validated 或参数上没有 @Valid,校验未触发,所以问题被隐藏。


错误表明自定义注解 @ValidExcelFile 缺少 Bean Validation 规范要求的 groups() 和 payload() 方法。以下是修正后的注解代码,同时建议检查其他自定义注解(如 @FileSize@FileType)并补充相同的方法。

修正 @ValidExcelFile

java

package com.weiyu.annotation;

import com.weiyu.validation.ExcelFileValidator;
import jakarta.validation.Constraint;
import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ExcelFileValidator.class)
public @interface ValidExcelFile {

    String message() default "请确保是有效的Excel文件(.xls 或 .xlsx 格式)";

    Class<?>[] groups() default {};

    Class<? extends jakarta.validation.Payload>[] payload() default {};
}

确保其他自定义注解也符合规范

1. @FileSize(如果未包含)

java

package com.weiyu.annotation;

import com.weiyu.validation.FileSizeValidator;
import jakarta.validation.Constraint;
import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FileSizeValidator.class)
public @interface FileSize {
    String message() default "文件大小不能超过 {max} 字节";
    long max() default 10 * 1024 * 1024;
    long min() default 0;
    Class<?>[] groups() default {};
    Class<? extends jakarta.validation.Payload>[] payload() default {};
}
2. @FileType(如果未包含)

java

package com.weiyu.annotation;

import com.weiyu.validation.FileTypeValidator;
import jakarta.validation.Constraint;
import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FileTypeValidator.class)
public @interface FileType {
    String message() default "文件类型不允许";
    String[] allowedExtensions() default {};
    String[] allowedContentTypes() default {};
    String[] excludedExtensions() default {};
    String[] excludedContentTypes() default {};
    Class<?>[] groups() default {};
    Class<? extends jakarta.validation.Payload>[] payload() default {};
}

说明

  • groups() 和 payload() 是 Bean Validation 规范要求的,即使不使用也必须声明,否则会导致 ConstraintDefinitionException

  • 所有自定义约束注解都必须包含这两个方法,通常返回空数组即可。

修复后重启应用,错误应消失。


之前没有报错的原因可能是校验未被触发。当你在 CapitalInfoController 类上添加 @Validated 后,Spring 会启用方法参数校验,从而扫描到所有自定义约束注解(如 @ValidExcelFile@FileSize@FileType)。如果这些注解缺少 Bean Validation 规范要求的 groups() 和 payload() 方法,就会抛出 ConstraintDefinitionException。之前由于没有 @Validated 或参数上没有 @Valid,校验未触发,所以问题被隐藏。

现在请为所有自定义约束注解补全这两个方法,包括 @ValidExcelFile@FileSize@FileType,以及项目中可能存在的其他自定义校验注解。按照上述示例添加即可,错误即可解决。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐