[特殊字符] 芋道项目中的参数校验机制详解:以 AppProductActivityListReqVO 为例

在芋道(yudao)框架的 APP 接口开发中,我们经常会遇到这样的代码:

java 复制代码
@GetMapping("/list")
@Operation(summary = "获得活动商品列表(按开始日期分组)")
@PermitAll
public CommonResult<List<AppProductActivityListRespVO>> getActivitySpuList(@Valid AppProductActivityListReqVO reqVO) {
    return success(appProductActivityService.getActivitySpuList(reqVO));
}

你可能会好奇 👇

✅ 为什么加上 @Valid 注解就能自动校验参数?

✅ 错误提示是从哪里来的?

✅ 怎么自定义规则,比如"结束时间不能早于开始时间"?

这篇文章就带你从入门到精通,彻底搞懂芋道的参数校验体系。


🧩 一、基础概念:@Valid 是做什么的?

在 Spring Boot 项目中,@Valid@Validated 用于触发参数自动校验机制

只要在 Controller 的入参上加上它:

java 复制代码
public CommonResult<?> test(@Valid XxxReqVO reqVO)

Spring 会在调用方法前自动验证 reqVO 里的字段,

如果不符合规则,直接抛出异常(由全局异常处理器拦截返回友好提示)。


🧱 二、核心校验注解讲解

我们看下实际的例子:

java 复制代码
@Schema(description = "用户 APP - 活动商品查询请求")
@Data
public class AppProductActivityListReqVO {

    @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2025-01-01")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
    @NotNull(message = "开始日期不能为空")
    private LocalDate startTime;

    @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2025-01-31")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
    @NotNull(message = "结束日期不能为空")
    private LocalDate endTime;

    @Schema(description = "商品分类编号,可选")
    private Long categoryId;

🔹 每个注解的含义如下:

注解 作用 示例
@Schema 仅用于 Swagger/OpenAPI 文档描述 自动生成接口文档字段说明
@DateTimeFormat 指定前端传入日期的格式 避免格式错误,如 "2025-01-01"
@NotNull 校验字段不为空 "开始日期不能为空"
@Valid 触发整个对象的校验 用在 Controller 入参上
@Data Lombok 注解,自动生成 getter/setter 简化代码

🧮 三、进阶校验:自定义逻辑(@AssertTrue)

除了基本的非空、长度、正则验证外,芋道还经常使用自定义逻辑校验。

看下面两个方法 👇

java 复制代码
@AssertTrue(message = "结束时间不能早于开始时间")
@JsonIgnore
public boolean isEndNotBeforeStart() {
    if (startTime == null || endTime == null) {
        return true; // 交给 @NotNull 提示
    }
    return !endTime.isBefore(startTime);
}

@AssertTrue(message = "时间范围不能超过90天")
@JsonIgnore
public boolean isRangeWithinLimit() {
    if (startTime == null || endTime == null) {
        return true;
    }
    return ChronoUnit.DAYS.between(startTime, endTime) <= 90;
}

✨ 含义解析:

注解/方法 含义
@AssertTrue 表示该方法返回 true 时校验通过;返回 false 时提示错误信息
@JsonIgnore 防止这个方法被序列化到 JSON 中(否则会在响应中看到它)
方法名通常以 is...() 开头 Java Bean Validation 默认识别布尔校验方法

这样写的好处:

  • 不用写自定义 Validator;
  • 校验逻辑与字段关系紧密;
  • 一目了然,错误提示友好。

🧰 四、Spring 如何处理这些错误?

当参数不符合要求时(例如 endTime 早于 startTime),

Spring 会抛出 MethodArgumentNotValidException

芋道框架的全局异常处理器会捕获它,返回统一格式:

json 复制代码
{
  "code": 400,
  "message": "结束时间不能早于开始时间"
}

这部分逻辑在:

复制代码
yudao-framework -> web -> core -> handler -> GlobalExceptionHandler.java

中实现,统一把校验错误转为 CommonResult 的标准结构。


🔧 五、如何在自己的项目中使用?

你只要做到以下几步就能复用:

✅ 1. 在依赖中引入 validation

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

✅ 2. 在 Controller 入参上加上 @Valid

java 复制代码
@PostMapping("/create")
public CommonResult<?> create(@Valid @RequestBody OrderCreateReqVO reqVO) {
    return success(orderService.create(reqVO));
}

✅ 3. 在 VO 上使用注解声明规则

java 复制代码
public class OrderCreateReqVO {
    @NotBlank(message = "订单编号不能为空")
    private String orderNo;

    @Min(value = 1, message = "数量必须大于0")
    private Integer count;
}

✅ 4. 自定义复杂逻辑时用 @AssertTrue 或写自定义校验器


💡 六、额外技巧:可选 vs 必填字段

有些字段并不是必须的,比如 categoryId

如果不加任何注解,Spring 就不会校验它。

要让它"可选但有条件约束",可以结合 @AssertTrue 动态判断,比如:

java 复制代码
@AssertTrue(message = "如果传入分类ID,必须大于0")
@JsonIgnore
public boolean isCategoryIdValid() {
    return categoryId == null || categoryId > 0;
}

🧭 七、总结

功能 用法 示例
非空验证 @NotNull, @NotBlank 字符串、数字、对象等
范围验证 @Min, @Max, @Size 限定长度或数值范围
格式验证 @Email, @Pattern 邮箱、手机号等
自定义逻辑 @AssertTrue + 布尔方法 校验时间、组合条件
全局统一返回 GlobalExceptionHandler 自动包装友好提示

✅ 八、总结一句话

芋道的参数校验机制本质上是:

Spring Boot + Hibernate Validator + 自定义异常处理器

组合实现的一套「自动参数校验 + 友好提示」体系。

你只要在入参 VO 上写好注解,

在 Controller 上加 @Valid

剩下的校验、错误提示、格式化返回,系统都会帮你自动完成。

相关推荐
小蕾Java4 小时前
Java 开发工具,最新2025 IDEA 使用,保姆级教程
java·开发语言·intellij-idea
刘登辉5 小时前
idea使用联网缓存的pom进行离线开发
java·ide·intellij-idea·离线开发
摆烂且佛系5 小时前
IDEA Maven 仓库配置优先级
github·maven·intellij-idea
瑶山7 小时前
社区版Idea怎么创建Spring Boot项目?Selected Java version 17 is not supported. 问题解决
java·spring boot·intellij-idea·创建项目
Deryck_德瑞克9 小时前
IDEA编译时报错OOM的解决方案
java·ide·intellij-idea
JH30739 小时前
Idea中新建package包,变成了Directory
java·ide·intellij-idea
Crazy_diamonds9 小时前
ubuntu下桌面应用启动图标的内容文件
linux·ubuntu·intellij-idea
momo_via11 小时前
maven下载与安装及在IDEA中配置maven
java·maven·intellij-idea
讓丄帝愛伱2 天前
idea 中 mapper.xml黄线警告怎么去掉
java·intellij-idea