聚合和继承
分布式开发必须要用
聚合模块(父模块)的打包方式必须为pom,否则无法完成构建
父模块里面一般不写代码。
父模块的packaging必须是pom

新建子模块

新建完子模块过后父模块的pom.xml多了一个东西

我们的maven-test就叫聚合模块或者说父模块
child-one就叫子模块
子模块的pom.xml里面有parent标签

在聚合多个项目时,如果这些被聚合的项目中需要引入相同的jar,那么可以将这些jar写入父pom中,各个子项目继承该pom即可。父模块的打包方式必须为pom,否则无法构建项目
例:
在maven仓库里找jar包


引入依赖,点击刷新,就会自动帮我们去网上下载
此时就能使用这个jar包里面的类了(在父模块里写的依赖,子模块在使用)

通过在各个子模块中配置来表明其继承于那一个父模块
<parent>
<artifactId>maven-test</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>child-one</artifactId>
可以被继承的POM元素如下:
- groupId:项目组ID,项目坐标的核心元素
- version:项目版本,项目坐标的核心因素(上面的子模块里就已经没有子groupId和version标签了,直接从父模块里继承,父模块是哪个组织的,那子模块就是哪个组织的,父模块的版本是什么,子模块当前的版本就是什么)
- properties:自定义的Maven属性 ,一般用于统一指定各个依赖的版本号
- dependencies:项目的依赖配置,公共依赖
- dependencyMangement:项目的依赖管理配置
- repositories:项目的仓库配置
- build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
一些对项目的描述
- descripitions:项目的描述信息
- organization:项目的组织信息
- inceptionYear:项目的创始年份
- url:项目的URL地址
- developers:项目的开发信息
- contributors:项目的贡献者信息
- distributionManagement:项目的部署配置
- issueManagement:项目的缺陷跟踪系统信息
- ciManagement:项目的持续继承系统信息
- scm:项目的版本控制系统
- malilingLists:项目的邮件列表信息
- reporting:包括项目的报告输出目录配置、报告插件配置等
POM文件
1.基础配置
一个典型的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">
<!-- pom模型版本,maven2和3只能为4.0.0,现在是maven2唯一支持的版本,必须这么写-->
<modelVersion>4.0.0</modelVersion>
<!-- 项目的组ID,用于maven定位,公司或组织的唯一标志,并且配置时生成的路径也是由此生成,如com.sunj.maven会将该项目打包成的jar包放本地路径:/com/sunj/ -->
<groupId>com.sunj</groupId>
<!-- 本项目的唯一ID,一个groupId下面可能有多个项目,就是靠artifactId来区分的-->
<artifactId>test</artifactId>
<!-- 本项目目前的版本-->
<version>1.0</version>
<!-- 项目的打包方式,如pom,jar,war,默认为jar-->
<!-- 如果是聚合工程,也就是说父工程,我们就写pom-->
<packaging>war</packaging>
<!-- 为pom定义一些常量,在pom中的其他地方可以直接引用,使用方式 如下:${file.encoding}-->
<!--常常用来整体控制一些依赖的版本号-->
<properties>
<file.encoding>UTF-8</file.encoding>
<java.source.version>1.8</java.source.version>
<!--我们定义了java.source.version的值是1.8 相当于定义了静态常量,以后想要使用时,就直接花括号包住,前面加$-->
<java.target.version>1.8</java.target.version>
</properties>
<!--定义项目的依赖关系,就是依赖的jar包-->
<dependencies>
<!--每个dependency都对应这一个jar包-->
<denpendency>
<!--一般情况下,maven是通过groupId、artifactId、version这三个元素(俗称坐标)来检索该构建,然后引入你的工程。如果他想引用你现在开发的这个项目(前提是已经开发完毕并发布到了远程仓库),就需要在他的pom文件中新建一个dependency节点,将本项目的groupId、artifactId、version写入,maven就会把你上传的jar包下载到本地-->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!--依赖范围-->
<scope>compile</scope>
<!--设置依赖是否可选。默认为false,即子项目默认都继承,如果为true,则子项目必须显示的引入-->
<optional>false</optional>
<!--依赖排除-->
<exclutions>
<exclution>
<groupId>org.slf4j</groupId>
<arifactId>slf4j-api</arifactId>
</exclution>
</exclutions>
</denpendency>
</dependencies>
<project>
一般来说,上面几个配置项对任何项目都是必不可少的,定义了项目的基本属性(除了properties)。
除了dependencies我们还用到了denpendencyManagement,区别如下
dependencies
即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承在依赖项(全部继承)。
继承下来就会被编译,如果子项目根本不用这个依赖会增加子工程的负担。
dependencyManagement
通常会在父工程中定义,目的是统一各个子模块的依赖版本,有不用实际依赖
- 只是声明依赖,并不实现引入
- 子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;
只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目总继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
在父模块中定义后,子模块不会直接使用对应依赖,但是在使用相同依赖的时候可以不加版本号,这样的好处是,父项目统一了版本,而且子项目可以在需要的时候才引用对应的依赖。
2.构建配置
约定大于配置,有约定尽量按照约定来,没有约定我们就进行配置。
<build>
<!--产生的构建的文件名,默认是${artifactId}-${version}-->
<finalName>myProject</finalName>
<!--构建产生的所有文件的存放目录,默认为${basedir}/target-->
<directory>${basedir}/target</directory>
<!--诸如以上这些还有很多,这个配置都有默认值,约定好了就这么建,你要是实在看了不爽也能改-->
</build>
我们常用的几个配置
关于资源处理的配置
有些小伙伴就喜欢在src中填写配置文件,都加上就能保证你写在src底下的配置文件也能生效
<build>
<resources>
<!--这个元素描述了项目相关或测试相关的所有资源路径-->
<resource>
<!-- 描述了资源的目标路径。该路径相对target/classes目录(例如${project.build.outputDirectory})。举个例 子,如果你想资源在特定的包里(org.apache.maven.messages),你就必须该元素设置为org/apache/maven /messages。然而,如果你只是想把资源放到源码目录结构里,就不需要该配置。-->
<!--描述存放资源的目录,该路径相对POM路径-->
<directory>src/main/java</directory>/>
<targetPath/>
<!--是否使用参数值代替参数名。参数值取自properties元素或者文件里配置的属性,文件在filters元素里列出。-->
<filtering/>
<!--包含的模式列表,例如**/*.xml.-->
<includes/>
<!--排除的模式列表,例如**/*.xml-->
<excludes/>
</resource>
</resources>
</build>
添加本地jar包
本地jar包,如:支付宝jar包要放到src/main/webapp/WEB-INF/lib文件夹下,如果没有配置,本地没问题,但是线上会找不到sdk类,为什么要引入,因为支付宝的jar包在中央仓库没有
<!--geelynote maven的核心插件之一compiler插件默认只支持编译java 1.4,因此需要加上支持高版本jre的配置,在pom.xml里面加上-->
<!--这个插件能保证我们编译的jdk版本是1.8,不加这个插件就默认的是1.5,要用这个插件提高java的编译版本-->
<plugin>
<groupId>org.apache.pulgins</groupId>
<artifactId>maven-compiler-pulgin</artifactId>
<configuation>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<compilerArgumnts>
<extdirs>${project.basedir}/src/main/webapp/WEB-INF/lib</extdirs>
</compilerArgumnts>
</configuation>
</plugin>
3.仓库配置
aliyun镜像在我们的settings.xml里面配置了,在pom.xml里面也能配
pom里配是针对于你这个单独的工程,
settings是对全局的配置。
如果pom里面配了,然后这个工程拿到别人的电脑上执行,他仍然会区阿里云里下载依赖,因为pom里面配了。如果不放心别人的setting里面有没有配阿里云,就可以把自己的pom里面也配一下,万无一失
<repositories>
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
pom.xml里面的仓库与setting.xml里的仓库功能是一样的。主要区别在于,pom里的仓库是个性化的。比如,很多家大公司里面的setting文件时公用的,所有的项目都用一个setting文件,但各个子项目却会引用不同的第三方库,所以就需要在pom.xml里设置自己需要的仓库地址。
4.项目信息配置(知道就行)
name:给用户提供更为友好的项目名
description:项目描述,maven文档中保存
url:主页的URL,maven文档中保存
inceptionYear:项目创建年份,4位数字。当产生版权信息时需要使用这个值
licenses:该元素描述了项目所有License列表。 应该只列出该项目的-
license列表,不要列出依赖项目的 license列表。如果列出多个license,用户可以选择它们中的一个而不是接受所有license。(如下)
<license>
<!--license用于法律上的名称-->
<name>...</name>
<!--官方的license正文页面的URL-->
<url>....</url>
<!--项目分发的主要方式:repo,可以从Maven库下载 manual, 用户必须手动下载和安装依赖-->
<distribution>repo</distribution>
<!--关于license的补充信息-->
<comments>....</comments>
</license>
Maven仓库
任何构建都有唯一的坐标,Maven根据这个坐标定义了构建在仓库中的唯一存储路径,
Maven仓库分为两类:
-
本地仓库
-
远程仓库,远程仓库又分为3种:
中央仓库
私服
其他公共库
1、本地仓库
本地仓库是Maven在本地存储构建的地方。Maven的本地仓库,在安装maven后并不会创建,它是在第一次执行Maven命令的死后才被创建。
Maven本地仓库的默认位置:无论是Windows还是Linux,在用户的目录下都有一个.m2/repository的仓库目录,这就是Maven仓库的默认位置。
在Maven的目录下的conf目录下,有一个setting.xml文件,是Maven的配置文件,在里面可以修改本地仓库的位置。
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构建的时候,他从私服请求,如果私服上不存在该构建,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。
Maven私服的优点:
- 加速构建
- 节省带宽
- 节省中央Maven仓库的带宽
- 稳定(应付一旦中央服务器出问题的情况)
- 可以建立本地内部仓库
- 可以建立公共仓库
maven再默认的青鸾管辖是从中央仓库下载构建,也就是id为central的仓库。如果没有特殊需求,**一般只需要将私服地址配置为镜像,同时配置其代理所有的仓库就可以实现通过私服下载依赖的供能。**镜像配置如下:
<mirror>
<id>Nexus Mirror</id>
<name>Nexus Mirror</name>
<url>http://localhost:8081/nexus/content/groups/public</url>
<mirror>*</mirror>
</mirror>
Maven插件
Maven插件介绍 plugin放在plugins里,plugins放在build里
Maven实际上是一个依赖插件执行的框架,每个任务实际上是由插件完成。Maven插件通常被用来:
- 打包jar文件
- 创建war文件
- 编译代码文件
- 代码单元测试
- 创建工程文档
- 创建工程报告
插件通常提供了一个目标的集合,并且可以使用下面的语法执行;
mvn [pulgin-name]:[goal-name]
例如,一个java工程可以使用maven-compiler-plugin的compile-goal编译,使用以下命令
mvn compiler:compile
2.maven-compiler-plugin
设置maven编译的版本,maven3默认用jdk1.5,maven2默认用jdk1.3
这个插件基本每个项目都要加上
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source><!--源代码使用的jdk版本-->
<target>1.8</target><!--需要生成的目标class文件的编译版本-->
<encoding>UTF-8</encoding><!--字符集编码-->
</configuration>
</plugin>
Tomcat插件
在maven里建web工程
新建一个工程右击Add Framework Support:


