Git和Maven的学习笔记
阅读原文时间:2023年07月09日阅读:2

Git

Git 是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种 项目。

Git 易于学习,占地面积小,性能极快。 它具有廉价的本地库,方便的暂存区域和多个工作 流分支等特性。其性能优于 Subversion、CVS、Perforce 和 ClearCase 等版本控制工具。

1.1、何为版本控制

版本控制是一种记录文件内容变化,以便将来查阅特定版本修订情况的系统。 版本控制其实最重要的是可以记录文件修改历史记录,从而让用户能够查看历史版本, 方便版本切换。

1.2、为什么需要版本控制

个人开发过渡到团队协作

1.3、版本控制工具

  • 集中式版本控制工具

    • CVS、SVN(Subversion)、VSS…… 集中化的版本控制系统诸如 CVS、SVN 等,都有一个单一的集中管理的服务器,保存 所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或 者提交更新。多年以来,这已成为版本控制系统的标准做法。 这种做法带来了许多好处,每个人都可以在一定程度上看到项目中的其他人正在做些什 么。而管理员也可以轻松掌控每个开发者的权限,并且管理一个集中化的版本控制系统,要 远比在各个客户端上维护本地数据库来得轻松容易。 事分两面,有好有坏。这么做显而易见的缺点是中央服务器的单点故障。如果服务器宕 机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。
  • 分布式版本控制工具

    • Git、Mercurial、Bazaar、Darcs…… 像 Git 这种分布式版本控制工具,客户端提取的不是最新版本的文件快照,而是把代码 仓库完整地镜像下来(本地库)。这样任何一处协同工作用的文件发生故障,事后都可以用 其他客户端的本地仓库进行恢复。因为每个客户端的每一次文件提取操作,实际上都是一次 对整个文件仓库的完整备份。 分布式的版本控制系统出现之后,解决了集中式版本控制系统的缺陷: 1. 服务器断网的情况下也可以进行开发(因为版本控制是在本地进行的) 2. 每个客户端保存的也都是整个完整的项目(包含历史记录,更加安全)

1.5、Git 工作机制

1.6、Git 和代码托管中心

代码托管中心是基于网络服务器的远程代码仓库,一般我们简单称为远程库。

  • 局域网

    • GitLab
  • 互联网

    • GitHub(外网)
    • Gitee 码云(国内网站)
  • 官网下载安装包,点击打开

到此,安装完成,鼠标右键出现菜单,打开bash终端,输入git --version,出现版本信息就说明安装成功。

命令名称

作用

git config --global user.name 用户名

设置用户名

git config --global user.email 邮箱

设置用户签名

git init

初始化本地库

git status

查看本地库状态

git add 文件名

添加到暂存区

git commit -m "日志信息" 文件名

提交到本地库

get reflog

查看历史记录

git reset --head 版本号

版本穿梭

3.1、设置用户签名

说明: 签名的作用是区分不同操作者身份。用户的签名信息在每一个版本的提交信息中能够看 到,

以此确认本次提交是谁做的。Git 首次安装必须设置一下用户签名,否则无法提交代码。

※注意:这里设置用户签名和将来登录 GitHub(或其他代码托管中心)的账号没有任 何关系。

3.2、初始化本地库

在项目中打开git终端,输入命令

3.3、查看本地库状态

首次查看没有任何文件

创建一个文件,添加点内容试试

检测到未追踪的文件,也就是这个文件还在工作区

3.4、添加到暂存区

颜色变成绿色,该文件已经被添加到暂存区

3.5、从暂存区中移除

git rm --cached 文件名 可以将文件移除暂存区,取消追踪该文件

3.6、提交本地库

git commit -m "日志信息" 文件名

提交之后,查看本地库状态,提示没有文件需要提交

将文件修改之后,再次查看本地库状态

提示文件被修改过,并且变成了红色

再次添加到暂存区

3.7、历史版本

语法:

  • git reflog 可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作),
  • git log 则不能察看已经删除了的commit记录

可以看到当前只有一个版本,再次提交,产生一个新的版本

再次查看,出现了一个新的版本

3.8、版本穿梭

基本语法:git reset --hard 版本号

先查看一下现在本地库的文件

现在回退到第一次提交的版本

再次查看文件

已经回退到第一次提交的版本

git版本切换,其实操作的就是head指针

head指向分支,分支指针指向版本

3.9、关于版本切换和head指针

git中的head指针用于记录当前工作的位置,可以指向commit版本,也可以指向分支

通常,我们工作在某一个分支上,比如 master 分支。当指向branch时commit提交后,master 指针和 HEAD 指针一起前进的,每做一次提交,这两个指针就会一起向前挪一步。

但是在某种情况下(例如 checkout 了某个commit),master 指针 和 HEAD 指针这种「绑定」的状态就被打破了,变成了分离头指针状态。下图就是处于分离头指针状态的情况:

HEAD 游离状态的利弊

好处:HEAD 处于游离状态时,开发者可以很方便地在历史版本之间互相切换,比如要回到某次提交,只需要 对应的 或者 名即可。

弊端:若在该基础上进行了提交,则会新开一个「匿名分支」;也就是说我们的提交是无法可见保存的,一旦切换到别的分支,原游离状态以后的提交就不可追溯了。

可以看到之后head指针指向了这个版本,而且有一个匿名分支

提交信息和当前文件也已经回到了这个版本的状态

切换回其他分支,此匿名分支就不见了

在head指针处于游离状态时,我们所做的add和commit都是没有意义的,切换到其他分支之后,head游离状态会消失,该分支也会消失

解决方法:在git checkout到提交的版本之后,创建一个新分支,然后我们所有操作都会保存到这个分支,之后在合并就好

另外,checkout还可以用于撤销文件修改,git checkout 文件名

该命令主要用于检出某一个指定文件。

如果不填写commit id,则默认会从暂存区检出该文件,如果暂存区为空,则该文件会回滚到最近一次的提交状态。

例如:

当暂存区为空,如果我们想要放弃对某一个文件的修改,可以用这个命令进行撤销:

3.10、关于git reset

reset有三种模式

  • --hard:重置位置的同时,直接将 working Tree工作目录index 暂存区repository 都重置成目标Reset节点的內容,所以效果看起来等同于清空暂存区和工作区。

  • --soft:重置位置的同时,保留working Tree工作目录index暂存区的内容,只让repository中的内容和 reset 目标节点保持一致,因此原节点和reset节点之间的【差异变更集】会放入index暂存区中(Staged files)。所以效果看起来就是工作目录的内容不变,暂存区原有的内容也不变,只是原节点和Reset节点之间的所有差异都会放到暂存区中。

  • --mixed(默认):重置位置的同时,只保留Working Tree工作目录的內容,但会将 Index暂存区Repository 中的內容更改和reset目标节点一致,因此原节点和Reset节点之间的【差异变更集】会放入Working Tree工作目录中。所以效果看起来就是原节点和Reset节点之间的所有差异都会放到工作目录中。

假设现在有两次提交,first commit和second commit,以下演示各自的区别

1、--hard,从second commit重置到first commit,second commit 提交记录消失,工作区和暂存区都回到first commit提交时的状态,也就是相当于first commit(第一次提交)-->直接撤销所有修改

2、--soft,从second commit重置到first commit,second commit 提交记录消失,工作区内容不变,将第二次修改的内容添加到暂存区,也就是相当于first commit(第一次提交)-->修改内容-->git add

3、--mixed(默认),从second commit重置到first commit,second commit 提交记录消失,工作区内容不变,暂存区回到没有将修改添加进暂存区的状态,也就是相当于first commit(第一次提交)-->修改内容-->

4.1、什么是分支

在版本控制过程中,同时推进多个任务,为每个任务,我们就可以创建每个任务的单独 分支。

使用分支意味着程序员可以把自己的工作从开发主线上分离开来,开发自己分支的时 候,不会影响主线分支的运行。

对于初学者而言,分支可以简单理解为副本,一个分支就是 一个单独的副本。(分支底层其实也是指针的引用)

4.2、分支的好处

同时并行推进多个功能开发,提高开发效率。 各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支有任何影响。失败 的分支删除重新开始即可。

4.3、分支的操作

命令名称

作用

git branch 分支名

创建分支

git branch -v

查看分支

git checkout 分支名

切换分支

git merge 分支名

把指定的分支合并到当前分支上

4.3.1、查看分支

4.3.2、创建分支

此时已经有两个分支(新建分分支是当前分支的副本)

在当前分支做修改,也就是master分支

再次提交到本地库

4.3.3、切换分支

git checkout -b 分支名

可以创建并切换分支

再次查看文件

可见,当前文件没有被修改

修改当前分支

切换回master分支,准备合并

4.3.4、合并分支

  • 正常合并

    创建一个文件,add和commit

创建一个新的分支并修改文件内容,add和commit

切换回master分支,合并新分支

可以看到文件直接修改了,并且提示信息是Fast-forward

  • 合并冲突

    首先创建一个文件

add和commit

创建并切换分支

在新分支里做如下修改

add和commit,切换回master分支

修改文件的同一行,add和commit

合并分支

提示合并发生冲突

查看本地库状态

打开修改的文件

手动修改之后

再次add和commit,查看本地库状态

合并之后提交必须全部一起提交,不然会报错

fatal: cannot do a partial commit during a merge.(无法在合并期间部分提交)

关于两个分支修改同一个文件,合并时产生的情况

修改同一个文件同一个区域会产生冲突

什么是文件的同一区域?

  • 文件的同一行
  • 文件的相邻行

演示:

master分支

新建分支修改文件

切换回master分支修改文件

合并发生冲突

打开文件

同样案例修改相隔一行:

分支修改文件

切换回master分支修改文件

合并分支

没有出现冲突,代码直接合并

  • 1、团队内协作

  • 2、跨团队协作

远程仓库国内可以使用gitee,访问速度更快,使用方法和github一样,这里只介绍github

注册账号,创建一个仓库

创建完成之后

上面的地址就是仓库地址

6.1、常用操作

命令名称

作用

git remote

查看所有远程仓库

git remote -v

查看所有远程仓库详细信息

git remote add 别名 远程地址

添加远程仓库并起别名

git push 远程仓库(可以别名) 分支

推送本地分支上的内容到远程库

git clone 远程地址

将远程仓库的内容克隆到本地

git pull 远程仓库 远程分支名

将当前远程仓库对于分支最新内容拉下来与当前本地分支直接合并

git remote rm 远程仓库

远程仓库

6.2、推送-git push

git push 远程仓库 本地分支名:远程分支名

若当前分支和远程分支名字相同,则可以省略

git push 远程仓库 分支名

注意:

第一次提交会要求选择登陆方式,如果浏览器登陆过了直接用浏览器登陆就好

这里登陆的账户和提交代码的账户没有关系,登陆之后只是说明这台电脑再次登陆github不需要用户名密码(以及验证这个账号对该仓库的权限), 具体提交代码的用户是谁看git设置的邮箱

如果git-email和github-email不一致,则即使github-username和git-username用户名相同,用户在本地git和在github上操作也会被认为是不同的用户在操作,意味着:github-email用户创建了仓库,git-email用户从本地上传的代码

如果git-email和github-email一致,则认为是同一用户,意味着:用户在本地git上操作再push到github上,和直接在github上操作没有区别

总结:第一次上传代码输入用户名密码只是为了这台电脑可以正常访问github

git的email和github的email相同,则github认为是本人操作

git的email和github的email不相同,也可以正常push,但是显示的是另外一个人

另外,同一台可以设置不同用户名密码

优先级:local > global > system

6.3、拉取代码-git pull

git pull 远程仓库 分支

拉取远程分支到本地当前分支,并且自动合并

6.4、克隆远程仓库-git clone

克隆远程仓库不需要登陆,公开仓库读权限对所有人公开

克隆也不需要初始化仓库,直接git clone 远程仓库地址

完成了克隆

6.5、团队内协作

合作者模式:

团队内协作先要邀请开发人员,不然是无法push的,提示

remote: Permission to Z-HaiHua/GitTest.git denied to FH0524.

仓库的所有者把邀请合作者一起开发这个项目(git提交代码会用这个账号进行权限验证,具体提交的人还是看git设置里面的邮箱),需要加入项目的人需要同意

成为合作者之后,才能通过这个登陆github的账户提交代码到仓库

关于合作模式

git有两种合作模式:

  • 合作者模式(collaborator)

    需要仓库主人将该用户添加进合作者,邀请该用户参与开发

    每个合作者新建自己部分的feature branch,在这个新分支上进行代码修改,提交合并

如果希望项目既有collaborator同时又可以限制他们的读写权利,尤其是限制其“写”的权利,可利用organization来为team成员赋予不同等级的权力。

另外,合作者在主页看不到自己合作的仓库,需要到setting下的repository部分才能看到自己合作的项目

  • 贡献者模式(contributor)--跨团队协作

    每个贡献者在他们fork的仓库上进行代码修改、发布自己负责的部分,再向主仓库提起pull request

