OkHttp学习 - POM 文件

Posted demonyan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OkHttp学习 - POM 文件相关的知识,希望对你有一定的参考价值。

前言

前段时间在项目中使用到了 OkHttp 这个 HTTP 开源库,感觉使用十分方便,而且也很高效。OkHttp 作为一款为 android 量身打造的 HTTP 客户端,支持 SPDY/HTTP 2 协议,通过阅读它的源码确实可以学到不少知识。本文通过对根目录的 POM 文件进行解析,从而对项目有个整理上的了解。

Maven 是一款优秀的跨平台的项目管理工具,主要用于 Java 平台的项目构建、依赖管理和项目信息管理。无论是小型的开源项目,还是大型的企业级应用,使用 Maven 都可以提高生产力。OkHttp 作为一个优秀和成熟的开源库,选择 Maven 来完成编译、单元测试、生成文档、打包、项目管理等工作算是明智之举。

为什么需要 Maven

首先Maven 是跨平台的,这意味着无论是在 Windows 平台,还是在 Linux 或者 Mac 平台,都可以使用同样的命令。

开发项目时,除了编写源代码,还有相当一部分时间花在了编译、运行单元测试、生成文档、打包和部署等烦琐且不起眼的构建工作上。如果现在还手工来完成构建工作,那成本是相当高的。Maven 使得软件的构建可以像自动流水线一样,只需要一条简单的命令,所有烦琐的步骤都能够自动完成。此外,Maven 能帮助我们标准化构建过程。在使用 Maven 之前,十个项目可能有十种不同的构建方式,而 Maven 使得所有项目的构建命令都是简单一致的,这极大地避免了不必要的学习成本,而且有利于促进项目团队的标准化。

任何 Java 应用几乎都会引用一些第三方的开源类库,这些类库都可通过依赖的方式引入到项目中来。随着依赖的增多,版本不一致、版本冲突、依赖臃肿等问题都会接踵而来。手工解决这些问题是十分枯燥的,Maven 提供了一个优秀的依赖管理解决方案,它通过一个坐标系统准确地定位每一个构件(artifact),也就是通过一组坐标找到任何一个 Java 类库(如 jar 文件)。Maven 给这个类库世界引入了经纬,让它们变得有秩序,于是我们可以借助它来有序地管理依赖,轻松地解决那些繁杂的依赖问题。

Maven 还能帮助我们管理原本分散在项目中各个角落的项目信息,包括项目描述、开发者列表、版本控制系统地址、许可证、缺陷管理系统地址等。Maven 还为全世界的 Java 开发者提供了一个免费的中央仓库,在其中可以找到几乎任何的流行开源类库。通过一些 Maven 的衍生工具(如 Nexus),还能对其进行快速地搜索。当然,Android Studio 的 Gradle 天然支持通过 Maven 坐标系统下载开源类库。

本节内容参考自《Maven实战》第一章。

OkHttp 的 POM 文件

