【问题标题】:Webflux webclient and generic typesWebflux webclient 和泛型类型
【发布时间】:2019-04-22 00:30:29
【问题描述】:

我正在尝试构建一个使用 REST api 的通用类。 api 根据 url 返回对象列表。

我已经建立了一个通用类

public class RestConsumer<T> {
    WebClient client;

    public RestConsumer(){
        //Initialize client
    }

    public List<T> getList(String relativeUrl){
        try{
            return client
                .get()
                .uri(relativeUrl)
                .retrieve()
                .bodyToMono(new ParameterizeTypeReference<List<T>> (){}
                .block()
        catch(Exception e){}
}

}

问题是 T 在编译时被 Object 替换,整个事情返回 LinkedHashMap 列表而不是 T 列表。 我尝试了很多解决方法,但没有运气。有什么建议吗?

【问题讨论】:

  • 找到解决方案了吗?

标签: java spring jackson spring-webflux


【解决方案1】:

创建一个类(比如 CollectionT)并在其中添加 T 的列表作为属性。然后您可以轻松地将其转换为 Mono,.map(x -> x.getList()) 将返回 T 列表的 Mono。它还通过避免 .block() 使您的代码看起来更加非阻塞

代码如下:->

public class CollectionT {

   private List<T> data;

   //getters
   public List<T> getData(){
    return data;
   }

   //setters
     ...
}

public class RestConsumer<T> {
    WebClient client = WebClient.create();

    public RestConsumer(){
        //Initialize client
    }

        public List<T> getList(String relativeUrl){

                return client
                    .get()
                    .uri(relativeUrl)
                    .retrieve()
                    .bodyToMono(CollectionT.class)
                    .map(x -> x.getData());

    }
}

【讨论】:

  • 上面的例子没有编译
【解决方案2】:

我遇到了同样的问题,为了工作,我添加了 ParameterizedTypeReference 作为该函数的参数。

public <T> List<T> getList(String relativeUrl, 
                           ParameterizedTypeReference<List<T>> typeReference){
    try{
        return client
            .get()
            .uri(relativeUrl)
            .retrieve()
            .bodyToMono(typeReference)
            .block();
    } catch(Exception e){
        return null;
    }
}

然后调用那个函数

ParameterizedTypeReference<List<MyClass>> typeReference = new ParameterizedTypeReference<List<MyClass>>(){};
List<MyClass> strings = getList(relativeUrl, typeReference);

【讨论】:

  • 非常聪明的答案!
【解决方案3】:

如果您使用的是 kotlin,关键是使用 reified 来保留调用字段上的泛型类型的类类型。

代码如下:

inline fun <reified T> getMonoResult(uriParam: String): T? = client
    .get()
    .uri(uriParam)
    .retrieve()
    .bodyToMono(T::class.java)
    .block(Duration.ofSeconds(1))

inline fun <reified T> getFluxResult(uriParam: String): MutableList<T>? = client
    .get()
    .uri(uriParam)
    .retrieve()
    .bodyToFlux(T::class.java)
    .collectList()
    .block(Duration.ofSeconds(1))

【讨论】: