Maven Wrapper、JDK 切换以及其他一些小知识

2026-03-09, 星期一, 11:31

DevJava

有些同学对自己的开发工具还不太熟练,故发此文。

使用 Maven Wrapper

Maven 3.8.1 开始默认阻止通过 HTTP 协议连接仓库,项目如果需要连接到某些使用 IP 地址或通过 HTTP 协议提供服务的私有仓库就会糟老罪。此外还有一些可能会碰到可能碰不到的版本兼容性问题,总不能叫参与项目的同学准备两到三个版本的 Maven 吧。

Maven Wrapper 是一个受到 Gradle Wrapper 启发的项目,用户可以借助相关脚本运行特定版本的 Maven 而不需要在操作系统中安装。

统一开发框架已经在项目中配置了相关文件,其他项目可以参考。

  • ./mvnw 代替 mvn 命令,例如 ./mvnw -Dmaven.test.skip=true clean package
  • 修改 .mvn/wrapper/maven-wrapper.properties 文件指定 Maven 版本

要解决 HTTP 仓库问题,声明一个低版本的 Maven,如 3.6.3。

# .mvn/wrapper/maven-wrapper.properties
distributionUrl=https://mirrors.huaweicloud.com/repository/maven/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://mirrors.huaweicloud.com/repository/maven/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

使用项目中的 settings.xml

如果要连接到一些有密码认证的私有仓库(例如公司的私有仓库),通常的做法是在项目的 pom.xml 中添加仓库地址,然后在 ~/.m2/settings.xml 中设置这个仓库的访问密码。

如果你碰到过:

  • 重装过系统然后忘了备份 ~/.m2/settings.xml
  • 接手项目发现资料中没有认证信息
  • 启动 CI 时需要去改构建环境的配置文件

可能就会觉得让仓库的认证信息跟着项目代码走这个主意也许没那么坏,特别是这个用户只有 R 权限,且仓库只能通过特定网段访问。

可以把用户认证信息写在项目根路径下的 settings.xml 中。CI/CD 环境在 Maven 命令中使用 --settings ./settings.xml 指定配置文件。编辑 .mvn/maven.config 文件指定配置,则可以让 IntelliJ 等 IDE 识别,从而在 GUI 菜单中支持。

--settings
settings.xml

如果 IDE 没有识别出来,在设置菜单中看看有没有 Use settings from .mvn/maven.config 之类的选项。

有写权限的用户凭证别这么干。

切换 JDK 版本

统一框架已经通过 Spring Boot 3 将 JDK 的基线提升到了 17,而老项目可能只支持 JDK 8 和 JDK 11。你可以在 IDE 中指定当前项目的 JDK 版本,这样 Maven 菜单中的操作就会选择正确的版本。对于命令行用户,通过修改当前会话的 JAVA_HOME 环境变量实现 JDK 版本切换。

Windows Powershell

Windows 用户如果使用基于命令行的 Maven Wrapper 和 maven.config,则可以遵循本文给出的方法,使用自定义 Powershell 函数在当前会话中切换 JDK 版本。

使用 notepad $profile 打开当前用户的配置文件,如果程序提示路径不存在,按这个环境变量的值创建目录和文件就好。在文件中添加如下内容,JDK 路径要按实际情况修改。

function jdk {
    If($args[0] -eq "17") {
        $env:JAVA_HOME = 'C:\jdk\openjdk-17'
    } else {
        $env:JAVA_HOME = 'D:\Program Files\Java\jdk1.8.0_151'
    }
    $env:Path = $env:JAVA_HOME+'\bin;'+$env:Path
    java -version
}

保存后开启新的 Powershell 会话或 . $profile 使配置生效。执行 jdk 17 就可以将当前会话环境的 JAVA_HOMEPATH 切换为 JDK 17 相关的路径,在项目中可以正常使用 Maven Wrapper。

> jdk 17
> ./mvnw compile

macOS 用户

运行 /usr/libexec/java_home -V 将显示所有已安装的 JDK。

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (2):
    17.0.1 (x86_64) "Eclipse Temurin" - "Eclipse Temurin 17" /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home
    1.8.0_312 (x86_64) "Eclipse Temurin" - "Eclipse Temurin 8" /Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home
/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home

zsh 用户可以在 ~/.zshrc 中添加 jdk() 函数。参照 Wrong JAVA_HOME after upgrade to macOS Big Sur v11.0.1,在 Big Sur 及之后系统中需注意:

  • -v 参数与过滤用的版本号之间需要添加空格
  • 需要先 unset JAVA_HOME,否则 /usr/libexec/java_home 只会返回当前 JAVA_HOME 指向的 JDK 版本
function jdk() {
    version=$1
    unset JAVA_HOME
    export JAVA_HOME=$(/usr/libexec/java_home -v "$version");
    java -version
}

使用 jdk 1.8jdk 17 可以在本示例的两个 JDK 版本间切换。

如果使用了不同供应商的同版本 JDK,例如 Temurin 21 和 OpenJ9 21,/usr/libexec/java_home 是不能区分的,仅会返回按照同版本的第一个匹配结果,可以改成:

function jdk() {
    version=$1
    unset JAVA_HOME
    if [ $version = "graalvm" ]; then
        export JAVA_HOME="/Library/Java/JavaVirtualMachines/graalvm-jdk-21.0.2+13.1/Contents/Home"
    elif [ $version = "openj9" ]; then
        export JAVA_HOME="/Library/Java/JavaVirtualMachines/openj9-21.jdk/Contents/Home"
    elif [ $version = "21" ]; then
        export JAVA_HOME="/Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home"
    else
        export JAVA_HOME=$(/usr/libexec/java_home -v "$version")
    fi
    java -version
}

这种方法只能切换当前 session 的 Java 版本,要进行全局切换,参考 How to set or change the default Java (JDK) version on macOS?

Linux 用户

通过包管理器安装的 JDK 一般位于 /usr/lib/jvm/ 目录下,可以使用该脚本创建一个交互式选择菜单。

jdk() {
    JAVA_HOME=$(find /usr/lib/jvm/ -maxdepth 1 -type d | fzf)
    export JAVA_HOME
    export PATH="$JAVA_HOME/bin:$PATH"
    java -version
}