Home maven 学习
Post
Cancel

maven 学习

Maven 是一款用于管理和构建 java 项目的工具

Maven 可以方便快捷的管理项目依赖的资源 (jar 包),避免版本冲突问题;提供标准、统一的项目结构;标准跨平台的自动化项目构建方式

安装

官网下载后解压,然后配置本地仓库,修改 conf/setting.xml 中的 <localRepository> 为一个指定目录

1
2
<!-- 例如本地库在 D:\develop\maven_repo -->
<localRepository>D:\develop\maven_repo</localRepository>

配置阿里云私服镜像,修改 conf/setting.xml 中的 <mirror> 标签,添加子标签

1
2
3
4
5
6
<mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>
</mirror>

配置环境变量:MAVEN_HOME 为 maven 解压目录,并将其 bin 目录加入 PATH 环境变量


测试安装完成:在命令行输入 mvn -v 查看输出

依赖配置

依赖:指当前项目运行所需要的 jar 包,一个项目中可以引入多个依赖

配置步骤:

  1. 在 pom.xml 中编写 <dependencies> 标签
  2. <dependencies> 标签中使用 <dependency> 引入坐标
  3. 定义坐标的 groupId, artifactId, version
  4. 刷新配置,引入新加入的坐标
1
2
3
4
5
6
7
8
<!-- 例如引入 logback -->
<dependencies>
	<dependency>
    	<groupId>ch.qos.logback</groupId>
    	<artifactId>logback-classic</artifactId>
    	<version>1.2.3</version>
	</dependency>
</dependencies>

可以到 https://mvnrepository.com/ 查找依赖坐标信息

依赖传递

依赖具有传递性

  • 直接依赖:在当前项目中通过依赖配置建立的依赖关系
  • 间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源

当添加依赖时,若此包依赖其他包,将自动添加相关包


当然,若某包的子包并不需要,可以排除依赖 (指主动断开依赖的资源,被排除的资源无需指定版本)

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 例如排除某项目的 junit -->
<dependency>
	<groupId>com.yexca</groupId>
    <artifactId>maven-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <exclusions>
    	<exclusion>
        	<groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

依赖范围

依赖的 jar 包,默认可以在任何地方使用,可以通过 <scope>...</scope> 设置其作用范围:

  • 主程序范围有效 (main 文件夹范围内)
  • 测试程序范围有效 (test 文件夹范围内)
  • 是否参与打包运行 (package 指令范围内)
scope 值 主程序 测试程序 打包 (运行) 范例
compile (默认) Y Y Y log4j
test - Y - junit
provided Y Y - servlet-api
runtime - Y Y jdbc 驱动
1
2
3
4
5
6
<dependency>
	<groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.10</version>
    <scope>test</scope>
</dependency>

生命周期

Maven 的生命周期就是为了对所有的 maven 项目构建过程进行抽象和统一

Maven 中有 3 套相互独立的生命周期:

  • clean:清理工作
  • default:核心工作,如:编译、测试、打包、安装、部署等
  • site:生成报告、发布站点等

其中每套生命周期包含一些阶段 (phase) ,阶段是有顺序的,后面的阶段依赖于前面的阶段

clean

  • pre-clean
  • clean:移除上一次构建生成的文件 (target 文件夹)
  • post-clean

default

  • validate
  • initialize
  • generate-sources
  • process-sources
  • generate-resources
  • process-resources
  • compile:编译项目源代码
  • process-classes
  • generate-test-sources
  • process-test-sources
  • generate-test-resources
  • process-test-resources
  • test-compile
  • process-test-classes
  • test:使用合适的单元测试框架运行测试 (junit)
  • prepare-package
  • package:将编译后的文件打包,如 jar、war 等
  • verify
  • install:安装项目到本地仓库
  • deploy

site

  • pre-site
  • site
  • post-site
  • site-deploy

在同一套生命周期中,当运行后面的阶段时,前面的阶段都会运行

分模块设计

分模块设计我们在进行项目设计阶段,就可以将一个大的项目拆分成若干个模块,每一个模块都是独立的,如果我们需要用到另外一个模块的功能,我们直接依赖模块就可以了

可以把一些通用的实体类或工具类单独作为一个模块,若某一模块需要使用,直接引入对应的依赖即可

方便项目的管理维护、扩展,也方便模块间的相互调用,资源共享

继承

像 Lombok 依赖,可能项目中的每个模块都会使用,每个模块都声明一次相当繁琐,可以通过继承解决这个问题

继承关系

创建一个父工程,将模块共有的依赖都提取到父工程进行配置,只要子类继承了父工程,依赖也会继承下来,这样就无需在各个子工程中进行配置了

继承描述的是两个工程间的关系,与 java 中的继承相似,子工程可以继承父工程中的配置信息,常见于依赖关系的继承,可以简化依赖配置、统一管理依赖

1
2
3
4
5
6
7
<!--指定父工程-->
<parent>
    <groupId>...</groupId>
    <artifactId>...</artifactId>
    <version>...</version>
    <relativePath>....</relativePath>
</parent>

如果是 JavaWeb 开发,可以让父工程继承 spring-boot-starter-parent,其他模块继承该父工程

一般情况下,在文件结构中,子工程为父工程子级

以下为例子

  1. 父工程的打包方式为 pom
1
2
3
4
5
6
7
8
9
10
11
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.5</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>net.yexca</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

Maven打包方式:

  • jar:普通模块打包,SpringBoot 项目基本都是jar包 (内嵌 tomcat 运行)
  • war:普通 web 程序打包,需要部署在外部的 tomcat 服务器中运行
  • pom:父工程或聚合工程,该模块不写代码,仅进行依赖管理
  1. 子工程指定父工程
1
2
3
4
5
6
7
8
9
10
11
12
13
<parent>
    <groupId>net.yexca</groupId>
    <artifactId>tlias-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- 指定父工程的pom文件的相对位置(如果不指定,将从本地仓库/远程仓库查找该工程) -->
    <relativePath>../tlias-parent/pom.xml</relativePath>
</parent>

<!-- <groupId>net.yexca</groupId> 
-	因为自动继承父工程,可以省略
-->
<artifactId>tlias-utils</artifactId>
<version>1.0-SNAPSHOT</version>
  1. 父工程中配置共有依赖
1
2
3
4
5
6
7
<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
    </dependency>
</dependencies>

版本锁定

某依赖部分模块需要,部分模块不需要,可以在父级中管理依赖的 version,方便管理与修改

可以通过 <dependencyManagement> 标签管理依赖版本

父工程

1
2
3
4
5
6
7
8
9
10
11
<!--统一管理依赖版本-->
<dependencyManagement>
    <dependencies>
        <!--JWT令牌-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
    </dependencies>
</dependencyManagement>

子工程

1
2
3
4
5
6
7
8
9
10
<dependencies>
    <!--JWT令牌-->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <!-- <version>0.9.1</version>
		- 因为父工程指定了版本,不需要填写
		-->
    </dependency>
</dependencies>

父工程的 <dependencyManagement> 配置只管理版本,不会将依赖引入子工程。只有在子工程引入才会引入,只是引入时无需指定版本号

<dependencies> 会把依赖引入子工程

属性配置

也可以通过自定义属性及属性引用的形式,在父工程中将依赖的版本号进行集中管理维护

自定义属性:

1
2
3
<properties>
	<lombok.version>1.18.24</lombok.version>
</properties>

引用属性:

1
2
3
4
5
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok.version}</version>
</dependency>

于是可以在父工程中将所以的版本号,集中管理维护

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>

    <lombok.version>1.18.24</lombok.version>
    <jjwt.version>0.9.1</jjwt.version>
    <aliyun.oss.version>3.15.1</aliyun.oss.version>
    <jaxb.version>2.3.1</jaxb.version>
    <activation.version>1.1.1</activation.version>
    <jaxb.runtime.version>2.3.3</jaxb.runtime.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
    </dependency>
</dependencies>