POM(Project Object Model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖等,这些基本信息保存在文件 pom.xml 中。从 GitHub 中将 OkHttp 仓库克隆下来,在项目根目录中就可以看到 pom.xml 文件。通过解析 pom.xml 文件,我们可以对 OkHttp 项目整体上有个基本了解。pom.xml 文件内容比较丰富,包含了以下几部分,首先是项目基本信息

  ......

  <parent>                                                                                                            [1]
    <groupId>org.sonatype.oss</groupId>
    <artifactId>oss-parent</artifactId>
    <version>7</version>
  </parent>

  <groupId>com.squareup.okhttp3</groupId>                                                                             [2]
  <artifactId>parent</artifactId>                                                                                     [3]
  <version>3.0.0</version>                                                                                            [4]
  <packaging>pom</packaging>                                                                                          [5]

  <name>OkHttp (Parent)</name>
  <description>An HTTP+SPDY client for Android and Java applications</description>
  <url>https://github.com/square/okhttp</url>

  <modules>                                                                                                           [6]
    <module>okhttp</module>
    <module>okhttp-tests</module>

    <module>okhttp-android-support</module>

    <module>okhttp-apache</module>
    <module>okhttp-testing-support</module>
    <module>okhttp-urlconnection</module>

    <module>okhttp-ws</module>
    <module>okhttp-ws-tests</module>

    <module>okhttp-logging-interceptor</module>

    <module>okcurl</module>
    <module>mockwebserver</module>
    <module>samples</module>
    <module>benchmarks</module>
  </modules>

  ......

本文基于 3.0.0 版本分析,克隆仓库后可以通过命令 git checkout parent-3.0.0 切换到 3.0.0 版本。

[1] 元素 parent 声明父模块,使得 OkHttp 能够上传到 Maven 中央仓库中,并且可以被其他人搜索使用。
[2] 元素 groupId 声明项目隶属的实际项目是 com.squareup.okhttp3
[3] 元素 artifactId 声明项目在 group 中唯一的 ID。
[4] 元素 version 声明项目当前所处的版本为 3.0.0
[5] 元素 packaging 定义打包方式。使用打包方式为 pom,表明这是一个聚合项目,后面使用 module 元素来定义聚合的模块。

在 Maven 的世界里,任何项目都是基于 Maven 坐标来定位。Maven 坐标是通过一些元素来定义的,它们是 groupId、artifactId、version、packaging 和 classifier。其中最重要且不可或缺的元素是 groupId、artifactId 和 version,这三个元素定义了项目基本的坐标。

[6] 元素 modules 用于包含聚合的模块。内部每个 module 元素都定义一个模块,可以看到 OkHttp 项目有如下模块:

模块内容
okhttp实现 OkHttp 库的模块
okhttp-testsOkHttp 库单元测试的模块
okhttp-android-support支持 android 平台使用 OkHttp 库的模块(cache 相关)
okhttp-apache实现 Apache HttpClient 接口(下一版本会弃用)
okhttp-testing-support支持单元测试的模块
okhttp-urlconnection实现 HttpURLConnection 接口(下一版本会弃用)
okhttp-ws支持 WebSocket
okhttp-logging-interceptor实现 Logging 拦截器
okcurl实现 OkCurl
mockwebserver脚本化 WebServer,用于测试 HTTP 客户端
samples示例代码
benchmarks测试 HTTP 客户端性能的模块

接下来使用 properties 元素定义项目属性,在 pom.xml 文件的其他地方使用 $属性名称 的方式引用该属性。类似于全局变量,这种做法的最大意义在于消除重复。属性内容如下所示:

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <!-- Compilation -->
    <java.version>1.7</java.version>
    <okio.version>1.6.0</okio.version>
    <!-- ALPN library targeted to Java 7 -->
    <alpn.jdk7.version>7.1.2.v20141202</alpn.jdk7.version>
    <!-- ALPN library targeted to Java 8 update 25. -->
    <alpn.jdk8.version>8.1.2.v20141202</alpn.jdk8.version>
    <bouncycastle.version>1.50</bouncycastle.version>
    <gson.version>2.2.3</gson.version>
    <apache.http.version>4.2.2</apache.http.version>
    <airlift.version>0.6</airlift.version>
    <guava.version>16.0</guava.version>
    <android.version>4.1.1.4</android.version>

    <!-- Test Dependencies -->
    <junit.version>4.11</junit.version>

    <!-- Plugin Dependencies -->
    <maven.bundle.plugin.version>3.0.1</maven.bundle.plugin.version>
  </properties>

需要注意的是的 JDK7 和 JDK8 使用不同的 ALPN 插件。ALPN(Application Layer Protocol Negotiation)是 TLS 的一个扩展,用于客户端和服务器之间协商确认对方是否支持 HTTP 2.0 协议。

接下来分别用元素 scm,元素 issueManagement 和元素 licenses 来定义项目的版本控制,问题追踪,许可协议等信息,内容如下所示:

  <scm>
    <url>https://github.com/square/okhttp/</url>
    <connection>scm:git:https://github.com/square/okhttp.git</connection>
    <developerConnection>scm:git:git@github.com:square/okhttp.git</developerConnection>
    <tag>parent-3.0.0</tag>
  </scm>

  <issueManagement>
    <system>GitHub Issues</system>
    <url>https://github.com/square/okhttp/issues</url>
  </issueManagement>

  <licenses>
    <license>
      <name>Apache 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
    </license>
  </licenses>

接下来使用 dependencyManagement 元素约束项目的依赖配置,内容如下所示:

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.squareup.okio</groupId>
        <artifactId>okio</artifactId>
        <version>$okio.version</version>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>$junit.version</version>
      </dependency>
      <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>$bouncycastle.version</version>
      </dependency>
      <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>$gson.version</version>
      </dependency>

      ......

      <dependency>
        <groupId>com.google.android</groupId>
        <artifactId>android</artifactId>
        <version>$android.version</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

我们知道 dependencies 元素包含的依赖配置是可以被子模块继承的,但大多数时候并不是所有的子模块都需要这些依赖配置,比如上面定义的 com.squareup.okio:okio:1.6.0 库就只有 okhttp 和 okhttp-tests 子模块需要。引用 dependencyManagement 元素后依赖配置不会引入实际的依赖,不过它能够约束依赖使用。比如子模块 okhttp 中还是需要引入依赖 com.squareup.okio:okio,但它的元素 version 可以省略,实际使用的是父模块中声明的 version,从而不会发生多个子模块使用依赖版本不一致的情况,如下所示:

  文件路径:okhttp/okhttp/pom.xml

  <dependencies>
    <dependency>
      <groupId>com.squareup.okio</groupId>
      <artifactId>okio</artifactId>
    </dependency>
    ......
  </dependencies>

因此使用 dependencyManagement 元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性。

接下来使用元素 <build><plugins><plugin>声明插件。我们知道,Maven 的核心仅仅定义了抽象的生命周期,具体的构建任务还是交由插件完成的,插件以独立的构件形式存在,更多相关内容请参考 Maven 实战第七章。OkHttp 项目父模块中主要包含以下插件:

插件用途
maven-compiler-plugin编译项目
maven-surefire-plugin执行测试
maven-javadoc-plugin生成文档
maven-release-plugin自动化项目版本发布
maven-checkstyle-plugin检测编码风格
animal-sniffer-maven-plugin检测代码 API

最后使用元素 <profiles><profile> 声明一些特殊的配置。为了能让构建在各个环境下方便地移植,Maven 引入了 profile 的概念,OkHttp 项目中使用 profile 根据 JDK 的版本来选择 alpn-boot 插件的版本。

项目构建生命周期

Maven 从大量项目的构建工具中学习,然后总结出了高度完善的、易扩展的生命周期。Maven 拥有三套相互独立的生命周期,它们分别为 clean、default 和site。clean 生命周期主要是清理项目,default 生命周期主要是构建项目,site 生命周期主要是发布项目。每个生命周期都包含一些阶段(phase),这些阶段按照顺序执行,并且后面的阶段依赖于前面的阶段。更多内容可以查阅官方文档 Introduction to the Build Lifecycle

OkHttp 这个开源库平时使用较多的是 clean 生命周期和 default 生命周期。官方鼓励提交代码继续完善项目,但需要首先通过以下构建命令:

mvn clean verify

最终如果一切顺利,构建过程完成后会输出以下结果。

参考资料:
1. Introduction to the POM
2. Maven实战

以上是关于OkHttp学习 - POM 文件的主要内容,如果未能解决你的问题,请参考以下文章

深入浅出安卓热门网络框架 OKHttp3 和 Retrofit 原理

关于pom文件的描述

网络请求框架OkHttp3全解系列:OkHttp的基本使用

Android网络框架OKhttp3学习笔记

Maven 的 pom 文件生命周期

Maven学习小结(三 基本概念)