Maven的作用
1.什么是maven
- maven的本质是一个项目架构管理工具,将项目开发和管理过程抽象成一个项目对象模型(POM)。
2.有哪些作用
- **依赖导入:**方便导入java类依赖的jar包
- **尽量避免jar之间的依赖和冲突:**以pom.xml文件中dependency属性管理依赖的jar包,小组之间建立个私服,大家都用通用的maven配置文件,可以避免相同的包重复导入
- **冲突时方便排包:**mvn dependency:tree -Dverbose命令,可以更直观的看出jar包依赖关系
- **项目构建、打包:**Maven是基于项目对象模型,可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。Maven能够很方便的帮你管理项目报告,生成站点,管理jar文件,等等。
3.Maven核心思想:约定大于配置
- 有约束,不要去违反
- Maven会规定好你应该如何去编写我们的java代码,必须按照这个规范来
Maven仓库分类
-
本地仓库,顾名思义,就是Maven在本地存储的地方,maven的本地仓库,在安装maven后并不会创建,它是在第一次执行maven命令的时候才被创建。**maven本地仓库的默认位置:**无论是Windows还是Linux,在用户的目录下都有一个.m2/repository/的仓库目录,这就是Maven仓库的默认位置。
-
远程仓库
-
中央仓库:最核心的是中央仓库,中央仓库是默认的远程仓库,maven在安装的时候,自带的就是中央仓库的配置,可以通过修改setting.xml文件来修改默认的中央仓库地址。中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载到;默认的,不需要显式的配置settings.xml
<repositories> <repository> <id>central</id> <name>Central Repository</name> <url>http://repo.maven.apache.org/maven2</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
-
私服
配置settings.xml
<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> <mirrors>
- 其他公共仓库
-
Maven目录结构
* src
* main
* java -java源代码文件
* resources -资源库
* webapp
* WEB-INF
* index.jsp
* Css、js
* Bin - 脚本库
* config - 配置文件
* Filters - 资源过滤库
* test
* java -java测试源代码文件
* resources - 测试资源库
* filters - 测试资源过滤库
* target - 存放项目构建后的文件和目录,比如jar包,war包,编译的class文件等
Maven核心pom文件
1.什么是pom
- **pom代表项目对象模型,它是Maven中工作的基本组成单位。**它是一个XML文件,始终保存在项目的基本目录中。pom包含的对象是使用maven来构建的,pom.xml文件包含了项目的各种配置信息,需要特别注意,每个项目都只有一个pom.xml文件。
2.项目配置信息
- **project**:工程的根标签
- **modelVersion**:pom模型版本,maven2和3只能为4.0.0
- **groupId**:这是工程组的标识。它在一个组织或者项目中通常是唯一的。例如,一个银行组织 com.companyname.project-group 拥有所有的和银行相关的项目。
- **artifactId**:这是工程的标识。它通常是工程的名称。例如,消费者银行。groupId 和 artifactId 一起定义了 artifact 在仓库中的位置
- **version**:这是工程的版本号。在 artifact 的仓库中,它用来区分不同的版本
- **packaging**:定义 Maven 项目的打包方式,有 JAR 、WAR 和 EAR 三种格式
jar:java应用
war:javaweb应用
3.super pom
父(Super)POM是 Maven 默认的 POM。所有的 POM 都继承自一个父 POM(无论是否显式定义了这个父 POM)。父 POM 包含了一些可以被继承的默认设置。因此,当 Maven 发现需要下载 POM 中的 依赖时,它会到 Super POM 中配置的默认仓库 。使用以下命令来查看 Super POM 默认配置:mvn help:effective-pom
4.依赖配置信息
- dependencies
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
- parent
<parent>
<groupId>xd.class<groupId>
<artifactId>demo-parent</artifactId>
<relativePath>/</relativePath>
<version>1.0</version>
</parent>
- groupId: 父项目的组Id标识符
- artifactId:父项目的唯一标识符
- relativePath:Maven首先在当前项目中找父项目的pom,然后在文件系统的这个位置 (relativePath),然后在本地仓库,再在远程仓库找。
- version: 父项目的版本
- modules
有些maven项目会做成多模块的,这个标签用于指定当前项目所包含的所有模块。之后对这个项目进行的maven操作,会让所有子模块也进行相同操作。
<modules>
<module>com-a</module>
<module>com-b</module>
<module>com-c</module>
</modules>
- **properties:**用于定义pom常量
<properties>
<java.version>1.7</java.version>
</properties>
上面这个常量可以在pom文件的任意地方通过${java.version}来引用
- dependencyManagement
-
作用:预定义依赖项的version,scope与exclusions,子项目中只需定义groupId和artifactId 即可
-
应用场景:当我们的项目模块很多的时候,我们依赖包的管理就会出现很多问题,为了项目的正确运行,必须让所有的子项目使用依赖项的同一版本,确保应用的各个项目的依赖项和版本一致,才能保证测试的和发布的是相同的结果。
-
使用的好处:在父模块中定义后,子模块不会直接使用对应依赖,但是在使用相同依赖的时候可以不加版本号,这样的好处是,可以避免在每个使用的子项目中都声明一个版本号,这样想升级或者切换到另一个版本时,只需要在父类容器里更新,不需要任何一个子项目的修改
-
和dependencies的区别:
dependencies:即在父项目中用dependencies声明后,在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项,全部继承
dependencyManagement:里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
举例:
父项目:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
子项目1:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
子项目2:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
子项目3:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>5.0</version>
</dependency>
Maven生命周期
1.什么是生命周期
- Maven的生命周期就是对所有的构建过程进行抽象和统一。包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等几乎所有的构建步骤。
2.maven的三个构建生命周期
-
clean:
- pre-clean 执行一些清理前需要完成的工作
- clean 清理上一次构建生成的文件
- post-clean 执行一些清理后需要完成的工作
-
default
- validate:验证工程是否正确(编译的时候)
- compile:编译项目的源代码
- test:使用合适的单元测试框架来测试已编译的源代码。
- package:把已编译的代码打包成可以发布的格式,比如jar或者war
- verify:运行所有检查,验证包是否有效
- install:安装到maven本地仓库
- deploy:部署到远程的仓库,使得其他开发者或者工程可以共享
-
Site
- 站点的生成
常用的maven基本命令
1.常用命令
- mvn validate 验证项目是否正确
- mvn package maven打包(只是打包,不会放到本地库中)
- mvn generate-sources 生成源代码(比如我们依赖的一个第三方的jar包,可以将它的源码下载下来)
- mvn compile 编译
- mvn test-compile 编译测试代码
- mvn test 运行测试
- mvn verify 运行检查
- mvn clean 清理项目
- mvn install 安装项目到本地仓库(打包,并放到本地库中)
- mvn deploy 发布项目到远程仓库
- mvn dependency:tree 显示Maven依赖树
- mvn dependency:list 显示Maven依赖列表
2.常用参数
- -D 指定参数,如 -Dmaven.test.skip=true 跳过单元测试;
- -P 指定 Profile 配置,可以用于区分环境;
3.web相关命令
- mvn tomcat:run 启动tomcat
- mvn jetty:run 启动jetty
- mvn tomcat:deploy 运行打包部署
4.如何导入第三方jar包到本地仓库
-
输入指令如下:
mvn install:install-file -Dfile=xxxxxx -DgroupId=com.alibaba -DartifactId=fastjson -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true
实例:
mvn install:install-file -Dfile=E:\document\TheThridParty\fastjson-1.2.76.jar -DgroupId=com.alibaba -DartifactId=fastjson -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true -DcreateChencksum=true
- -Dfile:第三方jar文件存放路径
- -DgroupId:一般为jar开发的组织名称,也是坐标groupId
- -DartifactId:一般为jar名称,也是坐标artifactId
- -Dversion:版本号(我们自定义的)
- -Dpackaging:打包类型
搭建你的第一个maven私人服务器
1.简介
私服是在局域网的一种特殊的远程仓库,目的是代理远程仓库及部署第三方构件。有了私服之后,当 Maven 需要下载jar包时,先请求私服,私服上如果存在则下载到本地仓库。否则,私服直接请求外部的远程仓库,将jar包下载到私服,再提供给本地仓库下载。
2.安装
我们可以使用专门的 Maven 仓库管理软件来搭建私服,这里我们使用Nexus;
下载地址:https://help.sonatype.com/repomanager2/download
Nexus 专业版是需要付费的,这里我们下载开源版 Nexus OSS,最新的是OSS3.x,我们选择稳定的版本2.x。
3.启动
- 以管理员身份打开cmd,进入到bin目录,先执行nexus install命令,再执行nexus start。
- 打开浏览器,访问http://localhost:8081/nexus
- 点击右上角Log in,使用用户名:admin,密码:admin123登录
4.Nexus私服的秘密花园
-
简介:介绍nexus服务器预置的仓库 – 类型
- hosted:是本地仓库,用户可以把自己的一些jar包,发布到hosted中,比如公司的第二方库
- proxy:代理仓库,它们被用来代理远程的公共仓库,如maven中央仓库。不允许用户自己上传jar包,只能从中央仓库下载
- group:仓库组,用来合并多个hosted/proxy仓库,当你的项目希望在多个repository使用资源时就不需要多次引用了,只需要引用一个group即可
- virtual:虚拟仓库基本废弃了。
-
介绍nexus服务器预置的仓库 – 策略
- Releases:用来部署正式发布版本构件
- Snapshots:用来部署开发版本构件。
-
介绍nexus服务器预置的仓库 – 预置仓库
- Central:该仓库代理Maven中央仓库,其策略为Release,因此只会下载和缓存中央仓库中的发布版本构件。
- 3rd party:这是一个策略为Release的宿主类型仓库,用来部署无法从maven中央仓库获得的第三方发布版本构件,比如IBM或者oracle的一些jar包(比如classe12.jar),由于受到商业版权的限制,不允许在中央仓库出现,如果想让这些包在私服上进行管理,就需要第三方的仓库。
- Public Repositories:一个组合仓库,用来管理其他仓库
5. 在nexus建立你的第一个仓库
- 建库,Add-- >Hosted Repository
- 填写仓库信息
- Respository ID 仓库编号
- Repository NAME 仓库名称
- Repository Type 仓库类型
- Repository Policy 仓库策略
- Default Local Storage Location 仓库路径
- Deployment Policy 发布策略(Allow Redeploy 允许发布)
- 然后选择Public Repositories,打开configuration选项卡,将自己创建的仓库添加到group
6.在项maven目中使用Nexus
- 配置settings.xml
<!-- 配置镜像-->
<mirrors>
<mirror>
<id>nexusMirror</id>
<mirrorOf>*</mirrorOf><!-- 指定从哪些仓库中引入*表示所有;*,!r1表示除了r1库之外的任何远程库-->
<name>local nexus</name>
<!-- 这里的ULR是nexus中Public Repositories的地址,因为我们已经将'xdclass'
加到public组里面,所以只要引入public就相当于把'xdclass'仓库也引入进来了-->
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<!-- 配置profile-->
<!-- profile简介:profile可以让我们定义一系列的配置信息,然后指定其激活条件。这样我们就可以定义多个profile,然后每个profile对应不同的激活条件和配置信息,从而达到不同环境使用不同配置信息的效果。-->
<profiles>
<profile>
<id>xd</id> <!-- id自定义,尽量与环境配置、业务场景或仓库相关的-->
<repositories> <!-- 远程仓库列表-->
<!-- 指定从哪个仓库加载 -->
<repository>
<id>local-nexus</id> <!-- id自定义-->
<url>http://localhost:8081/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled> <!-- 仓库属于releases策略-->
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
<!-- 激活profile-->
<activeProfiles>
<activeProfile>xd</activeProfile> <!-- 这里的id与profile下的id一致-->
</activeProfiles>
7.如何将项目发布到maven私服
- 配置mvn的配置文件:settings.xml,引入Nexus相关配置
<!-- 配置服务的验证:授权信息-->
<servers>
<server>
<id>xdclass</id> <!-- 这里的id是在nexus里面创建的仓库的ID-->
<username>admin</username>
<password>admin123</password>
</server>
</servers>
- 配置项目中的pom文件,指定要上传到那个仓库
<!-- 这个配置可以直接在nexus前端页面中选中对应要上传的仓库,然后再选择Summary,直接复制过来-->
<distributionManagement>
<repository>
<id>xdclass</id> <!-- id要和settings.xml中server的id一样 -->
<url>http://localhost:8081/nexus/content/repositories/xdclass</url>
</repository>
</distributionManagement>
- 执行命令,打包上传
- mvn clean 清理
- mvn package 打包(需要注意版本号,如果是Releases策略则版本号不能带有SNAPSHOT)
- mvn deploy 上传
8.将第三方jar包上传到Nexus
-
通过页操作添加
- 选择要目标仓库,选择Artifact Upload,填写相关信息,点击上传
-
通过命令上传
mvn deploy:deploy-file -DgroupId=com.alibaba -DartifactId=fastjson -Dversion=1.0 -Dpackaging=jar -Dfile=E:\document\TheThridParty\fastjson-1.2.76.jar -Durl=http://localhost:8081/nexus/content/repositories/xdclass -DrepositoryId=xdclass
mvn deploy:deploy-file
-DgroupId=xxxxxx 就相当于pom中的groupId
-DartifactId=xxxxxx 就相当于pom中的artifactId
-Dversion=xxxxxx 就相当于pom中的版本号version
-Dpackaging=xxxxxx 就相当于pom中打包方式
-Dfile=xxxxxx 本地环境
-Durl=xxxxxx 上传的url
-DrepositoryId=xxxxxx 对应的是setting.xml 里边server的id
9.Maven snapshot的秘密
-
产生背景:假设一个团队工作,其中有个项目叫做data-use,同时他们使用数据服务工程(data-service.jar:1.0)。现在负责数据服务的团队可能正在进行修 bug 或者更新迭代,每次发布都会发布工程到远程仓库中。现在如果数据服务团队每天上传新的版本,那么就会有下面的问题:1. 每次数据服务团队发布了一版更新的代码时,都要告诉应用接口团队。应用接口团队需要定期更新他们的 pom.xml 来得到更新的版本
-
什么是快照:快照是一个特殊的版本,它表示当前开发的一个副本。与常规版本不同,Maven 为每一次构建从远程仓库中检出一份新的快照版本。
-
快照 vs 版本:
-
对于版本,Maven 一旦下载了指定的版本(例如 data-service:1.0),它将不会尝试从仓库里再次下载一个新的 1.0 版本。想要下载新的代码,数据服务版本需要被升级到 1.1。
-
对于快照,每次用户接口团队构建他们的项目时,Maven 将自动获取最新的快照(data-service:1.0-SNAPSHOT)。
-
-
上传快照:
- 配置pom(上传与使用与常规版本一样)
<distributionManagement> <snapshotRepository> <id>xdclass_snapshot</id> <url>http://localhost:8081/nexus/content/repositories/xdclass_snapshot</url> </snapshotRepository> </distributionManagement>
-
maven快照延伸:
- settings.xml配置中的updateProlicy
<profiles> <profile> <id>xd</id> <repositories> <repository> <id>local-nexus</id><url>http://localhost:8081/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> <updatePolicy>always</updatePolicy> </snapshots> </repository> </repositories> </profile> </profiles> - always 每次都去远程仓库查看是否有更新 - daily 每天第一次的时候查看是否有更新 - interval 允许设置一个分钟为单位的间隔时间,在这个间隔时间内只会去远程仓库中查找一次 - never 从不会
maven的依赖管理
1.简介:
依赖是maven最为用户熟知的特性之一,单个项目的依赖管理并不难,但是要管理几个或者几十个模块的时,那这个依赖应该怎么管理。
- 依赖的传递性:传递性依赖是在maven2中添加的新特征,这个特征的作用就是你不需要考虑你依赖的库文件所需要依赖的库文件,能够将依赖模块的依赖自动的引入。
- 依赖的作用范围
compile:这是默认范围,编译依赖对项目所有的classpath都可用。此外,编译依赖会传递到依赖的项目
provided:表示该依赖项将由JDK或者运行容器在运行时提供,也就是说由Maven提供的该依赖项我们只有在编译和测试时才会用到,而在运行时将由JDK或者运行容器提供。
runtime:表明编译时不需要依赖,而只在运行时依赖
test:只在编译测试代码和运行测试的时候需要,应用的正常运行不需要此类依赖。
system:系统范围与provided类似,不过你必须显式指定一个本地系统路径的JAR,此类依赖应该一直有效,Maven也不会去仓库中寻找它。
<project>
...
<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>1.5.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
...
</project>
import:范围只适用于<dependencyManagement>部分。表明指定的POM必须使用<dependencyManagement>部分的依赖。因为依赖已经被替换,所以使用import范围的依赖并不影响依赖传递。
-
依赖的两大原则
-
路径近者优先
A > B > C-1.0
A > C-2.0 此时A依赖C2.0的版本 -
第一声明优先
A > B > D-1.0
A > C > D-2.0 此时A依赖于D-1.0版本
-
-
依赖的管理
- 依赖排除:任何可传递的依赖都可以通过 “exclusion” 元素被排除在外。举例说明,A 依赖 B, B 依赖 C,因此 A 可以标记 C 为 “被排除的”
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> <exclusions> <exclusion> <groupId>xxxxx</groupId> <artifactId>>xxxxxxxx</artifactId> </exclusion> </exclusions> </dependency>
- 依赖可选:任何可传递的依赖可以被标记为可选的,通过使用 “optional” 元素。例如:A 依赖 B, B 依赖 C。因此,B 可以标记 C 为可选的, 这样 A 就可以不再使用 C。
<dependency>
<groupId>xxxxx</groupId>
<artifactId>xxxxxxxxxxx</artifactId>
<version>5.1.5</version>
<optional>true</optional>
</dependency>
如何解决jar包冲突
命令: mvn dependency:tree -Dverbose
-Dverbose参数:显示最全的依赖树关系