项目管理工具Maven


Maven简介

Maven是一款为Java项目管理构建、依赖管理的工具,使用Maven可以自动化构建、测试、打包和发布项目。
依赖管理:Maven可以管理项目的依赖,包括自动下载所需依赖库、自动下载依赖并保证版本没有冲突、依赖版本管理等。通过Maven可以方便维护项目所依赖的外部库,避免版本冲突和转换错误等,这些进需要编写配置即可实现。

构建管理:项目构建是指将源代码、配置文件、资源文件等转化为能够运行或部署的应用程序或库的过程。Maven可以管理项目的编译、测试、打包、部署等构建过程。通过实现标准的构建生命周期,可以确保每一个构建过程都遵循同样的规则。同时,Maven的插件机制可以对构建过程进行扩展和定制。主动触发构建,只需简单的命令操作即可。

Maven的安装

Java:JDK 17

IDE:Idea 2023.2 (自带的Maven版本是3.9.3)

Maven:官网(根据自己的情况下载安装对应的版本,这里选择3.9.5版本)

环境变量配置:

vim .zprofile  

# Maven
export MAVEN_HOME=/Users/laobai/pllibrary/maven3.9.5
export PATH=$MAVEN_HOME/bin:$PATH

source .zprofile

mvn -v
Apache Maven 3.9.5 (57804ffe001d7215b5e7bcb531cf83df38f93546)

Maven的功能配置

Maven的配置文件是maven/conf/settings.xml,需要修改如下四处配置:

  • 本地仓库位置
  • maven下载镜像
  • maven选用编译项目的JDK版本
  • maven的插件下载配置
<!-- 本地仓库位置 (根节点) -->
<!-- 默认路径是"${user.home}/.m2/repository",这里配置为自定义的位置 -->
<localRepository>/Users/laobai/pllibrary/maven3.9.5/repository</localRepository>

<!-- maven下载镜像 (mirrors节点) -->
   <mirror>
      <id>alimaven</id>
      <mirrorOf>central</mirrorOf>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    </mirror>
    <mirror>
      <id>maven-default-http-blocker</id>
      <mirrorOf>external:http:*</mirrorOf>
      <name>Pseudo repository to mirror external repositories initially using HTTP.</name>
      <url>http://0.0.0.0/</url>
      <blocked>true</blocked>
    </mirror>

<!-- maven选用编译项目的JDK版本 (profiles节点) -->
    <profile>
      <id>jdk-17</id>

      <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>17</jdk>
      </activation>
      <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
      </properties>
    </profile>

<!-- maven的插件下载配置 (profiles节点) -->
<profile>
      <id>spring plugins</id>

      <activation>
        <jdk>spring plugins</jdk>
      </activation>

      <pluginRepositories>
        <pluginRepository>
          <id>spring plugins</id>
          <name>Spring plugins</name>
          <url>https://maven.aliyun.com/repository/spring-plugin</url>
          <layout>default</layout>
          <!-- <snapshotPolicy>always</snapshotPolicy>  -->
        </pluginRepository>
      </pluginRepositories>
    </profile>

Maven存储库地址:mvnrepository,这里主要用来查询插件包的依赖

在Idea中配置Maven

Idea中自带Maven,但没有修改过配置文件,这里将上面已经下载并配置好的Maven配置到Idea中。

设置 - 构建、执行、部署 - 构建工具 - Maven,修改配置项如下图所示:

基于Idea创建Maven工程

创建工程时的GAVP

在创建工程时会有4个属性值:GroupIDArtifactIDVersionPackaging

  • GroupID: com.{公司名}.{业务线}.{子业务线},最多4级
    • 例:com.plscript.user
  • ArtifactID:产品线名-模块名,一般跟工程的名称一样
  • Version:版本号,主版本号.次版本号.修订号
  • Packaging:选择将项目打包成什么类型的文件
    • 属性为 jar(默认值),代表普通的Java工程,打包以后是.jar结尾的文件。

    • 属性为 war,代表Java的web工程,打包以后.war结尾的文件。

    • 属性为 pom,代表不会打包,用来做继承的父工程。