6.6、跨团队协作

参加协作的人fork项目到自己的库当中,然后自己库中也会有一个和原仓库一模一样的仓库,进行修改之后,通过pull request 向原项目发送拉取请求

fork之后会出现

修改代码提交之后,点击 pull request,发送拉取请求

选择好合并的分支

再次点击pull request,打开刚才的pull request

仓库会收到pull request

打开之后

点击合并之后,可以看到仓库中代码已经改变

使用命令:

ssh-keygen -t rsa -C "#”

t是加密方式

c是备注消息,便于自己记住此密钥是干嘛的,可以随便填写

之后三次回车,什么都不输入即可(第一次输入文件保存位置,默认在c盘用户目录下.ssh文件夹,第二次输入密码,第三次确认密码)

第一次使用SSH连接会提示

Are you sure you want to continue connecting (yes/no)? yes

输入yes即可,以后这台电脑连接github就不需要账号密码了

8.1、配置忽略文件

在项目开发中 ,我们肯定不希望整个项目的所有文件都被git追踪,比如idea的配置文件,编译之后的class文件,这时候我们就需要配置忽略文件

1、创建忽略规则配置文件xxx.ignore(前缀随便,文件后缀必须是这个)该文件放在哪里都行

java项目中常用的ignore文件

*.class

# Eclipse
.project
.classpath
.settings/

# Intellij
*.ipr
*.iml
*.iws
.idea/

# Maven
target/

# Gradle
build
.gradle

# Log file
*.log
log/

# out
**/out/

# Mac
.DS_Store

# others
*.jar
*.war
*.zip
*.tar
*.tar.gz
*.pid
*.orig
temp/

然后配置到git当中,可以配置到系统、用户组、仓库

[core]
    ...
    excludesfile = D:/git/GitTest01/.git/.gitignore

8.2、idea中使用Git

8.2.1、配置Git

在idea中使用git进行版本控制

点击版本控制设置

8.2.2、配置Git忽略文件

将文件或者文件夹添加进忽略名单

忽略的文件

8.2.3、基本使用

添加暂存区和提交都是鼠标右键--->Git--->…….

切换版本

在idea中打开log窗口,可以查看所有提交记录,右键选择checkout或者reset

新建分支:右键-->Git-->branch-->New Branch

切换分支:右键-->Git-->branch-->选择要切换的分支-->点击-->checkout

删除分支:当前分支不能删除,需要切换到其他分支才可以删除当前分支,右键-->Git-->branch-->选择要删除的分支-->点击-->delete

合并分支

合并冲突

使用令牌登陆,首先创建令牌

令牌创建之后要立马复制下来,不然之后看不到了

然后到IDEA中添加账号

之后把令牌填上去就可以登陆了,登陆之后

9.1、IDEA中创建github仓库并分享项目

IDEA自带的github插件可以在idea中远程创建github仓库以及分享项目

9.2、IDEA中操作github

在idea中创建仓库必须要用账号密码登陆,其他操作可以用SSH免密登陆

添加一个SSH连接的git仓库就好

push和pull,都是右键-->Git-->push/pull

克隆项目

输入链接即可克隆项目

Maven基础

在Javaweb开发中,需要使用大量的jar包,我们手动去导入;

如何能够让一个东西自动帮我导入和配置这个jar包。由此,Maven诞生了!

Maven的本质是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型(POM)

Maven是用Java语言编写的。他管理的东西统统以面向对象的形式进行设计,最终它把一个项目看成一个对象,而这个对象叫做POM(project object model),即项目对象模型。

我们说一个项目就是一个对象,作为对象的行为、对象的属性都有哪些呢?

Maven说我们需要编写一个pom.xml文件,Maven通过加载这个配置文件就可以知道我们项目的相关信息了!到这里我们知道了Maven离不开一个叫pom.xml的文件。因为这个文件代表就一个项目。

提个问题大家思考,如果我们做8个项目,对应的是1个文件,还是8个文件?肯定是8个!

那Maven是如何帮我们进行项目资源管理的呢?这就需要用到Maven中的第二个东西:依赖管理。这也是它的第二个核心!

所谓依赖管理就是maven对项目所有依赖资源的一种管理,它和项目之间是一种双向关系,即当我们做项目的时候maven的依赖管理可以帮助你去管理你所需要的其他资源,当其他的项目需要依赖我们项目的时候,maven也会把我们的项目当作一种资源去进行管理,这就是一种双向关系。