在pom.xml里添加Tomcat插件,jdk的插件几乎每个项目都要引

可以通过命令行命令启动 也可以通过点击右边的插件启动

解决问题:老是标红是因为没有配置中央仓库
配置后:

这个网站里有插件的坐标,怕错的话可以直接复制


Maven项目模板
Archetype是一个Maven插件,其任务是按照其模板来创建一个xiangmujieg。
执行如下命令即可创建Maven项目
mvn archetype:generate
常用的archetype有以下两种:
maven-archetype-quickstar默认的Archetype
基本内容包括:
一个包含junit依赖声明的pom.xml
src/main/java主代码目录机一个名为App的类
src/test/java测试代码目录及一个名为AppTest的测试用例
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
没啥用
也可以新建的时候选模板
Maven父子工程进行版本统一
工程和工程之间是要进行交互的,我们用的依赖的版本应该一致
一些常用的工具类应该加到父工程pom.xml里的dependencies里,这里面的依赖会被传递到子工程。而dependencyManage里面写的依赖如果没有在子工程的pom里声明就不会被传递给子工程,如果子工程里声明(还是平常写依赖的方法,就是不写版本号)了,就会被传递过来(声明的时候是不需要写版本的,这就达到了版本的统一)
在父工程里定义properties,约定我们所有依赖的版本号
然后使用dependencyManagement把所有相关里依赖放在里面,进行版本的统一管理
如果有子工程需要依赖相关的jar包,只要声明即可,不需要写版本号
如果我们有一些共用类,特别是一些工具类,依然可以放在父工程的dependency里,传递给所有子工程。
总结:
Maven总得来说就是一个工具,工具没什么好理解的主要就是使用,用得多了就行,今后的项目基本就是建立在maven之上的,它可以帮助我们省去很多构建的过程,以后管理svn的时候,只需要把模块和pom文件传上去就行了。
哪怕自己的IDEA有问题,那就不用IDEA构建就行了,直接用mvn命令也行。
引到eclipse,eclipse也运行maven命令就行。
开发工具是多元化的,可能他们之间各种构建过程,jar包啥的都不一样,maven就可以给我们提供一个统一的处理解决方案。
把工程放到linux上,在linux上装个mvn,配个mvn环境也能跑起来。