告别 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 插件与调用统计]

相关推荐
华科易迅1 小时前
Spring 单元测试
java·spring·单元测试
默|笙1 小时前
【Linux】进程信号(2)_信号保存
linux·运维·服务器
youyoulg1 小时前
opencode在Linux终端中无法复制文字的解决方法
linux·服务器·人工智能
俄城杜小帅1 小时前
C++线程异步和wpf中比较
java·c++·wpf
umeelove352 小时前
Springboot的jak安装与配置教程
java·spring boot·后端
The_Ticker2 小时前
日股实时行情接口使用指南
java·经验分享·笔记·python·算法·区块链
啥咕啦呛2 小时前
java打卡学习2:Stream高级与Optional
java·windows·学习
试试勇气2 小时前
Linux学习笔记(十九)--生产消费模型与线程安全
java·笔记·学习
凌波粒2 小时前
LeetCode--24.两两交换链表中的节点(链表)
java·算法·leetcode·链表