maven的一点进阶

maven依赖范围

所谓依赖范围,指的是 依赖的jar包在maven项目生命周期里 作用的范围。
之前我们讲过,构建的gav坐标包括groupIdartifactIdversion,其实还有一个scope。如果没有明示scope,则默认是compile。这里的compile就是依赖范围的一种,表示项目在编译、运行、测试、打包的这些生命周期里都依赖这个jar包,这个jar包在这些阶段都在起作用。
scope有以下5个值,分别是

  • compile,表示编译运行测试打包阶段都依赖这个jar包。
    在这里插入图片描述
    比如,某个项目对spring-core的依赖。
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>5.3.9</version>
  <scope>compile</scope>
</dependency>

因为scope的默认值是compile,所以<scope>compile</scope>可以忽略不写,如下,

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>5.3.9</version>
</dependency>
  • provided,表示编译运行阶段会依赖这个jar包。
    在这里插入图片描述
    比如,容器相关的依赖,servlet-api,如下所示。
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

来看个具体的例子。
首先,在IDEA中使用模板创建一个web项目。
在这里插入图片描述
然后,修改pom.xml,引入对servlet-api的依赖,同时添加tomcat插件,插件用于后续的命令行运行。添加的内容如下所示。

<!-- 引入依赖servlet -->
<dependencies>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

<!-- 引入tomcat插件 -->
<build>
  <finalName>oct02</finalName>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

可以看到依赖servlet的scope值是provided
最后,我们使用命令行tomcat7:run运行下这个项目。
在这里插入图片描述
以上步骤很完美,没毛病。

现在,把servlet的scope值更改为compile,或者干脆把scope这行删掉(因为scope的默认就是compile嘛),如下所示。

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
  <scope>compile</scope>
</dependency>

改好后,我们再来运行下项目。
在这里插入图片描述
这下问题来了:HTTP Status 500 - java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different type with name “javax/servlet/http/HttpServletRequest”。
violation,“冲突”的意思。依赖servlet-api和tomcat自带的servlet之间发生了冲突,所以打包时就不应该包含servlet-api,即scope值就不应该是compile

  • system,表示编译运行阶段会依赖这个jar包。
    作用范围和provided相同。区别是,system必须配合systemPath一起使用,systemPath用来指定依赖的本地路径。如下所示,其中,${project.basedir}表示项目的根目录。
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <scope>system</scope>
    <version>4.5.25</version>
    <systemPath>${project.basedir}/lib/aliyun-java-sdk-core-4.5.25.jar</systemPath>
</dependency>

实际项目中,system这个范围很少使用。

  • runtime,表示只在运行阶段才会依赖这个jar包。但在打包的时候也会将该jar包包含进来。 在这里插入图片描述
    jdbc驱动就是这么一个使用场景,编译时不需要jdbc驱动,运行时则需要具体的第三方实现的jar包(如mysql-connector-java)。
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.27</version>
  <scope>runtime</scope>
</dependency>
  • test,表示只在测试阶段才会依赖这个jar包。
    在这里插入图片描述
    这个比较好理解,常见的就是junit,如下所示,
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>
maven父子项目的依赖传递

构建一个父子项目,就能理解项目里的依赖传递关系了。
首先,新建一个基本的java项目,记作oct02_parent
在这里插入图片描述
然后,修改项目的pom.xml,修改后的xml文件内容如下所示,

<?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>org.example</groupId>
  <artifactId>oct02_parent</artifactId>
  <version>1.0-SNAPSHOT</version>
<!--  父项目的打包方式-->
  <packaging>pom</packaging>
  <name>oct02_parent</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <junit.version>4.11</junit.version>
    <spring.version>5.3.9</spring.version>
    <log4j.version>1.2.17</log4j.version>
  </properties>

<!--  父项目的基本依赖-->
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.27</version>
    </dependency>
  </dependencies>

<!--  父项目中统一管理依赖(依赖容器,在子项目中使用时才会引入)-->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
      </dependency>
      <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

具体修改主要有以下3点内容,分别是,
第一点,如果没有明示,<packaging/>的默认值是jar。但父项目的打包方式必须为pom,所以<packaging>pom</packaging>
第二点,<dependencies/>中添加的依赖,会直接引入,而<dependencyManagement>中添加的依赖,只有子项目使用时,才会引入。这也是为什么当前父项目的External Libraries中只能看到mysql-connector-java(jdk1.8是本地依赖,mysql-connector-mysql依赖protobuf-java)。
在这里插入图片描述
第三点,在<properties/>中定义变量spring.versionlog4j.versionjunit.version的值,并使用${spring.version}${log4j.version}${junit.version}来确定所用依赖的最终版本。
这样做,方便实现依赖版本的统一管理。比如,一旦涉及到spring整体升级或回退,只需要修改一处就行。