那maven的依赖管理它管理的这些资源存在哪儿呢?主要有三个位置:本地仓库,私服,中央仓库

本地仓库顾名思义就是存储在本地的一种资源仓库,如果本地仓库中没有相关资源,可以去私服上获取,私服也是一个资源仓库,只不过不在本地,是一种远程仓库,如果私服上也没有相关资源,可以去中央仓库去获取,中央仓库也是一种远程仓库。

Maven除了帮我们管理项目资源之外还能帮助我们对项目进行构建,管理项目的整个生命周期,当然它的这些功能需要使用一些相关的插件来完成,当然整个生命周期过程中插件是需要配合使用的,单独一个无法完成完整的生命周期。

1.2、Maven的作用

Maven的作用我们可以分成三类:

(1)项目构建:提供标准的,跨平台的自动化构建项目的方式

(2)依赖管理:方便快捷的管理项目依赖的资源(jar包),避免资源间的版本冲突等问题

(3)统一开发结构:提供标准的,统一的项目开发结构,如下图所示:

各目录存放资源类型说明:

src/main/java:项目java源码

src/main/resources:项目的相关配置文件(比如mybatis配置,xml映射配置,自定义配置文件等)

src/main/webapp:web资源(比如html,css,js等)

src/test/java:测试代码

src/test/resources:测试相关配置文件

src/pom.xml:项目pom文件

旧版下载

解压即安装完成

各目录结构说明:

bin:可执行程序目录,

boot:maven自身的启动加载器

conf:maven配置文件的存放目录

lib:maven运行所需库的存放目录

配置环境变量

path环境变量中

输入命令

即安装成功

由于maven下载依赖默认从国外的中央仓库下载,网速会很慢,所以要配置镜像

打开conf下的settings文件

配置好镜像

<mirror>
      <id>aliyunmaven</id>
      <mirrorOf>central</mirrorOf>
      <name>阿里云公共仓库</name>
      <url>https://maven.aliyun.com/repository/public</url>
</mirror>

由于maven默认把依赖下载到c盘,这里改一下路径

3.1、仓库

关于仓库,我们前面讲到了有三种:本地仓库,私服,中央仓库,其中私服和中央仓库都属于远程仓库

中央仓库:maven团队自身维护的仓库,属于开源的

私服:各公司/部门等小范围内存储资源的仓库,私服也可以从中央仓库获取资源

本地仓库:开发者自己电脑上存储资源的仓库,也可从远程仓库获取资源

私服的作用:

(1)保存具有版权的资源,包含购买或自主研发的jar

(2)一定范围内共享资源,能做到仅对内不对外开放

3.2、坐标

我们说maven的仓库里存储了各种各样的资源(jar包),那这些资源我们如何找到它们呢?我们需要知道它们具体的一个位置才能知道如何找到它们,这个就叫坐标

坐标:maven中的坐标用于描述仓库中资源的位置

maven坐标的主要组成如下:

groupId:定义当前资源隶属组织名称(通常是域名反写,如:org.mybatis;com.itheima)

artifactId:定义当前资源的名称(通常是项目或模块名称,如:crm,sms)

version:定义当前资源的版本号

packaging:定义资源的打包方式,取值一般有如下三种

  • jar:该资源打成jar包,默认是jar java工程打包为jar

  • war:该资源打成war包 web工程打包为war

  • pom:该资源是一个父资源(表明使用maven分模块管理),打包时只生成一个pom.xml不生成jar或其他包结构


    http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    4.0.0

    war

    <!--组织id-->
    <groupId>com.zh</groupId>
    <!--项目id-->
    <artifactId>web01</artifactId>
    <!--组织id  release代表完成版,SNAPSHOT代表开发版-->
    <version>1.0-SNAPSHOT</version>
    
    <!--设置当前工程的所有依赖-->
    <dependencies>
        <!--具体的依赖-->
        <dependency>
        </dependency>
    </dependencies>

3.3、插件

Maven 实际上是一个依赖插件执行的框架,它执行的每个任务实际上都由插件完成的。Maven 的核心发布包中并不包含任何 Maven 插件,它们以独立构件的形式存在, 只有在 Maven 需要使用某个插件时,才会去仓库中下载。

Maven 默认为一些核心的生命周期阶段绑定了插件目标,当用户调用这些阶段时,对应的插件目标就会自动执行相应的任务。

运行web项目可以添加tomcat插件

