一、Maven 环境搭建
1. 安装
- 下载解压 apache-maven-版本-bin.zip 。
- 添加环境变量:
- MAVEN_HOME:配置 Maven 的安装目录。
- PATH:配置 bin 目录(%MAVEN_HOME%\bin)。
- 创建本地仓库目录:
- 在 Maven 解压目录下建立 repository 目录。
- 修改 conf/settings.xml 配置本地仓库地址。
<!--本地仓库位置, 默认`${user.home}/.m2/repository`-->
<localRepository>E:\java\maven\repository</localRepository>
- 配置远程仓库镜像:
- 修改 conf/settings.xml 配置远程仓库镜像。
- mvnrepository
- 阿里云云效 Maven
- 阿里云云效 Maven
<mirrors>
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
|
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
-->
<mirror>
<id>maven-default-http-blocker</id>
<mirrorOf>external:http:*</mirrorOf>
<name>Pseudo repository to mirror external repositories initially using HTTP.</name>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror>
<!-- maven2 -->
<mirror>
<id>mvnrepository</id>
<mirrorOf>*</mirrorOf>
<name>mvnrepository</name>
<url>https://repo1.maven.org/maven2/</url>
</mirror>
<!-- 阿里云镜像 -->
<mirror>
<id>central</id>
<mirrorOf>*</mirrorOf>
<name>central</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
<mirror>
<id>public</id>
<mirrorOf>*</mirrorOf>
<name>public</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
<mirror>
<id>gradle-plugin</id>
<mirrorOf>*</mirrorOf>
<name>gradle-plugin</name>
<url>https://maven.aliyun.com/repository/gradle-plugin</url>
</mirror>
<mirror>
<id>apache-snapshots</id>
<mirrorOf>*</mirrorOf>
<name>apache-snapshots</name>
<url>https://maven.aliyun.com/repository/apache-snapshots</url>
</mirror>
<mirror>
<id>google</id>
<mirrorOf>*</mirrorOf>
<name>google</name>
<url>https://maven.aliyun.com/repository/google</url>
</mirror>
<mirror>
<id>spring</id>
<mirrorOf>*</mirrorOf>
<name>spring</name>
<url>https://maven.aliyun.com/repository/spring</url>
</mirror>
<mirror>
<id>spring-plugin</id>
<mirrorOf>*</mirrorOf>
<name>spring-plugin</name>
<url>https://maven.aliyun.com/repository/spring-plugin</url>
</mirror>
<mirror>
<id>grails-core</id>
<mirrorOf>*</mirrorOf>
<name>grails-core</name>
<url>https://maven.aliyun.com/repository/grails-core</url>
</mirror>
<mirror>
<id>e-iceblue</id>
<mirrorOf>*</mirrorOf>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</mirror>
</mirrors>
2. 验证
# 查看`Maven`版本
maven -v
二、Maven 项目生命周期
1. clean 清理
- pre-clean:准备清理。
clean
:真正的清理工作(将 target 目录下的 class 和 jar 文件清理)。- post-clean:执行清理后的一些后续工作。
2. default 构建
- validate:验证。
- initialize:初始化配置。
- generate-sources:生成源代码编译目录。
- process-sources:处理项目主资源文件(复制资源文件到 outputclasspath)。
- generate-resources:生成资源目录。
- process-resources:处理资源文件。
complie
:编译源代码(将 java 源程序编译成 class 字节码文件)。- process-classes:处理编译后文件。
- generate-test-sources:生成测试目录。
- process-test-sources:处理项目测试资源文件(复制测试资源文件到 outputclasspath)。
- generate-test-resources:生成测试资源文件。
- process-test-resources:处理测试资源文件。
- test-compile:编译测试代码。
- process-test-classes:处理测试代码。
test
:单元测试,自动运行测试代码(执行 src/test/java 下的类)。- prepare-package:打包前的准备。
package
:将编译好的代码,打包成为 jar包、war包 或 ear 等。- pre-integration-test:准备整体测试。
- integration-test:整体测试。
- post-integration-test:为整体测试收尾。
- verify:验证。
install
:安装到本地 Maven 仓库。- deploy:将最终包部署到远程 Maven 仓库。
3. site 生成项目站点
- pre-site:准备生成站点。
- site:生成站点及文档。
- post-site:站点收尾。
- site-deploy:将生成的站点,发布到服务器上。
三、Maven 常用命令
# 查看`Maven`版本
mvn -v
# 不调试运行
mvn '命令名称'
# 调试运行
mvnDebug '命令名称'
# 清理
mvn clean
# 编译主程序
mvn compile
# 编译测试程序
mvn test-compile
# 执行测试
mvn test
# 打包
mvn package
# 安装
mvn install
# 打包
mvn clean package
# 打包跳过测试
mvn clean package -D maven.test.skip=true
1. Java 命令
# 命令行运行
java -jar 'xx.jar'
# 后台运行
nohup java -jar 'xx.jar' > /dev/null 2>&1 &
# 查看启动`Java`服务进程
ps -ef | grep java
# 停止进程
kill -9 '进程号'
四、依赖管理
1. scope 依赖范围
依赖范围 | 编译 ClassPath 有效 | 测试 ClassPath 有效 | 运行 ClassPath 有效 | 例子 |
---|---|---|---|---|
compile【默认】 | Y | Y | Y | spring-core |
provided | Y | Y | - | servlet-api |
runtime | - | Y | Y | JDBC 驱动 |
test | - | Y | - | Junit |
- compile:【默认值】
- jar包 会一直存在所有阶段(编译、测试、运行 都有效)。
- A 在 编译、测试、运行 时都依赖 B。
- 比如:strus-core、spring-beans 会打到 war包 或 jar包。
- provided:
- 不让 Servlet容器 和 本地仓库的 jar包 冲突(编译、测试有效)。
- A 在 编译、测试 时需要依赖 B。
- 比如:servlet-api 就是 编译 和 测试 有用,在运行时不用(Tomcat 容器已提供)不会打到 war 包。
- runtime:
- 运行、测试 有效。
- 比如:JDBC 驱动 在开发代码中,针对 Java 的 JDBC 接口开发,编译 不用。
- 在 运行、测试 时,需要通过 JDBC驱动包(MySQL 驱动)连接数据库,会打到 war 包。
- test:
- 只在 测试 有效(只会在单元测试类中使用,不会随项目发布)。
- 比如:Junit 不会打到 war 包。
- system: 类似 provided
- 需要显式提供包含依赖的 jar包。
- Maven 不会在 Repository 中查找它。
2. 依赖传递
直接依赖\传递依赖 | compile | provided | runtime | test |
---|---|---|---|---|
compile | compile | - | runtime | - |
provided | provided | provided | provided | - |
runtime | runtime | - | runtime | - |
test | test | - | test | - |
- 纵坐标:直接依赖。
- A 依赖 B,B 是 A 的直接依赖。
- 在 A 的 pom.xml 中添加 B 的坐标。
- 横坐标:传递依赖。
- B 依赖 C,C 是 A 的传递依赖。
- 中间部分:传递依赖的范围。
- A 依赖 C 的范围。
3. 依赖调节原则
- 项目 A 依赖于项目 B,项目 B 依赖于项目 C(v1)。
- 项目 A 依赖于项目 D,项目 D 依赖于项目 E,项目 E 依赖于 C(v2)。
# v1
A -> B -> C
# v2
A -> D -> E -> C
- 分析:项目 A 隐形依赖了两个版本的 C,那到底采用哪个版本呢?
- 依赖调解第一原则:路径优先。
- 很明显,第一种路径深度是 3。
- 第二种路径深度是 4。
- 所以,Maven 会采用 C(v1)。
- 依赖调解第二原则:声明优先。
假设路径深度相等,那么声明在前的会被引用。
4. 版本锁定 dependencyManagement
- 在 Maven 中
dependencyManagement
的作用,其实相当于一个对所依赖 jar 包进行版本管理的管理器。
4.1 pom.xml 文件中,jar 的版本判断的两种途径
- 如果 dependencies 里的 dependency,自己没有声明 version 元素。
- 那么 Maven 就会到 dependencyManagement 里面去找,有没有对该 groupId.artifactId 进行过版本声明。
- 如果有就继承它,如果没有就会报错,告诉你必须为 dependency 声明一个 version。
- 如果 dependencies 中的 dependency,声明了 version 元素。
那么无论 dependencyManagement 中有无对该 jar 的 version 声明,都以 dependency 里的 version 为准。
<!-- 版本管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.7.Final</version>
</dependency>
</dependencies>
</dependencyManagement>
5. exclusions 排除依赖
- 观察 Maven
Dependencies
下的 jar 包,会发现存在了两个javassist
包。
- 一个是
javassist-3.18.1-GA
。- 另一个是
javassist-3.11.0-GA
。
- 这是因为引入三大框架的 jar 包。
hibernate
依赖javassist-3.18.1-GA
,而struts
依赖javassist-3.11.0-GA
,这就是 jar包版本冲突。- 如果这两个 jar 包同时存在,会导致后续某些操作存在问题(比如:openSessionInView 失效)。
- 所以需要 排除低版本的 jar 包。
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.24</version>
<!-- 排除 struts 中依赖低版本的 javassist 的jar包 -->
<exclusions>
<exclusion>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
6. junit 单元测试
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext_dao.xml","classpath:applicationContext_datasource.xml"})
@Test
ApplicationContext appContext = new ClassPathXmlApplicationContext("classpath:META-INF/spring/applicationContext-common.xml");
ProjectServiceFacade projectServiceFacade = (ProjectServiceFacade) appContext.getBean("projectServiceFacade");
五、Maven 聚合
- 顾名思义,就是把多个 模块 或 项目 聚合到一起,建立一个专门负责聚合工作的 Maven 工程。
- 聚合模块本身也做为一个 Maven 项目,它必须有自己的
pom.xml
。- 它的打包方式必须为
pom
。- 引入了新的元素
<modules><module> xxx </module></modules>
。- 版本:聚合模块的版本,和被聚合模块版本一致。
- 相对目录:每个
module
的值都是一个当前pom
的相对目录。- 目录名称:
- 为了方便的快速定位内容,模块所处的目录应当与其 artifactId 一致(Maven 约定而不是硬性要求)。
- 总之,模块所处的目录必须和
<module>
模块,所处的目录</module>
相一致。
- 习惯约定:
- 为了方便构建,通常将聚合模块放在项目目录层的最顶层,其它模块作为子目录存在。
- 这样打开项目的时候,第一个看到的就是聚合模块的
pom
。
- 聚合模块减少的内容:
- 聚合模块的内容仅仅是一个
pom.xml
文件,它不包含src/main/Java
、src/test/java
等目录。- 因为它只是用来帮助其它模块构建的工具,本身并没有实质的内容。
- 聚合模块和子模块的目录:
- 可以是 父子类,也可以是 平行结构。
- 当然如果使用平行结构,那么聚合模块的
pom
也需要做出相应的更改。
六、Maven 继承
- 在项目开发的过程中,可能多个模块独立开发,但是多个模块可能依赖相同的元素。
- 比如:每个模块都需要
Junit
。
- 使用 Spring 的时候,其核心 jar 也必须都被引入,在编译的时候,
maven-compiler-plugin
插件也要被引入。- 这时我们采用继承,就不用在每个子模块分别定义了。
- 如何配置继承。
- 继承肯定是一个父子结构,那么在父工程中来创建一个
parent project
。<packaging>
:作为父模块的pom
,其打包类型也必须为pom
。- 结构:父模块只是为了帮助我们消除重复,所以它也不需要
src/main/java
、src/test/java
等目录。- 新的元素:
<parent>
, 它是被用在子模块中的。<parent>
元素的属性:
<relativePath>
:表示父模块 pom 的相对路径。- 在构建的时候,Maven 会先根据 relativePath 检查父 pom,如果找不到,再从本地仓库查找。
- relativePath 的默认值:
../pom.xml
- 子模块省略 groupId 和 version:
- 使用了继承的子模块中,可以不声明 groupId 和 version。
- 子模块将隐式的继承父模块的这两个元素。
七、聚合 与 继承区别
- 聚合 和 继承通常是结合使用的,但是其作用是不同的。
- 聚合 是将多个模块的工程,汇聚到一起。
- 而 继承 则是指明某个模块工程要 继承 另一个模块功能。
八、nexus 私服
1. nexus 安装
nexus-2.12.0-01-bundle.zip
解压。- dos 进入 bin 目录,nexus.bat 目录,敲入命令。
- 访问:http://localhost:8081/nexus,
admin/admin123
。
# 安装
nexus install
# 卸载
nexus uninstall
2. 构建索引
- 安装好的
nexus
是无法直接搜索到 jar 包的,必须下载索引才可以正常使用。- 我们到 中央仓库 下载以下两个索引压缩文件(这两个文件一般在此页面的最后的位置)。
- 还需要在网上下载一个名为
indexer-cli-5.1.1.jar
的 jar 包。
nexus-maven-repository-index.gz
nexus-maven-repository-index.properties
- 将三个文件放入一个文件夹,cmd 执行下面命令。
- 执行后生成
indexer
目录下的文件是索引文件。
java -jar indexer-cli-5.1.1.jar -u nexus-maven-repository-index.gz -d indexer
- 将
nexus-2.12.0-01-bundle\sonatype-work\nexus\indexer\central-ctx
目录下的文件删除。
将上边的索引文件拷贝到此目录下。- 拷贝后重新启动
nexus
,然后进入nexus
搜索 jar 包发现可以进行搜索了。
3. 仓库类型
- hosted:宿主仓库,自己项目的 jar 要放到 hosted 类型的仓库中。
- proxy:代理仓库,代理中央仓库。
- virtual:虚拟仓库,存储了 Maven1 的构件,一般不用。
- group:仓库组,将一些仓库组成一个组,自己项目连接仓库组去下载 jar 包。
平常开发中都去连接仓库组(仓库组中包括:hosted、proxy 等)。
4. 镜像配置
nexus
安装好,要开始使用它了。现在需要在 Maven 的配置文件 settings.xml 中配置镜像。- 让 Maven 找私服,而不是直接到中央仓库下载。
- 打开 Maven 的配置文件 settings.xml,添加如下配置。
<mirrors>
<mirror>
<id>nexus</id>
<!-- `*`代表私服里所有仓库 -->
<mirrorOf>*</mirrorOf>
<!-- 私服地址,所以仓库配置仓库组地址 -->
<url>http://localhost:8081/nexus/content/groups/public/</url>
</mirror>
</mirrors>
<!-- `mirrors`为镜像组,可以配置多个`mirror`(镜像),这里配置的是`nexus`中的中央代理仓库 -->
5. 发布自己的工程 jar
到 nexus
5.1 pom.xml
中添加配置信息
<distributionManagement>
<repository>
<!-- 私服仓库`Id`和私服`Url` -->
<id>releases</id>
<url>http://localhost:8081/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<url>http://localhost:8081/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
5.2 Maven
的 settings.xml
中配置信息
<servers>
<server>
<id>releases</id><!-- 和pom.xml<id>对应 -->
<username>admin</username>
<password>admin123</password>
</server>
<server>
<id>snapshots</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>
5.3 执行命令:deploy
6. 发布第三方的工程 jar
到 nexus
- 有很多 jar 包由于版权等问题,并不会出现在中央仓库中。
- 比如:Oracle 的驱动,那如何将这类 jar 包放在 nexus 中呢?
- 我们看下列操作步骤:
- 选择左侧菜单的 Repositories,在 Repositories 窗口中选择 3rd party。
- 在 3rd party 窗口中选择 Artifact Upload。
- 在 Artifact Upload 选项卡中填写坐标,并上传 jar 包。
九、其他
1. 引入本地jar包—打jar包
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${project.basedir}/src/main/resources/lib/sqljdbc4-4.2-6.jar</systemPath>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- `true`:把`本地`的`system作用域`的`jar包`也打包进来。-->
<includeSystemScope>true</includeSystemScope>-->
</configuration>
</plugin>
</plugins>
<!-- 选配。-->
<!-- 正常启动需注释以下代码,否则会包Shiro错误,打包部署放开以下注释。-->
<resources>
<resource>
<directory>${project.basedir}/../lib</directory>
<targetPath>/BOOT-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<targetPath>BOOT-INF/classes/</targetPath>
</resource>
</resources>
</build>
2. 引入本地jar包—打war包
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>system</scope>
<version>8.0.19-SNAPSHOT</version>
<systemPath>${project.basedir}/src/main/resources/lib/mysql-connector-java-8.0.19-SNAPSHOT.jar</systemPath>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<webResources>
<resource>
<!-- 本地jar包路径。-->
<directory>src/main/resources/lib</directory>
<!-- 打包到指定目录。-->
<targetPath>WEB-INF/lib</targetPath>
<filtering>false</filtering>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>