谈谈 Maven 的 settings.xml

问题起因

来公司开始使用 maven 以后, 会配置一个叫 settings.xml 的 maven 配置文件. 这个文件的内容不多, 格式大概如下:

settings.xml
<?xml version="1.0"?>
<settings 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/settings-1.0.0.xsd">
    <servers>
        <server>
            <id>snapshots</id>
            <username>{username}</username>
            <password>{passwd}</password>
            <filePermissions>664</filePermissions>
            <directoryPermissions>775</directoryPermissions>
        </server>
    </servers>

    <profiles>
        <profile>
            <id>MyProfile</id>
            <repositories>
                <repository>
                    <id>Nexus</id>
                    <url>http://test.com/nexus/content/groups/public</url>
                    <releases>
                        <enabled>true</enabled>
                        <!-- always , daily (default), interval:X (where X is an integer in minutes) or never.-->
                        <updatePolicy>daily</updatePolicy>
                        <checksumPolicy>warn</checksumPolicy>
                    </releases>
                    <snapshots>
                        <updatePolicy>always</updatePolicy>
                    </snapshots>
                </repository>
            </repositories>
            <pluginRepositories>
                <pluginRepository>
                    <id>Nexus</id>
                    <url>http://test.com/nexus/content/groups/public</url>
                    <releases>
                        <enabled>true</enabled>
                        <checksumPolicy>warn</checksumPolicy>
                    </releases>
                    <snapshots>
                        <updatePolicy>always</updatePolicy>
                    </snapshots>
                </pluginRepository>
            </pluginRepositories>
        </profile>
    </profiles>

    <activeProfiles>
        <activeProfile>MyProfile</activeProfile>
    </activeProfiles>

</settings>

之前一直不太明白这个文件各部分都是什么意思, 查了文档 settings 配置指南pom 配置指南 才大概明白此处的各个节点的意思.

<server /> 节点

<server /> 中定义了一些敏感的账号密码信息, 这些信息用于在发布新 jar 包的时候使用. 一般来讲, 我们只会填写 snapshot 的 username & password. 因为本地一般只会发布 snapshot 用于测试, 而 release 版本发布都是走 bds 发布系统, 所以不会写在这里.

根据文档的解释, 这里的 <id> 应该是需要对应 repository 或 mirror 的 id 值的, 但是这里的配置没有叫 snapshots 的 repository. 那么这个对应的 id 到底是什么呢? 原因在于 settings.xml 与 pom.xml 是联用的. 而我们一般在自己项目的 pom 里会引用公司的 super pom. 去 super pom 中查看, 可以看到一个信息如下

super-pom.xml
<distributionManagement>

    <repository>
        <id>releases</id>
        <name>Nexus Releases</name>
        <url>${nexus.releases}</url>
    </repository>

    <snapshotRepository>
        <id>snapshots</id>
        <uniqueVersion>false</uniqueVersion>
        <name>Nexus Snapshots</name>
        <url>${nexus.snapshots}</url>
    </snapshotRepository>

</distributionManagement>

原来这个叫 snapshots 的 repository 定义在这里. 那么, distributionManagement 又是什么? 根据文档的解释, 这个是用来配置发布 jar 包的时候用的地址. 例如我们的 snapshot, 就会发布到 ${nexus.snapshots} 这个变量定义的地方. 而发布的时候验证的权限则是使用 servers 节点中定义的 username 与 password.

<profiles /> 节点

<profiles /> 节点中主要定义了我们 local repository 在获取依赖的时候访问的 url 地址. 我们可以发现它与 super-pom 的 profiles 定义类似.

super-pom.xml
<profiles>

    <profile>
        <id>local</id>
        <properties>
            <deploy.type>local</deploy.type>
        </properties>
    </profile>

    <profile>
        <id>dev</id>
        <properties>
            <deploy.type>dev</deploy.type>
        </properties>
    </profile>

    <profile>
        <id>beta</id>
        <properties>
            <deploy.type>beta</deploy.type>
        </properties>
    </profile>

    <profile>
        <id>prod</id>
        <properties>
            <deploy.type>prod</deploy.type>
        </properties>
    </profile>

</profiles>

他们的联系在于 settings.xml 中定义的 profile 值会覆盖 pom.xml 中相同的 id 的 profile 参数. 当然, 我们此处 pom 中并没有定义与 settings 中相同的 key. 所以此处可以理解为最后在使用 local profile 编译的时候, 会合并使用 settings 和 pom 中对 local profile 定义的参数.

小结

从配置上看, 我们的发布和编译实际上是使用不同的 url 的, 总共会涉及到获取依赖的 repository, 发布 jar 包的 repository 两部分 repository, 分别定义在 <profile> 和 <distributionManagement> 两个节点中.

另外, settings 文件分为两种:

  • The Maven install: $M2_HOME/conf/settings.xml
  • A user’s install: ${user.home}/.m2/settings.xml

当两个同时存在时, 会合并使用两个配置文件, 出现冲突时, 优先考虑用户目录下的 settings.xml

最后, 我之前在考虑为什么不把获取依赖的 repository 直接定义到 super-pom, 而是要每个人都去修改自己的 settings 文件, 定义到 settings 文件里呢? 我发现这其实是一个悖论, 因为 super-pom 也是通过我们定义的 repository 来获取的.