<build>
    <plugins>
        <!--打war包插件-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.2.0</version>
        </plugin>
        <!--Tomcat插件 -->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
        </plugin>
    </plugins>
</build>

3.4、依赖

Maven项目可以通过声明式导入所需要的资源,需要什么,写几行代码,Maven就会自动把资源下载并添加到资源库中

<!--项目依赖-->
  <dependencies>
    <!--具体依赖的jar包配置文件-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
    </dependency>
  </dependencies>

3.5、POM文件

pom.xml 是Maven的核心配置文件

<?xml version="1.0" encoding="UTF-8"?>

<!--Maven版本和头文件-->
<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>com.zh</groupId>
  <artifactId>javaweb-01-maven</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!--Package:项目的打包方式
  jar:java应用
  war:JavaWeb应用
  -->
  <packaging>war</packaging>

  <!--配置-->
  <properties>
    <!--项目的默认构建编码-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!--编码版本-->
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <!--项目依赖-->
  <dependencies>
    <!--具体依赖的jar包配置文件-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
    </dependency>
  </dependencies>

  <!--项目构建用的东西-->
    <build>
        <plugins>
        <!--打war包插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.0</version>
            </plugin>
            <!--Tomcat插件 -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
            </plugin>
        </plugins>
    </build>
</project>

创建一个最简单的Maven项目

这就是一个最简单的Maven项目

创建完成记得看一眼是不是用的自己的Maven仓库

依赖传递:

依赖具有传递性,分两种

(1)直接依赖:在当前项目中通过依赖配置建立的依赖关系

(2)间接依赖:被依赖的资源如果依赖其他资源,则表明当前项目间接依赖其他资源

依赖传递冲突

依赖传递的冲突问题:

在依赖传递过程中产生了冲突,我们有三种优先法则

(1)路径优先:当依赖中出现相同资源时,层级越深,优先级越低,反之则越高

(2)声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖靠后的

(3)特殊优先:当同级配置了相同资源的不同版本时,后配置的覆盖先配置的

以一个项目为根,直接依赖称为1度资源,直接依赖的直接依赖称为2度资源,直接依赖的直接依赖的直接依赖称为3度资源。

当然依赖冲突在这里我们并不需要记,后面会有如何解决此问题的办法。

可选依赖

可选依赖指的是对外隐藏当前所依赖的资源-->不透明

加一个optional属性

<dependencies>
    <dependency>
        <groupId>Junit</groupId>
        <artifactId>Junit</artifactId>
        <version>4.12</version>
        <optional>true</optional>
    </dependency>
</dependencies>

排除依赖

排除依赖指主动断开依赖的资源,被排除的资源无需指定版本

<dependencies>
    <dependency>
        <groupId>Junit</groupId>
        <artifactId>Junit</artifactId>
        <version>4.12</version>
        <exclusions>
            <exclusion>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
            </exclusion>
    </dependency>
</dependencies>

依赖范围

依赖的jar默认情况可以在任何地方可用,可以通过scope标签设定其作用范围

这里的范围主要是指以下三种范围

(1)主程序范围有效(src/main目录范围内)

(2)测试程序范围内有效(src/test目录范围内)

(3)是否参与打包(package指令范围内)

此外:scope标签的取值有四种:

  • compile
  • test
  • provided
  • runtime

这四种取值与范围的对应情况如下:

Maven对项目构建的生命周期划分为3套

clear:清理工作

default:核心工作,例如编译、测试、打包、部署等

site:产生报告、发布站点等

6.1、clear生命周期

clean:清理工作

pre-clean:执行一些在clean之前的工作

clean:移除上一次构建产生的所有文件

post-clean:执行一些在clean之后立刻完成的工作

6.2、default生命周期

default:核心工作,例如编译,测试,打包,部署等

对于default生命周期,每个事件在执行之前都会将之前的所有事件依次执行一遍

6.3、site生命周期

site:产生报告,发布站点等

pre-site:执行一些在生成站点文档之前的工作

site:生成项目的站点文档

post-site:执行一些在生成站点文档之后完成的工作,为部署做准备

site-deploy:将生成的站点文档部署到特定的服务器上

pom文件中加入如下配置

<!--在build中配置resources,来防止我们资源导出失败的问题-->
<!--resources下的properties、xml都可以导出-->
<!--java下的properties、xml都可以导出-->
<build>
    <resources>
        <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
        </resource>
        <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.properties</include>
            <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
        </resource>
    </resources>
