license 标签必须嵌套在 licenses 容器内才生效,单独使用会被 maven 忽略;一个项目可声明多个 license,建议用 spdx id(如 apache-2.0)并配可访问的完整 url;第三方依赖许可证由其自身 pom.xml 提供,不继承自当前项目;license-maven-plugin 默认只校验不生成文件,需配置 add-third-party goal 并设 phase 为 generate-resources。

license 标签必须嵌套在 licenses 容器里,单独写会失效
很多人直接在 pom.xml 里加 <license></license>,以为能声明项目用的协议,结果 mvn verify 或生成的 notice.txt 里完全没出现——因为 Maven 要求它必须作为 <licenses><license>...</license></licenses> 的子元素存在。不套这层容器,解析时直接忽略。
常见错误写法:<license><name>Apache License, Version 2.0</name><url>https://www.apache.org/licenses/LICENSE-2.0</url></license>
正确位置:必须放在 <project></project> 下的 <licenses></licenses> 块内。
-
<name></name>值建议用 SPDX ID(如Apache-2.0),比自由文本更易被工具识别 -
<url></url>必须是可访问的完整 URL,不能是相对路径或本地文件 - 一个项目可声明多个
<license></license>,比如双协议发布时同时写MIT和Apache-2.0
第三方依赖的 license 不会自动继承到你的 pom.xml
你在自己的 pom.xml 里配了 <licenses></licenses>,只是声明「你自己发布的这个构件」遵循什么协议。它对依赖的 JAR 包毫无影响——那些依赖的许可证信息来自它们各自的 pom.xml,Maven 在构建时通过依赖传递链收集,不是靠你手动抄一遍。
想检查实际打包时包含了哪些许可证?得用插件:maven-license-plugin 或 license-maven-plugin 可生成 THIRD-PARTY-LICENSES.txt;syft + grype 这类 SBOM 工具也能提取依赖许可证树。
- 别在
<licenses></licenses>里罗列所有依赖的协议,那是冗余且易过期的 - 如果你发布的是库(非应用),要确保你选的协议和所用依赖的协议兼容(比如 AGPL 依赖不能放进 MIT 库)
- 某些 CI 流程会校验
compile范围依赖是否含禁用协议(如SSPL),这时靠的是插件扫描,不是你 pom 里的声明
license-maven-plugin 默认不生成 LICENSE 文件,要显式配置 goal
装了 license-maven-plugin,跑 mvn clean compile 却没见 LICENSE 文件生成?默认它只做校验(check goal),不生成(add-third-party 或 aggregate-add-third-party 才负责写文件)。
典型配置漏掉 <executions></executions> 或写错 goal 名,导致“配了等于没配”:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>license-maven-plugin</artifactId> <version>2.2.0</version> <executions> <execution> <id>add-third-party</id> <goals><goal>add-third-party</goal></goals> <phase>generate-resources</phase> </execution> </executions> </plugin>
- 注意
<phase></phase>设为generate-resources,太早(如initialize)可能读不到依赖元数据 - 生成路径默认是
${project.basedir}/target/generated-sources/license/,不是src/main/resources,需配合resources插件复制过去 - 若项目含
provided依赖,插件默认不扫描,得加<includeprovidedscope>true</includeprovidedscope>
SPDX 表达式支持有限,复杂组合协议要拆开声明
Maven 原生只认单个 SPDX ID(如 Apache-2.0),不支持表达式语法(如 Apache-2.0 OR MIT)。你硬写进去,部分插件会解析失败或静默忽略。
真实场景中,双协议发布很常见(比如允许用户自选),但 Maven 没有标准字段存 OR/AND 关系。折中做法是:
- 在
<licenses></licenses>里并列两个<license></license>,各自填一个 SPDX ID - 用
<comments></comments>字段补充说明选择关系(如<comments>You may choose either Apache-2.0 or MIT.</comments>) - 如果必须机器可读,考虑在
NOTICE文件里手写 SPDX 表达式,或用about-code-tool等外部工具管理
别指望 IDE 或 Nexus ui 自动理解你写的注释——它们只扫 <name></name> 和 <url></url>,<comments></comments> 是给人看的。