创建工程

创建了项目后,进入IDE的编辑界面,若第一次创建Maven工程,会在IDE的右下角显示下载关联依赖包的进度条。(之前已经创建过工程,已无需下载依赖包)

文件结构及每个文件的作用:

  • pom.xml:Maven 项目管理文件,用于描述项目的依赖和构建配置等信息。
  • src/main/java:存放项目的 Java 源代码。
  • src/main/resources:存放项目的资源文件,如配置文件、静态资源等。
  • src/main/webapp/WEB-INF:存放 Web 应用的配置文件。
  • src/main/webapp/index.jsp:Web 应用的入口页面。
  • src/test/java:存放项目的测试代码。
  • src/test/resources:存放测试相关的资源文件,如测试配置文件等。

基于Idea进行Maven工程构建

构建的概念及过程

项目构建是指将源代码、依赖库和资源文件等转换成可执行或可部署的应用程序的过程,在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤。项目构建是软件开发过程中至关重要的一部分,它能够大大提高软件开发效率,使得开发人员能够更加专注于应用程序开发和维护,而不必关心应用程序的构建细节。同时,项目构建还可以将多个开发人员的代码汇合到一起,并能够自动化项目的构建和部署,大大降低了项目的出错风险和提高开发效率。常见的构建工具包括MavenGradleAnt等。

清理 –> 编译 –> 测试 –> 报告 –> 打包 –> 部署

命令方式项目构建

命令 描述
mvn compile 编译项目,生成target文件
mvn package 打包项目,生成jar或war文件
mvn clean 清理编译或打包后的项目结构
mvn install 打包后上传到maven本地仓库
mvn deploy 打包,上传到maven私服仓库
mvn site 生成站点
mvn test 执行测试源码

创建一个User类

创建一个User类com.plscript.User

package com.plscript;

public class User {
    private int id;
    private String username;
    private int age;
}

mvnrepository查找lombok插件(Lombok(Project Lombok)是一个用于 Java 编程语言的开源库,它利用注解方式自动生成 java bean 中 getter、setter、equals 等方法,还能自动生成 logger、toString、hashCode、builder 等),这里选择的是最新的1.18.30版本,复杂构建工具maven下的代码拷贝到项目的pom.xml文件的dependencies节点中。

<?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>com.plscript</groupId>
    <artifactId>maven_java</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

保存xml后,点击悬浮的刷新按钮,或在maven页签中点击刷新即可。

增加lombok的注解,以生成getter、setter、toString、构成方法等方法

package com.plscript;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String username;
    private int age;
}

代码中只是增加了注解,但已经实现了getter、setter、toString、构成方法等方法

  1. 编译项目mvn compile

     mvn compile
    
    [INFO] Scanning for projects...
    [INFO] 
    [INFO] ----------------------< com.plscript:maven_java >-----------------------
    [INFO] Building maven_java 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    。。。。。。。
    
    [INFO] Changes detected - recompiling the module! :source
    [INFO] Compiling 1 source file with javac [debug target 17] to target/classes
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  6.934 s
    [INFO] Finished at: 2023-11-28T00:17:32+08:00
    [INFO] ------------------------------------------------------------------------

