使用 Spring Boot 3 本机映像的 Feign Client Jackson 序列化/反序列化问题

问题描述 投票:0回答:2

我正在尝试基于 Spring Boot 3 构建 Web 应用程序,并计划将其作为本机映像在 Kubernetes 中运行。所以我的目标是构建原生图像,但这是我在这里遇到 Feign 问题的地方。

我的应用程序使用 Feign 客户端访问第三方 API。

应用程序在非本机模式下作为纯 Java 应用程序运行时完美运行。但是一旦我在 Docker 中将它作为本机映像运行,它就无法进行第三方调用,因为请求/响应 DTO 类型在本机运行时不可用,迫使 Jackson 抛出错误:

Cannot construct instance of `com.steam.trading.trade.bot.client.steam.dto.SteamResponse`: cannot deserialize from Object value (no delegate- or property-based Creator): this appears to be a native image, in which case you may need to configure reflection for the class that is to be deserialized

我从这个错误中了解到,没有为 Feign Client 请求/响应 dto 数据类型创建 AOT 序列化提示。列出所有序列化类也不是一个选项,因为这将是大量的手工工作,而且很容易遗漏那里的东西。

问题是,这是 Open Feign 中的某种错误,是否有开箱即用的

RuntimeHintsRegistrar
导入还是我应该自己注册所有 DTO?

项目设置

我正在使用 Spring Cloud 依赖项中的 Spring Boot 3 和 OpenFeign。版本是:

    <spring-boot.version>3.0.4</spring-boot.version>
    <spring-cloud.version>2022.0.1</spring-cloud.version>

我有以下Feign客户:

@FeignClient(name = "steam-server-time-api", url = "${app.steam.api}", configuration = FeignSteamConfiguration.class)
public interface ServerTimeClient {

    @RequestLine("POST /ITwoFactorService/QueryTime/v1/")
    SteamResponse<QueryTime> getServerTime();
}

以下假装配置:

public class FeignSteamConfiguration {

    @Bean
    public Contract useFeignAnnotations() {
        return new Contract.Default();
    }

    @Bean
    public Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
        return new FormEncoder(new SpringEncoder(messageConverters));
    }

    @Bean
    public ErrorDecoder clientErrorDecoder() {
        return new CustomErrorDecoder();
    }
}

我尝试了默认和 Spring Contracts,但问题是一样的。

我正在使用命令构建图像:

mvn -Pnative spring-boot:build-image

我尝试使用 RegisterReflectionForBinding 手动注册,但是拥有 50 多个类并不是手动列出所有类的好办法。 我也尝试切换 Default 和 Spring 合同,但问题仍然相同。

spring-boot spring-cloud-feign java-17 graalvm-native-image spring-native
2个回答
0
投票

一些做对象序列化/反序列化的库(比如Jackson)不知道如何在spring native的运行时做这个,所以你应该告诉/注册到spring native关于代理类,资源文件/路径,反射方法,或要序列化/反序列化的对象。

所以我相信您需要创建一个实现

RuntimeHintsRegistrar
接口的类,并设置您需要序列化/反序列化的类,如以下链接所述:https://docs.spring .io/spring-boot/docs/current/reference/html/native-image.html#native-image.advanced.custom-hints(spring native 自定义提示)

或在某些配置类中注释以下注释:

@RegisterReflectionForBinding({YourCustomObject.class})


0
投票

您面临的问题是由于 AOT 序列化提示不是为 Feign 客户端请求/响应 DTO 数据类型创建的,这在本机运行时不可用。这会导致 Jackson 在尝试反序列化响应时抛出错误。

您可以尝试使用几个选项来解决此问题。一种选择是使用 Spring Native 项目提供的 @RegisterForReflection 注释来注册 DTO 类以进行反射。您可以将此注释添加到导致问题的每个 DTO 类,它应该可以解决问题。

另一种选择是使用Spring Native 项目提供的@NativeHint 注解为DTO 类配置AOT 序列化提示。此注释允许您为特定类和字段配置提示,并且应该用于注册 DTO 类以进行序列化。

也可以尝试使用Spring Native提供的@AutoConfigureJson注解,自动注册所有DTO类,使用Jackson进行序列化

此外,您可能需要考虑使用支持原生图像编译的不同序列化/反序列化库,例如 Protobuf 或 Avro。这些库可以自动生成所需的序列化提示,并且可能比使用原生图像的 Jackson 更容易使用。

总的来说,针对您的特定用例的最佳解决方案将取决于您的 DTO 类的复杂性和您需要对序列化/反序列化过程的控制级别。

© www.soinside.com 2019 - 2024. All rights reserved.