Maven工具使用
一、Maven的简介
管理java项目的工具,经常配合大项目进行使用。maven通过本地仓库来存储jar包,使得每一个maven项目(java项目)的大小大大缩减,当maven项目需要使用到jar包的时候,通过坐标来获取到本地仓库中的jar包。并且可以通过配置本地仓库索引来加快查询速率。
Maven的好处:
- 依赖管理:对jar包的统一管理
- 一键构建:在dos系统下通过命令运行maven项目
- 可以跨平台
- 应用于大型项目,进行分模块开发,将其他模块打包成jar包进行管理和使用
二、安装配置
为了使能够在dos系统中通过命令运行maven项目,需要下载maven软件,下载maven软件的网址:http://maven.apache.org/download.cgi
下载最新版本的maven,apache-maven-3.6.3-bin.zip
下载完之后直接解压:
- bin:用于存放命令文件,一个是正常执行的命令,一个是用于调式的命令
- boot:用于存放类加载器
- conf:用于存放maven配置文件,其中settings.xml是maven的核心配置文件
- lib:用于存放maven软件的相关jar包
接下来进行maven环境变量的配置:
- maven是基于java语言开发的,需要配置jdk,maven3.3以上的版本需要1.7以上版本jdk
- 配置maven环境变量
在本机系统上找到配置环境变量的位置:
新建一个系统变量,名为MAVEN_HOME,值为maven包解压的路径:
然后再将MAVEN_HOME添加到系统变量的Path中:
进入dos系统,输入mvn -v,如果出现如下画面即说明配置成功:
三、配置三种仓库
当运用dos系统进入到某一个maven项目里之后,使用命令mvn tomcat:run来运行maven项目的时候,需要使用到仓库repository,如果没有配置maven的仓库的话,使用的是默认仓库,其位置在本机C盘登录用户的.m2文件夹中,若是第一次使用该命令的话,则还会自动从网络上下载仓库至上述目录中,不过下载的仓库只会包含一下基本的jar包。
(一)本地仓库
配置仓库的话,我们可以将平常所需使用的jar包存放到默认仓库的位置中去,也可以手动配置其他的路径,用作maven的仓库,即配置本地仓库。
配置本地仓库的话,则需要通过上述所说的maven主要的配置文件setting.xml来配置。
打开setting.xml,可以看到很多注释的标签,其中有一个localRepository标签,通过这个标签我们就能自己手动配置仓库了。
将localRepository的注释符去掉之后,手动将本地仓库即自己想配置的仓库的位置填上去即可。
<localRepository>G:\笔记\repository</localRepository>
只要本地仓库中存在运行maven项目所需要的jar包,配置完之后即可运行。
(二)远程仓库
远程仓库又称为私服,在运行maven项目的时候,如果需要的jar包在本地仓库中找不到的话,需要从远程仓库中查找并下载到本地仓库中使用,这需要手动搭建配置。一般私服都由公司内部来搭建。
(三)中央仓库
当运行maven项目所需要的jar包在本地仓库又查找不到,且公司内部没有搭建远程仓库或者所需要的jar包在远程仓库查找不到的话,就会向中央仓库查找并下载,即通过互联网去下载所需要的jar包。中央仓库是由maven团队来维护的。
四、Maven项目介绍
(一)Maven项目的目录结构
- src:每一个maven项目都有一个src目录,用于存放源码
- pom.xml:maven项目的核心文件
- main:主目录
- test:测试目录
- main下的java:存放java文件
- main下的resources:存放相关配置文件,如properties文件,xml文件
- test下的java:存放java文件,junit测试文件
- test下的resources:存放相关配置文件,一般不放东西,如果为空的话,需要配置文件的话默认从main下的resources包下找。
(二)maven的常用命令
以下命令都在dos系统下使用,需要进入到相应的maven文件并加上前缀mvn
- clean:清理maven项目编译好所生成的文件,即编译后生成的target目录
- compile:编译main目录下的文件
- test:编译main跟test目录下的文件,并运行test目录下的文件
- package:将maven项目打包
- install:把项目发布到本地仓库
- site:生成项目的站点文档(静态页面),即对maven项目的相关内容作出解释的文档
- tomcat:run:一键启动
(三)maven的生命周期
maven包含三个生命周期:
- Clean生命周期:在这个阶段比较重要的命令是clean
- Default生命周期:在这个阶段比较重要的命令是:compile,test,package,install,deploy(将项目发布到私服)
- Site生命周期:在这个阶段比较重要的命令是site
不同的生命周期的命令可以同时执行
五、项目构建
(一)eclipse下的maven环境配置
在eclipse上构建maven项目,需要安装M2e插件,但是现在目前版本的eclipse大多都集成了Maven,不需要我们去手动安装M2e插件了,如果使用的eclipse版本比较低,需要更新版本或者手动安装。
安装或者更新了版本的eclipse,通过Preferences可以看到一个Maven选项。
点击Installations,可以发现默认版本并不是最新的
这里我们需要手动将从官网下载来的maven添加进去并勾选上
然后点击User Settings,可以发现给定了settings.xml文件的位置,我们将其修改为我们的settings.xml文件的位置
更改完之后,下面默认的本地仓库路径也会随之改变
这样的话,maven在eclipse的环境就配置完成了。
(二)Maven项目书写
- 新建一个Maven Project,可勾选是否跳过骨架,不勾选的话需要手动创建某一些目录,如resources。一般都勾选。
如果不勾选跳过的话,需要自己手动选择创建何种项目供maven管理,不勾选的好处在于可以选择自己构建的一个maven骨架,这样在频繁构建类似项目的时候就可以使用自己所创建的骨架,这里我们没有所以仍然是勾选上。
勾选之后点击next后会看到如下界面:
其中Group Id、Artifact Id、Version称为项目的坐标,别人如果需要使用到该项目,则通过坐标来寻找。
- Group Id:组的名称,经常为公司名称或者组织名称
- Artifact Id:模块名称或者称为项目名称
- Version:版本,默认只有一个,SNAPSHOT是快照的意思,即创建出来的为非正式版本。正式版为RELEASE。
- Packaging:打包方式,如果选择的是jar,默认创建出来的工程就是java工程,如果选择的是pom,创建出来的是一个父工程,如果选择的是war包,那就是web工程。
- Name&Description:对项目的描述,作用不大
- Parent Project:父工程,没有的话父工程那一块的坐标不用填写
点击finish,完成创建工程
2. 完成项目创建之后,我们发现编译的版本是1.5的,而jdk现在的版本是1.8,所以我们在pom.xml添加一下代码至project标签内。修改编译版本。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
修改完pom.xml文件之后,右键Maven项目选择Maven选项卡下的Update Project更新以下项目。
-
到项目的属性中的Maven选项卡下的Project Facets中勾选Dynamic Web Module,将版本改为2.5,并将Java版本改成1.8。点击应用之后,可以看到项目下多出了一个WebContent
-
在项目的src/main/java下创建Servlet
-
将上一步生成的WebContent目录下的两个文件夹都复制到src/main/webapp中
-
创建完Servlet之后会发现存在错误,是因为没有添加jar包,因此这一步就需要添加jar包,往pom.xml添加如下代码,将jsp包、servlet包引用进来:
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
添加完会发现jar包已经被添加进来,项目也不报错了
- 运行Maven项目,右键项目Run as,选择Maven build…,在Goals处输入tomcat:run,然后点击运行,将其发布到服务器上。
- 在浏览器输入localhost:8080/helloworld/HelloServlet,得到如下页面,说明项目发布成功。
六、依赖管理
(一)添加依赖包
在上面我们展示的是向pom.xml文件中手动插入代码来添加依赖包,但是这种方式并不好记忆。还有以下其他几种添加依赖包的方式。
- 右键pom.xml选择Maven选项卡下的Add Dependency
- 在pom.xml的Dependencies视图下添加依赖包
点击添加之后会出现如下界面:
要查找相关的包需要我们给包创建索引,先通过视图选项卡将Maven仓库视图打开。
右键Local Repository - Rebuild Index,点击确定,完成添加本地仓库包的索引。
这个时候再回到刚刚添加依赖包的界面,往里输入所需要的包,会看到界面上会显示搜索到的结果供我们选择。
点击确定之后就会自动在pom.xml中生成相应的代码。
(二)配置tomcat
web项目一般都涉及到jsp页面,jdk1.8版本编译jsp页面部署到服务器上且通过浏览器能够访问需要tomcat7,而Maven默认使用的是tomcat6,因此我们需要到pom.xml中配置tomcat的版本。在pom.xml中添加如下代码:
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
或者通过右键Maven-Add Plugin,搜索tomcat去添加tomcat7
并且运行Maven项目的时候使用tomcat7:run命令运行,这样的话jsp页面就能正常运行且访问了。
如果还想要修改tomcat的某一些配置的话,可以在plugin标签内通过configuration标签去做修改,比如修改端口号,访问路径等。
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8888</port>
<path>/maven</path>
</configuration>
</plugin>
这样的话运行maven项目后,可以通过localhost:8888/maven/…来访问。
(三)依赖范围
上面在添加依赖包的时候,还有一个可选项那就是Scope,也就是依赖范围,分别有compile,provided,runtime,test,system。
- compile:默认,使用各种命令时都需要用到此包
- provided:表示编译时,测试时需要用到此包,运行时、打包时不需要用到此包
- runtime:表示编译时不需要,测试时需要,运行时不需要,打包时需要此包
- test:表示编译时不需要,测试时需要此包,运行时、打包时不需要此包
- system
(四)查找坐标
添加依赖的时候常用的是重建索引的方法,重建索引之后添加jar包就方便的多,但是这种方式只适用于本地仓库中存在的包。如果不存在的话,那我们在添加依赖的时候需要指定依赖jar包的坐标,但很多时候我们并不知道jar包的坐标,此时通过网站https://mvnrepository.com或https://search.maven.org/来查询。
以第一个网址为例,搜索Spring,就会显示Spring相关的所有jar包。
点击想要使用的包,选择所需要的版本
即可在下方查看到相关的依赖代码,将这段代码放进pom.xml,就完成了添加依赖包,如果本地仓库、远程仓库都没有该包的话,会自动从中央仓库中下载到本地仓库。
(五)依赖冲突
- 当添加某一个依赖jar包的时候,这个jar包所依赖的jar包也会被自动添加进来,称为依赖传递。
- 当添加多个包且这几个包都依赖于不同版本的同名包的时候,就会形成冲突,称为依赖冲突。解决冲突依赖有以下四种方法。
(1)第一声明者原则
形成依赖冲突后依赖包的版本会以第一个出现的依赖包为准,也就是添加进来的依赖包版本是按照第一个出现的依赖包为准的(第一声明者原则)。即当发生依赖冲突的时候,我们使用的包的依赖包的版本可能并不是我们希望使用的。
这个时候我们可以将依赖于我们所需要的版本的依赖包的包放在第一个添加的位置,就可以解决依赖冲突的问题了,称为第一声明者原则。
(2)路径近者优先原则
当形成依赖冲突我们可以通过手动添加这个依赖包(路径近者优先原则),选择我们想要使用的版本来解决依赖冲突,称为路径近者优先原则。第一声明者原则和路径近者优先原则统称为调节原则。
(3)排除原则
排除原则是通过代码来将添加进来的包的某一个或几个依赖包排除,以达到使用其他的版本的依赖包的目的,这也可以解决依赖冲突。即在pom.xml中添加jar包的位置也就是在dependency标签中添加一个exclusions,在exclusions标签下能够配置多个exclusion标签,用来排除多个依赖包,在exclusion标签下配置依赖包的groupId、artifactId。
<exclusions>
<exclusion>
<groupId></groupId>
<artifactId></artifactId>
</exclusion>
</exclusions>
(4)版本锁定
当知道所添加的包有多个依赖于同名包的时候,我们可以提前设置我们所需要的版本,当依赖包的版本跟我们设置是一样的话,我们才会允许这个依赖包添加进来,否则会将不会允许我们添加进来的包的不符合我们设置的依赖包添加进来。这通过代码来实现,在pom.xml文件project标签下使用以下代码,同样的,填写我们想要锁定的包的groupId,artifactId,version等信息。
<dependencyManagement>
<dependencies>
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
</dependency>
</dependencies>
</dependencyManagement>
(六)配置变量
在进行版本锁定或配置其他东西的时候可能会常常使用到某一个相同的值,当需要修改这个值的时候就会比较麻烦,所以我们可以在pom.xml中配置一个变量。在project标签下配置一个properties标签,properties标签下的标签由我们自定义,可以认为是变量名,配置了变量之后,当需要使用的时候通过${变量名}来使用。
<!-- hh为变量名,标签内为变量值 -->
<properties>
<hh>junit</hh>
</properties>
<dependencies>
<dependency>
<groupId>${hh}</groupId>
<artifactId>${hh}</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>
七、分模块开发
(一)父工程与子模块
开发项目的时候经常需要分模块开发,分模块开发需要同属于一个工程,因此需要创建父工程供其他模块来继承。
新建一个父工程:
父工程内部目录十分简单,只需将各模块所依赖的jar包添加进来,然后供各模块继承即可,涉及项目之间的继承。父工程配置好之后,需要打包发布到本地仓库上。也就是右键父工程,Run as - Maven build…,利用install命令运行。
将所需要依赖的jar包添加进父工程的pom.xml中之后,开始新建子模块。
新建一个Maven Module
输入子模块名称,选择需要继承的父工程的名称:
点击next,Group Id 不需要更改,Packaging方式选择jar(如果是dao、service模块的话就选择jar,如果是web模块的话就选择war):
建完之后可以发现父工程内出现了一个以子模块名为名字的目录,且pom.xml中会自动增加一个module标签,而子模块的pom.xml文件中也会包含父工程的一些信息,不过子模块的pom.xml中不会出现父工程的pom.xml中的依赖包的代码,但是会继承父工程中的包。即双方之间产生了连接关系,父工程的配置都会在子工程中显示出来。
父工程的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.f</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 省略各种依赖包的添加。。。 -->
<modules>
<module>son</module>
</modules>
</project>
子模块的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>
<parent>
<groupId>com.f</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>son</artifactId>
</project>
当有多个子模块的时候,各个子模块所使用的配置文件可能会重复,比如Spring的配置文件applicationContext.xml,这个时候需要将配置文件名稍微做一下修改,并且保留这个模块所需要用到的配置文件中的内容,否则可能会发生冲突,且在配置这些重复用到的配置文件的路径时需要一起配置进来。如使用注解或者在web.xml中配置applicationContext.xml的路径时需要配置为classpath*:applicationContext-*.xml,第一个星号代表可从jar包中拿到以applicationContext-为前缀的配置文件。
各个模块编写完之后,可以通过运行web模块或者父工程来运行整个项目。
(二)子模块之间的依赖关系
有的时候,各个子模块之间还有可能会存在着依赖关系,这个时候就需要在子模块的pom.xml中将所需要依赖的模块添加为依赖包。添加为依赖包前要先将所需要依赖的模块发布到本地仓库中,这也是为什么前面新建模块时选择Packaging为jar的原因。
将某个模块作为依赖包之后,代码其实跟普通包是一样的。
子模块son2的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>
<parent>
<groupId>com.f</groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>son2</artifactId>
<dependencies>
<dependency>
<groupId>com.f</groupId>
<artifactId>son</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
(三)依赖范围对项目间的依赖传递的影响
项目间的依赖传递就是将某一个项目打包成jar包发布到仓库之后,然后让其他项目依赖于这个jar包。依赖于这个jar包的项目会继承这个jar包所依赖的其他jar包。
当给项目添加依赖包的时候,我们可以选择这个依赖包的依赖范围,不同的依赖范围对项目间的依赖传递会有不同的影响。通过不同的依赖范围,依赖包并不一定是一直传递下去的。
那么如何判断依赖范围对项目间的依赖传递的影响呢?
这里有一个表格,第一列表示直接依赖,表示项目直接依赖的包的依赖范围,第一行表示传递依赖,表示你依赖包的依赖包的依赖范围,它们之间的交叉代表依赖传递过来的包的依赖范围,-代表的是不传递。
compile | provided | runtime | test | |
---|---|---|---|---|
compile | compile | - | compile | - |
provided | provided | provided | provided | - |
runtime | runtime | - | runtime | - |
test | test | - | test | - |
由于依赖范围造成我们所需要依赖的包传递不过来的话,我们可以手动进行添加依赖包到本项目中去。一般不去修改其他模块。
八、私服nexus
(一)搭建私服
搭建私服需要下载压缩包
网上都可以下载,下载到这个压缩包之后,直接解压
- bin目录下放的是相关命令
- conf目录下放的是配置文件,可以通过配置文件查看私服访问地址
- lib目录放相关的jar包
- logs目录放日志文件,可查看错误信息
- nexus放B/S结构的一些相关文件,图标、图片之类
- tmp放临时文件
软件的安装过程,通过dos系统下进到nexus的bin目录下,利用命令nexus.bat install 进行安装,注意要通过管理员身份运行,否则可能安装不了:
然后通过nexus.bat start启动私服
启动之后就可以通过浏览器访问了,由于是在本地主机搭建私服,所以访问路径为localhost:8081/nexus
需要通过用户名和密码才能登录,默认的用户名为admin,密码为admin123。
点击Repositories可以看到多种仓库类型:
- virtual:虚拟仓库,如上面的Central M1 shadow
- proxy:代理仓库
- hosted:宿主仓库、本地仓库
- group:组仓库,包含多个仓库,相当于上面的仓库的集合,可在组中设置多个仓库
(二)将项目发布到私服上
- 先在项目的pom.xml中project标签下添加以下代码,snapshot版本用的仓库,不同版本发布的仓库名不一样:
<distributionManagement>
<!-- release版本项目发布的仓库,可同时配置多个仓库 -->
<!--<repository>
<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>
- 到maven核心配置文件settings.xml配置用户名密码,可配置多个,需要发布到哪个仓库,就需要配置哪个仓库的用户名跟密码
<servers>
<!--<server>
<id>releases</id>
<username>admin</username>
<password>admin123</password>
</server>-->
<server>
<id>snapshots</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>
- 右键Run as - Maven build…,使用命令deploy发布到私服上。发布成功后通过浏览器访问私服可以看到我们刚发布的项目。点击snapshot右边的网址,可以看到我们发布上去的项目。
(三)从私服上下载
- 到settings.xml中添加以下代码:
<profiles>
<profile>
<!--profile的id-->
<id>dev</id>
<repositories>
<repository>
<!--仓库id,repositories可以配置多个仓库,保证id不重复-->
<id>nexus</id>
<!--仓库地址,即nexus仓库组的地址-->
<url>http://localhost:8081/nexus/content/groups/public/</url>
<!--是否下载releases构件-->
<releases>
<enabled>true</enabled>
</releases>
<!--是否下载snapshots构件-->
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<!-- 插件仓库,maven的运行依赖插件,也需要从私服下载插件 -->
<pluginRepository>
<!-- 插件仓库的id不允许重复,如果重复后边配置会覆盖前边 -->
<id>public</id>
<name>Public Repositories</name>
<url>http://localhost:8081/nexus/content/groups/public/</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>dev</activeProfile>
</activeProfiles>
- 这样的话,需要的依赖包如果本地仓库没有的话就会到私服上自动下载到本地仓库中。