Maven (by Seven)
简介
-
apache公司的开源项目
-
项目自动化构建工具, 涵盖了项目的构建/编译/测试/打包/发布
-
基于项目对象模型(POM, Project Object Model), 通过一段描述信息构建和管理项目的工具
官网地址: maven.apache.org
Maven标准的项目目录结构
工程目录
|-- src // maven的源码根目录
|-- main // 主目录
|-- java // java源码目录
|-- resources // 项目资源目录
|-- webapp // web目录
|-- WEB-INF
|-- web.xml
|-- test // 测试目录
|-- java // 测试源码目录
|-- resources // 测试资源目录
|-- pom.xml // 描述项目对象模型的文件
Maven命令构建项目骨架
mvn archetype:generate
按照步骤提示操作, 可以通过携带参数的形式进行工程的构建, 如下
mvn archetype:generate -DgroupId=com.itany -DartifactId=demo02 -Dversion=1.0.1 -Dpackage=com.itany -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
命令参数说明
-
-DgroupId
: 指定工程的组织名, 公司域名倒置+工程名称 -
-DartifactId
: 指明工程模块名, 工程名-模块名 -
-Dversion
: 指明工程版本号 -
-Dpackage
: 指明代码所在包 -
-DarchetypeArtifactId
: 指定archetype创建工程类型-
maven-archetype-webapp
: 创建一个web项目 -
maven-archetype-quickstart
: 创建一个普通的java项目
-
-
-DinteractiveMode
: 是否使用交互模式
其它常用Maven命令
命令 | 说明 |
---|---|
mvn compile |
编译源码, maven工程的编译结果会生成一个target 目录 |
mvn test-compile |
编译测试代码 |
mvn clean |
清理编译目录, 将target 目录清理掉 |
mvn test |
执行测试代码 |
mvn package |
打包 |
mvn package -Dmaven.test.skip=true |
忽略测试直接打包 |
mvn jar:jar |
打成jar包 |
mvn install |
将当前工程打包并安装到本地仓库 |
坐标和仓库
工件坐标
工件: 也称为"构件", 可以理解为一个工程或一个jar包
每一个工程或jar包都有一个唯一标识
坐标由3部分组成
-
groupId
: 组织名 -
artifactId
: 模块名 -
version
: 版本号
每一个工程或jar包, 都由这三个属性定位
https://mvnrepository.com/
在该网站查找所需要依赖的工件坐标
仓库
maven用来存放jar包的地方
-
本地仓库
默认都是在用户主目录下的
.m2/repository/
-
远程仓库
maven全球中央仓库地址:
https://repo.maven.apache.org/maven2
备用地址:
http://repo1.maven.org
,http://repo2.maven.org
maven构建工程时, 根据依赖配置先在本地仓库中加载依赖jar包
如果本地仓库中没有相关jar包, maven会从远程仓库中将相关jar包下载到本地仓库, 再从本地仓库中将jar包引入到工程中
Maven项目的生命周期
完整的项目构建过程: 清理, 编译, 测试, 打包, 集成测试, 验证, 部署等步骤
Maven定义了三套相互独立的生命周期
-
clean: 清理项目
-
default: 构建项目
-
site: 生成项目站点
如执行install操作, clean -> compile -> test -> package -> install
POM解析
-
每一个maven工程都有且只有一个
pom.xml
该文件是maven工程的核心配置文件
<!-- 指定当前pom版本(固定值) -->
<modelVersion>4.0.0</modelVersion>
<!-- 当前工程的工件坐标 -->
<groupId>com.itany</groupId>
<artifactId>demo04</artifactId>
<version>1.0.0</version>
<!-- 当前工程的打包方式, 如果不配置, 默认打成jar包 -->
<packaging>war</packaging>
<!-- 工程的描述名称 -->
<name>demo04 Maven Webapp</name>
<!-- 项目地址, 实际开发中很少配置 -->
<url>http://www.example.com</url>
<!-- 项目描述 -->
<description></description>
<!-- 开发人员列表 -->
<devlopers></devlopers>
<!-- 许可证信息, 比如一些开源框架, 都会有许可证信息 -->
<licenses></licenses>
<!-- 组织信息 -->
<organization></organization>
<!-- 配置工程属性, 可以自定义一些属性 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- 依赖列表 -->
<dependencies>
<!-- 一项依赖 -->
<dependency>
<!-- 工件坐标 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!-- 依赖的生效范围 -->
<scope>test</scope>
<!-- 依赖是否可选 -->
<!-- true|false, 默认为false -->
<!-- 如果是false, 子项目自动继承该依赖 -->
<!-- 如果为true, 子项目不会自动继承该依赖, 如果需要, 必须显式地引入依赖 -->
<optional>false</optional>
<!-- 排除依赖传递列表 -->
<exclusions>
<!-- 一个子标签配置一个排除项, 可以配置多个排除项 -->
<exclusion></exclusion>
</exclusions>
</dependency>
</dependencies>
<!-- 依赖管理 -->
<!-- 该标签主要用在父工程中, 用来给子工程继承用 -->
<dependencyManagement>
<dependencies></dependencies>
</dependencyManagement>
<!-- 为构建行为提供支持 -->
<build>
<!-- 插件列表 -->
<plugings></plugings>
</build>
<!-- 用于子工程中, 指明对父工程的pom的继承 -->
<!-- 将父工程的工件坐标配置在这里 -->
<parent>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
</parent>
<!-- 用于多模块聚合 -->
<modules>
<!-- 配置一个模块 -->
<module></module>
</modules>
依赖范围
maven 项目不同的阶段引入到classpath中的依赖是不同的,例如,编译时,maven 会将与编译相关的依赖引入classpath中,测试时,maven会将测试相关的的依赖引入到classpath中,运行时,maven会将与运行相关的依赖引入classpath中,而依赖范围就是用来控制依赖于这三种classpath的关系。
<dependency>
<!-- 工件坐标 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!-- 依赖的生效范围 -->
<scope>test</scope>
</dependency>
<scope/>
标签的6个值
值 | 作用域 |
---|---|
compile |
默认值, 编译/测试/运行都有效. 举个简单的例子,假如项目中有spring-core的依赖,那么spring-core不管是在编译,测试,还是运行都会被用到,因此spring-core必须是编译范围(构件默认的是编译范围,所以依赖范围是编译范围的无须显示指定) |
test |
顾名思义就是针对于测试的,使用此依赖范围的依赖,只对测试classpath有效,在编译主代码和项目运行时,都将无法使用该依赖,最典型的例子就是 Junit, 构件在测试时才需要,所以它的依赖范围是测试,因此它的依赖范围需要显示指定为test ,当然不显示指定依赖范围也不会报错,但是该依赖会被加入到编译和运行的classpath中,造成不必要的浪费 。 |
provided |
使用该依赖范围的maven依赖,只对编译和测试的classpath有效,对运行的classpath无效,典型的例子就是servlet-api, 编译和测试该项目的时候需要该依赖,但是在运行时,web容器已经提供的该依赖,所以运行时就不再需要此依赖,如果不显示指定该依赖范围,并且容器依赖的版本和maven依赖的版本不一致的话,可能会引起版本冲突,造成不良影响。 |
runtime |
使用该依赖范围的maven依赖,只对测试和运行的classpath有效,对编译的classpath无效,典型例子就是JDBC的驱动实现,项目主代码编译的时候只需要JDK提供的JDBC接口,只有在测试和运行的时候才需要实现上述接口的具体JDBC驱动。 |
system |
依赖与classpath的关系与 provided依赖范围完全一致,但是系统依赖范围必须通过配置systemPath元素来显示指定依赖文件的路径,此类依赖不是由maven仓库解析的,而且往往与本机系统绑定,可能造成构件的不可移植,因此谨慎使用,systemPath元素可以引用环境变量: |
import |
它只使用在dependencyManagement 标签中, 表示从其它pom中导入dependency 配置 |
传递性依赖与依赖冲突
maven解决依赖冲突有2个原则
-
短路优先: 优先解析传递路径短的版本
a => b => c => d-1.0
a => c => d-1.1
-
如果路径长度相同, 先声明的先解析
jar包的本地化管理
1. systemPath
<dependency>
<groupId>ojdbc</groupId>
<artifactId>ojdbc</artifactId>
<version>14.0.0</version>
<!-- 将scope设定为system -->
<scope>system</scope>
<!-- 通过systemPath标签指明jar文件的绝对路径 -->
<systemPath>e:\ojdbc6-12.1.0.1-atlassian-hosted.jar</systemPath>
</dependency>
这种管理方式的平台移植性较差, 更换电脑之后可能需要修改配置中jar文件的路径
2. 配置仓库
在工程根目录下创建一个目录, 将其配置为一个仓库来使用
<repositories>
<repository>
<id>local</id>
<name>local</name>
<url>file://${project.basedir}/repo</url>
</repository>
</repositories>
-
${project.basedir}
: maven的全局变量, 可以获取当前工程的根目录 -
file://${project.basedir}/repo
: 将当前工程根目录下的repo目录作为仓库使用 -
file://
表示通过文件协议访问仓库, 而不是网络协议 -
注意事项: 将jar包copy到文件仓库时, 按照坐标进行目录的创建, 最后jar文件的文件名必须按照
artifactId-version.jar
的格式进行重命名
Maven中项目的关系
maven中项目关系有三种: 继承, 聚合, 依赖
1. 继承
一个Maven项目可以继承自另一个Maven项目. 项目之间就产生了父子级关系
应用场景: 多个子项目中使用相同的依赖或插件, 可以将这些相同的配置抽取成一个父项目, 进行统一管理, 保持一致. 让子项目继承该父项目, 可以保证子项目的技术统一
2. 聚合
配置继承之后, 需要各个工程聚合起来, 便于统一管理
配置方式: 在一个总的聚合工程中, 配置各个参与聚合的模块
可以将父工程作为聚合工程, 也可以单独创建一个专门用于聚合的工程
这里我们选择以父工程作为聚合工程来配置各个子工程
对聚合工程进行操作, 就是对各个参与聚合的子工程统一操作, 比如clean或compile或install
3. 依赖
各个模块之间也可以互相依赖
使用Nexus搭建Maven私服
下载地址:
http://nexus.sonatype.org/downloads/
https://www.sonatype.com/nexus-repository-oss
安装
nexus-2.14.10-01-bundle版本的安装
配置文件: conf/nexus.properties
bin目录下有jsw目录, 根据不同系统的分类目录
win64系统目录如下
以管理员身份运行install-nexus.bat
, 如果安装失败以管理员身份运行命令提示符, 在命令行下运行该脚本
安装完成后启动nexus服务
在系统的服务管理中启动, 或运行
start-nexus.bat
nexus服务默认端口号8081, 可以在配置文件中修改
服务启动完成之后, 可以在浏览器中访问localhost:8081/nexus
, 页面正常打开, 表示服务OK
服务器的一些配置需要登录
右上角log in登录
用户名: admin, 密码: admin123
maven配置私服地址
配置私服的远程仓库
默认的中央仓库
添加阿里的仓库
save之后, 仓库列表中多出了刚才添加的ali-mvn仓库
接下来要将该仓库添加到查找列表中
将远程仓库上没有的jar包添加到私服仓库中(比如oracle的ojdbc.jar包)
tomcat插件
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!--<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/webdemo</path>
</configuration>
</plugin>-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat8-maven-plugin</artifactId>
<version>3.0-r1655215</version>
<configuration>
<port>8080</port>
<path>/webdemo</path>
</configuration>
</plugin>
</plugins>
</build>
配置插件仓库
<pluginRepositories>
<pluginRepository>
<id>tomcat8-maven-plugin</id>
<url>https://repo2.maven.org/maven2/org/apache/tomcat/</url>
<!-- https://repository.apache.org/content/repositories/snapshots/org/apache/tomcat/ -->
</pluginRepository>
</pluginRepositories>
-
以tomcat7插件启动工程: maven命令
tomcat7:run
即可启动 -
以tomcat8插件启动工程时, 应当使用
tomcat8:run-war
命令启动tomcat8的插件存在一些问题,
tomcat8:run
启动工程访问页面会报500
maven配置文件
maven配置文件位置:
常见配置文件修改:
// 修改本地仓库位置:
<localRepository>D:\software\maven\apache-maven-3.6.0\repository</localRepository>
// 添加阿里云镜像。
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
IDEA中maven的常见设置:
注:每个新建项目中maven都需要设置一次。因为idea中默认idea自带的maven。