目录
Maven 依赖管理
Maven 一个核心的特性就是依赖管理。当我们处理多模块的项目(包含成百上千个模块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难。针对此种情形,Maven 提供了一种高度控制的方法。
可传递性依赖发现
一种相当常见的情况,比如说 A 依赖于其他库 B。如果,另外一个项目 C 想要使用 A ,那么 C 项目也需要使用库 B。
Maven 可以避免去搜索所有所需库的需求。Maven 通过读取项目文件(pom.xml),找出它们项目之间的依赖关系。
我们需要做的只是在每个项目的 pom 中定义好直接的依赖关系。其他的事情 Maven 会帮我们搞定。
通过可传递性的依赖,所有被包含的库的图形会快速的增长。当有重复库时,可能出现的情形将会持续上升。Maven 提供一些功能来控制可传递的依赖的程度。
功能 | 功能描述 |
---|---|
依赖调节 | 决定当多个手动创建的版本同时出现时,哪个依赖版本将会被使用。 如果两个依赖版本在依赖树里的深度是一样的时候,第一个被声明的依赖将会被使用。 |
依赖管理 | 直接的指定手动创建的某个版本被使用。例如当一个工程 C 在自己的依赖管理模块包含工程 B,即 B 依赖于 A, 那么 A 即可指定在 B 被引用时所使用的版本。 |
依赖范围 | 包含在构建过程每个阶段的依赖。 |
依赖排除 | 任何可传递的依赖都可以通过 "exclusion" 元素被排除在外。举例说明,A 依赖 B, B 依赖 C,因此 A 可以标记 C 为 "被排除的"。 |
依赖可选 | 任何可传递的依赖可以被标记为可选的,通过使用 "optional" 元素。例如:A 依赖 B, B 依赖 C。因此,B 可以标记 C 为可选的, 这样 A 就可以不再使用 C。 |
依赖范围
传递依赖发现可以通过使用如下的依赖范围来得到限制:
范围 | 描述 |
---|---|
编译阶段 | 该范围表明相关依赖是只在项目的类路径下有效。默认取值。 |
供应阶段 | 该范围表明相关依赖是由运行时的 JDK 或者 网络服务器提供的。 |
运行阶段 | 该范围表明相关依赖在编译阶段不是必须的,但是在执行阶段是必须的。 |
测试阶段 | 该范围表明相关依赖只在测试编译阶段和执行阶段。 |
系统阶段 | 该范围表明你需要提供一个系统路径。 |
导入阶段 | 该范围只在依赖是一个 pom 里定义的依赖时使用。同时,当前项目的POM 文件的 部分定义的依赖关系可以取代某特定的 POM。 |
依赖管理
通常情况下,在一个共通的项目下,有一系列的项目。在这种情况下,我们可以创建一个公共依赖的 pom 文件,该 pom 包含所有的公共的依赖关系,我们称其为其他子项目 pom 的 pom 父。 接下来的一个例子可以帮助你更好的理解这个概念。
接下来是上面依赖图的详情说明:
-
App-UI-WAR 依赖于 App-Core-lib 和 App-Data-lib。
-
Root 是 App-Core-lib 和 App-Data-lib 的父项目。
-
Root 在它的依赖部分定义了 Lib1、lib2 和 Lib3 作为依赖。
App-UI-WAR 的 pom.xml 文件代码如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.companyname.groupname</groupId>
<artifactId>App-UI-WAR</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.companyname.groupname</groupId>
<artifactId>App-Core-lib</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.companyname.groupname</groupId>
<artifactId>App-Data-lib</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
App-Core-lib 的 pom.xml 文件代码如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>Root</artifactId> <groupId>com.companyname.groupname</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-Core-lib</artifactId> <version>1.0</version> <packaging>jar</packaging> </project>
App-Data-lib 的 pom.xml 文件代码如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>Root</artifactId> <groupId>com.companyname.groupname</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-Data-lib</artifactId> <version>1.0</version> <packaging>jar</packaging> </project>
Root 的 pom.xml 文件代码如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>Root</artifactId> <version>1.0</version> <packaging>pom</packaging> <dependencies> <dependency> <groupId>com.companyname.groupname1</groupId> <artifactId>Lib1</artifactId> <version>1.0</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname2</groupId> <artifactId>Lib2</artifactId> <version>2.1</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname3</groupId> <artifactId>Lib3</artifactId> <version>1.1</version> </dependency> </dependencies> </project>
现在当我们构建 App-UI-WAR 项目时, Maven 将通过遍历依赖关系图找到所有的依赖关系,并且构建该应用程序。
通过上面的例子,我们可以学习到以下关键概念:
- 公共的依赖可以使用 pom 父的概念被统一放在一起。App-Data-lib 和 App-Core-lib 项目的依赖在 Root 项目里列举了出来(参考 Root 的包类型,它是一个 POM).
- 没有必要在 App-UI-W 里声明 Lib1, lib2, Lib3 是它的依赖。 Maven 通过使用可传递的依赖机制来实现该细节。
Maven 自动化部署
项目开发过程中,部署的过程包含需如下步骤:
- 将所的项目代码提交到 SVN 或者代码库中并打上标签。
- 从 SVN 上下载完整的源代码。
- 构建应用。
- 存储构建输出的 WAR 或者 EAR 文件到一个常用的网络位置下。
- 从网络上获取文件并且部署文件到生产站点上。
- 更新文档并且更新应用的版本号。
问题描述
通常情况下上面的提到开发过程中会涉及到多个团队。一个团队可能负责提交代码,另一个团队负责构建等等。很有可能由于涉及的人为操作和多团队环境的原因,任何一个步骤都可能出错。比如,较旧的版本没有在网络机器上更新,然后部署团队又重新部署了较早的构建版本。
解决方案
通过结合以下方案来实现自动化部署:
- 使用 Maven 构建和发布项目
- 使用 SubVersion, 源码仓库来管理源代码
- 使用远程仓库管理软件(Jfrog或者Nexus) 来管理项目二进制文件。
修改项目的 pom.xml
我们将会使用 Maven 发布的插件来创建一个自动化发布过程。
例如,bus-core-api 项目的 pom.xml 文件代码如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>bus-core-api</groupId>
<artifactId>bus-core-api</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<scm>
<url>http://www.svn.com</url>
<connection>scm:svn:http://localhost:8080/svn/jrepo/trunk/
Framework</connection>
<developerConnection>scm:svn:${username}/${password}@localhost:8080:
common_core_api:1101:code</developerConnection>
</scm>
<distributionManagement>
<repository>
<id>Core-API-Java-Release</id>
<name>Release repository</name>
<url>http://localhost:8081/nexus/content/repositories/
Core-Api-Release</url>
</repository>
</distributionManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.0-beta-9</version>
<configuration>
<useReleaseProfile>false</useReleaseProfile>
<goals>deploy</goals>
<scmCommentPrefix>[bus-core-api-release-checkin]-<
/scmCommentPrefix>
</configuration>
</plugin>
</plugins>
</build>
</project>
在 pom.xml 文件中,我们常用到的一些重要元素节点如下表所示:
元素节点 | 描述 |
---|---|
SCM | 配置 SVN 的路径,Maven 将从该路径下将代码取下来。 |
repository | 构建的 WAR 或 EAR 或JAR 文件的位置,或者其他源码构建成功后生成的构件的存储位置。 |
Plugin | 配置 maven-release-plugin 插件来实现自动部署过程。 |
Maven Release 插件
Maven 使用 maven-release-plugin 插件来完成以下任务。
mvn release:clean
清理工作空间,保证最新的发布进程成功进行。
mvn release:rollback
在上次发布过程不成功的情况下,回滚修改的工作空间代码和配置保证发布过程成功进行。
mvn release:prepare
执行多种操作:
- 检查本地是否存在还未提交的修改
- 确保没有快照的依赖
- 改变应用程序的版本信息用以发布
- 更新 POM 文件到 SVN
- 运行测试用例
- 提交修改后的 POM 文件
- 为代码在 SVN 上做标记
- 增加版本号和附加快照以备将来发布
- 提交修改后的 POM 文件到 SVN
mvn release:perform
将代码切换到之前做标记的地方,运行 Maven 部署目标来部署 WAR 文件或者构建相应的结构到仓库里。
打开命令终端,进入到 C:\ > MVN >bus-core-api 目录下,然后执行如下的 mvn 命令。
C:\MVN\bus-core-api>mvn release:prepare
Maven 开始构建整个工程。构建成功后即可运行如下 mvn 命令。
C:\MVN\bus-core-api>mvn release:perform
构建成功后,你就可以可以验证在你仓库下上传的 JAR 文件是否生效。
"We know that in this world, it is important to know facts and truth, but this spirit of inquiry can easily turn into a complaining mood and strong anger, which is not good. We should know the facts, acknowledge them, and use our strengths, rather than simply complain. Complaining cannot find the truth and progress, only by recognizing can we move forward better."
Maven Web 应用
本章节我们将学习如何使用版本控制系统 Maven 来管理一个基于 web 的项目,如何创建、构建、部署以及运行一个 web 应用。
创建 Web 应用
我们可以使用 maven-archetype-webapp 插件来创建一个简单的 Java web 应用。
打开命令控制台,进入到 C:\MVN 文件夹,然后执行以下的 mvn 命令:
mvn archetype:generate "-DgroupId=com.companyname.automobile" "-DartifactId=trucks" "-DarchetypeArtifactId=maven-archetype-webapp" "-DinteractiveMode=false"
Maven 目录结构是标准的,各个目录作用如下表所示:
文件夹结构 | 描述 |
---|---|
trucks | 包含 src 文件夹和 pom.xml 文件。 |
src/main/webapp | 包含 index.jsp 文件和 WEB-INF 文件夹. |
src/main/webapp/WEB-INF | 包含 web.xml 文件 |
src/main/resources | 包含图片、properties资源文件。 |
pom.xml 文件代码如下:
接下来我们打开 C:\ > MVN > trucks > src > main > webapp > 文件夹,可以看到一个已经创建好的 index.jsp 文件,代码如下:
构建 Web 应用
打开命令控制台,进入 C:\MVN\trucks 目录,然后执行下面的以下 mvn 命令:
mvn clean package
部署 Web 应用
打开 C:\ < MVN < trucks < target < 文件夹,找到 trucks.war 文件,并复制到你的 web 服务器的 web 应用目录,然后重启 web 服务器。
大家这里可以去下载一个Tomcat,之后去配置一下就可以啦
推荐一个博文:
IDEA配置本地tomcat启动项目_fengchao2016的博客-CSDN博客
真的很离谱,当时一直报红色,我还以为我部署的有问题呢