父项目建立好了,在oct02_parent下创建一个子项目:一个基本的java项目oct02_child
在这里插入图片描述
修改子项目oct02_childpom.xml,建立oct02_parentoct02_child之间的父子关系。

<!--继承关系:继承一个项目-->
<parent>
  <groupId>org.example</groupId>
  <artifactId>oct02_parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <relativePath>../pom.xml</relativePath>
</parent>
<!-- 继承关系中,子项目会自动继承父项目的groupId-->
<!--  <groupId>org.example</groupId>-->
<artifactId>oct02_child</artifactId>
<version>1.0-SNAPSHOT</version>

使用<parent/>为子项目oct02_child指定父项目,注意哈,<relativePath/>是父项目oct02_parent的pom文件所在路径(相对路径)。
继承关系建立起来后,子项目便会自动继承父项目的groupId。
父项目oct02_parent的pom文件中<dependencies/>中添加的依赖,子项目oct02_child会全部自动继承,所以,可以在子项目的External Libraries中看到这些继承下来jar包:mysql-connector-java,如下图所示。
在这里插入图片描述
父项目oct02_parent的pom文件中<dependencyManagement/>中添加的依赖,只有子项目oct02_child使用时才会引入到项目中。比如,在子项目中使用以下依赖。

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
  </dependency>
</dependencies>

在这里插入图片描述
关于父子项目的依赖传递,用下面一个图做一个小结。
在这里插入图片描述
父子项目的优缺点是比较明显的。
优点:可以合理有效地复用依赖jar包;子项目互相独立,更加便于敏捷开发和独立管理。
缺点:项目之间的系统集成性能比较差。

maven项目聚合统一管理

聚合项目不仅实现了依赖jar包的复用,同时也较好地解决了父子项目的缺点,项目的聚合关系使得项目之间的整体性提高,便于系统集成和维护。
构建一个聚合项目,就能理解项目是怎么进行聚合统一管理。
在这里,笔者不使用maven模板,所以在IDEA中提前设置好maven的home path、settings file和local repositories,如下图所示。
在这里插入图片描述

首先,新建一个项目oct03_aggregation
在这里插入图片描述
然后,修改pom.xml,顶级项目的<packaging/>的值也必须是pom,如下所示。

<groupId>org.example</groupId>
<artifactId>oct03_aggregation</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

New >Module,新建子模块oct03_module01
在这里插入图片描述

可以看到,子模块oct03_module01自动与顶级模块oct03_aggregation建立了继承关系。

<!--子模块oct03_module01的pom.xml的部分内容 -->
<parent>
    <artifactId>oct03_aggregation</artifactId>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>oct03_module01</artifactId>

顶级模块oct03_aggregation也自动聚合了子模块oct03_module01

<!--顶级模块oct03_aggregation的pom.xml的部分内容 -->
<modules>
   <module>oct03_module01</module>
</modules>
maven项目常用插件

maven提供了很多插件,可以到maven官网(https://maven.apache.org/)看看。
在这里插入图片描述
比如有生命周期插件,cleancompilerdeployinstallresources等,也有常用的操作插件,比如jardependencyApache Tomcat等等。
之前有介绍如何使用tomcat插件,现在来讲讲如何使用dependency插件。
首先,在官网上查看下dependency插件的用法。
在这里插入图片描述
然后,使用maven模板新建一个聚合项目。
在这里插入图片描述
顶级pom.xml内容如下。

<!-- 顶级模块的pom.xml-->
<?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>org.example</groupId>
  <artifactId>oct03_aggregation</artifactId>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>oct03_module01</module>
  </modules>
  <packaging>pom</packaging>

  <name>oct03_aggregation</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <spring.version>5.3.9</spring.version>
    <junit.version>4.11</junit.version>
    <log4j.version>1.2.17</log4j.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.27</version>
    </dependency>
  </dependencies>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

子模块pom.xml内容如下。

<!--子模块的pom.xml-->
<?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>
  <parent>
    <groupId>org.example</groupId>
    <artifactId>oct03_aggregation</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>oct03_module01</artifactId>

  <name>oct03_module01</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

提示:如果子模块自动生成的pom.xml中没有<parent/>,可以自己手动加上。
再然后,在子模块的pom.xml中添加dependency插件,如下所示。

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>3.2.0</version>
</plugin>

最后添加maven命令:dependency:tree便可查看子模块的依赖树。
在这里插入图片描述
以上只是为了演示如何使用maven插件 。
其实,要查看依赖树结构,使用Diagrams这种图形化展示,更直观。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值