Vert.x中GET/POST请求收发JSON对象的实现问题及代码纠错求助
Vert.x 请求参数获取问题修复方案
现有代码存在的核心问题
- 缺少
BodyHandler注册:Vert.x默认不会预加载请求体内容,必须先注册BodyHandler才能调用getBodyAsJson()获取请求JSON - GET请求携带请求体不符合HTTP规范:绝大多数服务端/客户端都不会处理GET请求的请求体,需要传递JSON参数的场景应该统一使用POST请求
- 全局共享请求参数对象存在线程安全问题:代码中定义的
reqJo是所有请求共享的实例,高并发场景下会出现参数覆盖、脏数据问题 - POST handler未读取当前请求的参数:现有POST逻辑直接使用全局的
reqJo,没有读取本次POST请求携带的JSON参数 - 存在两处拼写错误:响应头
content-type被误写为content-tpye,produces配置的*/json不符合规范,应为application/json
修复后完整代码
public void start(Promise<Void> startPromise) throws Exception { ImageRecognition imageRecogService = new ImageRecognition(); Router router = Router.router(vertx); // 注册BodyHandler,必须放在所有路由前面才能生效,用于解析请求体 router.route().handler(BodyHandler.create()); // 不需要GET接口可以直接删除,保留的话改造成用query参数传递name router.get("/getCall").handler(req -> { String name = req.getParam("name"); JsonObject resp = new JsonObject().put("name", name); req.response() .putHeader("content-type", "application/json") .end(resp.encodePrettily()); }); router.post("/getCall") .produces("application/json") .handler(plateReq -> { // 读取当前请求的JSON参数 JsonObject reqJson = plateReq.getBodyAsJson(); // 直接传递当前请求的参数给业务方法,不使用共享变量 JsonObject num = imageRecogService.getNum(reqJson); plateReq.response() .putHeader("content-type", "application/json") .end(num.encodePrettily()); }); vertx.createHttpServer() .requestHandler(router) .listen(8080) .onSuccess(ok -> { log.info("http server running on port 8080"); startPromise.complete(); }) .onFailure(startPromise::fail); }
额外优化建议
可以在获取请求参数后增加非空校验逻辑,避免非法请求导致服务空指针异常,示例代码:
JsonObject reqJson = plateReq.getBodyAsJson(); if (reqJson == null || !reqJson.containsKey("name")) { plateReq.response() .setStatusCode(400) .putHeader("content-type", "application/json") .end(new JsonObject().put("msg", "请求参数非法,缺少name字段").encodePrettily()); return; }
内容的提问来源于stack exchange,提问作者user17085185
相关产品推荐
相关产品推荐

