Vert.x OpenAPI v4.5.10 POST请求必填Body验证失败问题求助
Vert.x OpenAPI v4.5.10 POST请求必填Body验证失败问题求助
你好,我仔细看了你的代码和问题描述,发现核心问题出在请求体的读取时机和验证逻辑的配合上,咱们一步步来解决这个问题:
问题根源分析
- 你手动创建了
RequestValidator,但Vert.x的请求体是异步读取的——如果直接调用requestValidator.validate(ctx.request(), "addUser"),此时请求体可能还没被读取完成,导致验证器误以为请求没有携带Body,抛出The related request does not contain the required body异常。 - 虽然你创建
RouterBuilder时用了RequestExtractor.withBodyHandler(),但后续手动调用验证器的方式,和RouterBuilder内置的验证逻辑没有配合好,相当于重复验证且时机不对。
解决方案一:使用RouterBuilder内置验证(推荐,更符合框架设计)
Vert.x OpenAPI的RouterBuilder本身已经内置了请求验证逻辑,包括自动读取请求体和验证,不需要手动创建RequestValidator和ResponseValidator,这样代码更简洁也不容易出错。
修改后的代码如下:
public void start() { String pathContract = "./api.yaml"; contract = OpenAPIContract.from(vertx , pathContract); contract.onSuccess(contractRes -> { // 创建RouterBuilder时指定RequestExtractor,确保请求体被自动读取和验证 routerBuilder = RouterBuilder.create(vertx, contractRes , RequestExtractor.withBodyHandler()); // 直接绑定operationId对应的路由,内置验证会自动处理 routerBuilder.getRoute("addUser").addHandler(this::addUser); router = routerBuilder.createRouter(); vertx.createHttpServer().requestHandler(router).listen(8000 , res -> { if (res.succeeded()) { System.out.println("server is running"); } else { System.out.println("error " + res.cause()); } }); System.out.println("Validator created successfully."); }).onFailure(error -> { System.out.println("Failed to load OpenAPI contract: " + error.getMessage()); }); } public void addUser(RoutingContext ctx) { // 验证已经由RouterBuilder完成,直接获取验证后的请求对象 ValidatedRequest validatedRequest = RequestExtractor.getValidatedRequest(ctx); JsonObject bodyData = validatedRequest.getBody().getJsonObject(); String name = bodyData.getString("name"); if (!name.isEmpty()) { // 符合OpenAPI定义,返回201状态码 ctx.response().setStatusCode(201).end("name is : " + name); } else { ctx.response().setStatusCode(400).end("error: name cannot be empty"); } }
解决方案二:手动使用RequestValidator(适合自定义验证场景)
如果你确实需要手动控制验证逻辑,必须确保请求体已经被读取完成后再执行验证,所以要先添加BodyHandler处理请求体:
修改你的addUser方法:
public void addUser(RoutingContext ctx) { // 先通过BodyHandler读取请求体,确保验证器能拿到Body内容 BodyHandler.create().handle(ctx, ar -> { if (ar.succeeded()) { // 请求体读取完成后再执行验证 requestValidator.validate(ctx.request(), "addUser").onSuccess(validatedRequest -> { JsonObject bodyData = validatedRequest.getBody().getJsonObject(); String name = bodyData.getString("name"); if (!name.isEmpty()) { ctx.response().setStatusCode(201).end("name is : " + name); } else { ctx.response().setStatusCode(400).end("error " + name); } }).onFailure(err -> { ctx.response().setStatusCode(400).end("error " + err.getMessage()); }); } else { ctx.response().setStatusCode(400).end("Failed to read request body: " + ar.cause().getMessage()); } }); }
额外注意点
- 你的OpenAPI YAML里路径是
/user,operationId为addUser,和代码里的routerBuilder.getRoute("addUser")匹配正确,这点没问题。 - 成功响应时记得返回
201状态码,和你的OpenAPI定义一致。
备注:内容来源于stack exchange,提问作者Youssef Amerzag
相关产品推荐
相关产品推荐

