
在使用Spring Boot构建微服务应用时,我们经常需要通过WebClient进行RESTful API调用。当尝试将一个由Spring管理的、特别是被增强过的Bean(如通过`@ConfigurationProperties`注解配置的Bean)直接作为请求体发送时,可能会遇到序列化异常。本文将深入分析这一问题,并提供两种解决方案,包括一种实用的规避方案和一种更符合最佳实践的推荐方法。
在某些场景下,为了避免重复创建请求对象,开发者可能希望直接使用一个已配置好的Spring Bean作为REST请求的JSON体。例如,一个通过@ConfigurationProperties注解管理的配置Bean,其结构如下:
@ConfigurationProperties(prefix = "myprefix")
@Configuration("configname")
@Getter
@Setter
public class ConfigDetails {
private String c1;
private String c2;
private String c3;
}当尝试使用WebClient将此ConfigDetails Bean发送出去时,代码可能类似于:
// configDetails 是通过 @Autowired 注入的 ConfigDetails 实例 webClient.post().body(Mono.just(configDetails), ConfigDetails.class).retrieve().bodyToMono(String.class).block();
然而,在序列化过程中,通常会遇到类似以下堆栈跟踪的错误:
No serializer found for class org.springframework.context.expression.StandardBeanExpressionResolver and no properties discovered to create BeanSerializer (to *oid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.example.ConfigDetails$$EnhancerBySpringCGLIB$$cad0a6e6["$$beanFactory"]->org.springframework.beans.factory.support.DefaultListableBeanFactory["beanExpressionResolver"])
这个错误信息揭示了问题的核心:ConfigDetails$$EnhancerBySpringCGLIB$$cad0a6e6。这表明Spring在运行时对ConfigDetails Bean进行了增强,通常是通过CGLIB库创建了一个代理子类。这种增强是为了实现Spring的AOP(面向切面编程)功能、代理作用域或处理@Configuration类中的@Bean方法等。
被CGLIB增强的Bean实例,除了我们定义的业务属性(如c1, c2, c3)外,还会包含一些Spring框架内部使用的属性,例如$$beanFactory、$$beanName等。当Jackson等JSON序列化库尝试序列化这些增强过的Bean时,它会遍历所有属性。对于这些Spring内部的属性,Jackson找不到对应的序列化器,也无法将其识别为普通的J*a Bean属性,从而抛出No serializer found的异常。
一种直接的规避方法是在被增强的Bean内部维护一个其自身属性的“纯净”副本。这个副本不会被Spring增强,因此在序列化时不会携带额外的Spring内部属性。
具体实现步骤如下:
修改后的ConfigDetails类如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import j*ax.annotation.PostConstruct;
import lombok.Getter;
import lombok.Setter;
@ConfigurationProperties(prefix = "myprefix")
@Configuration("configname")
@Getter
@Setter
public class ConfigDetails {
private String c1;
private String c2;
private String c3;
// 静态变量,用于保存非增强的ConfigDetails副本
private static ConfigDetails staticConfigDetailsInstance;
@PostConstruct
public void init(){
// 在Bean初始化后,将当前实例的属性复制到静态副本
staticConfigDetailsInstance = new ConfigDetails();
staticConfigDetailsInstance.setC1(this.c1);
staticConfigDetailsInstance.setC2(this.c2);
staticConfigDetailsInstance.setC3(this.c3);
// 如果有其他属性,也需要在此处进行复制
}
// 提供静态方法获取非增强的副本
public static ConfigDetails getInstance(){
return staticConfigDetailsInstance;
}
}现在,在WebClient调用时,不再直接使用注入的configDetails实例,而是使用其静态副本:
6pen Art
AI绘画生成
213
查看详情
// 使用静态方法获取非增强的实例进行序列化
webClient.post()
.body(Mono.just(ConfigDetails.getInstance()), ConfigDetails.class)
.retrieve()
.bodyToMono(String.class)
.block();此方案的优缺点:
更符合软件工程最佳实践的方法是使用数据传输对象(DTO)。DTO是专门为数据传输设计的简单J*a对象,它不包含任何业务逻辑,也不会被Spring增强。通过DTO,我们可以将内部的配置Bean与外部API的契约解耦。
实现步骤:
// 1. 定义一个简单的DTO类
@Getter
@Setter
@NoArgsConstructor // 需要无参构造函数以供Jackson使用
@AllArgsConstructor // 方便构造
public class ConfigRequestDTO {
private String c1;
private String c2;
private String c3;
}import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class MyApiService {
private final WebClient webClient;
private final ConfigDetails configDetails; // 注入原始的ConfigDetails Bean
@Autowired
public MyApiService(WebClient webClient, ConfigDetails configDetails) {
this.webClient = webClient;
this.configDetails = configDetails;
}
public String sendConfigToApi() {
// 2. 将ConfigDetails的属性映射到ConfigRequestDTO
ConfigRequestDTO requestDTO = new ConfigRequestDTO(
configDetails.getC1(),
configDetails.getC2(),
configDetails.getC3()
);
// 3. 使用DTO作为WebClient的请求体
return webClient.post()
.uri("/api/endpoint") // 替换为实际的API路径
.body(Mono.just(requestDTO), ConfigRequestDTO.class)
.retrieve()
.bodyToMono(String.class)
.block();
}
}此方案的优缺点:
当Spring Bean(特别是被CGLIB增强的Bean)作为WebClient请求体进行序列化时,由于其包含Spring内部属性,可能导致序列化失败。
静态非增强副本是一种快速解决问题的规避方案。它通过在Bean内部创建一个纯净的静态副本进行序列化。此方法适用于配置Bean属性相对稳定且不频繁变动的场景,但需注意手动维护属性复制的风险。
使用数据传输对象(DTO)是更推荐的最佳实践。它通过引入一个专门用于API通信的POJO来解耦内部Bean和外部API契约。DTO模式不仅解决了序列化问题,还提高了代码的可维护性、可读性和API契约的清晰度,是构建健壮微服务应用的优选方案。
在实际开发中,我们应优先考虑使用DTO模式,以确保API接口的稳定性和代码的健壮性。只有在极度追求简洁且明确知晓风险的情况下,才可考虑静态非增强副本的规避方案。
以上就是Spring Boot WebClient发送增强型Bean序列化问题的解决方案的详细内容,更多请关注其它相关文章!
# 增强型
# 网站优化如何做出效果图
# 衡阳网站建设和制作
# 昆山短视频seo优化
# 模拟课堂关键词排名查询
# 沧州网站优化设计文案
# 合肥建设网站方案
# 渝中网站建设优化排名
# 河南闲鱼关键词排名
# 廊坊网站推广服务公司
# 新乡网站建设路隧道
# 更符合
# 类中
# 如何实现
# 创建一个
# 解决问题
# react
# 软件工程
# 数据结构
# 子类
# 序列化
# r
# spring框架
# api调用
# 作用域
# restful api
# ai
# 栈
# cad
# json
# js
# java
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
Composer reinstall命令重装损坏的包
如何在CSS中实现盒模型多列间距_grid-gap与padding结合
word怎么将图片设置为页面背景并不影响打印_Word图片背景设置方法
使用jQuery精确检测除指定元素外任意位置的点击事件
谷歌浏览器怎么把网页翻译成中文_Chrome网页翻译功能使用方法
掌握产品代码正则表达式:避免常见陷阱与精确匹配
Linux如何开发轻量级数据服务模块_Linux服务化设计
如何取消数字签名
TikTok笔记文字无法编辑如何解决 TikTok笔记文字编辑优化方法
windows10怎么开启wsl_windows10安装linux子系统教程
如何自定义苹果手机铃声
解决Go encoding/json 将JSON大数字解析为浮点数的问题
Symfony路由参数转换器:实体存在性验证与错误处理策略
小红书如何引流到私信?引流到私信有用吗?
iPhone14开启Apple TV遥控设置
mysql通配符能用于日志查询吗_mysql通配符在系统日志查询中的实际使用方法
解决SQLAlchemy模型跨文件关联的Linter兼容性指南
百度输入法在AutoCAD中无法输入中文怎么办_百度输入法CAD输入异常解决方法
《领英》查看屏蔽名单方法
PHP 4 函数中引用参数的默认值限制与解决方案
研招网官方网站招生平台入口_中国研究生招生信息网官网登录
《via浏览器》强制缩放网页设置方法
极兔快递官网查询入口手机版 手机极兔快递登录查询入口官方
优化Leaflet弹出层图片显示:条件渲染策略
Python中处理嵌套字典与列表的数据提取与过滤教程
Python对象引用与属性赋值:理解链表中的行为
可米酷漫画在线阅读入口_ 可米酷漫画官网直达链接
铁路12306入口 铁路12306官网版入口登录网址
Mac如何开启画中画模式_Mac Safari浏览器视频画中画功能
雨课堂官网在线登录 网页版雨课堂登录链接
抖音如何解除|直播|权限绑定_抖音关闭并解绑|直播|功能的方法
《密马》发布账号方法
Win10如何彻底关闭OneDrive Win10禁用云同步功能【纯净】
《原神》月之一版本新增书籍一览
猫眼电影app如何筛选支持退改签的影院_猫眼电影退改签影院筛选方法
如何在 WordPress 前端实现内容提交:古腾堡编辑器的替代方案与实践
虫虫助手如何更新游戏
纯CSS实现自适应宽度与响应式布局的水平按钮组
汽水音乐车机版 汽水音乐车机版官方入口
Dash应用多值文本输入处理与类型转换教程
《撕歌》会员开通方法
优化响应式标题底部边框:CSS实现技巧与最佳实践
《蓝色星原:旅谣》坐骑获取攻略
12306不能订票的时间段是固定的吗? | 节假日购票时间有无变化
在PHP环境中正确加载HTML资源:CSS样式与图片路径指南
sublime如何撤销关闭的标签页_sublime重新打开已关闭文件技巧
iPhone16Plus参数配置如何调整声音_iPhone16Plus参数配置声音调整详细方法
WooCommerce 新客户订单自动添加管理员备注教程
win11如何运行chkdsk命令 Win11检查和修复磁盘逻辑错误教程【修复】
126邮箱网页在线登录2025_126邮箱网页版入口官方地址
2025-12-04
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。