将 flux/mono 反序列化为 Feign Spring Cloud 的问题

Problem deserialize flux/mono into Feign Spring Cloud

我使用 Kotlin Webflux (Reactor3)、Eureka、Zuul 和 Feign 开发了一个微服务应用程序。除了当我通过我的微服务 Feign 调用 API 时总是出错。看起来他无法反序列化数据。你能告诉我 Feign 是否与 Flux 和 Monno 兼容吗? 谢谢

{ "timestamp": "2019-05-29T07:39:43.998+0000", "path": "/爱好/", "status": 500, "error": "Internal Server Error", "message": "Type definition error: [simple type, class reactor.core.publisher.Flux]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of reactor.core.publisher.Flux (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information\n at [Source: (PushbackInputStream); line: 1, column: 1]" }

Feign 不支持 Mono/Flux 反序列化。存在完全支持它的替代伪装库:feign-reactive

但请注意,这是对 feign 的重写,完全使用响应式代码,与 OpenFeign 的 Feign 核心不同。

这里有一个关于如何使用它的片段,以及普通的 Feign,摘自 sample app

@SpringBootApplication(exclude = ReactiveLoadBalancerAutoConfiguration.class)
@RestController
@EnableReactiveFeignClients
@EnableFeignClients
public class FeignApplication {

    @Autowired
    private GreetingReactive reactiveFeignClient;

    @Autowired
    private Greeting feignClient;

    public static void main(String[] args) {
        SpringApplication.run(FeignApplication.class, args);
    }

    @GetMapping("/greetingReactive")
    public Mono<String> greetingReactive() {
        return reactiveFeignClient.greeting().map(s -> "reactive feign! : " + s);
    }

    @GetMapping("/greeting")
    public String greeting() {
        return "feign! : " + feignClient.greeting();
    }
}

除了 Adhika Setya Pramudita 的回应,我想提一下,为了在控制器中 return Mono,你必须使用 Spring WebFlux 而不是 Spring MVC

我无法使@Adhika Setya Pramudita 解决方案起作用,直觉告诉我它甚至不能 运行 由于混合 @EnableReactiveFeignClients and @EnableFeignClients 需要相应的 @EnableWebFlux @EnableWebMvc 因此定义两者可能会编译但会失败运行时间。

由于 op 没有提到目标语言,我想分享适用于我的情况的 Kotlin 设置:

build.gradle.kts

implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("com.playtika.reactivefeign:feign-reactor-core:2.0.22")
implementation("com.playtika.reactivefeign:feign-reactor-spring-configuration:2.0.22")
implementation("com.playtika.reactivefeign:feign-reactor-webclient:2.0.22")

Config.kt

@Configuration
@EnableWebFlux
@EnableReactiveFeignClients
class Config {
}

MyEntity.kt

class MyEntity @JsonCreator constructor(
        @param:JsonProperty("my_value") val my_value: String
)

MyFeignClient.kt

@Component
@ReactiveFeignClient(
        url = "${package.service.my-service-url}",
        name = "client"
)
interface MyFeignClient {
    @GetMapping(value = ["/my/url?my_param={my_value}"], consumes = ["application/json"])
    fun getValues(
            @PathVariable(name = "my_value") myValue: String?,
        ): Mono<MyEntity?>?
}

然后这里是一些服务中的代码class:

val myClient: MyFeignClient = WebReactiveFeign.builder<MyFeignClient>()
        .contract(ReactiveContract(SpringMvcContract()))
        .target(MyFeignClient::class.java, "http://example.com")

// feel free to add .block() to get unpacked value or just chain your logic further
val response = myClient.getValues(param)