</build>

Maven进阶

按模块划分之后,将需要使用的模块使用引入资源的方式引入即可,注意,在引入之前,需要先将该模块安装到本地库中

2、聚合模块

作用:快速构建maven工程,处理多模块工程比较方便

使用:创建一个空模块,打包类型为pom,此模块不需要src

<packaging>pom</packaging>

定义当前模块构建时关联的其他模块名称

<modules>
    <module>ssm-controller</module>
    <module>ssm-service</module>
    <module>ssm-dao</module>
    <module>ssm-pojo</module>
</modules>

参与集合的模块构建顺序与模块间的依赖有关,与配置无关

3、继承

作用:通过继承,可以实现在子工程中沿用父工程中的配置

使用:在子工程中声明父工程坐标与对应路径

注意,继承和聚合一样,父工程中也只有一个pom文件

<parent>
    <groupId>. . .</groupId>
    <artifactId>. . .</artifactId>
    <version>. . .</version>
    <relativePath>. . .</relativePath>
</parent>

在父工程中管理依赖

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${springframework.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

插件管理

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

这里声明只是为子工程设定版本,并不是实际的去引用依赖

子工程继承之后,不在需要写完整的GAV,让父工程统一管理

<groupId>com.juvenxu.mvnbook.account</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>

只需要写

<artifactId>account-parent</artifactId>

同时,在依赖和插件中也只需要写

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
</dependency>

版本通过父工程继承

可继承的pom元素

  • groupId:项目组ID,项目坐标的核心元素
  • version: 项目版本, 项目坐标的核心元素
  • description: 项目的描述信息
  • organization: 项目的组织信息
  • inceptionYear: 项目的创始年份
  • url: 项目的URL地址
  • developers: 项目开发者信息
  • contributors: 项目的贡献者信息
  • distributionManagement: 项目的部署配置
  • issueManagement: 项目的缺陷跟踪系统信息
  • ciManagement: 项目的持续集成系统信息
  • scm: 项目的版本控制系统信息
  • mailingLists: 项目的邮件列表信息
  • properties: 自定义的maven属性
  • dependencies: 项目的依赖配置
  • dependencyManagement: 项目的依赖管理配置
  • repositories: 项目的仓库配置
  • build: 包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
  • reporting: 包括项目的报告输出目录配置、报告插件配置等

继承与聚合

  • 作用

    • 聚合用于快速构建项目
    • 继承用于快速配置
  • 相同点

    • 聚合与继承的pom文件打包方式都为pom,可以将两种关系制作在同一个pom文件中
    • 聚合与继承属于设计模式,并无实际的模块内容
  • 不同点

    • 聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些
    • 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己

4、属性

Maven中允许自定义属性,相当于变量,在需要的地方引用

<properties>
    <spring.framework>4.0.4.RELEASE</spring.framework>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.framework}</version>
    </dependency>
</dependencies>

此外,maven属性分为

  • 内部属性

    • 内置属性
    • 项目属性
    • setting属性
    • 自定义属性
  • 外部属性

    • java系统属性
    • 环境变量属性

具体不在这里赘述

5、版本管理

工程版本

  • SNAPSHOT (快照版本)

    • 项目开发过程中,为方便团队成员合作,解决模块间相互依赖和时时更新的问题,开发者对每个模块进行构建的时候,输出的临时性版本叫快照版本(测试阶段版本)
    • 快照版本会随着开发的进展不断更新
  • RELEASE (发布版本)

    • 项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的,即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本

工程版本号约定

  • 约定规范:

    • <主版本>.<次版本>.<增量版本>.<里程碑版本>
    • 主版本:表示项目重大架构的变更,如: spring5相较 于spring4的迭代
    • 次版本:表示有较大的功能增加和变化,或者全面系统地修复漏洞
    • 增量版本:表示有重大漏洞的修复
    • 里程碑版本:表明- -个版本的里程碑(版本内部)。这样的版本同下一-个正式版本相比,相对来说不是很稳定,有待更多的测试
  • 范例:

    5.1.9.RELEASE

6、资源配置

maven支持配置文件使用pom文件里面配置的属性

使用:在pom文件中定义属性和属性值,在配置文件中使用${属性} 的方式引用

<properties>
    <jdbc.url>jdbc:mysql://localhost:3306/de01</jdbc.url>
