《Maven权威指南(Part1)》要点总结

简介

  • maven是一个声明式的项目管理工具;
  • maven本身不能构建项目,是通过借助各个插件,并将插件的goal绑定到各个生命周期去执行来实现;
  • maven通过引入唯一的四元组来定位依赖,并将其下载到本地仓库;
  • 祖先pom是所有pom的默认祖先,里面定义了一系列默认值,包括path、插件,以及默认插件绑定的生命周期。

生命周期

maven的生命周期模式,个人理解为设计模式中的模板模式,即定义了生命周期运行的骨架,将各个阶段的实现延迟到具体的插件中。

maven常见的生命周期如下:

  • default:编译源代码并处理打包项目相关的所有事情
阶段解释
validate验证项目是正确的,所有必要信息都可用,所有依赖项都已下载
compile编译项目源代码
test使用适当的单元测试框架对编译后的源代码运行测试
package将编译后的代码打包成可发布格式,例如JAR
install将包安装到本地存储库中,以便在本地的其他项目中作为依赖项使用
deploy将最终包复制到远程存储库,以便与其他开发人员和项目共享
maven default 生命周期
  • clean:清理构建输出,包括生成的编译类、JAR文件等
  • site:为项目生成文档

实例——父项目

<?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>

    # 下述四元组唯一定义了一个maven项目
    <groupId>com.bytedance.ecom</groupId>
    <artifactId>huskar</artifactId>
    # 类型为pom
    <packaging>pom</packaging>
    <version>1.0.0</version>

    # 子模块定义
    <modules>
        <module>huskar-web</module>
        ...
    </modules>

    # 配置的key-val值
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        ...
        <kafka-clients-version>0.10.1.2-bd1.7.5</kafka-clients-version>
    </properties>

    # 公共依赖版本定义
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.bytedance</groupId>
                <artifactId>env-conf</artifactId>
                <version>${bytedance-env-conf}</version>
            </dependency>
            ...
        </dependencies>
    </dependencyManagement>

    <build>
        # 使用的插件/自定义默认插件
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version> <!-- or newer version -->
                ...
                </configuration>
            </plugin>
        </plugins>
    </build>

    # 发布(deploy)的仓库
    <distributionManagement>
        <repository>
            <id>bytedance-releases</id>
            <url>http://maven.byted.org/repository/releases</url>
        </repository>
        ...
    </distributionManagement>

    # 依赖的下载仓库
    <repositories>
        <repository>
            <id>bytedance-snapshots</id>
            <url>http://maven.byted.org/repository/snapshots</url>
        </repository>
        ...
    </repositories>

    # 插件的下载仓库
    <pluginRepositories>
        <pluginRepository>
            <id>bytedance-releases</id>
            <url>https://maven.byted.org/repository/releases</url>
        </pluginRepository>
        ...
    </pluginRepositories>

</project>

实例——模块

<?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>

    # 父pom,继承他的所有属性
    <parent>
        <artifactId>huskar</artifactId>
        <groupId>com.bytedance.ecom</groupId>
        <version>1.0.0</version>
    </parent>
    # groupId继承父pom,packaging默认为jar
    <artifactId>huskar-web</artifactId>
    <version>1.0.0</version>

    # 依赖
    <dependencies>
        <dependency>
            <groupId>com.bytedance.ecom</groupId>
            <artifactId>huskar-biz</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>

    <!--打包指令 : mvn package spring-boot:repackage -->
    <build>
        <finalName>${project.artifactId}-${project.version}</finalName>
        <!--资源文件目录-->
        <resources>
            # 指定main/java目录下的mepper.xml等文件为配置文件
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.yml</include>
                    <include>**/*.xml</include>
                </includes>
                # 是否替换资源文件中的占位符
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>


        <plugins>
            <plugin>
                <groupId>com.bytedance</groupId>
                <artifactId>cloud-mvn</artifactId>
                <version>${cloud-mvn-version}</version>
                # 执行命令
                <executions>
                    <execution>
                        <id>toutiao cloud scm package</id>
                        # 绑定:将插件的repackage的goal绑定到validate阶段
                        <phase>validate</phase>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                    ...
                </executions>
            </plugin>
            ...
        </plugins>
    </build>

    <!--profiles-->
    # 配置,用来根据不同环境定义不同的pom属性
    <profiles>
        <profile>
            <id>dev</id>
            # 激活条件
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            # 这里可以填pom中的任意属性,进行覆盖,如<properties/>
        </profile>
        ...
    </profiles>
</project>

最佳实践

  1. maven不允许循环依赖;
  2. 在父pom中定义子模块的公共部分,如依赖配置(包括传递依赖)(dependencyManagement)、插件配置(pluginManagement)、公共依赖(dependencies)、公共插件(plugins)等。通常,将版本号信息额外做成map,保存在properties中;
  3. 由于兄弟依赖之间的版本号通常是同步的,使用project.version进行定义;
  4. 将项目中的直接依赖显式写在pom中,不要使用间接依赖,使用mvn dependency:analyze进行检查;
  5. 如果需要同时依赖一个jar包的不同版本,使用maven-shade-plugin插件,为其中一个版本建立shade包(仅仅修改包名),并在pom中引用它;
  6. 为统一jdk编译版本,通常在maven-compiler-plugin中显式定义,如使用到了基于java的APT的类库,如lombok,需要在annotationProcessorPaths标签中进行定义。
上一篇
下一篇