文章目录
一、jar包
jar(Java Archive File)包,是Java的一种文档格式,是一种与平台无关的文件格式,可将多个文件合为一个文件,主要是对.class字节码文件进行打包,且因为.class字节码文件是跨平台的,所以jar包也是跨平台的。它与zip包非常相似,二者唯一的区别在于,jar包中包含了一个META-INF/MANIFEST.MF文件,该文件是在生产jar文件时自动创建的,包含了jar包的版本、创建人、类搜索路径等信息。若是可执行jar包,则还会包含Main-Class属性,表名Main方法入口。
一般地,当开发一个应用程序后这个应用程序包含了很多类,如果需要把这个程序提供给别人使用,通常会将这些类文件打包成一个JAR文件,把这个文件提供给别人使用。只要在别人系统的CLASSPATH环境变量中添加这个文件,则java虚拟机就可以自动在内存中解压这个jar包。
(一)打开一个jar包
可使用以下命令来查看jar包的内容:
jar tf 文件名.jar
例如,此处打开mysql-connector-java.jar包:
PS D:\IntelliJ IDEA\Demo\target\Demo-1.0-SNAPSHOT\WEB-INF\lib> jar tf mysql-connector-j-8.0.31.jar
META-INF/
META-INF/MANIFEST.MF
META-INF/services/
META-INF/services/java.sql.Driver
com/
com/mysql/
com/mysql/cj/
com/mysql/cj/AbstractQuery.class
com/mysql/cj/BindValue.class
com/mysql/cj/CacheAdapter.class
... //太多了,给省略了
com/mysql/jdbc/
com/mysql/jdbc/Driver.class
com/mysql/jdbc/SocketFactory.class
com/mysql/jdbc/SocketFactoryWrapper.class
META-INF/INDEX.LIST
INFO_BIN
INFO_SRC
LICENSE
README
其中包含了各种文件夹、java程序经过编译之后所得到的字节码文件等等。
这里,在IDEA的外部库中查看mysql-connector-java.jar的内部结构:
- com.mysql:包含各种.class字节码文件,平时所调用的类、接口等都存放在这里。
- META-INF目录:相当于一个信息包,目录中的文件和目录获得Java 2平台的认可与解释,用来配置应用程序、扩展程序、类加载器和服务manifest.mf文件,在用jar打包时自动生成。
- INDEX.LIST:索引
- MANIFEST.MF:包含了jar文件的内容描述,以及在应用程序运行时向JVM提供应用程序的信息(一般都是"key-value:属性值"的形式存储),例如:
Manifest-Version: 1.0 //生成的manifest.mf文件的版本
Ant-Version: Apache Ant 1.10.7 //版本信息
Created-By: 1.8.0_241-b07 (Oracle Corporation) //文件的开发来源
Built-By: pb2user //文件的生成工具
Specification-Title: JDBC //文件的标题
//以上是mysql-connector-java中的一部分,除此之外,还有一些常见的属性:
一、一般属性
1.Signature-Vresion:定义jar文件的签名版本
2.Class-Path:内部的类搜索路径,提供给应用程序或者类装载器
二、应用程序的相关属性
1.Main-Class:定义jar文件的入口类,该类必须可执行,一旦定义了该属性就可以使用:
java -jar 程序名.jar 来运行该jar文件
- WEB-INF目录:Java的WEB应用的安全目录。所谓安全就是客户端无法访问,只有服务端可以访问的目录。如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问。
- WEB-INF和META-INF的区别:META-INF 存放的是 jar 包的标签信息,jar 都会有这个文件夹,war 也会有。而 WEB-INF 是 java web 应用所特有的一个文件夹,属于 web 应用的安全目录,该目录客户端无法进行访问,只有服务端可以访问。如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问。
- INFO-BIN:此处是用来存放mysql-connector-java的bin目录信息的文件。
- INFO-SRC:此处是用来存放mysql-connector-java的src目录信息的文件。
- LICENSE:许可证文件,在我们在发布自己的软件的时候跟软件代码一起发布。它用来规定使用该软件的开发人员或组织对该软件的使用权限。拥有清晰的许可证有助于明确定义该软件可以使用的范围。比如,如果想完全开源,用Apache2.0就行,googlecode就是用的这个,很多的框架和开源软件也是这个。如果不想开源也可以自己写,列明软件使用者的注意事项,随软件一起发布。
- README:对项目的主要信息进行描述。
(二)打包一个jar包
创建普通jar包:
jar cf test.jar test
//不显示压缩过程将当前路径下的test路径下的全部内容生成一个test.jar文件,如果已经存在则被覆盖。
jar cvf test.jar test
//显示压缩过程
jar cvfM test.jar test
//不生成清单文件
jar cvfm test.jar manifest.mf test
//自定义清单文件信息,m指定读取用户清单信息,清单文件是普通文本文件
jar cvfm test.jar a.txt test
//将清单文件a.txt中的key-value对提取到META-INF/MANIFEST.MF文件中
jar tf test.jar
//查看jar包内容
jar tf test.jar > a.txt
//如果jar包中的文件路径和文件非常多,用上一个命令就无法查看所有,所以用重定向将显示结果保存到文件中
jar tvf test.jar
//查看详细内容
jar xf test.jar
//解压,将jar文件解压到当前目录下
jar xvf test.jar
//解压,显示解压过程的信息
jar uf test.jar Hello.class
//更新test.jar中的Hello.jar文件,如果存在则覆盖,否则添加
jar uvf test.jar Hello.class
//更新时显示详细信息;
比较重要的一个打包命令:
javac 类名1.java 类名2.java ... -d 指定生成的文件夹名
若文件夹不存在,则会自动创建。
案例:
Person.java
package com.Hello.MyInterface;
public interface Person {
void say();
}
Man.java
package com.Hello.MyClass;
import com.Hello.MyInterface.*;
public class Man implements Person{
private String Name;
private int Age;
public Man(){}
public Man(String name,int age){
Name=name;
Age=age;
}
public void say(){
System.out.println("My Name is "+Name+",I'm "+Age+" now!");
}
}
在命令行中使用命令:
javac Man.java Person.java -d test
就可得到一个完整的jar包结构:
命令行打包成jar包:
C:\Users\lenovo\Desktop>jar cvf test.jar test
已添加清单
正在添加: test/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: test/com/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: test/com/Hello/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: test/com/Hello/MyClass/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: test/com/Hello/MyClass/Man.class(输入 = 1067) (输出 = 593)(压缩了 44%)
正在添加: test/com/Hello/MyInterface/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: test/com/Hello/MyInterface/Person.class(输入 = 135) (输出 = 122)(压缩了 9%)
创建可运行jar包
在上述打成的jar包中,会自动生成META-INF目录,其中包含MANIFESIT.MF清单,内容为:
Manifest-Version: 1.0
Created-By: 18.0.2 (Oracle Corporation)
此时生成的jar包还不能执行,因为缺少先前说的Main-Class属性,导致jar被执行的时候,不知道执行哪个main函数。
因此我们需要加上Main-Class,后接main函数所在类的全路径名(注意冒号之后一定要跟英文的空格,整个文件最后有一行空行)这里我们可自己创建MANIFEST.MF文件:
Manifest-Version: 1.0
Created-By: 11 (Oracle Corporation)
Main-Class: main函数所在类的全路径
并在打包时指明该文件:
jar -cvfm test.jar META-INF/MANIFEST.MF
(参数m用于传入修改完成后的MANIFEST.MF文件)
再使用命令执行即可:
java -jar test.jar
事实上,还有一种更灵活的方式,使用jar命令-e选项,该选项指定JAR包中作为程序入口的主类的类名。
jar cvfe test.jar 主程序类路径 test
二、Maven
(一)概述
Maven是一个项目管理工具,它包含了一个对象模型、一组标准集合、一个依赖管理系统和用来运行定义在生命周期阶段中插件目标和逻辑。其将项目开发和管理过程抽象成一个项目对象模型(POM),其核心功能是合理叙述项目间的依赖关系,通俗点就是通过pom.xml文件的配置获取jar包不用手动的去添加jar包,而一个POM.xml文件相当于一个项目。
作用:
- 项目构建:提供标准化、跨平台的自动化项目构建方式。
- 管理项目依赖,项目依赖指项目各项任务之间存在相互联系和相互依赖关系,避免资源间版本冲突的问题。
- 编译代码。
- 自动运行单元测试。
- 一开发结构,提供标准的、统一的项目结构,有一个pom.xml文件用于维护当前项目所使用的jar包,且,所有的jar包都放在"maven"仓库里,当项目需要使用相应的jar包时,只需给出jar包的名称和版本号即可,这也使得jar包实现了共享,而避免了冗余。
常见概念:
- POM:pom.xml,项目对象模型,将一个项目当做一个模型使用,类似于控制层,完成编译、测试、打包、安装、部署等等。
- 依赖:jar包、插件等资源。
- 依赖管理:管理项目所用到的jar包、插件等资源。
- 项目的生命周期:Maven可管理一个项目从开发到使用所经历的所有过程,包括:
- Maven构建的Java项目结构:在新建项目时可使用Maven来构建项目的架构:
从而得到:
目录名称 | 描述 |
---|---|
.idea | IDEA项目的配置文件,自动生成的 |
src | 代码源文件存放目录 |
main | 实际开发内容 |
java | 存放项目源代码 |
resources | 资源目录,存放项目资源、配置文件等 |
test | 存放项目测试源代码 |
pom.xml | Maven项目的配置文件 |
target | 项目编译后产生,用于存放项目的资源、jar包、war包、class文件等 |
外部库 | 存放扩展的类库(jar包) |
(二)仓库与坐标
用于存储资源,包含各种jar包,pom.xml中通过设置索引来到仓库中寻找jar包,其中,仓库分为:本地仓库、第三方仓库、中央仓库。
获取jar包的流程:优先从本地仓库查找,查找不到时,若配置了私服,就从私服中查找,私服没有则从中央仓库中查找,然后下载到本地仓库;若未配置私服,则直接从中央仓库查找。
①本地仓库
来存储从远程仓库或中央仓库下载的插件和jar包,项目中使用的插件或jar包优先从本地仓库查找,本地仓库是中央仓库的一个子集。
本地仓库的位置是可以自己进行配置的,打开Maven安装目录下的conf文件夹,打开setting.xml文件,在文件中有英文的配置指导:
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<localRepository>D:\maven\maven-repository</localRepository>
这里,打开我存放的目录:
如,其中保存了我使用过的mysql-connector-java的jar包目录。
②第三方仓库(私服)
一般由公司自己设立,只为本公司内部共享使用,它既可以作为公司内部构建协作和存档,也可作为公用类库镜像缓存,减少在外部访问和下载的频率使用私服为了减少对中央仓库的访问私服可以使用的是局域网,中央仓库必须使用外网。也就是说,一般来说,公司会创建这种第三方仓库,保证项目开发时,项目所需用的jar都从该仓库中拿,每个人的版本就都一样,且,只需要本地仓库连接私服即可,这相当于是一个局域网,访问速度非常快。 注意:连接私服,需要单独配置。如果没有配置私服,默认不使用。
作用:
- 保存具有版权的资源,包含购买或自主研发的jar(中央仓库中的jar都是开源的,不能存储具有版权的资源)。
- 一定范围内共享资源,仅对内部开放,不对外共享。
③中央仓库
这是由Maven团队自己维护的仓库,里面存储了非常全的jar包,包含世界上大部分流行的开源项目构建,一般地,在国内都是用阿里的远程仓库,同样是在settings.xml配置文件中进行配置:
<mirrors>
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of 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>
-->
<!-- 阿里云仓库 -->
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
④坐标
maven中使用坐标来定位仓库中资源的位置,可以唯一性定位资源位置,通过该标识可以将资源的识别与下载工作交由Maven来自动完成,其主要组成为:
标识 | 作用 |
---|---|
groupId | 组织名,定义当前maven项目隶属组织名称,通常是域名反写,如:org.mybatis。 |
artifactId | 项目名,定义当前maven项目名称,通常是模块名称。 |
version | 版本号,定义当前的版本号。 |
packaging | 定义当前项目的打包方式 |
scope | 使用范围。 |
坐标的获取
Maven官方维护了一个仓库,地址为:
https://mvnrepository.com/
以Junit为例,进入官网,并选择版本号后,即可得到其坐标:
(三)POM文件解析
注,以下内容参考博客:https://blog.csdn.net/jk418756/article/details/87917776
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--基本信息-->
<groupId>…</groupId>
<artifactId>…</artifactId>
<version>…</version>
<packaging>…</packaging>
<dependencies>…</dependencies>
<!--POM之间的关系-->
<parent>…</parent>
<dependencyManagement>…</dependencyManagement>
<modules>…</modules>
<!--定义属性-->
<properties>…</properties>
<!--构建设置-->
<build>…</build>
<reporting>…</reporting>
<profiles>...</profiles>
<!--更多项目信息-->
<name>…</name>
<description>…</description>
<url>…</url>
<inceptionYear>…</inceptionYear>
<licenses>…</licenses>
<organization>…</organization>
<developers>…</developers>
<contributors>…</contributors>
<!--环境设置-->
<repositories>…</repositories>
<pluginRepositories>…</pluginRepositories>
<distributionManagement>…</distributionManagement>
</project>
①项目基本信息
头信息
<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">
- xmlns:命名空间。
- xmlns:xsi:xml遵循的标签规范。
- xsi:schemaLocation:用来定义xmlschema的地址,也就是xml书写时需要遵循的语法。
注:这是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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.funtl</groupId>
<artifactId>itoken-dependencies</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<name>itoken dependencies</name>
<url>www.funtl.com</url>
</project>
- modelVersion:声明POM模型的版本。
- groupId:公司或组织的唯一标志的,且,配置时生成的路径也是由此生成,如,com.winner.trade,则,maven会将该项目打成的jar包放在本地路径:/com/winner/trade。
- artifactId:项目的唯一ID,一个group下面可能有多个项目,通过artifactId来区分。
- version:本项目目前所处的版本。
- packaging:打包的类型,在使用mvn package命令时起作用,可选类型有:pom、jar、war、rar等等。
- name:项目的名称,给Maven产生的文档使用。
- url项目主页的URL,Maven文档使用。
②POM之间的关系
1.依赖关系
< dependency >< /dependecy >标签描述了项目相关的所有依赖关系(jar包关系),Maven会根据依赖的坐标从仓库中下载。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>xxx</groupId>
<artifactId>xxx</artifactId>
</exclusion>
</exclusions>
</dependency>
…
</dependencies>
其中,groupId、artifactId、version的含义与基本设置中的相同,其余的为:
- type:依赖的类型,默认是jar,还可以是war等类型。
- scope:可以选择依赖jar包的使用范围,默认情况下,jar可以在任何地方使用。三种使用范围:
- 主程序中是否可用(即为main文件夹范围内)。
- 测试程序中是否可用(即为test文件夹内)。
- 是否参与打包(package指令范围内)。
a)依赖的传递性:Maven中依赖关系是有传递性的,如,项目A依赖于项目B(A->B),项目B依赖于项目C(B->C),则项目A传递依赖于项目C。且,依赖传递过程中,遵循着以下准则(层级指的是jar包的层次结构):
- 路径优先:当依赖(jar包)中出现相同的资源时,(jar包)层级越深,(资源)优先级越低;层级越浅,优先级越高。
- 声明优先:当资源在相同层级被项目依赖时(资源所在的jar包不同),资源的jar包在pom.xml文件中配置顺序靠前的覆盖配置顺序靠后的。
- 特殊优先:当同级(同一个项目配置文件)配置了相同jar包的不同版本时,后配置的覆盖先配置的。
注意:这里所说的资源是jar包内部的资源,而非jar包。
例:
(上层与项目直接相连的是项目自身所引入的依赖,而下层是项目所引入的模块,以及模块所引入的依赖)
- 路径优先:当使用资源相同时,1度会覆盖2度,2度会覆盖3度,并以此类推。
- 声明优先:对于同度依赖的相同资源,如,同为2度,则取决于1度的配置文件中配置包含两个资源的jar包的先后顺序。
- 特殊优先:同级当中配置不同版本的jar包时,则后配置覆盖先配置的,如:
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.13</version>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
则生效的是1.2.14版本。
Maven依赖管理中,有两种方式来管理依赖关系,分别是可选依赖(Optional Dependencies)和依赖排除(Dependency Exclusions)。
b)可选依赖:
- optional:可选依赖(Optional Dependencies),当一个项目A依赖另一个项目B时,项目A可能用到了项目B很少一部分功能,此时就可以在A中配置对B的可选依赖(即,只需要一部分内容)。举例来说,项目B类似hibernate,它支持对mysql、oracle等各种数据库的支持,但是在引用这个项目时,我们可能只用到其对mysql的支持,此时就可以在A项目中配置对项目B的可选依赖。
例:
项目A中依赖于项目B,且是可选依赖关系(只依赖B的部分内容)。
<project>
...
<dependencies>
<!-- declare the dependency to be set as optional -->
<dependency>
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
<version>1.0</version>
<scope>compile</scope>
<optional>true</optional> <!-- value will be true or false only -->
</dependency>
</dependencies>
</project>
此时,若有一个项目C依赖于A(C–>A),C就不会依赖于项目B了,若想要继续使用B的功能,则需要在C的pom.xml文件中另外配置。
c)依赖排除:
- exclusions:依赖排除(Dependency Exclusions),当一个项目A依赖项目B,而项目B同时依赖项目C(且非可选依赖),如果项目A中因为各种原因不想引用项目C,则在配置项目B的依赖时,可以排除对C的依赖。此时依赖关系就别为:A–>B,B–>C。
例,项目A依赖于B,B依赖于C,但A不依赖于C:
<project>
...
<dependencies>
<dependency>
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>sample.ProjectC</groupId>
<artifactId>Project-C</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
对于多重依赖,如:
Project-A
-> Project-B
-> Project-D
-> Project-E <! -- 需要被排除的依赖 -->
-> Project-F
-> Project C
即,A传递依赖于项目E,当需要排除对项目E的依赖时,则需要在配置对B的依赖时排除对E的依赖,pom.xml配置如下:
<dependencies>
<dependency>
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>sample.ProjectE</groupId> <!-- Exclude Project-E from Project-B -->
<artifactId>Project-E</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
当A和B同时依赖C,但不是C的同一个版本:
添加检查插件:
<dependencies>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.4.0</version>
<type>maven-plugin</type>
</dependency>
</dependencies>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</reporting>
然后在Maven控制台运行:
mvn project-info-reports:dependencies
来查看依赖项检查报告,并使用exclusions来去除依赖项。
2.聚合关系
Maven中项目的继承和聚合目的都是用来方便工程模块的管理的,而Maven管理项目是方式是通过pom文件来实现的,所以Maven的继承和聚合关系本质又是不同模块间pom文件的关系。
- Maven聚合:目的是让聚合工程来管理多个子模块工程,事实上,子模块不一定知道自己被聚合,因为聚合的配置在聚合工程的pom中,而与子模块自身无关。
- Maven继承:目的是让子模块工程来获取父模块工程的配置,子模块会知道继承的父模块工程,因为继承的配置是在子模块工程的pom当中。
在实际开发当中,聚合工程和父工程往往是同一工程,方便对子模块工程的管理:
聚合的实现:如,聚合starter、web、service三个子工程,则需要给出当前被聚合POM的相对路径,一般地,会将被聚合模块放在聚合模块的目录下,如:
- 当前聚合模块MyProject绝对路径:D:\IntelliJ IDEA\MyProject。
- starter绝对路径:D:\IntelliJ IDEA\MyProject\starter。
- web的绝对路径:D:\IntelliJ IDEA\MyProject\web。
- service的绝对路径:D:\IntelliJ IDEA\MyProject\service。
<modules>
<module>starter</module>
<module>web</module>
<module>service</module>
</modules>
特点:
- 聚合工程中不用关心module顺序,maven会根据依赖自动按续打包。
- 对聚合工程的操作,会同步操作到其下的所有的子模块。
注意:对于聚合模块来说,其打包方式必须为pom(< packaging >< /packaging >标签),否则无法构建。
3.继承关系
&emps;继承关系,实际上是为了解决工程之间的依赖关系、资源关系。如,对于项目B(必须是POM工程),若项目A继承于B,则A默认依赖B所依赖的所有资源,应用B工程中定义的所有资源信息,例,假设B工程有jar包:
则创建子工程后,即使pom.xml文件中并未引入该jar包,子工程的外部库中也会出现该jar包:
继承的目的:把共同的配置放在一个父模块中,使得子模块不需要另外配置,以此方式来消除重复的配置。
继承方式:子模块中需要声明< parent >标签:
[...]
<parent>
<groupId>父模块的groupId</groupId>
<artifactId>父模块的artifactId</artifactId>
<version>父模块的版本号</version>
<!--relativePath,表示父模块POM的相对路径,当项目构建时,Maven会首先根据<relativePath>检查父POM,如果找不到,再从本地仓库查找-->
<relativePath>../父模块项目路径/pom.xml</relativePath>
</parent>
[...]
可继承的父模块元素:< groupId >、< version >、< distributionManagement >、< properties >、< dependencies >、< dependencyManagement >、< repositories >。
- < dependecyManagement >:该标签用来在根pom中管理jar包版本,如果后面的jar包没有申明版本,会以这里面的版本为主,使用该标签并不会引入jar包,一般是在父级pom文件申明,方便管理jar包版本。
- < pluginManagement >:通过 pluginManagement 标签管理起来的插件就像 dependencyManagement 一样,子工程使用时可以省略版本号,起到在父工程中统一管理版本的效果。
③属性设置
1.Maven内置属性
两个常用属性:
2.POM属性
&emps; POM属性,即为当前项目的基本信息。
3.自定义属性
自定义属性,相当于定义变量,方便统一维护。
定义格式:
<properties>
<属性名>属性内容</属性名>
</properties>
调用方式:
${属性名}
常用场景:同一各依赖的版本,如:
<!--依赖1-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--依赖2-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<!--依赖3-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
以上三个依赖同属于org.springframework,但是版本并不相同,为了实现资源版本的统一,且便于以后修改,可在pom.xml文件中配置:
<!--自定义属性-->
<properties>
<spring.version>5.1.9.RELEASE</spring.version>
</properties>
<!--依赖-->
<!--依赖1-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--依赖2-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--依赖3-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
4.settings属性
用户使用${settings.}开头的属性可以引用 maven settings.xml 文件中XML元素的值。
5.Java系统属性
所有Java系统属性都可以使用Maven属性引用,这里列举一些常用的java系统属性。
6.环境变量实现
所有环境变量都可以使用以env.开头的Maven属性引用,如,${env.JAVA_HOME}表示JAVA_HOME环境变量的值。
④构建设置
a)build标签
使用maven构建的项目可以直接使用命令maven build完成项目的编译、测试、打包,无需额外配置,而build标签描述了如何编译及打包项目,具体的编译和打包工作是通过其中的plugin配置来实现的。
分类:
- 项目构建:项目构建build标签,全局配置,针对整个项目的所有情况都有效
<!--项目构建,直接写-->
<build></build>
- 轮廓构建:在profile标签中,针对不同的profile配置。
<profiles>
<profile>
<build>...</build>
</profile>
</profiles>
元素介绍:对于project下的build,其包含build的基本元素和<…Directory>元素,而profiles下的build只包含build的基本元素。
1.常见<…Directory>元素:
2.常见基本元素:
- defaultGoal:执行构建(即编译或打包吧)时默认的goal或phase,如jar:jar或者package。
- directory:构建的结果所在的路径,默认为${basedir}/target目录。
- finalName:打包文件的文件名。
- resources:用于引用或排除资源文件,资源往往不是代码,而是properties或xml文件,无需编译,构建过程中往往会将资源文件从源路径复制到指定的目标路径,resources则给出各个资源在maven项目中的具体路径。常见子标签有:
子标签 | 作用 |
---|---|
targetPath | 资源文件的目标路径。 |
filtering | 构建过程中是否对资源进行过滤,默认false。 |
directory | 资源文件源路径,默认位于${basedir}/src/main/resources/目录下。 |
includes | 一组文件名的匹配模式,被匹配的资源文件将被构建过程处理。 |
excludes | 一组文件名的匹配模式,被匹配的资源文件将被构建过程忽略。同时也被includes的文件依然被忽略。 |
filters | 给出对资源文件进行过滤的属性文件的路径,默认位于${basedir}/src/main/filters/目录下。属性文件中定义若干了键值对,用于在构建过程中将资源文件中出现的变量(键)替换为对应的值。 |
testResources | test过程中涉及的资源文件,默认位于${basedir}/src/test/resources/目录下,它们不会被构建到目标构件中。 |
- plugins:设置构建过程中所用的插件。
- extensions:是否加载该插件的扩展,默认为false。
- inherited: 该插件的configuration中的配置是否可以被继承(继承该pom中的其他maven项目),默认true。
- configuration:该插件所需要的特殊配置,在父子项目之间可以覆盖或合并。
- dependencies: 该插件所需要的依赖类库。
- executions: 该插件的某个goal的执行方式。一个executions有如下属性:
1.id:唯一标识。
2.goals:要执行的插件的goal,如run。
3.phase: 插件的goal要嵌入到Maven的phase中执行,如verify。
4.inherited: 该execution是否可被子项目继承
5.configuration:该execution的其他配置参数
例:
<build>
<plugins>
<!-- maven-source-plugin提供项目自动将源码打包并发布的功能
执行 mvn install,maven会自动将source install到repository 。
执行 mvn deploy,maven会自动将source deploy到remote-repository 。
执行 mvn source:jar,单独打包源码。
注意:在多项目构建中,将source-plugin置于顶层或parent的pom中并不会发挥作用,必须置于具体项目的pom中
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugins>
<!--
打包插件
在添加了该插件之后,当运行“mvn package”进行打包时,
会打包成一个可以直接运行的 JAR 文件,使用“java -jar”命令就可以直接运行
-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.liangzhi.house.HouseApplication</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
即使不配置,也会默认引入以下插件:
这是因为Maven本身实际上就是插件的集合,通过不同的插件来完成项目周期的操作。
- < pluginManagement >:插件管理器,通过 pluginManagement 标签管理起来的插件就像 dependencyManagement 一样,子工程使用时可以省略版本号,起到在父工程中统一管理版本的效果,但是dependencies和dependencymanagement隶属于最外层的project标签,而plugin和pluginManagement隶属于build标签。
例:
在父项目中声明插件和版本信息:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
在子项目中引入插件:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
</plugins>
- extensions:执行构建过程中可能用到的其他工具,在执行过程中被加入到classpath中;也可以激活构建插件,从而改变构建的过程。通常通过它给出通用插件的一个具体实现,用于构建过程。
b)reporting标签
< reporting >中的配置作用于Maven的site阶段,用于生成报表。< reporting >中也可以配置插件< plugins >,并通过一个< plugin >的< reportSet >为该插件配置参数。注意,对于同时出现在< build>和< reporting >中的插件,< reporting >中对该插件的配置也能够在构建过程中生效,即该插件的配置是< build >和< reporting >中的配置的合并。示例如下:
<reporting>
<!--执行maven site时,是否生成报表,默认false-->
<excludeDefaults>false</excludeDefaults>
<!--报表的生成目录,默认为${basedir}/target/site-->
<outputDirectory>${basedir}/target/site</outputDirectory>
<!--报表中特别用到的插件-->
<plugins>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.0.1</version>
<!--对于该插件的某个goal的执行参数-->
<reportSets>
<reportSet>
<id>sunlink</id>
<reports>
<report>javadoc</report>
</reports>
<inherited>true</inherited>
<configuration>
<links>
<link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
</links>
</configuration>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
c)profiles标签
profile是一组可选的配置,可以用来根据环境参数或命令行参数激活某个构建处理,能让你为不同的环境定义不同的构建。
命令激活:通过maven 的-P参数激活指定的profile,参数的值是profile的id,多个profile以逗号分割,如果不想激活某个默认的profile,就在它的id前加个!,例:
mvn clean package -Dmaven.test.skip=true -P test,dev,!prod
根据环境参数激活:隐式激活,需要在activation元素中指定激活条件,若不用条件二直接激活,可指定activeByDefault为true,表示当没有指定其他profile为激活状态时,该profile就默认会被激活。
&emps; 表示不同类型的隐式激活方式可以组合使用,如根据同时指定根据操作系统类型和JDK版本来激活profile,只有但两个条件都匹配是才激活之。
例,默认激活:
<profiles>
<profile>
<id>profileTest1</id>
<properties>
<hello>world</hello>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>profileTest2</id>
<properties>
<hello>andy</hello>
</properties>
</profile>
</profiles>
例,根据操作系统激活:
<profiles>
<profile>
<activation>
<os>
<!-- 不必指定所有信息 -->
<name>linux</name>
<family>unix</family>
<arch>amd64</arch>
<version>3.19.0-30-generic</version>
</os>
</activation>
</profile>
</profiles>
例,根据JDK版本激活:
<!-- 如果jdk的版本为1.8则激活该profile -->
<profiles>
<profile>
<activation>
<jdk>1.8</jdk>
</activation>
</profile>
</profiles>
⑤更多项目信息
<name>…</name>
<description>…</description>
<url>…</url>
<inceptionYear>…</inceptionYear>
<licenses>…</licenses>
<organization>…</organization>
<developers>…</developers>
<contributors>…</contributors>
- name:项目的全名称,可以是大写空格多个词,比如 Spring Boot Starter Parent,而 artifactId 是用来区分同一个groupId 下的子项目,比如前面对应的是 spring-boot-starter-parent。
- description:项目的详细描述, Maven 产生的文档用,可直接填写内容。
- url:项目主页的URL,Maven产生的文档用。
- inceptionYear:项目创建年份,4位数字。
- licenses:含有子标签license,填写项目许可授权等 。
- organization:项目所属组织。
- developers:项目开发人员。
- contributors:项目贡献人员。
⑥环境设置
<repositories>…</repositories>
<pluginRepositories>…</pluginRepositories>
<distributionManagement>…</distributionManagement>
- repositories:指定Maven的仓库位置,如,设置远程仓库:
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
- pluginRepositories:指定插件仓库。
- distributionManagement:分发构件至远程仓库。
(四)项目构建命令
①手动使用命令
Maven构建命令,即,mvn,后面可添加功能参数,可以依次执行多个命令,用空格分隔。常用命令有:
mvn clean package -Dmaven.test.skip=true -- 跳过单测打包
mvn clean install -Dmaven.test.skip=true -- 跳过单测打包,并把打好的包上传到本地仓库
mvn clean deploy -Dmaven.test.skip=true -- 跳过单测打包,并把打好的包上传到远程仓库
mvn -v //查看版本
mvn archetype:create //创建 Maven 项目
mvn compile //编译源代码
mvn test-compile //编译测试代码
mvn test //运行应用程序中的单元测试
mvn site //生成项目相关信息的网站
mvn package //依据项目生成 jar 文件
mvn install //在本地 Repository 中安装 jar
mvn -Dmaven.test.skip=true //忽略测试文档编译
mvn clean //清除目标目录中的生成结果
mvn clean compile //将.java类编译为.class文件
mvn clean package //进行打包
mvn clean test //执行单元测试
mvn clean deploy //部署到版本仓库
mvn clean install //使其他项目使用这个jar,会安装到maven本地仓库中
mvn archetype:generate //创建项目架构
mvn dependency:list //查看已解析依赖
mvn dependency:tree com.xx.xxx //看到依赖树
mvn dependency:analyze //查看依赖的工具
mvn help:system //从中央仓库下载文件至本地仓库
mvn help:active-profiles //查看当前激活的profiles
mvn help:all-profiles //查看所有profiles
mvn help:effective -pom //查看完整的pom信息
下面以一个项目为例
1.进入一个项目的pom.xml文件所在目录
(base) PS D:\IntelliJ IDEA\MyRedis> ls
目录: D:\IntelliJ IDEA\MyRedis
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2022/10/23 10:41 .idea
d----- 2022/10/23 10:07 src
-a---- 2022/10/22 21:05 648 pom.xml
pom.xml内容为:
<?xml version="1.0" encoding="UTF-8"?>
<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>org.example</groupId>
<artifactId>MyRedis</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>18</maven.compiler.source>
<maven.compiler.target>18</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
2.编译pom.xml文件:
(base) PS D:\IntelliJ IDEA\MyRedis> mvn compile
3.得到target文件夹
target文件夹即为编译生成文件,使用mvn clean命令即可将其删除。
4.打包为jar包
使用命令:
mvn package
即可将源程序打包为jar包:
②IDEA图形化界面
在IDEA内可非常方便地使用mvn命令:
三、Maven Helper
Maven Helper插件,可用于实现快速解决依赖冲突。
- Conflicts:查看冲突。
- All Dependencies as List:列表形式查看所有依赖。
- All Dependencies as Tree:树形式查看所有依赖。
在出现冲突时会自动显示:
点击 Exclude 之后,插件自动会在 pom.xml 文件中添加 相关代码,进行子依赖的排除,这样即可快速排除了依赖。