You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java实现Maven JAR文件直接与传递依赖的黑名单校验?

解决方案:Maven JAR依赖(含传递依赖)校验方案

一、修复Java调用mvn dependency:tree的问题

你在Java中调用该命令失败,通常是因为环境变量未配置Maven路径、未指定正确工作目录、未处理命令流导致进程阻塞这几个原因,以下是修复后的实现方案:

具体实现步骤

  1. 从上传的JAR文件中提取pom.xml到临时目录
  2. 指定Maven命令的完整路径(需匹配服务器实际安装路径),并将工作目录设为临时目录
  3. 同步读取命令的输出流与错误流,避免进程挂起

示例代码片段:

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;

public class MavenDependencyTree {
    public static String getDependencyTree(Path tempPomDir) throws IOException, InterruptedException {
        // 替换为服务器上Maven的实际路径
        String mvnCmd = "/usr/local/maven/bin/mvn dependency:tree -DoutputType=text";
        ProcessBuilder pb = new ProcessBuilder(mvnCmd.split(" "));
        pb.directory(tempPomDir.toFile());
        pb.redirectErrorStream(true); // 合并错误流到输出流,避免进程阻塞

        Process process = pb.start();
        StringBuilder output = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
        }
        int exitCode = process.waitFor();
        if (exitCode != 0) {
            throw new RuntimeException("Maven命令执行失败,输出:" + output.toString());
        }
        return output.toString();
    }
}

解析输出时,可按[groupId]:[artifactId]:[version]格式提取所有依赖,再与黑名单比对。

二、更可靠的方案:使用Maven Resolver(Aether)API

直接调用外部Maven命令依赖服务器环境配置,在云端场景下稳定性不足。推荐使用Maven Resolver(原Aether)——Maven官方的依赖解析库,可直接在Java代码中解析pom.xml,获取完整依赖树(含传递依赖)。

实现步骤

  1. 添加Maven Resolver相关依赖到项目pom.xml:
<dependencies>
    <dependency>
        <groupId>org.apache.maven.resolver</groupId>
        <artifactId>maven-resolver-api</artifactId>
        <version>1.9.15</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven.resolver</groupId>
        <artifactId>maven-resolver-impl</artifactId>
        <version>1.9.15</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven.resolver</groupId>
        <artifactId>maven-resolver-transport-http</artifactId>
        <version>1.9.15</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-core</artifactId>
        <version>3.9.5</version>
    </dependency>
</dependencies>
  1. 编写解析代码获取所有依赖:
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.resolver.examples.util.BasicRepositorySystemFactory;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.DependencyRequest;
import org.eclipse.aether.resolution.DependencyResult;

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

public class DependencyChecker {
    private static final RepositorySystem system = BasicRepositorySystemFactory.newRepositorySystem();

    public static List<String> getAllDependencies(InputStream pomInputStream) throws Exception {
        List<String> allDependencies = new ArrayList<>();
        // 读取pom.xml
        MavenXpp3Reader reader = new MavenXpp3Reader();
        Model model = reader.read(pomInputStream);

        // 构建依赖请求
        RepositorySystemSession session = BasicRepositorySystemFactory.newSession(system);
        DefaultArtifact artifact = new DefaultArtifact(
                model.getGroupId(), model.getArtifactId(), "pom", model.getVersion()
        );
        CollectRequest collectRequest = new CollectRequest();
        collectRequest.setRoot(new Dependency(artifact, null));
        // 添加公司私有仓库或中央仓库,按需调整
        collectRequest.addRepository(new RemoteRepository.Builder("central", "default", "https://repo1.maven.org/maven2/").build());

        DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, null);
        DependencyResult result = system.resolveDependencies(session, dependencyRequest);

        // 遍历依赖树收集所有依赖
        traverseDependencyTree(result.getRoot(), allDependencies);
        return allDependencies;
    }

    private static void traverseDependencyTree(DependencyNode node, List<String> dependencies) {
        if (node.getArtifact() != null) {
            String depKey = node.getArtifact().getGroupId() + ":" + node.getArtifact().getArtifactId() + ":" + node.getArtifact().getVersion();
            dependencies.add(depKey);
        }
        for (DependencyNode child : node.getChildren()) {
            traverseDependencyTree(child, dependencies);
        }
    }
}
  1. 黑名单校验:将收集到的依赖列表与黑名单(可存储为Set<String>)比对,若存在交集则返回false,禁止文件上传。

三、云端场景优化建议

  • 缓存依赖树:对同一版本的依赖缓存解析结果,提升校验效率
  • 配置私有仓库:在Maven Resolver中添加公司内部Maven仓库,确保能解析内部私有依赖
  • 离线模式支持:若云端无法访问外部仓库,可提前同步常用依赖到本地仓库,使用离线解析

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:12:20