ktor client:支持协程的HTTP工具库

最近用kotlin开发服务端,用了很多库,像Spring boot的RestTemplate,okhttp还有retrofit,觉得retrofit很好用。但是,在用retrofit来实现协程的时候,遇到了一个问题

image-20200519192935519

如图所示,提示Inappropriate blocking method call,说这种协程的使用方式是不合适的。我在Stack Overflow上搜了一下,发现如下解答

image-20200519193116994

也就是说这个execute方法会阻塞当前线程,因此不能令线程挂起,导致协程失效,而这个execute的原方法中:

@Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else {
          throw (RuntimeException) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }

    return parseResponse(call.execute());
  }

内部用了一个大的synchronized内部锁,导致线程阻塞。因此这种获取HTTP数据的方式用协程来实现是没有效果的,这里我们选择另一个提到的ktor client来实现。

ktor client是kotlin官方提供的一个用于读取HTTP数据的一种工具库。而父组件ktor是一个用纯kotlin实现的一个服务端,类似Spring Boot,这里我们只需要他获取HTTP数据的功能

导库,一定要导入全,kotlin官方是推荐Gradle,但是我这里用的maven。导入的包比较多也比较烦

<-- 导入CIO库,这是一个支持协程的版本 -->
<dependency>
    <groupId>io.ktor</groupId>
    <artifactId>ktor-client-cio</artifactId>
    <version>1.3.1</version>
</dependency>
    <-- 用于支持json的解析 -->
<dependency>
    <groupId>io.ktor</groupId>
    <artifactId>ktor-client-json</artifactId>
    <version>1.3.1</version>
</dependency>
        <-- 选择Gson作为解析的工具库 -->
<dependency>
    <groupId>io.ktor</groupId>
    <artifactId>ktor-client-gson</artifactId>
    <version>1.3.1</version>
</dependency>

<-- 协程库-->
<dependency>
    <groupId>org.jetbrains.kotlinx</groupId>
    <artifactId>kotlinx-coroutines-core</artifactId>
    <version>1.3.4</version>
</dependency>
    <-- 采用jdk8编译 -->
<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib-jdk8</artifactId>
    <version>${kotlin.version}</version>
</dependency>
    <-- 解析json涉及到序列化,一定要导入反射包 -->
<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-reflect</artifactId>
    <version>1.3.72</version>
    <scope>runtime</scope>
</dependency>

以上的包一定要全部导完,一个不能少。至于有一个kotlinx serialization的库,用来标识序列化的数据类,我试了试,不用也可以。

接下来在IDEA中下载插件

image-20200519193930321

扫描二维码关注公众号,回复: 11273879 查看本文章

用过GsonFormatter的同学应该会比较熟悉,这个是kotlin的将JSON转换成对应的数据类的工具,接下来转换的时候注意设置:

image-20200519194033704

Enable Inner Class Model要勾上,这样JSON内部还有类的话也可以解析。

这是一个数据类型的模板:

image-20200519194135719

@SerializedName来标识序列化的JSON String,因为属性里面是不允许出现特殊字符,而JSON String里面是可以有的。

同时,需要给每个值赋一个初始值,这样才会有一个无参的构造函数,我之前用fastjson有这个问题,不知道gson是不是这样的

data class Coordinate(
    val X: Double = 0.0,
    val Y: Double = 0.0,
    val Z: Double = 0.0
)

接下来就是用ktor client来解析数据了。

首先定义HTTP Client:

// 指定解析引擎为CIO(Coroutine-based I/O),也是kotlin官方推荐的引擎
// 之所以CIO后面没加括号是因为CIO是一个单例类
val httpClient = HttpClient(CIO){
    //这个必须要在引入ktor-client-gson后才可以使用,用于指定解析工具
    install(JsonFeature){
        serializer = GsonSerializer()
    }
}

用定义好的httpClient从http获取数据

// 注意给网络通信指定IO协程池
val absoluteValues = async(Dispatchers.IO) {
    // 指定HTTP方法,以及返回的JSON字符串对应的类。后面的run其实是把结果换成了一个新的类的列表
    httpClient.get<Coordinate>("http://localhost:8080/coors/absolute").run {
        sequenceOf(X, Y, Z).map { DataValue(Variant(it)) }.toList()
    }
}

接下来就可以愉快的用协程来实现HTTP的读写了~

猜你喜欢

转载自blog.csdn.net/qq_41989109/article/details/106221734