​ 在src同级目录下生成了target目录并项目文件

  1. 清理项目mvn clean ,将target目录及其中的文件删除掉

     mvn clean  
       
    [INFO] Scanning for projects...
    [INFO] 
    [INFO] ----------------------< com.plscript:maven_java >-----------------------
    [INFO] Building maven_java 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] Artifact org.apache.maven.plugins:maven-clean-plugin:pom:3.2.0 is present in the local repository, but cached from a remote repository ID that is unavailable in current build context, verifying that is downloadable from [alimaven (http://maven.aliyun.com/nexus/content/groups/public/, default, releases)]
    ..........
    [INFO] 
    [INFO] --- clean:3.2.0:clean (default-clean) @ maven_java ---
    [INFO] Deleting /Users/laobai/IdeaProjects/maven_java/target
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  0.716 s
    [INFO] Finished at: 2023-11-28T00:28:28+08:00
    [INFO] ------------------------------------------------------------------------
  2. 测试 mvn test

    先在test目录中新建测试类test/java/com.plscript/MavenTest.java

    package com.plscript;
    
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    
    public class MavenTest {
    
        @Test
        public void testAssert(){
            int a = 10;
            int b = 20;
    
            Assertions.assertEquals(a+b, 20);   // 这里断言10+20 = 20
        }
    }

    再次编译项目,mvn compile

    mvn compile
    [INFO] Scanning for projects...
    [INFO] 
    [INFO] ----------------------< com.plscript:maven_java >-----------------------
    [INFO] Building maven_java 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] 
    [INFO] --- resources:3.3.1:resources (default-resources) @ maven_java ---
    [INFO] Copying 0 resource from src/main/resources to target/classes
    [INFO] 
    [INFO] --- compiler:3.11.0:compile (default-compile) @ maven_java ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  0.193 s
    [INFO] Finished at: 2023-11-28T06:31:16+08:00
    [INFO] ------------------------------------------------------------------------

    这里已经在target目录中生成了test-classes目录,里面存放了测试程序的字节码文件。(有的版本需要再次执行mvn test-compile才能生成test-classes)

    再次执行测试 mvn test

     mvn test
    [INFO] Scanning for projects...
    [INFO] 
    [INFO] ----------------------< com.plscript:maven_java >-----------------------
    [INFO] Building maven_java 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] 
    [INFO] --- resources:3.3.1:resources (default-resources) @ maven_java ---
    [INFO] Copying 0 resource from src/main/resources to target/classes
    [INFO] 
    [INFO] --- compiler:3.11.0:compile (default-compile) @ maven_java ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO] 
    [INFO] --- resources:3.3.1:testResources (default-testResources) @ maven_java ---
    [INFO] skip non existing resourceDirectory /Users/laobai/IdeaProjects/maven_java/src/test/resources
    [INFO] 
    [INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ maven_java ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO] 
    [INFO] --- surefire:3.1.2:test (default-test) @ maven_java ---
    [INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
    [INFO] 
    [INFO] -------------------------------------------------------
    [INFO]  T E S T S
    [INFO] -------------------------------------------------------
    [INFO] Running com.plscript.MavenTest
    [ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.018 s <<< FAILURE! -- in com.plscript.MavenTest
    [ERROR] com.plscript.MavenTest.testAssert -- Time elapsed: 0.010 s <<< FAILURE!
    org.opentest4j.AssertionFailedError: expected: <30> but was: <20>
            at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
            at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
            at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
            at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:150)
            at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:145)
            at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:527)
            at com.plscript.MavenTest.testAssert(MavenTest.java:13)
            at java.base/java.lang.reflect.Method.invoke(Method.java:568)
            at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
            at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    
    [INFO] 
    [INFO] Results:
    [INFO] 
    [ERROR] Failures: 
    [ERROR]   MavenTest.testAssert:13 expected: <30> but was: <20>
    [INFO] 
    [ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
    [INFO] 
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD FAILURE
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  0.526 s
    [INFO] Finished at: 2023-11-28T06:39:34+08:00
    [INFO] ------------------------------------------------------------------------
    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.1.2:test (default-test) on project maven_java: There are test failures.
    [ERROR] 
    [ERROR] Please refer to /Users/laobai/IdeaProjects/maven_java/target/surefire-reports for the individual test results.
    [ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
    [ERROR] -> [Help 1]
    [ERROR] 
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR] 
    [ERROR] For more information about the errors and possible solutions, please read the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

    测试失败了:MavenTest.testAssert:13 expected: <30> but was: <20>

    将20改为30,再次执行测试

     mvn test
    [INFO] Scanning for projects...
    [INFO] 
    [INFO] ----------------------< com.plscript:maven_java >-----------------------
    [INFO] Building maven_java 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] 
    [INFO] --- resources:3.3.1:resources (default-resources) @ maven_java ---
    [INFO] Copying 0 resource from src/main/resources to target/classes
    [INFO] 
    [INFO] --- compiler:3.11.0:compile (default-compile) @ maven_java ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO] 
    [INFO] --- resources:3.3.1:testResources (default-testResources) @ maven_java ---
    [INFO] skip non existing resourceDirectory /Users/laobai/IdeaProjects/maven_java/src/test/resources
    [INFO] 
    [INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ maven_java ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO] 
    [INFO] --- surefire:3.1.2:test (default-test) @ maven_java ---
    [INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
    [INFO] 
    [INFO] -------------------------------------------------------
    [INFO]  T E S T S
    [INFO] -------------------------------------------------------
    [INFO] Running com.plscript.MavenTest
    [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 s -- in com.plscript.MavenTest
    [INFO] 
    [INFO] Results:
    [INFO] 
    [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    [INFO] 
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  0.551 s
    [INFO] Finished at: 2023-11-28T06:42:13+08:00
    [INFO] ------------------------------------------------------------------------

    测试成功了。

    另,测试的类名和方法名,均需要以testXXXXtest开头或以xxxxTesttest结尾,否则不会被识别为测试类/方法。

  3. 打包项目mvn package

    mvn package
    [INFO] Scanning for projects...
    [INFO] 
    [INFO] ----------------------< com.plscript:maven_java >-----------------------
    [INFO] Building maven_java 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] 
    [INFO] --- resources:3.3.1:resources (default-resources) @ maven_java ---
    [INFO] Copying 0 resource from src/main/resources to target/classes
    [INFO] 
    [INFO] --- compiler:3.11.0:compile (default-compile) @ maven_java ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO] 
    [INFO] --- resources:3.3.1:testResources (default-testResources) @ maven_java ---
    [INFO] skip non existing resourceDirectory /Users/laobai/IdeaProjects/maven_java/src/test/resources
    [INFO] 
    [INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ maven_java ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO] 
    [INFO] --- surefire:3.1.2:test (default-test) @ maven_java ---
    [INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
    [INFO] 
    [INFO] -------------------------------------------------------
    [INFO]  T E S T S
    [INFO] -------------------------------------------------------
    [INFO] Running com.plscript.MavenTest
    [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 s -- in com.plscript.MavenTest
    [INFO] 
    [INFO] Results:
    [INFO] 
    [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    [INFO] 
    [INFO] 
    [INFO] --- jar:3.3.0:jar (default-jar) @ maven_java ---
    [INFO] Building jar: /Users/laobai/IdeaProjects/maven_java/target/maven_java-1.0-SNAPSHOT.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  0.659 s
    [INFO] Finished at: 2023-11-28T07:39:14+08:00
    [INFO] ------------------------------------------------------------------------

    上面的打包日志中可以看到,打包过程中,首先要构建项目并进行测试,测试ok后才进行打包。生成的打包文件存放在target目录中/Users/laobai/IdeaProjects/maven_java/target/maven_java-1.0-SNAPSHOT.jar

    上面构建的是java程序,对于javaweb程序,其他步骤都一样,但在打包时需要在POM.xml中增加通过maven生成war包(java程序是jar包,javaweb程序是war包)的插件

    <build>
        <!-- jdk17 和 war包版本插件不匹配 -->
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.4.0</version>
            </plugin>
        </plugins>
    </build>
  4. 安装项目mvn install

    在开发程序过程时,会出现,这个程序调用另外一个程序的情况,相当于上面描述的安装插件一样需要在POM.xml进行配置。

    比如另外的程序需要调用到上面已经打包好的程序,可以在pom.xml中的dependencies节点增加如下配置:

    <dependency>
        <groupId>org.plscript</groupId>
        <artifactId>maven_java</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    配置在pom.xml中的插件/程序,首先在本地仓库中进行查找,找不到就会去中央仓库去查找。

    这里就可以用mvn install将上面的maven_java上传到本地仓库中,这样新开发的程序就可以对其进行配置调用。

    mvn install
    [INFO] Scanning for projects...
    [INFO] 
    [INFO] ----------------------< com.plscript:maven_java >-----------------------
    [INFO] Building maven_java 1.0-SNAPSHOT
    [INFO]   from pom.xml
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] 
    [INFO] --- resources:3.3.1:resources (default-resources) @ maven_java ---
    [INFO] Copying 0 resource from src/main/resources to target/classes
    [INFO] 
    [INFO] --- compiler:3.11.0:compile (default-compile) @ maven_java ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO] 
    [INFO] --- resources:3.3.1:testResources (default-testResources) @ maven_java ---
    [INFO] skip non existing resourceDirectory /Users/laobai/IdeaProjects/maven_java/src/test/resources
    [INFO] 
    [INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ maven_java ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO] 
    [INFO] --- surefire:3.1.2:test (default-test) @ maven_java ---
    [INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
    [INFO] 
    [INFO] -------------------------------------------------------
    [INFO]  T E S T S
    [INFO] -------------------------------------------------------
    [INFO] Running com.plscript.MavenTest
    [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.018 s -- in com.plscript.MavenTest
    [INFO] 
    [INFO] Results:
    [INFO] 
    [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    [INFO] 
    [INFO] 
    [INFO] --- jar:3.3.0:jar (default-jar) @ maven_java ---
    [INFO] Building jar: /Users/laobai/IdeaProjects/maven_java/target/maven_java-1.0-SNAPSHOT.jar
    [INFO] 
    [INFO] --- install:3.1.1:install (default-install) @ maven_java ---
    [INFO] Installing /Users/laobai/IdeaProjects/maven_java/pom.xml to /Users/laobai/pllibrary/maven3.9.5/repository/com/plscript/maven_java/1.0-SNAPSHOT/maven_java-1.0-SNAPSHOT.pom
    [INFO] Installing /Users/laobai/IdeaProjects/maven_java/target/maven_java-1.0-SNAPSHOT.jar to /Users/laobai/pllibrary/maven3.9.5/repository/com/plscript/maven_java/1.0-SNAPSHOT/maven_java-1.0-SNAPSHOT.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  0.723 s
    [INFO] Finished at: 2023-11-28T08:06:21+08:00
    [INFO] ------------------------------------------------------------------------

    通过日志可以看到maven_java的jar被上传到了/Users/laobai/pllibrary/maven3.9.5/repository/com/plscript/maven_java/1.0-SNAPSHOT/maven_java-1.0-SNAPSHOT.jar ,这样其他程序就可以通过配置在本地仓库进行调用了。

可视化构建项目

上面是通过命令行的方式进行项目构建,Idea中提供了界面的可视化构建

在界面右侧的maven页签里的生命周期,双击某个指令,就会触发对应的过程。

构建生命周期可以理解成是一组固定构建命令的有序集合,触发周期后的命令,会自动触发周期前的命令。

默认周期:定义了真正构件时所需要执行的所有步骤,它是生命周期中最核心的部分

包含命令:compile -  test - package - install - deploy	

基于Idea进行Maven依赖管理

什么是依赖管理

Maven的依赖管理能够帮助开发人员自动解决软件包依赖问题,使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中,避免出现版本冲突和依赖缺失等问题。

通过在POM.xml文件中进行配置,Maven能够自动解析项目的依赖关系,并通过maven仓库自动下载和管理依赖,从而避免了手动下载和管理依赖的繁杂工作及可能引发版本冲突的可能。

前文中创建工程时提到了GAVP,这里再做一下说明

<!-- 模型版本 -->
<modelVersion>4.0.0</modelVersion>
<!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.companyname.project-group,maven会将该项目打成的jar包放本地路径:/com/companyname/project-group -->
<groupId>com.companyname.project-group</groupId>
<!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
<artifactId>project</artifactId>
<!-- 版本号 -->
<version>1.0.0</version>

<!--打包方式
    默认:jar
    jar指的是普通的java项目打包方式! 项目打成jar包!
    war指的是web项目打包方式!项目打成war包!
    pom不会讲项目打包!这个项目作为父工程,被其他工程聚合或者继承!后面会讲解两个概念
-->
<packaging>jar/pom/war</packaging>

配置依赖管理

需要进行依赖的模块或第三方框架/库,需要添加到pom.xml文件的dependencies节点中

<!-- 
   通过编写依赖jar包的gav必要属性,引入第三方依赖!
   scope属性是可选的,可以指定依赖生效范围!
   依赖信息查询方式:
      1. maven仓库信息官网 https://mvnrepository.com/
      2. mavensearch插件搜索
 -->    

		<dependencies>
    		<!-- 引入具体的依赖包 -->
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.10.0</version>
          	<!-- 依赖范围 -->
            <scope>test</scope>
        </dependency>

    </dependencies>

上面的配置中,groupIdartifactIdscope都不能修改,唯一可修改的是scope,为了方便维护版本,可以将版本号提取到properties进行维护,properties节点中的标签名可以进行自定义命名。

<properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  			<!-- 自定义命名,指定需要的版本号 -->
        <junit.version>5.10.0</junit.version>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
          	<!-- 引用properties声明版本 -->
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

依赖范围

通过设置坐标的依赖范围(scope),可以设置对应jar包的作用范围:编译环境(main目录中是否可用)、测试环境(test目录中是否可用)、运行环境(jar包或war包中是否可用)

依赖范围 描述
compile 编译依赖范围,scope 元素的缺省值。使用此依赖范围的 Maven 依赖,对于三种 classpath 均有效,即该 Maven 依赖在上述三种 classpath 均会被引入。例如,log4j 在编译、测试、运行过程都是必须的。
test 测试依赖范围。使用此依赖范围的 Maven 依赖,只对测试 classpath 有效。例如,Junit 依赖只有在测试阶段才需要。
provided 已提供依赖范围。使用此依赖范围的 Maven 依赖,只对编译 classpath 和测试 classpath 有效。例如,servlet-api 依赖对于编译、测试阶段而言是需要的,但是运行阶段,由于外部容器已经提供,故不需要 Maven 重复引入该依赖。
runtime 运行时依赖范围。使用此依赖范围的 Maven 依赖,只对测试 classpath、运行 classpath 有效。例如,JDBC 驱动实现依赖,其在编译时只需 JDK 提供的 JDBC 接口即可,只有测试、运行阶段才需要实现了 JDBC 接口的驱动。
system 系统依赖范围,其效果与 provided 的依赖范围一致。其用于添加非 Maven 仓库的本地依赖,通过依赖元素 dependency 中的 systemPath 元素指定本地依赖的路径。鉴于使用其会导致项目的可移植性降低,一般不推荐使用。
import 导入依赖范围,该依赖范围只能与 dependencyManagement 元素配合使用,其功能是将目标 pom.xml 文件中 dependencyManagement 的配置导入合并到当前 pom.xml 的 dependencyManagement 中。

常用的依赖范围:compiletestprovided

依赖下载失败解决

在使用 Maven 构建项目时,可能会发生依赖项下载错误的情况,主要原因有以下几种:

  1. 下载依赖时出现网络故障或仓库服务器宕机等原因,导致无法连接至 Maven 仓库,从而无法下载依赖。
  2. 依赖项的版本号或配置文件中的版本号错误,或者依赖项没有正确定义,导致 Maven 下载的依赖项与实际需要的不一致,从而引发错误。
  3. 本地 Maven 仓库或缓存被污染或损坏,导致 Maven 无法正确地使用现有的依赖项。

解决方案:

  1. 检查网络连接和 Maven 仓库服务器状态。

  2. 确保依赖项的版本号与项目对应的版本号匹配,并检查 POM 文件中的依赖项是否正确。

  3. 清除本地 Maven 仓库缓存(lastUpdated 文件),因为只要存在lastupdated缓存文件,刷新也不会重新下载。本地仓库中,根据依赖的gav属性依次向下查找文件夹,最终删除内部的文件,刷新重新下载即可!

Build构建配置

项目构建是指将源代码、依赖库和资源文件等转换成可执行或可部署的应用程序的过程,在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤。默认情况下,构建不需要额外配置,都有对应的缺省配置。也可以在pom.xml定制一些配置,来修改默认构建的行为和产物!

  1. 指定构建打包文件的名称,非默认名称

    <!-- 默认的打包名称:artifactid+verson.打包方式 -->
    <build>
      <finalName>maven_java-1.0.jar</finalName>
    </build>  
  2. 制定构建打包时,指定包含文件格式和排除文件

    如果在java文件夹中添加java类,会自动打包编译到classes文件夹下!但是在java文件夹中添加xml文件,默认不会被打包!默认情况下,按照maven工程结构放置的文件会默认被编译和打包!除此之外、我们可以使用resources标签,指定要打包资源的文件夹要把哪些静态资源打包到 classes根目录下!

    ​ 应用场景:mybatis中有时会将用于编写SQL语句的映射文件和mapper接口都写在src/main/java下的某个包中,此时映射文件就不会被打包,如何解决

    <build>
        <!--设置要打包的资源位置-->
        <resources>
            <resource>
                <!--设置资源所在目录-->
                <directory>src/main/java</directory>
                <includes>
                    <!--设置包含的资源类型-->
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
  3. 打包插件版本过低,配置更高版本插件

    dependencies标签下引入开发需要的jar包!可以在build/plugins/plugin标签引入插件。

    常用的插件:修改jdk版本、tomcat插件、mybatis分页插件、mybatis逆向工程插件等等。

    <build>
      <plugins>
          <!-- java编译插件,配jdk的编译版本 -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
              <encoding>UTF-8</encoding>
            </configuration>
          </plugin>
          <!-- tomcat插件 -->
          <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
             <version>2.2</version>
              <configuration>
              <port>8090</port>
              <path>/</path>
              <uriEncoding>UTF-8</uriEncoding>
              <server>tomcat</server>
            </configuration>
          </plugin>
        </plugins>
    </build>

Maven依赖传递和依赖冲突

依赖传递

假如有Maven项目A,项目B依赖A,项目C依赖B。那么我们可以说 C依赖A。也就是说,依赖的关系为:C—>B—>A, 那么我们执行项目C时,会自动把B、A都下载导入到C项目的jar包文件夹中,这就是依赖的传递性。

传递的原则

在 A 依赖 B,B 依赖 C 的前提下,C 是否能够传递到 A,取决于 B 依赖 C 时使用的依赖范围以及配置

  • B 依赖 C 时使用 compile范围:可以传递

  • B 依赖 C 时使用 testprovided范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地方明确配置依赖才可以。

  • B 依赖 C 时,若配置了optional标签,则不能传递

依赖传递终止

  • compile范围进行依赖传递
  • 使用optional配置终止传递
  • 依赖冲突(传递的依赖已经存在)

依赖冲突

当直接引用或者间接引用出现了相同的jar包,这时项目就会出现相同的重复jar包,这就算作冲突!依赖冲突避免出现重复依赖,并且终止依赖传递!maven自动解决依赖冲突问题能力,会按照自己的原则,进行重复依赖选择。

自动解决冲突选择原则

  • 短路优先原则(第一原则)

    A—>B—>C—>D—>E—>X(version 0.0.1)

    A—>F—>X(version 0.0.2)

    则A依赖于X(version 0.0.2)。

  • 依赖路径长度相同情况下,则“先声明优先”(第二原则)

    A—>E—>X(version 0.0.1)

    A—>F—>X(version 0.0.2)

    在<depencies></depencies>中,先声明的,路径相同,会优先选择!

Maven工程继承和聚合关系

工程继承关系

  1. 继承概念

    Maven 继承是指在 Maven 的项目中,让一个项目从另一个项目中继承配置信息的机制。继承可以让我们在多个项目中共享同一配置信息,简化项目的管理和维护工作。

  2. 继承作用

    在父工程中统一管理项目中的依赖信息。

    它的背景是:

    • 对一个比较大型的项目进行了模块拆分。
    • 一个 project 下面,创建了很多个 module。
    • 每一个 module 都需要配置自己的依赖信息。

    它背后的需求是:

    • 在每一个 module 中各自维护各自的依赖信息很容易发生出入,不易统一管理。
    • 使用同一个框架内的不同 jar 包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一。
    • 使用框架时所需要的 jar 包组合(或者说依赖信息组合)需要经过长期摸索和反复调试,最终确定一个可用组合。这个耗费很大精力总结出来的方案不应该在新的项目中重新摸索。
      通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目使用规范、准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力。
  3. 继承语法

    • 父工程

      <groupId>com.plscript.maven</groupId>
       <artifactId>pro03-maven-parent</artifactId>
       <version>1.0-SNAPSHOT</version>
       <!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是 pom -->
       <packaging>pom</packaging>
    • 子工程

      <!-- 使用parent标签指定当前工程的父工程 -->
      <parent>
        <!-- 父工程的坐标 -->
        <groupId>com.plscript.maven</groupId>
        <artifactId>pro03-maven-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
      </parent>
      
      <!-- 子工程的坐标 -->
      <!-- 如果子工程坐标中的groupId和version与父工程一致,那么可以省略 -->
      <!-- <groupId>com.plscript.maven</groupId> -->
      <artifactId>pro04-maven-module</artifactId>
      <!-- <version>1.0-SNAPSHOT</version> -->
  4. 父工程依赖统一管理

    • 父工程声明版本

      <!-- 使用dependencyManagement标签配置对依赖的管理 -->
      <!-- 被管理的依赖并没有真正被引入到工程 -->
      <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>6.0.10</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>6.0.10</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.10</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>6.0.10</version>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>6.0.10</version>
          </dependency>
        </dependencies>
      </dependencyManagement>
    • 子工程引用版本

      <!-- 子工程引用父工程中的依赖信息时,可以把版本号去掉。  -->
      <!-- 把版本号去掉就表示子工程中这个依赖的版本由父工程决定。 -->
      <!-- 具体来说是由父工程的dependencyManagement来决定。 -->
      <dependencies>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-expression</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
        </dependency>
      </dependencies>

工程聚合关系

  1. 聚合概念

    Maven 聚合是指将多个项目组织到一个父级项目中,以便一起构建和管理的机制。聚合可以帮助我们更好地管理一组相关的子项目,同时简化它们的构建和部署过程。

  2. 聚合作用

    1. 管理多个子项目:通过聚合,可以将多个子项目组织在一起,方便管理和维护。
    2. 构建和发布一组相关的项目:通过聚合,可以在一个命令中构建和发布多个相关的项目,简化了部署和维护工作。
    3. 优化构建顺序:通过聚合,可以对多个项目进行顺序控制,避免出现构建依赖混乱导致构建失败的情况。
    4. 统一管理依赖项:通过聚合,可以在父项目中管理公共依赖项和插件,避免重复定义。
  3. 聚合语法

    父项目中包含的子项目列表。

    <project>
      <groupId>com.plscript</groupId>
      <artifactId>parent-project</artifactId>
      <packaging>pom</packaging>
      <version>1.0.0</version>
      <modules>
        <module>child-project1</module>
        <module>child-project2</module>
      </modules>
    </project>

文章作者: 老百
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 老百 !
  目录