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-tests | OkHttp 库单元测试的模块 |
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 文件的主要内容,如果未能解决你的问题,请参考以下文章