《Maven实战》读书笔记

本文深入探讨Maven的核心概念,包括POM文件的基本元素、依赖管理、仓库机制、生命周期和插件等内容,并介绍了聚合与继承的区别及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 概念和原理

1.1 POM文件的基本元素

modelVersion:指定POM模型的版本,对Maven2Maven3来说只能是4.0.0

groupId:定义Maven项目(模块)隶属的实际项目,即项目属于那个组,主要来标志项目,格式为:com+公司名+项目名,例如”com.mycom.myapp”

artifactId:定义实际项目的Maven项目(模块),即项目的模块名称,主要是来标志模块,例如“util”、“implementation”,如果模块可以分为子模块,那么可以用“-”或者“.”分开,比如“util.io,util.log”或者“util-io,util-log”。有些情况下也在artifactId命名以groupId作为前缀,比如myapp-utli,这样有区别于其他项目的util-XXX-util

version:项目当前的版本,这个要和modelVersion区分。

packaging:定义打包类型,jar或者war,默认是jar。:

name:声明的对用户更友好的名称,有助于交流信息,这个不是必须的属性,但是这个属性会在Maven执行过程的打印信息中作为模块的描述,所以建议写全。

classfier:该语速用来半数定义构建输出的一些附属构件,这个属性不能直接定义。

注意:

1modelVersiongroupIdpackagingversionclassfier定义了一个项目的基本坐标,在Maven世界,任何的jarpom或者war都是以基于这些基本的坐标进行区分的。一般jar文件的命令格式:groupId+ artifactId+ -+version +.jjar

2、在Maven世界中,任何一个依赖(依赖的jar包)、插件(各种功能插件)或者项目输出(目标插件或者目标jar等)都可以称为构件

 1.2 依赖

1.2.1 依赖范围

依赖范围就是用来控制依赖与编译classpath、测试classpath、运行classpath这三种classpath的关系。

compile:编译依赖范围,使用这种依赖,对于编译、测试、运行三种classpath都有效。如果没有指定,默认就是这种依赖。典型的例子是spring-core,编译、测试和运行都需要使用该依赖。

test:测试依赖范围,使用这种依赖,只对测试classpath有效,在编译住代码或者运行项目时无法使用此依赖。典型的例子是JUnit,,它只有在编译测试代码以及运行测试的时候才需要。

provided:已提供的依赖方位。使用这种依赖,对于编译和测试的classpath有效,但是运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要依赖,但是运行的时候,由于容器已经提供,就不需要Maven重复地引入一遍。

runtime:运行时依赖。这种依赖对于测试和运行的classpath有效,但是编译猪代码时无效。典型的例子是JDBC驱动实现,项目猪代码的编译需要JDK提供的JDBC接口。只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。

system:系统依赖范围。该依赖与但中classpath的关系和provided依赖范围完全一直。但是,使用system范围的依赖时必须通过systemPaht元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构件的不可以移植,因此应该谨慎使用。

import(Maven2.0.9及以上):导入依赖范围。该依赖类型不会对三种classpath产生实际影响。在依赖管理配置实现导入现有POM中配置的依赖管理。

1.2.2 依赖配置

可以在POM或者setting.xml中配置,具体见常见配置。

1.3 仓库

1.3.1 仓库分类                 


本地仓库:本地库,查找依赖和构件都基于该仓库。如果该仓库没有,从远程仓库下载到本地仓库,再供使用。默认的中央仓库位置在$M2_HOME/lib/maven-model-builder-3.0.jarPOM文件中已经定义。

远程仓库-中央仓库:中央仓库是Maven核心自带的远程仓库,它包含了大部分开源的构建。

远程仓库-私服:特殊的远程仓库,代理所有外部的远程仓库,提供内部项目的构建给其他项目使用。


私服的作用:节省带宽、加速Maven构建、部署第三方构件、提高稳定性,增强控制、降低中央仓库的负荷。

远程仓库-其他公共库:比如JAVA.NET,JBOSS

1.3.2 从仓库解析依赖的机制


1.3.3 镜像

如果仓库X可以提供仓库Y的所有内容,那么就可以认为XY的一个镜像。换句话说,任何一个可以从仓库Y获得的构件,都可以从它的镜像中获取。实际中可以配置中央仓库的镜像、配置所有仓库的镜像—私服(私服就是所有仓库的镜像)。

