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

相关推荐
jump_jump6 小时前
为了重玩金庸群侠传,我研究了一下 Ruffle 怎么复活 Flash
游戏·rust·github
SimonKing6 小时前
艹,维护AI写的代码,我心态崩了......
java·后端·程序员
用户298698530146 小时前
Java Word 文档样式进阶:段落与文本背景色设置完全指南
java·后端
小bo波1 天前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
zzzzzz3101 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
XIAOHEZIcode1 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
nanxun8862 天前
记一次诡异的 Docker 容器"串包"故障排查
java
用户1563068103512 天前
Day01 | Java 基础(Java SE)
java
行者全栈架构师2 天前
Maven dependency:tree 的 8 个高级用法
java·后端
Aloys_Code2 天前
逆向一个被遗忘的DVD游戏格式:从DES加密到Rust模拟器
游戏·模拟器·retroarch·复古游戏·native32·sunplus·赤刃·钢铁风暴