You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

旧Java项目不改造结构,实现Maven依赖管理与maven-embedder调用

使用Maven Embedder实现指定POM的依赖构建与Classpath生成

我刚好处理过类似的需求,用Maven Embedder完全能实现你想要的效果——不用改动原有项目结构,直接读取指定POM执行目标,还能通过API获取结果,完全不用去解析命令行输出。下面是具体的实现步骤和代码示例:

第一步:准备Maven Embedder依赖

你需要先把Maven Embedder相关的JAR包引入到你的工具项目中(因为你不能修改原有项目,建议单独写一个小工具来完成这件事)。如果你的工具是用Maven管理的,在pom.xml里添加这些依赖即可:

<dependencies>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-embedder</artifactId>
        <version>3.9.6</version> <!-- 用最新稳定版即可 -->
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-core</artifactId>
        <version>3.9.6</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven.shared</groupId>
        <artifactId>maven-shared-utils</artifactId>
        <version>3.4.1</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.sisu</groupId>
        <artifactId>org.eclipse.sisu.inject</artifactId>
        <version>0.3.5</version>
    </dependency>
</dependencies>

如果不用Maven管理,直接去Maven仓库下载这些JAR包,确保它们在你的工具的classpath里就行。

第二步:编写核心代码实现功能

下面的Java代码会复刻你指定的命令:mvn test dependency:build-classpath -f "C:\Users\Desktop\My_Pom.xml" -DoutputDirectory="C:\ProgramData\MyDirectoeyRepository",并且能通过API获取构建好的classpath,同时自动把依赖下载到指定目录。

import org.apache.maven.shared.invoker.*;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class MavenEmbedderTool {
    public static void main(String[] args) throws MavenInvocationException {
        // 1. 配置基础参数
        File pomFile = new File("C:\\Users\\Desktop\\My_Pom.xml");
        File outputRepoDir = new File("C:\\ProgramData\\MyDirectoeyRepository");

        // 2. 构建调用请求
        InvocationRequest request = new DefaultInvocationRequest();
        request.setPomFile(pomFile);
        // 设置要执行的目标:先执行test,再执行dependency:build-classpath
        List<String> goals = new ArrayList<>();
        goals.add("test");
        goals.add("dependency:build-classpath");
        request.setGoals(goals);

        // 3. 设置系统属性:指定输出仓库目录
        request.addSystemProperty("outputDirectory", outputRepoDir.getAbsolutePath());
        // 可选:配置自定义仓库地址(如果默认仓库访问有问题)
        request.addSystemProperty("repoUrl", "https://repo1.maven.org/maven2/");

        // 4. 指定本地仓库路径(直接用你设置的outputDirectory)
        request.setLocalRepositoryDirectory(outputRepoDir);

        // 5. 执行Maven命令
        Invoker invoker = new DefaultInvoker();
        invoker.setMavenHome(new File(System.getenv("MAVEN_HOME"))); // 确保环境变量MAVEN_HOME配置正确
        InvocationResult result = invoker.execute(request);

        // 6. 处理执行结果,获取Classpath
        if (result.getExitCode() == 0) {
            // 更优雅的方式:让Maven把classpath写入文件,直接读取文件内容
            request.getGoals().clear();
            request.getGoals().add("dependency:build-classpath");
            request.addSystemProperty("outputFile", "C:\\temp\\classpath.txt");
            invoker.execute(request);
            System.out.println("Classpath已生成到文件:C:\\temp\\classpath.txt");
        } else {
            System.err.println("Maven执行失败:" + result.getExecutionException().getMessage());
        }
    }
}

关键细节说明

  • 避免解析命令行输出:通过设置outputFile参数,让Maven把classpath直接写入文件,你只需要读取这个文件就行,完全不用处理Runtime.exec()的输出内容。
  • 不修改原有项目结构:所有操作都是基于你指定的pom.xml文件,不会改动原有项目的任何文件或目录。
  • 仓库配置:如果你的环境无法访问默认中央仓库,可以通过request.addSystemProperty("repoUrl", "你的仓库地址")指定自定义仓库,和你之前用的mvn dependency:get参数逻辑一致。
  • Maven环境依赖:确保运行环境中配置了MAVEN_HOME环境变量,Embedder需要依赖Maven的核心运行环境才能工作。

替代方案:直接解析POM获取依赖列表

如果你不需要执行test目标,只是想获取依赖的Jar包路径,可以用Maven Project API直接解析POM:

import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.FileReader;
import java.io.IOException;

public class PomParser {
    public static void main(String[] args) throws IOException, XmlPullParserException {
        MavenXpp3Reader reader = new MavenXpp3Reader();
        Model model = reader.read(new FileReader("C:\\Users\\Desktop\\My_Pom.xml"));
        // 遍历所有依赖
        model.getDependencies().forEach(dep -> {
            String depPath = String.format("%s/%s/%s/%s-%s.jar",
                    "C:\\ProgramData\\MyDirectoeyRepository",
                    dep.getGroupId().replace('.', '/'),
                    dep.getArtifactId(),
                    dep.getVersion(),
                    dep.getArtifactId(),
                    dep.getVersion());
            System.out.println("依赖路径:" + depPath);
        });
    }
}

不过这种方式不会自动下载依赖,只是解析POM里的依赖声明,适合你需要手动处理下载的场景。

内容的提问来源于stack exchange,提问作者user578219

火山引擎 最新活动