</properties>
.....
配置资源文件对应的信息
<resources>
    <resource>
    <!-设定配置文件对应的位置目录,支持使用属性动态设定路径-->
    <directory>${project.basedir}/src/main/resources</directory>
    <!--开启对配置文件的资源加载过滤-->
    <filtering>true</ filtering>
    </resource>
</resources>

7、多环境开发配置

<!--多环境配置-->
<!--创建多环境-->
<profiles>
<!--定义具体的环境:生产环境-->
    <profile>
    <!--定义环境对应的唯一名称-->
        <id>pro_ env</id>
        <!--定义环境中专用的属性值-->
        <properties>
            <jdbc.ur1>jdbc:mysql://127.1.1.1:3306/ssmdb</jdbc.ur1>
        </ properties>
        <!--设置默认启动-->
        <activation>
            <activeByDefault>true</ activeByDefault>
        </activation>
    </profi1e>
    <!--定义具体的环境:开发环境-->
    <profile>
    <id>dev_env</id>
    ....
    </profi1e>
</profiles>

8、跳过测试

  • 使用命令跳过测试

    mvn 指令 -D skipTests

  • 使用idea界面操作

  • 通过配置插件


    maven- surefire -plugin
    2.22. 1
    true /UserTest.java /UserTestCase.java

9、私服

Nexus仓库类型

Nexus仓库类型有三种:

1.hosted:宿主仓库(服务器本地仓库):通常我们上传自己的依赖到这一类型的仓库,比如公司的第二方库。

2.proxy:代理仓库:它们被用来代理远程的公共仓库,如maven中央仓库

3.group:仓库组:仓库的集合,把多个仓库的依赖都整合到一个大的集合中来;用来合并多个hosted/proxy仓库,当你的项目希望在多个repository使用资源时就不需要多次引用了,只需要引用一个group即可。

安装好Nexus后,系统会预先自带几个仓库:如图:

下面说说,另外三种仓库的作用:

1.Releases: 这里存放我们自己项目中发布的构建,通常是Release版本的,已经正式发布的。

2.Snapshots:存放临时的依赖,非最终版本、非稳定版本的依赖,比如你正在开发的starter,你的同事需要引用里面的类,就可以发布到这个类型的仓库中。

3.3rd Party:存放第三方的依赖。

安装nexus

下载之后直接解压即可

启动nexus

切换到安装目录下的bin目录下的命令行

启动:./nexus start

关闭:./nexus stop

端口修改:端口可以在配置文件中修改  xxx/nexus-3.28.1-01/etc/nexus-default.properties

浏览器访问 \http://localhost:8081即是nexus登陆页面

登录

账户:admin

密码:查看 sonatype-work/nexus3/admin.password

基础操作

./nexus status 查看启动状态

./nexus stop 停止

./nexus restart重启

配置私服的镜像路径

获取资源的路径,配置仓库组,表示从仓库组中获取资源

在settings.xml 文件的 mirrors 内添加以下镜像地址

<mirror>
    <id>maven-public</id>
    <name>maven-public</name>
    <mirrorOf>*</mirrorOf>
    <url>http://localhost:8081/repository/maven-public/</url>
</mirror>

配置服务器信息

本地访问仓库的权限,用于上传资源

<!-- 服务器的账户密码配置-->
<servers>
    <server>
      <!-- id可以随便取 但是在pom中引用的时候需要保持一致-->
        <id>maven_release</id>
        <username>admin</username>
        <password>admin</password>
    </server>
    <server>
        <id>maven_snapshots</id>
        <username>admin</username>
        <password>admin</password>
    </server>

    <server>
      <id>maven-central</id>
      <username>admin</username>
      <password>admin</password>
    </server>
</servers>

配置当前项目访问私服上传资源保存位置(pom.xml)

<distributionManagement><!-- 远程部署管理信息 -->
<!-- 项目部署到私服配置 id和上面server中配置的id一致-->
        <repository><!--部署项目产生的构件到远程仓库需要的信息 -->
            <id>maven_release</id>
            <name>maven-releases</name>
            <url>http://localhost:8081/repository/maven-releases/</url>
        </repository>
        <snapshotRepository><!-- 如果没有配置该元素,默认部署到repository元素配置的仓库 -->
            <id>maven_snapshots</id>
            <name>maven-snapshots</name>
            <url>http://localhost:8081/repository/maven-snapshots/</url>
        </snapshotRepository>
</distributionManagement>

发补资源到私命令

mvn deploy