告别 if-else 地狱 —— JSR380 参数验证在 ionet 中的应用

你的 Action 方法长什么样?

很多开发者的业务方法,前一半都是在检查参数:

java 复制代码
// 不使用验证框架的写法
private void createRoom(CreateRoomMessage message) {
    if (message.roomName == null || message.roomName.isEmpty()) {
        throw new RuntimeException("房间名不能为空");
    }
    if (message.roomName.length() > 20) {
        throw new RuntimeException("房间名太长");
    }
    if (message.maxPlayers < 2 || message.maxPlayers > 10) {
        throw new RuntimeException("人数限制不合法");
    }
    if (message.gameMode < 0 || message.gameMode > 3) {
        throw new RuntimeException("游戏模式不合法");
    }
    // 终于可以写业务了...
}

可以看出参数验证不是业务,却写在了业务里面。


JSR380:声明式验证

ionet 支持 JSR380(Bean Validation)规范。你可以在协议类上用注解声明验证规则:

java 复制代码
@ProtobufClass
public class CreateRoomMessage {
    @NotNull(message = "房间名不能为空")
    @Size(min = 1, max = 20, message = "房间名长度需在1-20之间")
    public String roomName;

    @Min(value = 2, message = "至少2人")
    @Max(value = 10, message = "最多10人")
    public int maxPlayers;

    @Min(value = 0, message = "游戏模式不合法")
    @Max(value = 3, message = "游戏模式不合法")
    public int gameMode;
}

现在你的 Action 方法变成了:

java 复制代码
@ActionMethod(RoomCmd.create)
private RoomInfo createRoom(CreateRoomMessage message) {
    // 直接写业务逻辑!参数已经验证通过了
    Room room = roomService.create(message.roomName, message.maxPlayers);
    return room.toInfo();
}

验证失败时,框架自动将错误信息返回给客户端。 你的业务方法里不会出现任何参数检查代码。


常用验证注解

注解 作用 示例
@NotNull 不能为 null @NotNull(message = "不能为空")
@NotEmpty 不能为 null 且不为空字符串 适用于 String
@Size 字符串/集合长度范围 @Size(min=1, max=50)
@Min 最小值 @Min(1)
@Max 最大值 @Max(100)
@Positive 必须为正数 适用于数字类型
@Email 邮箱格式
@Pattern 正则表达式 @Pattern(regexp="[a-zA-Z]+")

与断言机制的配合

JSR380 负责格式层 的验证(数据类型、长度、范围),断言机制负责业务层的验证(用户是否存在、金币是否足够)。

两者配合使用,让你的代码分层更清晰:

java 复制代码
@ProtobufClass
public class BuyMessage {
    @Positive(message = "商品ID必须为正数")
    public int itemId;

    @Min(value = 1, message = "至少购买1个")
    @Max(value = 99, message = "最多购买99个")
    public int count;
}

@ActionMethod(ShopCmd.buy)
private void buyItem(FlowContext flowContext, BuyMessage message) {
    // JSR380 已经验证了 itemId > 0, 1 <= count <= 99

    Item item = itemService.getItem(message.itemId);
    ErrorCode.itemNotFound.assertTrue(item != null);        // 业务断言
    ErrorCode.itemOffSale.assertTrue(item.isOnSale());      // 业务断言
    ErrorCode.goldNotEnough.assertTrue(hasEnoughGold(item)); // 业务断言

    // 纯粹的业务逻辑
    doPurchase(flowContext.getUserId(), item, message.count);
}

格式验证 → 注解完成,业务验证 → 断言完成,剩下的就是纯业务逻辑。


小结

JSR380 + 断言机制的组合,让你的代码呈现出清晰的三层结构:

  1. 格式验证层@NotNull@Min...)→ 注解声明,零代码
  2. 业务验证层ErrorCode.xxx.assertTrue)→ 一行断言
  3. 业务逻辑层 → 你真正要写的代码

更多资源

下一篇预告开发神器:DebugInOut 插件与调用统计

相关推荐
云飞云共享云桌面29 分钟前
自动化设备厂 10 人研发团队,如何共用一台服务器做 SolidWorks 建模?
运维·服务器·网络·3d·自动化·制造
xierui12312332 分钟前
AI Agent 隐私架构:本地化重点为什么是登录态与执行权限
java·人工智能·网络安全·架构
cfm_291442 分钟前
Spring AI Tool 调用架构全解
java·人工智能·spring
筝筝ba1 小时前
Configure IP Address Via Different User Roles And Verify(1)
服务器
sun༒1 小时前
Spring @Scheduled 定时任务详解:Cron表达式、执行顺序、优先级与并行调度
java·后端·spring
QH139292318801 小时前
NVIDIA H200 H300服务器
运维·服务器·开发语言·网络·信息与通信
xixiaoyunya1 小时前
中小微企业轻量组网方案的技术选型与实践:从传统专线到软定义隧道的成本与效能分析
服务器·php·apache
Hello-FPGA1 小时前
嵌入式LINUX 设备 ip配置后怎么保存才能掉电不消失?
linux·运维·服务器
一次旅行1 小时前
DeepSeek‑V4‑Flash‑Vision‑Exp 小白入门实战|3种传图方式、完整可跑代码、避坑排障
java·前端·人工智能
野生技术架构师1 小时前
Spring Boot 实现数据脱敏:自定义注解 + Jackson 序列化器
java·spring boot·后端