Maven笔记——高级篇
Maven笔记——高级篇

Maven笔记——高级篇

一,分模块开发与设计

分模块开发意义:将原始模块按照功能拆分成若干个子模块,方便模块间的相互调用,接口共享

新建两个模块,一个是总模块,负责调用其他模块,一个子模块,包含了domain:

  1. 在子模块Maven_pojo修改pom文件,只留下模块本身信息:
<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/maven-v4_0_0.xsd">
    <parent>
        <artifactId>Maven_ssm</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima</groupId>    <artifactId>Maven_pojo</artifactId>    <version>1.0-SNAPSHOT</version>


</project>
  1. 总模块Maven01_ssm中引入子模块依赖:
<!--        依赖domain-->
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>Maven_pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
  1. 还有很重要的一步,要把依赖的子模块打包到本地仓库:

如果报错:不再支持源选项 5。请使用 7 或更高版本。

pom请加上:

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
</properties>

报错:Failed to start component [StandardEngine[Tomcat]

8月 21, 2023 6:47:09 下午 org.apache.catalina.core.ContainerBase startInternal
严重: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]]
        at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
        at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1123)
        at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:302)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:732)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.startup.Tomcat.start(Tomcat.java:335)
        at org.apache.tomcat.maven.plugin.tomcat7.run.AbstractRunMojo.startContainer(AbstractRunMojo.java:1091)
        at org.apache.tomcat.maven.plugin.tomcat7.run.AbstractRunMojo.execute(AbstractRunMojo.java:512)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
        at org.codehaus.classworlds.Launcher.main(Launcher.java:47)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost]]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
        at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
        at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1131)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:800)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        ... 7 more

二,依赖管理

依赖传递:依赖具有传递性

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

依赖传递冲突问题

  • 路径优先:当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高
  • 声明优先: 当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的
  • 特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的

4.11覆盖4.12生效

可以点击maven插件的这个俺妞妞查看当前模块依赖分析图:

可选依赖(不透明)

有时候为了隐藏模块的依赖,可以使用option标签标记当前依赖是否向后传递:

<dependency>
    <groupId>org.example</groupId>
    <artifactId>maven01_domain</artifactId>
    <version>1.0-SNAPSHOT</version>
    <optional>true</optional>
</dependency>

表示maven01_domain依赖项不再向上级默哀快传递:

添加option之前:

之后:

可以看到domain模块被隐藏了,并且ssm模块无法使用domain模块里面的方法和对象了

排除依赖(不需要)

  • 当用了别人的依赖,想要隐藏掉或者排除掉其中的间接依赖,这时候无法再向其中加入option标签,可以使用排除依赖
  • 注:被排除的资源无需指定版本—不需要
  • 指排除掉间接依赖,比如要排除dao模块里面的间接以来log4j,使用exclusion标签:

三,聚合与继承

聚合

  • 聚合:将多个模块组织成一个整体,同时进行项目构建的过程称为聚合
  • 聚合工程:通常是一个不具有业务功能的“空”工程(有且仅有一个pom文件)
  • 作用:使用聚合工程可以将多个工程编组,通过对聚合工程进行构建,实现对所包含的模块进行同步构建
    • 当工程中某个模块发生更新(变更)时,必须保障工程中与已更新模块关联的模块同步更新,此时可以使用聚合工程来解决批量模块同步构建的问题
  1. 创建Maven模块,设置打包类型为pom

<packaging>pom</packaging>

  1. 设置当前聚合工程所包含的子模块名称:
<modules>
    <module>../../Maven_ssm/maven01_domain</module>
    <module>../../Maven_ssm/maven02_dao</module>
    <module>../../Maven_ssm/mavenSSM</module>
</modules>
  1. 执行聚合工程的compile操作:
