Javaweb12-Maven基础和进阶
Maven技术基础
一.Maven基础
Maven是Apache旗下的一个开源项目,是一款用于管理和构建java项目的工具。,它基于项目对象模型(Project Object Model , 简 称: POM)的概念,通过一小段描述信息来管理项目的构建、报告和文档。
1.Maven的作用:
- 依赖管理
自动下载和管理项目所需的库和插件,减少手动处理的复杂性。们只需要在maven项目 的pom.xml文件中,添加一段配置信息即可实现。
<dependencies>
<!-- 依赖项 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
- 统一项目结构
提供标准、统一的项目结构。推荐的项目目录结构帮助组织代码和资源,提升项目的可维护性和可读性。
my-app
│
├── src
│ ├── main
│ │ ├── java # 源代码
│ │ └── resources # 资源文件
│ ├── test
│ │ ├── java # 测试代码
│ │ └── resources # 测试资源
│
├── target # 构建输出目录
└── pom.xml # 项目配置文件
- 标准的项目构建流程
maven提供了标准的、跨平台(Linux、Windows、MacOS) 的自动化项目构建方式。提供标准化的构建过程,涵盖编译、测试、打包和部署等步骤,确保每次构建的一致性。
mvn clean
:清理构建输出目录。mvn compile
:编译源代码。mvn test
:运行测试。mvn package
:打包项目。mvn install
:将构建结果安装到本地 Maven 仓库。
2.Maven模型:
- 项目对象模型 (Project Object Model)
POM 是 Maven 的核心配置文件 pom.xml
。它定义了项目的基本信息(如项目的 groupId
, artifactId
, version
),项目依赖(外部库和插件),以及构建和部署的配置。POM 文件还允许定义项目的模块结构和继承关系。
以上图中紫色框起来的部分属于项目对象模型,就是将我们自己的项目抽象成一个对象模型,有自己专属的坐标(坐标,就是资源(jar包)的唯一标识,通过坐标可以定位到所需资源(jar包)位置)
<groupId>org.example</groupId>
<artifactId>DataStructure</artifactId>
<version>1.0-SNAPSHOT</version>
:
这是项目的组织或公司标识符。groupId 通常对应于项目的根包名或公司域名的反向形式。它帮助 Maven 确定依赖项的唯一性和位置。
:
这是项目的唯一标识符,用于区分同一 groupId 下的不同项目。artifactId 通常表示项目的名称或主要模块。
:
这是项目的版本号。1.0-SNAPSHOT 表示这是一个开发中的版本,尚未正式发布。SNAPSHOT 标记表明这个版本是不断变化的,可能会有多个更新。
- 依赖管理模型(Dependency)
Maven 通过 pom.xml
文件中的 <dependencies>
元素管理项目所需的库。每个依赖项都指定了其 groupId
, artifactId
, 和 version
。Maven 会从中央仓库或自定义仓库下载这些依赖,并将它们添加到构建路径中。依赖项还可以继承和共享,减少版本冲突和管理复杂性。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
Maven仓库:用于存储资源,管理各种jar包
本地仓库:自己计算机上的一个目录(用来存储jar包)
中央仓库:由Maven团队维护的全球唯一https://repo1.maven.org/maven2/
远程仓库(私服):一般由公司团队搭建的私有仓库
- 构建生命周期/阶段(Build lifecycle & phases)
Maven 定义了三个内置的构建生命周期:
default:处理项目的构建,如编译、测试、打包等。
clean:清理项目输出目录,通常在每次构建前运行。
site:生成项目的文档和报告。
3.POM文件及依赖
<?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>maven-project</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- 第1个依赖 : logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
<!-- 第2个依赖 : junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
<project>
:pom文件的根标签,表示当前maven项目
<modelVersion>
:声明项目描述遵循哪一个POM模型版本
<groupId>
:定义当前Maven项目隶属组织名称(通常是域名反写)
<artifactId>
:定义当前Maven项目名称(通常是模块名称,例如 order-service、goods service)
<version>
:定义当前项目版本号
<dependencies>
:指当前项目运行所需要的jar包。一个项目中可以引入多个依赖
- 依赖传递:
- 直接依赖:在当前项目中通过依赖配置建立的依赖关系
- 间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源
projectA依赖了projectB。对于projectA 来说,projectB 就是直接依赖。
projectB依赖了projectC及其他jar包。 那么此时,在projectA中也会将projectC的依 赖传递下来。对于projectA 来说,projectC就是间接依赖。
- 排除依赖:
依赖具有传递性。那么A依赖B,B依赖C,如果A不想将C依赖进来,在maven项目中,我们可以通过排除依赖来实现。
排除依赖:指主动断开依赖的资源。(被排除的资源无需指定版本)
<dependency>
...
<!--排除依赖, 主动断开依赖的资源-->
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency
- 依赖范围:
<dependencies>
<!--junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope><!--仅在test文件夹范围有效-->
</dependency>
</dependencies>
- 主程序范围有效(main文件夹范围内)
- 测试程序范围有效(test文件夹范围内)
- 是否参与打包运行(package指令范围内)
scope标签的取值范围:
4.Maven生命周期
Maven对项目构建的生命周期划分为3套(相互独立):
**clean:**负责删除以前构建过程中生成的文件,以确保干净的构建环境。
clean:移除上一次构建生成的文件(将target目录删除)
**default:**核心工作。如:编译、测试、打包、安装、部署等。
compile:编译项目源代码
test:使用合适的单元测试框架运行测试(junit)
package:将编译后的文件打包,如:jar、war等
install:安装项目到本地仓库
**site:**生成报告、发布站点等。
- 生命周期的顺序是:clean --> validate --> compile --> test --> package --> verify --> install --> site --> deploy
- 在同一套生命周期中s,我们在执行后面的生命周期时,前面的生命周期都会执行。
二.Maven高阶
1.分模块设计与开发
- **问题提出:**在开发大型项目的时候,如果将所有业务代码放在一个Java模块中开发,这定会造成不同开发人员很难实现项目中组件的重用,也不利于项目的维护和管理
- **解决方法:**因此需要采用分模块设计的方法开发项目,分模块设计就是将项目按照功能/结构拆分成若干个子模块,方便项目的管理维护、拓展,也方便模块间的相互调用、资源共享。每个模块间可以通过maven坐标引用实现关联
- **举例说明:**下面以黑马程序员的Javaweb课程项目举例说明,如何进行分模块开发
当项目组的其他成员想使用我们开发的pojo和utils包下的代码时,我们可以通过以下方式实现:
将pojo包下的实体类,抽取到一个maven模块中 tlias-pojo
将utils包下的工具类,抽取到一个maven模块中 tlias-utils
将其他的业务代码,放在tlias-web-management这个模块中,在该模块中需要用到实体类 pojo、工具类utils,直接引入对应的依赖即可
1.创建Maven模块,将pojo包内的代码放在新tlias-pojo下
2.创建Maven模块,将utils包内的代码放在新tlias-utils下
3.分别在tlias-pojo和tlias-utils的pom.xml中添加相关所需依赖
4.在项目tlias-web-management中,将tlias-pojo和tlias-utils的坐标引入
<dependency>
<groupId>com.itheima</groupId>
<artifactId>tlias-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.itheima</groupId>
<artifactId>tlias-utils</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
到此就已经完成了模块的拆分,拆分出了 tlias-pojo、tlias-utils、tlias-web management ,如果其他项目中需要用到 pojo,或者 utils工具类,就可以直接引入依赖。
2.继承
- **问题提出:**在案例项目分模块开发之后啊,我们会看到tlias-pojo、tlias-utils、tlias-web-management 中都引入了一个依赖 lombok 的依赖,比较繁琐
-
**解决方法:**我们可以再创建一个父工程 tlias-parent ,然后让上述的三个模块 tlias-pojo、tlias utils、tlias-web-management 都来继承这个父工程 。 然后再将各个模块中都共有的依赖,都 提取到父工程 tlias-parent中进行配置,只要子工程继承了父工程,依赖它也会继承下来,这样就 无需在各个子工程中进行配置了
继承:描述的是两个工程间的关系,子工程可以继承父工程中的配置信息,常见于依赖关系的继承。
- **举例说明:**下面按上述情况举例说明,如何进行继承
我们在看tlias-web-management 项目时发现,此项目已经有继承关系,由于继承只能为单继承,因此需要重新定义一个父类并继承spring-boot-starter-parent这个父类
因此可以得到
1.创建Maven模块tlias-parent,该工程为父工程,其余模块为其子工程,需要继承父工程
2.添加父工程的打包方式为pom,并为其添加父工程和各个工程共有的依赖(子工程会自动继承父工程的依赖)
Maven打包方式:
jar:普通模块打包,springboot项目基本都是jar包(内嵌tomcat运行)
war:普通web程序打包,需要部署在外部的tomcat服务器中运行
pom:父工程或聚合工程,该模块不写代码,仅进行依赖管理
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent
</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itheima</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
</dependencies>
3.在子工程的pom.xml文件中,配置继承关系
<parent>
<groupId>com.itheima</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../tlias-parent/pom.xml</relativePath>
</parent>
注意:
在子工程中,配置了继承关系之后,坐标中的groupId是可以省略的,因为会自动继承父工程的 。
relativePath指定父工程的pom文件的相对位置(如果不指定,将从本地仓库/远程仓库查 找该工程)。
3.版本锁定
- **问题描述:**由于我们父工程往往添加的依赖是各个继承的项目所共有的依赖,因此在各个不同的项目之间相同的依赖的版本可能存在差异,因此我们很难管理,为了解决此问题,Maven提供了版本锁定的功能。
- **解决方案:**版本锁定,即在父工程中规定了要引入依赖的版本号,在其他继承的项目中如果添加此规定的依赖,不用指定依赖的版本号,直接从父工程中继承,如果没有添加此依赖就不会继承此依赖。在maven中,可以在父工程的pom文件中通过 来统一管理依赖版本。
父工程( </dependencyManagement>
):
<!--统一管理依赖版本-->
<dependencyManagement>
<dependencies>
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
</dependencyManagement>
子工程:
<dependencies>
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
</dependencies>
- **自定义属性:**如果父工程中出现过多的依赖,在每次迭代版本的时候查找很不方便,因此可以通过Maven的自定义属性解决这一难点
父工程:
<properties>
<lombok.version>1.18.24</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
通过 <properties>
标签,里面添加自定义标签用来存放版本号,在添加依赖的时候通过${lombok.version}
来添加依赖。
4.聚合
- **问题提出:**在上述项目中,我们不难看出tlias-web-management模块不仅继承了tlias-parent模块,而且还使用了tlias-pojo、tlias-utils模块,这样在打包项目是,就要依次将tlias-parent,tlias-pojo,tlias-utils通过install安装到本地maven仓库再进行对tlias-web-management模块的package打包,这样做比较繁琐且容易出错
- **解决方法:**如果将这些模块作为一个整体打包就不会很麻烦了,我们把这个工程叫做聚合。
- **举例说明:**对于上述问题可以通过以下方法实现聚合
1.找到聚合工程:一个不具有业务功能的“空”工程(有且仅有一个pom文件) 【PS:一般来说,继承关 系中的父工程与聚合关系中的聚合工程是同一个】
2.以在聚合工程中通过 <modules>
设置当前聚合工程所包含的子模块的名称。
<modules>
<module>../tlias-pojo</module>
<module>../tlias-utils</module>
<module>../tlias-web-management</module>
</modules>
3.此时在聚合工程上进行打包操作或进行Maven的生命周期即可
5.私服
Maven 私服(私有仓库)是一种用于托管和管理 Maven 构建依赖项的本地存储库。使用私服可以让团队在内网中共享构建依赖项,并且可以缓存外部依赖项,提高构建速度和稳定性。
上传资源: A 连接上私服之后,他就可以把jar包直接上传 到私服当中。
1.在maven的配置文件setting.xml中配置访问私服的用户名、密码。
<server>
<id>maven-releases</id>
<username>admin</username>
<password>admin</password>
</server>
<server>
<id>maven-snapshots</id>
<username>admin</username>
<password>admin</password>
</server>
2.在maven的配置文件setting.xml中配置连接私服的地址(url地址)。
3.在项目的pom.xml文件中配置上传资源的位置(直接在tlias-parent中配置发布地址)。
<distributionManagement>
<!-- release版本的发布地址 -->
<repository>
<id>maven-releases</id>
<url>http://192.168.150.101:8081/repository/maven
releases/</url>
</repository>
<!-- snapshot版本的发布地址 -->
<snapshotRepository>
<id>maven-snapshots</id>
<url>http://192.168.150.101:8081/repository/maven
snapshots/</url>
</snapshotRepository>
</distributionManagement>
4.配置完成之后,我们就可以在tlias-parent中执行deploy生命周期,将项目发布到私服仓库中。
**下载资源:**B 团队的所有开发人员也连接同一台私服。连接上这一台私服之后,他就会根据坐标的信息,直接从私 服当中将对应的jar包下载到自己的本地仓库,如果我们在项目中需要使用其他第三方提供的依赖,如果本地仓库没有,也会自动连接私服下载,如 果私服没有,私服此时会自动连接中央仓库,去中央仓库中下载依赖,然后将下载的依赖存储在私服仓 库及本地仓库中。