当前位置: 首页 > news >正文

Feign接口调用-请求响应数据底层实现

Feign 使用编解码器(Encoder/Decoder)处理请求和响应的序列化与反序列化。默认使用 Jackson 编解码器,支持 JSON 格式。


Jackson 是一个广泛使用的 JSON 编解码库,用于将 Java 对象序列化为 JSON 字符串(编码),以及将 JSON 字符串反序列化为 Java 对象(解码)。它的底层实现逻辑非常高效且灵活,以下是 Jackson 编解码器的底层实现逻辑详解:


1. Jackson 的核心组件

Jackson 的核心组件包括:

ObjectMapper:核心类,负责序列化和反序列化操作。

JsonParser:用于解析 JSON 数据流,生成令牌(tokens)。

JsonGenerator:用于生成 JSON 数据流。

Serializer:负责将 Java 对象转换为 JSON 数据。

Deserializer:负责将 JSON 数据转换为 Java 对象。

AnnotationIntrospector:用于解析注解(如 @JsonProperty、@JsonIgnore 等)。

2. Jackson 的编码(序列化)流程

编码是将 Java 对象转换为 JSON 字符串的过程。
2.1 调用 ObjectMapper.writeValueAsString()
用户调用 ObjectMapper.writeValueAsString(Object) 方法,传入需要序列化的 Java 对象。
2.2 选择序列化器
ObjectMapper 根据对象的类型,从 SerializerProvider 中获取对应的 JsonSerializer。

如果对象类型是简单类型(如 String、Integer),使用内置的序列化器。

如果对象类型是复杂类型(如 POJO),使用 BeanSerializer。
2.3 生成 JSON 数据
JsonSerializer 使用 JsonGenerator 生成 JSON 数据。

JsonGenerator 将 Java 对象的字段逐个写入 JSON 数据流。

对于字段名,使用 @JsonProperty 注解或字段名本身。

对于字段值,递归调用序列化器。
2.4 处理注解
如果字段上有注解(如 @JsonIgnore、@JsonProperty),
AnnotationIntrospector 会处理这些注解,
决定是否忽略字段或修改字段名。
2.5 返回 JSON 字符串
JsonGenerator 将生成的 JSON 数据写入字符串或输出流,
最终返回 JSON 字符串。

3. Jackson 的解码(反序列化)流程

解码是将 JSON 字符串转换为 Java 对象的过程。
3.1 调用 ObjectMapper.readValue()
用户调用 ObjectMapper.readValue(String, Class) 方法,
传入 JSON 字符串和目标 Java 类型。
3.2 创建 JsonParser
ObjectMapper 创建 JsonParser,用于解析 JSON 数据流。

JsonParser 将 JSON 字符串分解为一系列令牌(tokens),
如 START_OBJECT、FIELD_NAME、VALUE_STRING 等。
3.3 选择反序列化器
ObjectMapper 根据目标类型,从 DeserializerProvider 中获取对应的 JsonDeserializer。

如果目标类型是简单类型(如 String、Integer),使用内置的反序列化器。

如果目标类型是复杂类型(如 POJO),使用 BeanDeserializer。
3.4 解析 JSON 数据
JsonDeserializer 使用 JsonParser 逐个读取令牌,构建 Java 对象。

对于字段名,使用 @JsonProperty 注解或字段名本身。

对于字段值,递归调用反序列化器。
3.5 处理注解
如果字段上有注解(如 @JsonIgnore、@JsonProperty),
AnnotationIntrospector 会处理这些注解,决定是否忽略字段或修改字段名。
3.6 返回 Java 对象
JsonDeserializer 将解析后的数据填充到目标 Java 对象中,并返回该对象。

4. Jackson 的底层实现细节

4.1 ObjectMapper 的核心作用
ObjectMapper 是 Jackson 的核心类,负责管理序列化和反序列化的配置(如日期格式、空值处理等)。

它内部维护了 SerializerProvider 和 DeserializerProvider,用于获取序列化器和反序列化器。
4.2 JsonParser 的工作原理
JsonParser 使用基于事件驱动的模型解析 JSON 数据。

它将 JSON 字符串分解为一系列令牌(tokens),如:

START_OBJECT:表示 JSON 对象的开始({)。

FIELD_NAME:表示字段名。

VALUE_STRING:表示字符串值。

END_OBJECT:表示 JSON 对象的结束(})。
4.3 JsonGenerator 的工作原理
JsonGenerator 用于生成 JSON 数据流。

它提供了一系列方法(如 writeStartObject()、writeFieldName()、writeString())来构建 JSON 数据。
4.4 序列化器和反序列化器的注册
Jackson 支持自定义序列化器和反序列化器。