<!--统一管理依赖版本-->
<dependencyManagement>
    <dependencies>
        <!--JWT令牌-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jjwt.version}</version>
        </dependency>

        <!--阿里云OSS-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>${aliyun.oss.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>${jaxb.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>${activation.version}</version>
        </dependency>
        <!-- no more than 2.3.3-->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>${jaxb.runtime.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

若想要修改依赖的版本,只需要在父工程的自定义属性,修改相应属性值即可

聚合

若一个模块依赖另一个模块,打包该模块前需要先将其他模块 install 到本地仓库,然后再打包。如果依赖的模块很多,那么需要执行的操作过于繁琐

通过 maven 的聚合就可以轻松实现项目的一键构建 (清理、编译、测试、打包、安装等)

  • 聚合:将多个模块组织成一个整体,同时进行项目的构建
  • 聚合工程:一个不具有业务功能的“空”工程 (有且仅有一个pom文件。一般来说,继承关系中的父工程与聚合关系中的聚合工程是同一个)
  • 作用:快速构建项目 (无需根据依赖关系手动构建,直接在聚合工程上构建即可)

可以在聚合工程中通过 <modules> 设置当前聚合工程所包含的子模块的名称

1
2
3
4
5
6
7
<!--聚合其他模块-->
<modules>
    <!-- 工程路径 -->
    <module>../tlias-pojo</module>
    <module>../tlias-utils</module>
    <module>../tlias-web-management</module>
</modules>

之后进行编译、打包、安装操作只在聚合工程上即可,其他工程会自动同步操作

  继承 聚合
作用 继承用于简化依赖配置、统一管理依赖 聚合用于快速构建项目
相同点 打包方式均为 pom,通常制作到同一 pom 均属于设计型模块,无实际内容
不同点 继承是在子模块中配置关系
父模块无法感知哪些子模块继承了自己
聚合是在聚合工程中配置关系
聚合可以感知到参与聚合的模块有哪些

私服

私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的中央仓库,用于解决团队内部的资源共享与资源同步问题

如果在项目中需要使用其他第三方提供的依赖,如果本地仓库没有,会自动连接私服下载,如果私服没有,私服此时会自动连接中央仓库,去中央仓库中下载依赖,然后将下载的依赖存储在私服仓库及本地仓库中

私服一般一个公司一台,不用自己配置

私服仓库与项目版本

私服仓库说明:

  • RELEASE:存储自己开发的 RELEASE 发布版本的资源
  • SNAPSHOT:存储自己开发的 SNAPSHOT 发布版本的资源
  • Central:存储的是从中央仓库下载下来的依赖

项目版本说明:

  • RELEASE (发布版本):功能趋于稳定、当前更新停止,可以用于发行的版本,存储在私服中的RELEASE仓库中
  • SNAPSHOT (快照版本):功能不稳定、尚处于开发中的版本,即快照版本,存储在私服的SNAPSHOT仓库中

配置

设置私服的访问用户名与密码,在 Maven 安装目录的 conf/settings.xml 的 servers 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
<servers>
<server>
    <id>maven-releases</id>
    <username>admin</username>
    <password>admin</password>
</server>
    
<server>
    <id>maven-snapshots</id>
    <username>admin</username>
    <password>admin</password>
</server>
</servers>

设置私服依赖下载的仓库组地址,文件同上,mirrors 与 profiles 标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<mirrors>
<mirror>
    <id>maven-public</id>
    <mirrorOf>*</mirrorOf>
    <url>http://127.0.0.1:8081/repository/maven-public/</url>
</mirror>
</mirrors>

<profiles>
<profile>
    <id>allow-snapshots</id>
        <activation>
        	<activeByDefault>true</activeByDefault>
        </activation>
    <repositories>
        <repository>
            <id>maven-public</id>
            <url>http://127.0.0.1:8081/repository/maven-public/</url>
            <releases>
            	<enabled>true</enabled>
            </releases>
            <snapshots>
            	<enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
</profile>
</profiles>

pom 文件配置上传地址,在父工程中配置即可

1
2
3
4
5
6
7
8
9
10
11
12
13
<distributionManagement>
    <!-- release版本的发布地址 -->
    <repository>
        <id>maven-releases</id>
        <url>http://127.0.0.1:8081/repository/maven-releases/</url>
    </repository>

    <!-- snapshot版本的发布地址 -->
    <snapshotRepository>
        <id>maven-snapshots</id>
        <url>http://127.0.0.1:8081/repository/maven-snapshots/</url>
    </snapshotRepository>
</distributionManagement>

配置完成后,执行父工程的 deploy 生命周期即可将项目发布到私服仓库

This post is licensed under CC BY 4.0 by the author.

JavaWeb 入门

Spring 请求响应