[INFO] maven01_domain ..................................... SUCCESS [  0.674 s]
[INFO] maven02_dao ........................................ SUCCESS [  0.029 s]
[INFO] mavenSSM Maven Webapp .............................. SUCCESS [  0.094 s]
[INFO] maven00_parent ..................................... SUCCESS [  0.001 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.893 s
[INFO] Finished at: 2023-08-22T14:32:28+08:00
[INFO] ------------------------------------------------------------------------

继承

  • 概念:继承描述的是两个工程间的关系,与java中的继承相似,子工程可以继承父工程中的配置信息,常见于依赖关系的继承
  • 作用:简化配置,减少版本冲突

子工程加上继承信息:

<parent>
  <groupId>org.example</groupId>
  <artifactId>maven_01_parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <relativePath>../maven_01_parent/pom.xml</relativePath>
</parent>

然后将所有子工程的通用配置提取到父工程,比如依赖坐标信息,然后刷新maven可以看到子工程也有了这些坐标:

继承管理可以实现父工程修改依赖版本等信息,子工程批量跟着变得效果

有些依赖或者配置子工程不一定全都要,可以在父工程中使用<dependencyManagement>标签:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

这样在子工程中使用这些依赖时候可以不写版本信息:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
</dependency>

聚合与继承的区别

作用

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

相同点:

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

不同点:

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

四,属性管理

定义属性:

<properties>
    <spring.version>5.2.10.RELEAS</spring.version>
</properties>

使用属性:

<dependency>
    <version>${spring.version}</version>
</dependency>

在resources文件中读取pom文件定义的属性

设置jdbc.properties:

jdbc.url=${jdbc.url}

然后再父工程pom中:

<properties>
    <jdbc.url>jdbc:mysql://127.0.0.1:3306/spring_db?useSSL=false</jdbc.url>
</properties>
<build>
    <resources>
        <!--设置properties标签信息可以被读取的文件-->
        <resource>
            <directory>../maven_02_ssm/src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

然后刷新maven,可以看到左边目录结构发生了调整:

可以看到,父工程可以直接访问子工程的resources资源文件了

如果需要所有的子项目的resources都可以使用父工程定义的属性,可以这样写:

<build>
    <resources>
        <!--设置properties标签信息可以被读取的文件-->
        <resource>
            <directory>${project.basedir}/src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

${project.basedir}称为maven内置属性:

版本管理

  • 工程版本
    • SNAPSHOT (快照版本)
      • 项目开发过程中临时输出的版本,称为快照版本
      • 快照版本会随着开发的进展不断更新
    • RELEASE (发布版本)
      • 项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的,即便进行功能的后续开发,也不会改变当前发布版本内容,这和版本称为发布版本
  • 发布版本
    • alpha版
    • beta版
    • 纯数字版(3.1.2)

五,多环境配置与应用

maven提供配置多种环境的设定,帮助开发者使用过程中快速切换环境

pom文件中加入:

<!--    配置多环境-->
    <profiles>
        <profile>
            <id>env_dep</id>
            <properties>
                <jdbc.url>jdbc:mysql://127.0.0.1:3306/spring_db?useSSL=false</jdbc.url>
            </properties>

        </profile>
        <profile>
            <id>env_test</id>
            <properties>
                <jdbc.url>jdbc:mysql://127.1.1.1:3306/spring_db?useSSL=false</jdbc.url>
            </properties>

        </profile>
        <profile>
            <id>env_produce</id>
            <properties>
                <jdbc.url>jdbc:mysql://127.2.2.1:3306/spring_db?useSSL=false</jdbc.url>
            </properties>
            <activation>
                <!--                默认启动环境-->
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
    </profiles>

表示配置了三个环境,其中第三个生产环境是默认项目启动环境,编译,可以看到生成的目标文件的jdbc.properties文件的url、变了:

jdbc.url=jdbc:mysql://127.2.2.1:3306/spring_db?useSSL=false

使用maveninstall时,可以手动改指定环境:

mvn install -P env_test

跳过测试

maven install时默认会执行测试,有时不需要测试,需要跳过,应用场景:

  • 功能更新中并且没有开发完毕
  • 快速打包

方法:

  1. 直接点击maven插件按钮:
  1. 还可以直接在pom文件中配置跳过测试,首先需要找到测试的插件,执行打包package操作,找到测试插件:
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven_02_ssm ---
[INFO] No tests to run.

pom文件配置:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.12.4</version>
    <configuration>
        <skipTests>true</skipTests>
    </configuration>
</plugin>

还可以设置部分测试类跳过测试:

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.12.4</version>
    <configuration>
        <skipTests>false</skipTests>        <excludes>            <exclude>**/BookServiceImplTest.java</exclude>        </excludes>
    </configuration>
</plugin>
  1. 指令跳过测试:
mvn package -D skipTests

六,私服

1,私服简介

  • 私服是一台独立的服务器,用于解决团队内部的资源共享与资源同步问题
  • 流行的私服Nexus:Sonatype公司的一款maven私服产品

nexus使用:

1,打开目录:D:\Program Files (x86)\Nexus\nexus-3.59.0-01-win64\nexus-3.59.0-01\bin

2,cmd,输入:nexus.exe /run nexus

这个启动一次比较慢,建议启动后cmd窗口就别关了

3,浏览器访问localhost:8081 登录:

按照提示找到密码:9edc0708-227d-4046-8634-xxxxxxxxxx

按照步骤设置好基础配置:

  • 修改基础配置信息:
    • 安装路径下etc目录中nexus-default.properties文件保存有nexus基础配置信息,例如默认访问端口
  • 修改服务器运行配置信息:
    • 安装路径下bin目录中nexus.vmoptions文件保存有nexus服务器启动对应的配置信息,例如默认占用内存空间

2,私服仓库分类

默认情况下模块包都是在maven本地仓库中,安装私服后,可以放在私服仓库中,其他人可以在这个私服仓库中拿

3,私服资源上传与下载

以上配置需要在maven的conf下的setteings.xml文件中配置:

打开后,找到server标签,复制一段出来,放在server标签内:

可以看到需要仓库名,打开nexus,点击齿轮,创建仓库:

命名为:

表示创建一个宿主仓库,注意,version-policy千万别选错,否则最后的deploy项目会报错400:400 Repository version policy: RELEASE does not allow version。

翻到最底下点创建

重复上面的步骤,在创建一个itheima-release仓库,类型选择release,version-policy选release

接下来在xml中填入server名称:

    <!-- 配置访问私服的权限 -->
    <server>
      <id>itheima-snapshot</id>
      <username>admin</username>
      <password>320320</password>
    </server>
    <server>
      <id>itheima-release</id>
      <username>admin</username>
      <password>320320</password>
    </server>

然后需要配url映射,在xml文件中找到mirrors:

复制一个模板出来:

     <!-- 私服访问路径 -->
     <mirror>
      <id>mirrorId</id>
      <mirrorOf>repositoryId</mirrorOf>
      <url>http://my.repository.com/repo/path</url>
    </mirror>

需要填写私服id,打开

可以看到刚才创建的不在所管辖的仓库中,将左边俩拖过去:

记得点击save

然后将maven-public粘贴到id中去,mirrorof填*,然后填上url,完整如下:

     <!-- 私服访问路径 -->
     <mirror>
      <id>maven-public</id>
      <mirrorOf>*</mirrorOf>
      <url>http://localhost:8081/repository/maven-public/</url>
    </mirror>

保存关闭xml文件

最后还需要配置每个工程打包到哪个私服仓库中,打开工程pom文件,加入:

    <distributionManagement>
<!--        配置正式版发布的仓库(非必要)-->
        <repository>
            <id>itheima-release</id>
            <url>http://localhost:8081/repository/itheima-release/</url>
        </repository>
<!--        配置快照版发布的仓库(非必要)-->
        <snapshotRepository>
            <id>itheima-snapshot</id>
            <url>http://localhost:8081/repository/itheima-snapshot/</url>
        </snapshotRepository>
    </distributionManagement>

接下来测试将工程打包放到私服,install是打包放在本地,deploy是上传到私服

打包deploy之前还需要做一件事,每个模块的pom都需要有<distributionManagement>标签,没有的话会报错,所以需要给每个子模块都加上这个标签,一种妥善的方式是父模块协商,子模块继承,就需要给每个子模块加上继承parent标签:

<parent>
  <groupId>org.example</groupId>
  <artifactId>maven_01_parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <relativePath>../maven_01_parent/pom.xml</relativePath>
</parent>

最后,就可以执行deploy操作了,静等BUILD SUCCESS:

[INFO] maven_01_parent .................................... SUCCESS [  1.191 s]
[INFO] maven_03_pojo ...................................... SUCCESS [  2.035 s]
[INFO] maven_04_dao ....................................... SUCCESS [  0.543 s]
[INFO] maven_02_ssm Maven Webapp .......................... SUCCESS [  3.550 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.399 s
[INFO] Finished at: 2023-08-24T14:10:17+08:00
[INFO] ------------------------------------------------------------------------

Process finished with exit code 0

查看发布成功效果:

如果你的项目pom的version配的snapshot的话,就只会发布到snapshot仓库,如果是release就会发布到release仓库中去

报错:400 Repository version policy: RELEASE does not allow version

背景:将项目打包到nexus私服仓库中报错

出错代码:

    <distributionManagement>
<!--        配置正式版发布的仓库(非必要)-->
        <repository>
            <id>itheima-release</id>
            <url>http://localhost:8081/repository/itheima-release/</url>
        </repository>
<!--        配置快照版发布的仓库(非必要)-->
        <snapshotRepository>
            <id>itheima-snapshot</id>
            <url>http://localhost:8081/repository/itheima-snapshot/</url>
        </snapshotRepository>
    </distributionManagement>

原因:

1,要么是你创建仓库时version-policy选错了,snapshot仓库的version-policy选成了release等

2,要么是xml的distributionManagement填岔了

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Index