1.4  生命周期和插件

三套生命周期cleandefaultsite,每套生命周期包括若干阶段,每个阶段依赖于前面的阶段。各个生命周期独立。

命令行与生命周期:命令行执行maven任务的主要方式是调用Maven生命周期的阶段。

生命周期和插件:插件实现生命周期各个阶段的具体任务,生命周期和插件进行了内置的绑定,但是通过修改配置也能替换内置的插件(修改绑定)或者增加默认(内置)没有绑定的绑定关系(自定义绑定)。为了复用代码,一个插件往往能完成多个任务,每个功能称作插件的一个目标。完成了插件和生命周期的绑定之后,用户还可以配置插件目标的参数,进一步调整插件目标所执行的任务,以满足项目的需求。几乎所有Maven插件的目标都有一些可配置的参数,用户可以通过命令行和POM配置的方式来配置这些参数。

1.4.1 常用Maven命令和执行的任务(目标—对插件而言、阶段—对生命周期而言)

cleanclean                            mvn clean

resourcesresources-主资源处理

compilercompile-主代码编译            mvn compile

resourcesrestResources-测试资源处理

compilertestCompile-测试代码编译

surfiretest-测试                       mvn test

jarjar-打包                           mvn package

installinstall-安装(到本地repository   mvn install

1.4.2 插件

1.4.2.1 插件仓库

与依赖构件一样,插件构件同样基于坐标存在Maven仓库中。在需要的时候,Maven会从本地仓库寻找插件,如果不存在,则从远程仓库查找。找到插件之后,再下载到本地仓库使用。Maven会区别对待依赖的远程仓库与插件的远程仓库,因此依赖的远程仓库和插件的远程仓库是分别配置的,前者用<repositories >标签,而后者用<pluginRepository>标签,标签下的配置项目含义一致,同样可以在POM或者setting.xml中配置。

1.4.2.2 插件解析

原理和依赖解析一致。但是插件有前缀的概念,即执行命令的时候可以省略groupId,省略的时候默认去org.mavenorg.codehause中去解析,即默认会使用org.maven.maven.pluginsorg.codehause.mojo这两个gourpId。也可以通过setting.xmlMaven检查其他groupId上的插件仓库元数据。

<settings>
   <pluginGroups>
    <pluginGroup>com.your.plugins<pluginGroup>
    <pluginGroups>
<settings>

基于上面的配置,Maven就不仅仅检查org/apache/maven/plugins/maven-metadata.xmlorg/codehaus/mojo/ maven-metadata.xml,还会检查org/com/your//plugins/maven-metadata.xml

1.5 聚合与继承

1.5.1聚合

Maven聚合(或者称为多模块)提供多POM模块(项目)的统一处理机制。

<project>
       <modelVersion>4.0.0</modelVersion>
       <groupId>com.juvenxu.mvnbook.account</groupId>
       <artifactId>account-aggregator</artifactId>
       <version>1.0.0-SNAPSHOT</version>
       <packaging> pom </packaging>
       <name>Account Aggregator</name>
        <modules>
              <module>account-email</module>
              <module>account-persist</module>
        </modules>
</project>

packaging的类型为pom module的值是一个以当前POM为主目录的相对路径。

1.5.2 继承

Maven继承是为了消除重复,简化配置等提供的机制。

父模块

<project>
       <modelVersion>4.0.0</modelVersion>
       <groupId>com.juvenxu.mvnbook.account</groupId>
       <artifactId> account-parent </artifactId>
       <version>1.0.0-SNAPSHOT</version>
       <packaging>pom</packaging>
       <name>Account Parent</name>
</project>

子模块声明继承

<project>
       <modelVersion>4.0.0</modelVersion>
      
       < parent >
              <groupId>com.juvenxu.mvnbook.account</groupId>
              <artifactId> account-parent </artifactId>
              <version>1.0.0-SNAPSHOT</version>
              < relativePath >../account-parent/pom.xml</ relativePath>
       </ parent >
      
       <artifactId> account-email </artifactId>
       <name>Account Email</name>
  ...
</project>

 最后,同样还需要把 account-parent加入到聚合模块account-aggregator中。聚合的 POM

<project>
       <modelVersion>4.0.0</modelVersion>
       <groupId>com.juvenxu.mvnbook.account</groupId>
       <artifactId>account-aggregator</artifactId>
       <version>1.0.0-SNAPSHOT</version>
       <packaging> pom </packaging>
       <name>Account Aggregator</name>
       <modules>
              <module>account-email</module>
              <module>account-persist</module>
              <module> account-parent</module>
       </modules>
</project>
注意:

1、子模块没有声明groupIdversion, 这两个属性继承至父模块。但如果子模块有不同与父模块的 groupIdversion ,也可指定;

2、不应该继承artifactId,如果groupId versionartifactId 完全继承的话会造成坐标冲突;另外即使使用不同的 groupIdversion,同样的 artifactId也容易产生混淆。

3、使用继承后 parent也必须像自模块一样加入到聚合模块中。也就是在在聚合模块的 pom中加入<module>account-parent</module>

1.5.2.1 可继承的POM 元素

groupId :项目组 ID,项目坐标的核心元素;

version :项目版本,项目坐标的核心元素;

description :项目的描述信息;

organization :项目的组织信息;

inceptionYear :项目的创始年份;

url :项目的 url地址

develoers :项目的开发者信息;

contributors :项目的贡献者信息;

distributionManagerment:项目的部署信息;

issueManagement :缺陷跟踪系统信息;

ciManagement :项目的持续继承信息;

scm :项目的版本控制信息;

mailingListserv :项目的邮件列表信息;

properties :自定义的 Maven属性;

dependencies :项目的依赖配置;

dependencyManagement:醒目的依赖管理配置;

repositories :项目的仓库配置;

build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等;

reporting :包括项目的报告输出目录配置、报告插件配置等。

1.5.2.2 依赖管理

Maven提供的dependencyManagement元素,既能让子模块集成到父模块的依赖配置,又能保证子模块依赖使用的灵活性。在dependencyManagement元素下的依赖声明不会引入实际的依赖,不过它能够约束dependencies下的依赖使用。

父模块中如此声明

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mavenbook</groupId>
  <artifactId>a-parent</artifactId>
  <version>1.0.0</version>
  ...
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.2</version>
      </dependency>
      ...
    <dependencies>
  </dependencyManagement>

子模块中如此声明

<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.sonatype.mavenbook</groupId>
    <artifactId>a-parent</artifactId>
    <version>1.0.0</version>
  </parent>
  <artifactId>project-a</artifactId>
  ...
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
  </dependencies>
</project>

作用

1、代码量减少,不用多次重复声明 version等元素。

2version受父管理,父变则子变,便于修改。

3dependencyManagement一旦定义,可以复用。

依赖管理导入

导入现有的依赖管理

<dependencyManagement>
       <dependencies>
              <dependency>
                     <groupId>com.juvenxu.mvnbook.account</groupId>
                     <artifactId> account-parent </artifactId>
                     <version>1.0-SNAPSHOT</version>
                     <type>pom</type>
                     <scope>import</scope>
              </dependency>
       </dependencies>
</dependencyManagement>

1.5.2.3 插件管理

和依赖管理类似,Maven提供了pluginManagement元素帮助管理插件。

1.5.3 聚合与继承的关系

区别 

1.对于聚合模块来说,它知道有哪些被聚合的模块,但那些被聚合的模块不知道这个聚合模块的存在。

2.对于继承关系的父 POM来说,它不知道有哪些子模块继承与它,但那些子模块都必须知道自己的父 POM是什么。

共同点 

1.聚合 POM与继承关系中的父POM packaging都是pom

2.聚合模块与继承关系中的父模块除了 POM之外都没有实际的内容。

注:在现有的实际项目中一个 POM既是聚合POM,又是父 POM,这么做主要是为了方便

1.5.4 反应堆

在一个多模块的Maven项目中,反应堆(Reactor)是指所有模块组成的一构建结构。对于单模块的项目,反应堆就是该模块本身,但是对于多模块的项目来说,反应堆包含了各个模块之间的继承和依赖的关系,从而能够自动计算出合理的模块构建顺序。

裁剪反应堆

mvn clean install参数模块1,模块2…,具体参数如下:

-am:同时构建所列模块的依赖模块

-amd:同时构建依赖于所列模块的模块

-pl:构建指定模块

-rf:从指定的模块返回一个反应堆对象

技巧:如果想编译模块之间前后顺序mvn clean compile等出现“Reactor Build Order后直接Ctrl +C中断或者直接mvn clean

2 常用命令

定义骨架

mvn archetype:generate

查看当前项目的已解析依赖

mvn dependencylist

查看当前项目的依赖树

mvndependencytree

分析当前项目的依赖

mvndependencyanalyze(只会分析编译主代码和测试代码需要用到的依赖,一些执行测试和运行是需要的依赖他就发现不了,因此对于分析出来的Unused declared dependencies不应立马删除,需要仔细分析后再做决定)

安装并且强制检查更新

mvn clean install-U

编译并且打印详细信息

mvn compile -X

查看插件目标的默认绑定阶段

:mvn help:describe –Dplugin=org.apache.maven.plugins:maven-source-plugin:2.1.1 –Ddetail

查看插件信息

:mvn help:describe –Dplugin=org.apache.maven.plugins:maven-compiler-plugin:2.1 –Ddetail

mvn help:describe –Dplugin=org.apache.maven.plugins:maven-compiler-plugin

mvn help:describe –Dplugin=compiler [–Ddetail]【可以加上–Ddetail参数】

mvn help:describe –Dplugin=compiler-Dgoal=compile【仅仅查看插件目标信息】

跳过测试

mvn install –Dmaven.test.skip=true【改变插件目标参数】

3、常用配置

定义jar包的最终名称finalName可以定义jar包的文件名称

<project>
      <groupId>aaa</groupId> 
      <artifactId>bbb</artifactId> 
      <version>2.0</version> 
   <finalName>aaa.bbb-20.jar</finalName
</project>

打包的时候配置manifest信息

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>1.4</version>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
        <configuration>
          <transformers>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
              <mainClass>com.juvenxu.mavenbook.HelloWorldCli</mainClass>
            </transformer>
          </transformers>
        </configuration>
      </execution>
    </executions>
  </plugin>

依赖配置

<dependencies> 
<dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>4.0</version> 
      <type>jar</type> //依赖的类型,对应项目坐标定义的packaging,默认jar
      <scope>test</scope>//依赖范围
      <optional>true</optional> //标记依赖是否可选
   <exclusions>//用来排除传递性依赖
<exclusion>
        <groupId>com.aaa</groupId>//排除依赖不需要指定版本
          <artifactId>bbb</artifactId> 
</exclusion>
</exclusions>
    </dependency>
</dependencies> 

系统依赖配置

systemPath元素可以引用环境变量,如

<dependency> 
      <groupId>javax.sql</groupId> 
      <artifactId>jabc-stdext</artifactId> 
      <version>2.0</version> 
      <scope>system</scope>
   <systemPath>${java.home}/lib/rt.jar</systemPath>
    </dependency>

定义属性

<project>
      <groupId>aaa</groupId> 
      <artifactId>bbb</artifactId> 
      <version>2.0</version> 
   <properties>
      <springframe.version>2.5.6</springframe.version>
</properties
</project>

本地仓库目录设置

<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:\java\repository</localRepository>
</settings>

设置远程仓库(下载依赖)

<project>
  ...
  <repositories>
    <repository>
      <id>jboss</id>
      <name>JBoss Repository</name>
      <url>http://repository.jboss.com/maven2/</url>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
    <snapshots>
      <enabled>false</enabled>
<updatePolicy>daily</updatePolicy>//never-从不检查更新,always-每次构建都检查更新,daily-每天检查一次,默认的选,X-每X分钟检查一次更新
<checksumPolicy>ignore</checksumPolicy>//检验和验证对应的校验和文件失败后的策略,默认warn警告,fail-遇到校验和错误就让构建失败,ignore-完全忽略校验和错误。
    </snapshots>
    <layout>default</layout>
  </repositories>
  ...
</project>

注意:这里的ID要和setting.xmlserver设置远程仓库认证ID一致。

部署(依赖)至远程仓库

<project>
  ...
  <destributionManagement>
    <repository>
      <id>proj-releases</id>
      <name>Proj Release Repository</name>
      <url>http://192.168.1.100/content/repositories/proj-releases</url>
    </repository>
    <snapshotRepository>
      <id>proj-snapshots</id>
      <name>Proj Snapshot Repository</name>
      <url>http://192.168.1.100/content/repositories/proj-snapshots</url>
    </snapshotRepository>
  </destributionManagement>
  ...
</project>

注意:这里的ID要和setting.xmlserver设置远程仓库认证ID一致。

远程仓库认证

<settings>
  ...
  <servers>
    <server>
      <id>my-proj</id>
      <username>repo-user</username>
      <password>repo-pwd</password>
    </server>
  </servers>
  ...
</settings>

注意:这里的ID要和POM中设置远程仓库的ID一致。

配置中央仓库镜像

<settings>
  ...
  <mirrors>
    <mirror>
      <id>maven.net.cn</id>
      <name>one of the central mirrors in china</name>
      <url>http://maven.net.cn/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>
  ...
</settings>

配置所有仓库的镜像—私服,私服就是所有仓库的镜像

<settings>
  ...
  <mirrors>
    <mirror>
      <id>internal-repository</id>
      <name>Internal Repository Manager</name>
      <url>http://192.168.1.100/maven2</url>
      <mirrorOf>*</mirrorOf>//匹配所有的远程仓库
    </mirror>
  </mirrors>
  ...
</settings>

注意:如果需要认证,那么需要配置一个idinternal-repository<server>认证信息。

自定义绑定插件目标,比如verify阶段生成doc文件

 <build>
       <plugins>
              <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-source-plugin</artifactId>
                     <version>2.1.1</version>
                     <executions>
                            <execution>
                                   <id>attach-sources</id>
                                   <phase>verify</phase>
                                   <goals>
                                          <goal>jar-no-fork</goal>
                                   </goals>
                            </execution>
                     </executions>
              </plugin>
       </plugins>
   </build>

配置  编译的 JDK 版本

<build>
   <plugins>
          <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.0.2</version>
                     <configuration>
                            <source>1.6</source>
                             <target>1.6</target>
                      </configuration>
           </plugin>
  </plugins>
</build>

或者

<profiles>
      <profile>
          <id>jdk-1.6</id>
             <activation>
                       <activeByDefault>true</activeByDefault>
                        <jdk>1.6</jdk>
               </activation>
              <properties>
                       <maven.compiler.source>1.6</maven.compiler.source>
                        <maven.compiler.target>1.6</maven.compiler.target>
                    <maven.compiler.compilerVersion>1.6</maven.compiler.compilerVersion>
               </properties>
      </profile>
</profiles>

POM中配置插件任务,比如调用ant任务

<build>
       <plugins>
              <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-antrun-plugin</artifactId>
              <version>1.3</version>
              <executions>
                     <execution>
                            <id>ant-validate</id>
                            <phase>validate</phase>
                            <goals>
                                   <goal>run</goal>
                            </goals>
                            <configuration>
                                   <tasks>
                                          <echo>I'm bound to validate phase.</echo>
                                   </tasks>
                            </configuration>
                     </execution>
                     <execution>
                            <id>ant-verify</id>
                            <phase>verify</phase>
                            <goals>
                                   <goal>run</goal>
                            </goals>
                            <configuration>
                                   <tasks>
                                          <echo>I'm bound to verify phase.</echo>
                                   </tasks>
                            </configuration>
                     </execution>
              </executions>
              </plugin>
       </plugins>
</build>

设置远程仓库(下载插件)

<project>
  ...
  < pluginRepositories>
        <pluginRepository>
          <id>nexus</id>
          <url>http:// </url>
          <releases>
            <enabled>true</enabled>
            <updatePolicy>always</updatePolicy>
          </releases>
          <snapshots>
            <enabled>true</enabled>
            <updatePolicy>always</updatePolicy>
          </snapshots>
        </pluginRepository>
  </ pluginRepositories>
  ...
</project>

注意:这里的ID要和setting.xmlserver设置远程仓库认证ID一致。

4、常见问题

1POMsetting.xml中配置依赖和插件有什么区别(或者说配置远程仓库)?

POM是针对一个POM文件,setting.xml中针对全局,后者可以减少重复配置,后者需要通过配置profile来实现。

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值