跳到主要内容

JSR380 验证规范

介绍

业务框架支持 JSR 380 验证规范 (由 hibernate-validator 支持)。

业务参数的验证不在需要写在业务代码里面,可以使得业务代码更干净。

若不使用验证框架,常规的做法是不断的在业务代码中疯狂使用 if else 输出,这将造成业务代码混乱。 关于验证框架的更多的好处,请自行查询。

下面,我们使用两个示例对比来说明 JSR380 的优势。 一个是使用了 JSR380 的示例,一个是没有使用 JSR380 的示例。

不开启验证的示例

现在先让我们看一个没有使用 JSR380 的示例。

在这个示例中,我们对电子邮箱和年龄这两个属性的数据进行合法验证。 验证包括邮箱的格式和年龄的最小范围。


message 的值设置如下

  • message.email="a";
  • message.age = 1;

@ActionController(1)
public class JsrJakartaAction {
@ActionMethod(1)
public void verify(ValidMessage message) {
String email = message.email;

GameCode.emailChecked.assertNullThrows(email == null);

Pattern pattern = Pattern.compile("[a-zA-Z0-9_-]+@\\w+\\.[a-z]+(\\.[a-z]+)?");
var result = pattern.matcher(email).find()
GameCode.emailChecked.assertTrue(result);

int age = message.age;
GameCode.ageChecked.assertTrueThrows(age < 2);

// Your biz code
...
}
}

@ProtobufClass
public class ValidMessage {
public String email;
public int age;
}

@Getter
public enum GameCode implements MsgExceptionInfo {
emailChecked(100, "Email error."),
ageChecked(101, "Age error."),
;

final int code;
final String msg;

GameCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
}

可以看出,这里只有两个字段需要验证,就有很多代码了。 如果在多加几个需要验证的字段或多几个字段的验证规则,那么代码就会非常的多。

实际上这样的代码是重复的,对于这样相关的代码在 JSR380 中已经给出了统一的解决方案。 在大部分的框架中也支持了,所以我们的业务框架也是支持这些验证的。

如何安装

提示

JSR380 是一个按需使用的功能,所以需要在你的项目 maven 中引入

pom.xml
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>7.0.4.Final</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.glassfish/jakarta.el -->
<!-- EL实现。在Java SE环境中,您必须将实现作为依赖项添加到POM文件中 -->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.el</artifactId>
<version>4.0.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/jakarta.validation/jakarta.validation-api -->
<!-- 验证器 Maven 依赖项 -->
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version>
</dependency>

如何使用

开启验证选项

在业务框架中开启验证选项

public BarSkeleton createBarSkeleton() {
BarSkeletonBuilder builder = ...;
builder.getSetting().setValidator(true);
return builder.build();
}

action example

我们给 ValidMessage 加上了一些 JSR 相关的注解,这些注解是帮助我们简化验证的。

同样的,在这个示例中我们对电子邮箱和年龄这两个属性的数据进行合法验证, 验证包括邮箱的格式和年龄的最小范围。


@ActionController(1)
public class JsrJakartaAction {
@ActionMethod(1)
public void verify(ValidMessage message) {
// Your biz code
...
}
}

@ProtobufClass
public class ValidMessage {
@NotNull
@Email
public String email;

@Min(value = 2, message = "Age error")
public int age;
}

代码中没有任何的逻辑(干净的业务体),因为验证相关的逻辑全都由业务框架来做了,包括错误码的响应。 这段代码与上面没有开启验证的示例代码达到同等的验证效果

除了可以达到同等验证效果的同时,业务框架还做了一些小优化。 如果业务参数验证没有通过,就不会执行action,可以减少一次损耗。

业务框架结合了 JSR380 和异常机制,使得程序员只需关注真正的业务。

因为 email 字段给的值 "a",所以会给出失败的结果。

业务框架会把这个错误码和错误提示给到游戏端。

┏━━━━━ Error. [JsrJakartaAction.java] ━━━ [.(ValidAction.java:1).validate] ━━━ [cmd:1-1] ━━━ [JsrLogicServer 游戏逻辑服]
┣ 参数: validMessage : ValidMessage(email=a, age=2)
┣ 错误码: -1001
┣ 验证信息: 不是一个合法的电子邮件地址
┣ 时间: 0 ms (业务方法总耗时)
┗━━━━━ [ioGame:21.27] ━━━━━ [线程:User-8-3] ━━━━━ [连接方式:WebSocket] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

错误码 -1001

错误码 -1001 是业务框架内定的一个响应码,用于验证失败时响应给请求端(一般是游戏前端)的信息。

JSR380 验证组

JSR380 新增参数分组校验,分组校验在 web 开发中很常见,ioGame 也支持这一特性。

提示

该特性由 双眼皮男孩 - Gitee.com 贡献

@ActionController(1)
public class DemoAction {
...
@ActionMethod(0)
public void validateUpdate(@ValidatedGroup(value = Update.class) BirdValid birdValid) {
log.info("dogValid : {}", birdValid);
}

@ActionMethod(1)
public void validateCreate(@ValidatedGroup(value = Create.class) BirdValid birdValid) {
log.info("dogValid : {}", birdValid);
}
}

Jakarta 与 Javax

现在 ioGame 的 JSR 校验支持 Jakarta 和 Javax 两种,基于 java SPI 实现。 支持 Javax 是为了兼容一些老项目(非 ioGame 项目)迁移到 ioGame 中。 新项目推荐使用 Jakarta,通常在 ioGame 的项目中,开启 JSR380 验证规范时,默认使用的是 Jakarta。

在示例目录中,单独的增加了 Jakarta 和 Javax 的使用示例。

提示

基于 java SPI 的实现由 shenjk 贡献;

Example Source Code

see https://github.com/iohao/ioGameExamples

path : SimpleExample/example

  • example-jsr-jakarta