前言:
Maven(翻译为"专家","内行")是一个跨平台的项目管理工具
主要服务于基于Java平台的项目构建,依赖管理和项目信息管理,基本上所有的java IDE都内置了maven
本文使用Eclipse来演示
Maven在eclipse下安装配置参考:https://blog.csdn.net/wcc27857285/article/details/81812304
概念区分:
在新建maven项目的时候,可以选择打包方式packging,分别有pom和war,jar三种
pom、war、jar的区别
war包可以理解成jar包的集合,既可以放在webapp目录下被tomcat,jetty等执行的,类似与.exe文件,可以用7z解压
jar就是打包成可依赖的代码集合,类似于dll
pom用在父级工程或聚合工程中,用来做jar包的版本控制,通常是只定义jar包依赖,而不实际依赖
在新建maven项目,也可以选择maven project和maven module
maven project和maven module的区别
project 可以作为父工程,可以以作为一个单独的maven工程
project 如果作为父工程的时候,通常为pom
module就是子工程,创建时必须选择父工程,而且父工程必须为pom的packing形式
project作为一个单独的maven项目时,也可以选择jar, war的形式
常见的两种工程形式:
第一种:
创建一个project工程作为父工程,为A,选择packging为pom,管理jar包的依赖。然后再创建若干module工程作为子工程,以A为父工程,这些子工程可以根据项目需求任意选择war,或者jar的形式。通常是一个为war,其余的为jar,这个war依赖几个jar工程,然后在maven build,install,clean的时候就使用A项目即可,无需每一个module操作,既通过父工程A来管理几个子工程
第二种:
单独创建project工程,packging为jar,或者war。
创建maven project和maven module示例:
创建maven project:
创建maven project的时候会让我们选择Create a simple project (skip archetype selection) 的选项
这个选项的意思就是:是否创建一个简单的项目(跳过对原型模板的选择),如果勾选则会生成一个最简单的maven工程,
若不勾选,则会进入archetype selection选择页面,可以选择web,quickstart,plugin,site等类型的工程,具体要根据项目需求
那么回到本文,我是要演示下创建父子工程,父工程pom工程作为管理依赖jar包,为了方便我们自定义,建议勾选。
但是我依然选择分别尝试下勾选和不勾选两种情况。。。
下面演示下勾选的情况:
菜单File->New->选择Maven project ,勾选Create a simple project
点击next下一步:
输入groupid和artifactId,选择version, packging选择pom
不需要设置下方的parent,直接点击Finish,完成。生成项目如下:
只有一个pom文件:
<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>cn.kevin</groupId>
<artifactId>testParent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
</project>
在pom中我们可以定义jia包的依赖,我们稍作编辑:
<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>cn.kevin</groupId>
<artifactId>testParent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<!--定义依赖版本号 -->
<properties>
<junit.version>4.12</junit.version>
<mybatis.version>3.2.8</mybatis.version>
<solrj.version>4.10.3</solrj.version>
</properties>
<!-- 只定义依赖的版本,不实际依赖 -->
<dependencyManagement>
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- solrj -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>${solrj.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
作为演示,我简单定义了junit,mybatis,solrj的依赖版本号,但是并没有实际依赖这些jar包。很简单,此时修改下比如mybatis的版本号,但是本地仓库没有的,然后保存下pom.xml文件,eclipse不会自动去下载该版本号的jar包,因为这里并没有实际依赖
接下来我们尝试不勾选Create a simple project,再来创建一次
1.File->New--> Maven project
2.在弹出界面中不要选择“Create a simple project”(这样就可以使用archetype来创建项目)
3.使用默认的Archetype (quickstart)
点击完成Finsh创建完毕
此时会有一大堆东西,这些是自动创建的一个maven项目所需要的文件
因为是父工程只管理jar包依赖,并没有具体代码,我么可以进入文件目录把src文件夹删除掉
删完之后变成这样,有用的就是pom.xml
然后修改pom.xml:
<packaging>pom</packaging> 中的jar 改成pom
改完后可能会报错,选择项目右键maven->update project即可
注意是选择项目右键,而不是pom.xml右键
创建maven module project:
1.选中刚建的父项目,在弹出菜单中点击 New ->Maven Module
可以看到,由于是选择了刚父项目,右键,所以上图中直接选择了testParent,不需要我们再次选择。
2.点击next ,默认选中的是quickstart,什么都不要修改直接继续next
3.点击Finsh即创建完毕
这样一个子项目就创建完成了,在文件系统中,子项目会建在父项目的目录中。在父目录中运行mvn test
等命令,所有的子项目都会按顺序执行。
我们可以发现,通过这个步骤创建子项目的同时,会修改父项目的pom.xml,增加了类似下面的信息:
<modules>
<module>child01</module>
</modules>
接下来就是优化下pom.xml了:
打开子项目的pom.xml可以删除groupid和versionid
Eclipse也在groupid和versionid上给出了黄色警告
鼠标移上去发现提示:Version is duplicate of parent version(版本号已经在父项目中定义过了)
所以子项目的groupid和versionid都可以删掉,下方的url 和properties父项目中也有一模一样的,也可删除
然后我们在子项目的pom中加入一些依赖:
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.kevin</groupId>
<artifactId>testParent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>child01</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</dependency>
</dependencies>
</project>
可以看到dependency节点下,不需要写version了,因为在父项目中已经定义
查看maven dependencies,可以看到已经依赖了定义的三个jar包---solrj、mybatis、junit
之所以有这么多是因为solrj,本身依赖了很多jar包,一并依赖了过来
子项目的pom还可以继续优化,<dependencyManagement> 标签 可以进一步优化子pom中的内容,在文章后面的各类标签中有详解
总之,parent 和module 如果是父子关系的话,就是继承关系,可以极大的优化项目结构和pom的内容
groupid和artifactId如何填写
在创建maven时会要求我们填写groupid和artifactId
groupid和artifactId被统称为“坐标”是为了保证项目唯一性而提出的,如果你要把你项目弄到maven本地仓库去,你想要找到你的项目就必须根据这两个id去查找。
groupId一般分为多个段,这里我只说两段,第一段为域,第二段为公司名称。域又分为org、com、cn等等许多,其中org为非营利组织,com为商业组织。举个apache公司的tomcat项目例子:这个项目的groupId是org.apache,它的域是org(因为tomcat是非营利项目),公司名称是apache,artigactId是tomcat。
比如我创建一个项目,我一般会将groupId设置为cn.kevin,cn表示域为中国,kevin是我个人喜欢的代号,artifactId设置为testPro,表示你这个项目的名称是testPro,依照这个设置,你的包结构最好是cn.snowin.testPro打头的,如果有个UserDao,它的全路径就是cn.kevin.testPro.dao.UserDao
各类标签:
<optional>可选依赖
举例:projectA 依赖projectB, projectB 依赖projectC时
projectB的pom.xml如下:
<dependency>
<groupId>com.projectC</groupId>
<artifactId>projectC</artifactId>
<version>0.0.1-SNAPSHOT</version>
<optional>true</optional>
</dependency>
当projectB的optional=true时, projectA中如果没有显式的引入projectC, 则projectA不依赖projectC, 即projectA可以自己选择是否依赖projectC,默认<optional>的值为false, 既子项目必须依赖
简单来说就是,ProjectB配置了optiona=true,就意味着ProjectB的子项目不能依赖ProjectA,要依赖只能手动依赖
<exclusion>排除依赖
传递性依赖会给项目隐式地引入很多依赖,这极大简化了项目依赖的管理,但是有些时候这种特性也会带来问题。
例如,项目A依赖B,而这个B依赖了C,那么这个C就会成为A的传递性依赖,而C由于是不稳定版本SNAPSHOT,会直接影响到当前的项目A。这时就需要排除掉A对C的依赖。这就是排除依赖。
A的pom.xml:
<dependency>
<groupId>com.projectB</groupId>
<artifactId>project-B</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>com.projectC</groupId>
<artifactId>project-C</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependencyManagement> 统一管理依赖
dependencyManagement的作用其实相当于一个对所依赖jar包进行版本管理的管理器
举例:B继承自A,A中集中管理Jar版本,B中就无需再声明version,直接从A中继承。如果有C,D继承A,也无需声明version。若需要升级某个Jar版本,也只需要在A中修改一次即可,无需B,C,D一个个项目改过来。
若子项目中某个jar声明了version,这个jar就不会从dependencyManagement中继承,而是按照声明的来,也很灵活
父项目A 的pom.xml:
<!-- 集中定义依赖版本号 -->
<properties>
<joda-time.version>2.5</joda-time.version>
<solrj.version>4.10.3</solrj.version>
</properties>
<!-- 只定义依赖的版本,并不实际依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>
</dependencyManagement>
子项目B的pom.xml:
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<--!从父项目继承version,不用再声明version-->
</dependency>
遇到的问题:
pom.xml报错:Missing artifact joda-time:joda-time:jar:4.12
其实原因很简单,就是joda-time.jar这个jar包版本没到4.12,最高版本也就2.几,所以无法正常下载,version改成2.5即可正常下载