最近在学习Vert.x,至于它是什么有什么用等我学习的差不多了会更新在博客中,总之它比SpringBoot要轻,快速。本篇内容是在练习中遇到的一个报错,在这里记录以下,分享给遇到同样问题的初学Vert.x的小伙伴。
这个Demo是用来练习路由请求并进行处理后返回json响应数据,下面我创建了一个实体类,包含了四个属性,主要报错是在类型为LocalDateTime这个属性上。
package demo.module;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
/**
* @author Huhailong
* @Description
* @Date 2022/11/9.
*/
public class UserInfo {
private String username;
private Integer age;
private String gender;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
}
测试路由主要代码如下:
package demo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import demo.module.UserInfo;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonObject;
import io.vertx.core.json.jackson.DatabindCodec;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import java.time.LocalDateTime;
public class MainVerticle extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {
System.setProperty("vertxweb.environment","dev");
HttpServer httpServer = vertx.createHttpServer(); //创建HTTP服务
Router router = Router.router(vertx); //创建路由对象
UserInfo userInfo = new UserInfo();
userInfo.setUsername("huhailong");
userInfo.setAge(26);
userInfo.setGender("man");
userInfo.setCreateTime(LocalDateTime.now());
router.get("/some/path/").respond(ctx-> Future.succeededFuture(new JsonObject().put("hello","world")));
router.get("/some/path2/").respond(ctx-> Future.succeededFuture(userInfo));
httpServer.requestHandler(router).listen(8888);
}
}
测试demo中我定义了俩个路由,这里主要看path2这个路由,它返回了一个将UserInfo序列化为JSON的结果,问题就出现在这里,报错内容如下:
十一月 09, 2022 12:28:46 下午 io.vertx.ext.web.RoutingContext
严重: Unhandled exception in router
io.vertx.core.json.EncodeException: Failed to encode as JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to ena
ble handling (through reference chain: demo.module.UserInfo["createTime"])
at io.vertx.core.json.jackson.DatabindCodec.toBuffer(DatabindCodec.java:173)
at io.vertx.core.spi.json.JsonCodec.toBuffer(JsonCodec.java:69)
at io.vertx.core.json.Json.encodeToBuffer(Json.java:60)
at io.vertx.ext.web.RoutingContext.json(RoutingContext.java:752)
at io.vertx.ext.web.Route.lambda$null$0(Route.java:361)
at io.vertx.core.impl.future.SucceededFuture.onSuccess(SucceededFuture.java:64)
at io.vertx.ext.web.Route.lambda$respond$1(Route.java:341)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
at io.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:68)
at io.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:37)
at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:67)
at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:30)
at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:55)
at io.vertx.core.impl.DuplicatedContext.emit(DuplicatedContext.java:158)
at io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:145)
at io.vertx.core.net.impl.ConnectionBase.read(ConnectionBase.java:157)
at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:153)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
at io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler.channelRead(WebSocketServerExtensionHandler.java:99)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.vertx.core.http.impl.Http1xUpgradeToH2CHandler.channelRead(Http1xUpgradeToH2CHandler.java:116)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:336)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:308)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.vertx.core.http.impl.Http1xOrH2CHandler.end(Http1xOrH2CHandler.java:61)
at io.vertx.core.http.impl.Http1xOrH2CHandler.channelRead(Http1xOrH2CHandler.java:38)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerCon at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerConte
xt.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.jav
a:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerCon
text.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
报错内容显示需要添加jackson-datatype-jsr310
依赖,但是我添加了,还是这个错误。
根据网上查找资料得知,在2.13版本后默认不再支持Java8 date/time 的序列化,然后去Vert.x的官网发现其实官方已经给出了解决方法
为ObjectMapper注册time模块
ObjectMapper mapper = DatabindCodec.mapper();
mapper.registerModule(new JavaTimeModule());
解决后的代码
package demo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import demo.module.UserInfo;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonObject;
import io.vertx.core.json.jackson.DatabindCodec;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import java.time.LocalDateTime;
public class MainVerticle extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {
System.setProperty("vertxweb.environment","dev");
HttpServer httpServer = vertx.createHttpServer(); //创建HTTP服务
Router router = Router.router(vertx); //创建路由对象
ObjectMapper mapper = DatabindCodec.mapper();
mapper.registerModule(new JavaTimeModule());
UserInfo userInfo = new UserInfo();
userInfo.setUsername("huhailong");
userInfo.setAge(26);
userInfo.setGender("man");
userInfo.setCreateTime(LocalDateTime.now());
router.get("/some/path/").respond(ctx-> Future.succeededFuture(new JsonObject().put("hello","world")));
router.get("/some/path2/").respond(ctx-> Future.succeededFuture(userInfo));
httpServer.requestHandler(router).listen(8888);
}
}
运行结果
Vert.x 在对LocalDate或LocalDateTime进行序列化时需要将jsr310的日期时间模块注册到ObjectMapper中生效。
还是得仔细阅读官网文档呀!!!