在进行SpringBoot项目练习的过程中,项目成功启动,但是从客户端(浏览器)请求数据的时候发生消息转换异常,提示信息如下:
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2925b78]
[2m2024-01-31T14:35:06.931+08:00[0;39m [31mERROR[0;39m [35m15380[0;39m [2m---[0;39m [2m[nio-8080-exec-2][0;39m [2m[0;39m[36mo.a.c.c.C.[.[.[/].[dispatcherServlet] [0;39m [2m:[0;39m Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.mytest.spbootdemo.demos.web.Book]] with root cause
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.mytest.spbootdemo.demos.web.Book and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.ArrayList[0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1308) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:414) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:53) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:30) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:479) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:399) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1568) ~[jackson-databind-2.15.3.jar:2.15.3]
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1061) ~[jackson-databind-2.15.3.jar:2.15.3]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:483) ~[spring-web-6.1.3.jar:6.1.3]
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:114) ~[spring-web-6.1.3.jar:6.1.3]
......
查阅网上资料,首先有说是简单数据对象缺少Getter和Setter方法定义的,如链接:
https://www.cnblogs.com/FlyGoldfish/articles/15378669.html
但是我的代码中已经采用了lombok的@Data注解,默认是有Getter和Setter实现的,为什么还会出现这个问题呢?
我的简单数据对象定义如下:
package com.mytest.spbootdemo.demos.web;
import lombok.Data;
@Data
public class Book {
private Integer id;
private String type;
private String name;
private String description;
}
继续查找相关文章,又发现说必须将FAIL_ON_EMPTY_BEANS属性设置为false来解决的(异常信息中恰有该属性的提示),参考链接:
https://blog.youkuaiyun.com/weixin_45066871/article/details/125128258
但是我的问题又跟他的不同,我的数据对象是有成员变量的,那又是为什么呢?继续找,终于找到有深入分析原因并提供解决方案的,参考链接:
https://blog.youkuaiyun.com/u012188107/article/details/107297356/
按照文章中的解决方案,添加代码(注意首先要添加依赖项,fastjson版本已经更新到1.2.83,可以通过阿里云仓库查询相关软件包的版本,点击链接:https://developer.aliyun.com/mvn/search输入软件包名进行查询)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
添加的WebConfig配置类代码如下:
package com.mytest.spbootdemo.demos.web;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.ALL);
fastConverter.setSupportedMediaTypes(mediaTypes);
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastConverter.setFastJsonConfig(fastJsonConfig);
converters.set(0, fastConverter);
}
}
注意其中导入类的声明(我在实操时,FastJsonHttpMessageConverter不会自动引入,需要自己手工写代码)。
以上解决方案确认可行,程序运行后请求数据不再报异常,但是请求到的数据却全部为空元素,调试信息显示已经从数据库查询到了十多条记录,但是记录未自动转换成Json数据,实际结果为:[ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} ],推测是Lombok插件没有起效。继续在网上查找,有各种表示Eclipse默认不支持Lombok功能,需要手动安装插件的,以下链接算是描述最清晰的:
https://blog.youkuaiyun.com/shencomd/article/details/130783190
参照执行,不过记住:在操作完成之后,如果重启Eclipse后仍然不生效,可以尝试执行Maven->Update Project来更新项目,然后就可以了。
有关FastJsonHttpMessageConverter的更多信息可以参考:https://blog.youkuaiyun.com/qq_28754027/article/details/129928792