<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-validation</artifactId>
<version>5.0.12</version>
</dependency>
Vert.x Web Validation 参数与请求体验证
Vert.x Web Validation 帮助你高效解析并校验传入 HTTP 请求的各项入参(Parameters)与请求体(Bodies)。
核心特性支持:
-
深度解析并校验各类请求参数(支持序列化展开 exploded 与深层嵌套对象)
-
解析并校验请求体,包括 JSON 报文与各种 Form 表单
-
支持配置请求前置断言谓词(Request Predicates)
-
允许在同一路由下支持多种不同格式的请求体,并进行统一一致的解析与校验
-
支持自定义扩展解析与校验规则
-
统一拦截并结构化管理解析与校验失败异常
底层基于 Vert.x Json Schema 定义请求参数与请求体的模式规范。
使用 Vert.x Web Validation
在项目构建配置中添加以下依赖:
-
Maven(在
pom.xml中):
-
Gradle(在
build.gradle文件中):
dependencies {
compile 'io.vertx:vertx-web-validation:5.0.12'
}
对比:未使用 Web Validation 时的样板代码
当接收到一个 HTTP 请求时,通常需要编写大量繁琐的手动类型转换与边界校验:
router
.get("/user")
.handler(routingContext -> {
// 获取原始字符串参数
String aParamUnparsed = routingContext.queryParam("aParam").get(0);
if (aParamUnparsed == null) {
routingContext.fail(400);
return;
}
// 手动解析整型
int aParam;
try {
aParam = Integer.parseInt(aParamUnparsed);
} catch (NumberFormatException e) {
routingContext.fail(400, e);
return;
}
// 业务数值校验:例如不能大于 100
if (aParam > 100) {
routingContext.fail(400);
return;
}
// 参数校验准备完毕后,才能开始聚焦核心业务逻辑
});
而 Vert.x Web Validation 提供了极具表达力的流式 API,让你声明式地完成校验:
router
.get("/user")
.handler(
ValidationHandlerBuilder
.create(schemaRepository)
.queryParameter(param(
"aParam",
intSchema().with(maximum(100))
))
.build()
)
.handler(routingContext -> {
RequestParameters parameters =
routingContext.get(ValidationHandler.REQUEST_CONTEXT_KEY);
int aParam = parameters.queryParameter("aParam").getInteger();
// 直接使用强类型合法参数,聚焦核心业务逻辑
});
创建 ValidationHandler
该模块提供了简洁明了的 Builder API 用于构建 ValidationHandler。该 Handler 负责自动拦截请求并执行解析与校验。
调用 ValidationHandlerBuilder.create 即可初始化构建器。
定义参数规则 (Defining parameters)
支持针对 HTTP 请求的四个不同位置定义参数:Query 查询串、Cookie、Header 请求头以及 URL Path 路径。
每个参数由 ParameterProcessor 承载,可通过 Parameters 工具类快速声明:
ValidationHandlerBuilder
.create(schemaRepository)
.pathParameter(Parameters.param("myPathParam", stringSchema()))
.queryParameter(Parameters.optionalParam("myQueryParam", intSchema()));
自定义错误提示信息 (Defining custom error messages)
校验失败提示信息支持自由定制:
-
validationErrorMessage:自定义校验未通过提示 -
parsingErrorMessage:自定义反序列化异常提示 -
missingParameterErrorMessage:自定义必填参数缺失提示
Header 和 Path 通常只支持简单单值参数,而 Query 与 Cookie 则原生支持诸如数组展开(exploded)以及深度嵌套对象(deepObject):
ValidationHandlerBuilder
.create(schemaRepository)
.queryParameter(Parameters.explodedParam(
"myArray",
arraySchema().items(stringSchema())
)) // 接收 myArray=item1&myArray=item2 数组展开格式
.queryParameter(Parameters.deepObjectParam(
"myDeepObject",
objectSchema()
.property("name", stringSchema())
)); // 接收 myDeepObject[name]=francesco 对象嵌套格式
定义请求体验证 (Defining request bodies)
每种请求体类型根据 Content-Type 请求头进行分流匹配。
你可以为同一个 ValidationHandler 同时挂载多种受支持的请求体处理器。
若未匹配到已配置的 Body 处理器,默认不会直接报错,除非配置了下文提到的“必须包含请求体”断言。
通过 Bodies 便捷声明:
ObjectSchemaBuilder bodySchemaBuilder = objectSchema()
.property("username", stringSchema())
.property("password", stringSchema());
ValidationHandlerBuilder
.create(schemaRepository)
.body(Bodies.json(bodySchemaBuilder))
.body(Bodies.formUrlEncoded(bodySchemaBuilder));
在上述配置中,ValidationHandler 能同时无缝兼容 JSON 报文与传统 URL 编码表单。
特别是 Form 表单会被自动转换为 JSON 统一结构,业务代码无需关心底层客户端究竟是以 Form 还是以 JSON 形式提交。
定义请求前置断言 (Defining request predicates)
通过 RequestPredicate 可以对请求设置强制前置条件。
例如要求该路由请求体必填:
ValidationHandlerBuilder
.create(schemaRepository)
.predicate(RequestPredicate.BODY_REQUIRED);
构建与挂载 ValidationHandler
配置好所有参数、请求体与前置断言后,调用 build() 生成 Handler 并挂载到路由上:
router
.get("/user")
.handler(
ValidationHandlerBuilder
.create(schemaRepository)
.build()
);
在业务中读取解析后的强类型数据
ValidationHandler 会将验证合规的参数统一写入 RoutingContext:
router
.get("/user")
.handler(
ValidationHandlerBuilder
.create(schemaRepository)
.queryParameter(Parameters.explodedParam(
"myArray",
arraySchema().items(stringSchema())
))
.body(Bodies.json(objectBodySchemaBuilder))
.body(Bodies.formUrlEncoded(objectBodySchemaBuilder))
.build()
).handler(routingContext -> {
RequestParameters parameters =
routingContext.get(ValidationHandler.REQUEST_CONTEXT_KEY);
JsonArray myArray = parameters.queryParameter("myArray").getJsonArray();
JsonObject body = parameters.body().getJsonObject();
});
统一异常与失败管理 (Manage the failures)
每当 ValidationHandler 检测到反序列化异常或数据校验不通过时,会自动触发 RoutingContext.fail(400),并将 BadRequestException 的具体子类实例作为 cause 挂载在 context 异常中。
你可以通过 Vert.x Web 的 errorHandler 统一拦截定制 400 响应。
常见的异常细分子类包括:
-
ParameterProcessorException:参数解析或校验失败 -
BodyProcessorException:请求体格式不符或校验失败 -
RequestPredicateException:请求未满足前置断言条件
拦截异常与响应示例:
router.errorHandler(400, routingContext -> {
if (routingContext.failure() instanceof BadRequestException) {
if (routingContext.failure() instanceof ParameterProcessorException) {
// 处理参数校验失败异常
} else if (routingContext.failure() instanceof BodyProcessorException) {
// 处理请求体校验失败异常
} else if (routingContext.failure() instanceof RequestPredicateException) {
// 处理前置条件不满足异常
}
}
});
BadRequestException 还贴心地提供了 toJson 方法,可直接一键将校验失败明细转为 JSON 格式回写给调用方。
请注意:ValidationHandler 采用 快速失败(Fail-Fast) 设计原则,一旦检测到首个校验违背项,会立刻中断流程并通知 RoutingContext 抛出异常。