我有一个 FeignClient 需要调用一个端点,该端点返回包装在 PageView 对象中的数据。我不想用这个对象打扰任何服务,所以我正在寻找一种方法来在处理响应期间完成它。
Feign 客户端看起来像这样(Kotlin):
@FeignClient(
value = "myFeignClient",
url = "\${controller.baseUrl}",
configuration = [CustomFeignConfiguration::class]
)
interface MyFeignClient {
@GetMapping(value = ["v1/myObjects/someProperty/{value}"])
fun getMyObjectsBySomeProperty(@PathVariable(value="value") value: String): List<MyObject>
PageView 类如下所示:
data class PageView<T>(
val metadata: PageMetadataView,
val content: List<T>,
)
我知道可以通过定义自定义解码器来完成,但是Spring Cloud Open Feign的文档没有涵盖这个主题。
我找到了一种使用自定义解码器来解决此问题的方法。所有代码示例均采用 Kotlin 语言。
首先,为PageView创建一个类,Jackson可以使用该类进行反序列化。您只需要指定相关属性,在我的例子中是“内容”。当然,您的数据类还需要在某个地方定义,以便 Jackson 正确地反序列化它。
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
@JsonIgnoreProperties(ignoreUnknown = true)
class MyObjectsPageView(val content: List<MyObject>)
然后像这样定义一个解码器:
import feign.Response
import feign.codec.Decoder
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import java.lang.reflect.Type
class MyObjectsPageViewDecoder : Decoder {
private val jacksonConverter = MappingJackson2HttpMessageConverter()
override fun decode(response: Response?, type: Type?): List<MyObject> {
val pageView: MyObjectPageView = jacksonConverter.objectMapper.readValue(response!!.body().asInputStream(), MyObjectsPageView::class.java)
return pageView.content
}
}
请注意,我没有采取任何努力使这个解码器变得通用。我对 Kotlin 和泛型还不够熟悉 :-P
最后,您需要 FeignConfiguration 来提供此自定义解码器作为 bean:
class CustomFeignConfiguration{
@Bean
fun pageViewDecoder(): Decoder = MyObjectsPageViewDecoder ()
}
请注意,将为您的 feign 客户端中的所有功能提供此自定义解码器。