跳到主要内容

maven

如何在java项目中使用maven
为什么需要maven

考虑一个常见的场景:以项目A为例,开发过程中,需要依赖B-2.0.jar的包,如果没有maven,那么正常做法是把B-2.0.jar拷贝到项目A中,但是如果B-2.0.jar还依赖C.jar,我们还需要去找到C.jar的包,因此,在开发阶段需要花费在项目依赖方面的精力会很大。

因此,开发人员需要找到一种方式,可以管理java包的依赖关系,并可以方便的引入到项目中。

maven如何工作

查看pom.xml

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

可以直接在项目中添加上dependency ,这样来指定项目的依赖包。

思考:如果spring-boot-starter-thymeleaf包依赖别的包,怎么办?

spring-boot-starter-thymeleaf同时也是一个maven项目,也有自己的pom.xml

查看一下:

  <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.3.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>3.0.4.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>

这样的话,使用maven的项目,只需要在自己的pom.xml中把所需的最直接的依赖包定义上,而不用关心这些被依赖的jar包自身是否还有别的依赖。剩下的都交给maven去搞定。

如何搞定?maven可以根据pom.xml中定义的依赖实现包的查找

去哪查找?maven仓库,存储jar包的地方。

当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库:

本地仓库:

  • Maven 的本地仓库,在安装 Maven 后并不会创建,它是在第一次执行 maven 命令的时候才被创建。

  • 运行 Maven 的时候,Maven 所需要的任何包都是直接从本地仓库获取的。如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库,然后再使用本地仓库的包。

  • 默认情况下,不管Linux还是 Windows,每个用户在自己的用户目录下都有一个路径名为 .m2/respository/ 的仓库目录。

  • Maven 本地仓库默认被创建在 %USER_HOME% 目录下。要修改默认位置,在 %M2_HOME%\conf 目录中的 Maven 的 settings.xml 文件中定义另一个路径。

    <settings xmlns="http://maven.apache.org/SETTINGS/_1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"\>
    <localRepository>D:\opt\maven-repo</localRepository>
    </settings>

中央仓库:

Maven 中央仓库是由 Maven 社区提供的仓库,中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载到。

中央仓库的关键概念:

  • 这个仓库由 Maven 社区管理。
  • 不需要配置,maven中集成了地址 http://repo1.maven.org/maven2
  • 需要通过网络才能访问。

私服仓库:

通常使用 sonatype Nexus来搭建私服仓库。搭建完成后,需要在 setting.xml中进行配置,比如:

<profile>
<id>localRepository</id>
<repositories>
<repository>
<id>myRepository</id>
<name>myRepository</name>
<url>http://127.0.0.1:8081/nexus/content/repositories/myRepository/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>

方便起见,我们直接使用国内ali提供的仓库,修改 maven 根目录下的 conf 文件夹中的 setting.xml 文件,在 mirrors 节点上,添加内容如下:

<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>

在执行构建的时候,maven会自动将所需的包下载到本地仓库中,所以第一次构建速度通常会慢一些,后面速度则很快。

那么maven是如何找到对应的jar包的?

我们可以访问 https://mvnrepository.com/ 查看在仓库中的jar包的样子。

\<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections --\>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>

刚才看到spring-boot-starter-thymeleaf的依赖同样有上述属性,因此maven就可以根据这三项属性,到对应的仓库中去查找到所需要的依赖包,并下载到本地。

其中groupId、artifactId、version共同保证了包在仓库中的唯一性,这也就是为什么maven项目的pom.xml中都先配置这几项的原因,因为项目最终发布到远程仓库中,供别人调用。

思考:我们项目的dependency中为什么没有写version ?

是因为sprintboot项目的上面有人,来看一下项目parent的写法:

    <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.6.RELEASE</version>
<relativePath/> \<!-- lookup parent from repository --\>
</parent>

parent模块中定义过的dependencies,在子项目中引用的话,不需要指定版本,这样可以保证所有的子项目都使用相同版本的依赖包。

生命周期及mvn命令实践

Maven有三套相互独立的生命周期,分别是clean、default和site。每个生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。

  • clean生命周期,清理项目
    • 清理:mvn clean    --删除target目录,也就是将class文件等删除
  • default生命周期,项目的构建等核心阶段
    • 编译:mvn compile  --src/main/java目录java源码编译生成class (target目录下)
    • 测试:mvn test    --src/test/java 执行目录下的测试用例
    • 打包:mvn package  --生成压缩文件:java项目#jar包;web项目#war包,也是放在target目录下
    • 安装:mvn install   --将压缩文件(jar或者war)上传到本地仓库
    • 部署|发布:mvn deploy  --将压缩文件上传私服
  • site生命周期,建立和发布项目站点
    • 站点 : mvn site --生成项目站点文档

各个生命周期相互独立,一个生命周期的阶段前后依赖。 生命周期阶段需要绑定到某个插件的目标才能完成真正的工作,比如test阶段正是与maven-surefire-plugin的test目标相绑定了 。

举例如下:

  • mvn clean

    调用clean生命周期的clean阶段

  • mvn test

    调用default生命周期的test阶段,实际执行test以及之前所有阶段

  • mvn clean install

    调用clean生命周期的clean阶段和default的install阶段,实际执行clean,install以及之前所有阶段

在linux环境中演示:

创建gitlab组,luffy-spring-cloud,在该组下创建项目springboot-demo

  • 提交代码到git仓库

    $ git init
    $ git remote add origin http://gitlab.luffy.com/luffy-spring-cloud/springboot-demo.git
    $ git add .
    $ git commit -m "Initial commit"
    $ git push -u origin master
  • 使用tools容器来运行

    $ docker run --rm -ti -v /var/run/docker.sock:/var/run/docker.sock 172.21.65.226:5000/devops/tools:v3 bash
    # vi /etc/hosts 添加 172.21.65.226 gitlab.luffy.com
    # git clone http://gitlab.luffy.com/luffy-spring-cloud/springboot-demo.git
    # cd springboot-demo
    # mvn clean package
  



想系统学习maven,可以参考: https://www.runoob.com/maven/maven-pom.html