3、Maven高级:自定义插件开发、Archetype脚手架生成、Nexus私服搭建与部署

好,咱们进入Maven的高级部分。说实话,很多同学用了好几年Maven,也就停留在配置依赖、写写pom.xml的阶段。但真正到了企业级项目里,你会发现光会这些远远不够。今天我要讲的这三个主题——自定义插件、Archetype脚手架、Nexus私服——说白了,就是让你从Maven的“使用者”变成“掌控者”。

3.1 自定义Maven插件开发

先问个问题:你有没有遇到过这样的场景?每次发布前,都要手动改版本号、打时间戳、生成API文档。重复劳动不说,还容易出错。我当时在一个金融项目里,就因为手动改版本号漏了一个地方,导致线上包和代码对不上,排查了整整一个下午。

嗯,这时候你就需要自定义插件了。Maven插件本质上就是一个Mojo(Maven Old Java Object),继承AbstractMojo类,实现execute()方法就行。

3.1.1 快速上手:写一个打印时间的插件

我习惯先从一个最简单的例子入手。创建一个maven项目,pom.xml里加上maven-plugin的打包方式:

<packaging>maven-plugin</packaging>

然后引入核心依赖:

<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-plugin-api</artifactId>
    <version>3.8.1</version>
</dependency>
<dependency>
    <groupId>org.apache.maven.plugin-tools</groupId>
    <artifactId>maven-plugin-annotations</artifactId>
    <version>3.6.0</version>
    <scope>provided</scope>
</dependency>

接下来写Mojo类:

@Mojo(name = "showtime")
public class ShowTimeMojo extends AbstractMojo {

    @Parameter(property = "showtime.format", defaultValue = "yyyy-MM-dd HH:mm:ss")
    private String format;

    public void execute() throws MojoExecutionException {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        getLog().info("当前时间:" + sdf.format(new Date()));
    }
}

执行 mvn com.example:my-plugin:showtime 就能看到输出了。你看,是不是很简单?

我的小技巧: 开发插件时,记得用 @Parameter 注解暴露配置项。这样用户就能在pom.xml里灵活配置,不用改代码。

3.1.2 实战:自动化版本号插件

我在项目中遇到过最头疼的事,就是多模块项目的版本号管理。几十个模块,每次发版都要逐个改。后来我写了个插件,自动读取Git标签来生成版本号。

@Mojo(name = "auto-version", requiresProject = true)
public class AutoVersionMojo extends AbstractMojo {

    @Parameter(defaultValue = "${project.version}")
    private String version;

    public void execute() throws MojoExecutionException {
        // 读取Git标签
        String gitTag = getGitTag();
        if (gitTag != null) {
            // 自动替换版本号
            MavenProject project = (MavenProject) getPluginContext().get("project");
            project.setVersion(gitTag);
            getLog().info("版本号已自动设置为:" + gitTag);
        }
    }
}
注意: 我曾经犯过一个错误——在插件里直接修改了pom.xml文件。千万别这么做!Maven的版本号是运行时概念,用 project.setVersion() 就够了,改文件会导致版本控制混乱。

3.2 Archetype脚手架生成

每次新建项目都要重复搭架子:建目录、写pom.xml、配日志框架、加单元测试依赖……烦不烦?反正我是烦了。Archetype就是解决这个问题的。

3.2.1 从现有项目生成Archetype

我推荐一个最快的方法:找一个你满意的项目,直接用它生成Archetype。

mvn archetype:create-from-project

这个命令会在 target/generated-sources/archetype 下生成脚手架项目。你只需要调整 archetype-metadata.xml 文件,定义哪些文件是模板、哪些是静态资源。

3.2.2 自定义模板变量

举个例子,你的项目里有个 Application.java,里面引用了包名。你可以把它改成模板文件:

package ${package};

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ${className}Application {
    public static void main(String[] args) {
        SpringApplication.run(${className}Application.class, args);
    }
}

然后在 archetype-metadata.xml 里声明:

<requiredProperties>
    <requiredProperty key="className">
        <defaultValue>Demo</defaultValue>
    </requiredProperty>
</requiredProperties>

核心思路: Archetype的本质就是“模板引擎 + 文件复制”。你定义好变量,Maven在生成项目时自动替换。说白了,就是把你手动做的事情自动化了。

3.3 Nexus私服搭建与部署

说到私服,我记得刚入行时在一家小公司,团队就五六个人,连私服都没有。每次加依赖都要从中央仓库下载,慢得要命。更坑的是,有一次中央仓库挂了,整个团队干等了一上午。

后来我搭了Nexus,世界清净了。

3.3.1 搭建步骤(Docker版)

现在搭私服太简单了,用Docker几分钟搞定:

docker run -d -p 8081:8081 --name nexus sonatype/nexus3

启动后访问 http://localhost:8081,默认管理员账号是 admin,密码在容器里的 /nexus-data/admin.password 文件中。

3.3.2 仓库类型与配置

Nexus有三种核心仓库类型,我整理了个表格:

仓库类型 用途 我常用的场景
proxy 代理中央仓库 缓存外部依赖,加速构建
hosted 存放私有构件 公司内部jar包、第三方商业库
group 聚合多个仓库 一个URL访问所有仓库

配置好之后,在项目的 pom.xml 里加上:

<repositories>
    <repository>
        <id>nexus</id>
        <url>http://你的私服地址:8081/repository/maven-public/</url>
    </repository>
</repositories>

3.3.3 部署构件到私服

部署到私服需要配置 settings.xml 里的认证信息:

<servers>
    <server>
        <id>nexus-releases</id>
        <username>admin</username>
        <password>你的密码</password>
    </server>
</servers>

然后在pom.xml里配置发布地址:

<distributionManagement>
    <repository>
        <id>nexus-releases</id>
        <url>http://私服地址:8081/repository/maven-releases/</url>
    </repository>
    <snapshotRepository>
        <id>nexus-snapshots</id>
        <url>http://私服地址:8081/repository/maven-snapshots/</url>
    </snapshotRepository>
</distributionManagement>
避坑指南: 我曾经把SNAPSHOT版本部署到了releases仓库,结果导致版本号混乱。记住:releases仓库只放正式版,snapshots仓库放开发版。Nexus默认不允许重复发布同一个release版本,但snapshot可以覆盖。

执行 mvn deploy,你的构件就上传到私服了。其他同事只需要配置好仓库地址,就能直接引用。

好了,这三个技能你掌握了,基本上Maven这块就没什么能难住你的了。从写插件自动化重复工作,到用Archetype统一项目结构,再到搭私服管理构件——这一套组合拳打下来,你团队的构建效率至少提升50%。