可以通过 SimpleModule 注册自定义的序列化器和反序列化器:
SimpleModule module = new SimpleModule();
module.addSerializer(User.class, new UserSerializer());
module.addDeserializer(User.class, new UserDeserializer());
objectMapper.registerModule(module);
4.5 注解处理
Jackson 支持丰富的注解,用于控制序列化和反序列化的行为。

常见的注解包括:

@JsonProperty:指定字段名。

@JsonIgnore:忽略字段。

@JsonFormat:指定日期格式。

@JsonInclude:控制空值的序列化行为。

5. Jackson 的性能优化

缓存:Jackson 缓存了序列化器和反序列化器,避免重复创建。

流式 API:JsonParser 和 JsonGenerator 使用流式 API,减少内存占用。

线程安全:ObjectMapper 是线程安全的,可以在多线程环境中共享。

6. 示例代码

6.1 序列化
ObjectMapper objectMapper = new ObjectMapper();
User user = new User(1, "John");
String json = objectMapper.writeValueAsString(user);
System.out.println(json); // 输出: {"id":1,"name":"John"}
6.2 反序列化
String json = "{\"id\":1,\"name\":\"John\"}";
User user = objectMapper.readValue(json, User.class);
System.out.println(user.getName()); // 输出: John
6.3 自定义序列化器
public class UserSerializer extends StdSerializer<User> {
    protected UserSerializer() {
        super(User.class);
    }

    @Override
    public void serialize(User user, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeNumberField("userId", user.getId());
        gen.writeStringField("userName", user.getName());
        gen.writeEndObject();
    }
}
6.4 自定义反序列化器
public class UserDeserializer extends StdDeserializer<User> {
    protected UserDeserializer() {
        super(User.class);
    }

    @Override
    public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        int id = node.get("userId").asInt();
        String name = node.get("userName").asText();
        return new User(id, name);
    }
}

7. 总结

Jackson 的编解码器底层实现逻辑包括:

序列化:通过 ObjectMapper 和 JsonGenerator 将 Java 对象转换为 JSON 字符串。

反序列化:通过 ObjectMapper 和 JsonParser 将 JSON 字符串转换为 Java 对象。

注解处理:通过 AnnotationIntrospector 解析注解,控制序列化和反序列化的行为。

性能优化:通过缓存、流式 API 和线程安全机制提高性能。

Jackson 的高效性和灵活性使其成为 Java 生态中最流行的 JSON 编解码库。

tips:
今天碰到一个问题,后端定义的响应体字段类型明明是Long类型,
结果响应却是String类型的;原因就是因为序列化时看到Long类型会转成String;

就类似上面4.4说的有自定义的处理:
SimpleModule module = new SimpleModule();
module.addSerializer(Long.class, ToStringSerializer.instance);//
module.addDeserializer(User.class, new UserDeserializer());
objectMapper.registerModule(module);

相关文章:

  • 深挖vue3基本原理之六 —— 类型系统设计与运行时核心架构
  • 【MyBatis】_使用XML实现MyBatis
  • 【transformers.Trainer填坑】在自定义compute_metrics时logits和labels数据维度不一致问题
  • 通过沙箱技术测试识别潜在的威胁
  • 第一章:认识Tailwind CSS - 第三节 - Tailwind CSS 开发环境搭建和工具链配置
  • redis的哨兵模式和集群模式
  • 1.3 AI大模型应用浪潮解析:高校、硅谷与地缘政治的三角博弈
  • vscode调试和环境路径配置
  • 【微软- Entra ID】Microsoft Entra ID
  • 强化学习《初学者》--基础概念贝尔曼公式
  • 【Java】一文了解spring的三级缓存
  • 如何使用智能化RFID管控系统,对涉密物品进行安全有效的管理?
  • 在香橙派5 NPU上使用Yolov5
  • Ollama+Deepseek+chatbox快速部署属于自己的大模型
  • SSM课设-学生选课系统
  • 格式工厂 FormatFactory v5.18.便携版 ——多功能媒体文件转换工具
  • 玄机——第一章 应急响应-Linux入侵排查
  • 在 Go 中实现事件溯源:构建高效且可扩展的系统
  • Jupyter lab 无法导出格式 Save and Export Notebook As无法展开
  • CSS实现单行、多行文本溢出显示省略号(…)
  • 现场丨“影像上海”启幕:串联摄影、电影与当代艺术
  • 国家卫健委:有条件的二级及以上综合医院要开设老年医学科
  • 外交部答澎湃:美方攻击抹黑中加关系与合作的卑劣图谋不会得逞
  • 光大华夏:近代中国私立大学遥不可及的梦想
  • 央行行长详解降息:将通过利率自律机制引导商业银行相应下调存款利率
  • 巴基斯坦军方:印度向巴本土及巴控克什米尔发射导弹