{"id":17994072,"url":"https://github.com/anylisten/maven-dependency-downloader","last_synced_at":"2025-03-26T02:30:47.718Z","repository":{"id":94641476,"uuid":"139728450","full_name":"AnyListen/maven-dependency-downloader","owner":"AnyListen","description":"maven dependency downloader","archived":false,"fork":false,"pushed_at":"2018-10-18T01:01:51.000Z","size":19,"stargazers_count":22,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-21T01:34:28.670Z","etag":null,"topics":["maven","maven-pom","pom"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AnyListen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-04T13:50:21.000Z","updated_at":"2023-06-16T06:13:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"b5bdf274-fd2c-407a-84e3-dd0de6438615","html_url":"https://github.com/AnyListen/maven-dependency-downloader","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnyListen%2Fmaven-dependency-downloader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnyListen%2Fmaven-dependency-downloader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnyListen%2Fmaven-dependency-downloader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnyListen%2Fmaven-dependency-downloader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AnyListen","download_url":"https://codeload.github.com/AnyListen/maven-dependency-downloader/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245576522,"owners_count":20638123,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["maven","maven-pom","pom"],"created_at":"2024-10-29T20:13:57.880Z","updated_at":"2025-03-26T02:30:47.712Z","avatar_url":"https://github.com/AnyListen.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# maven-dependency-downloader\n本项目实现了两种功能：\n1. 根据pom.xml文件将其全部依赖下载到指定的文件夹；\n2. 根据Jar信息（groupId:artifactId:version）将其全部依赖下载到指定的文件夹。\n\n\u003e 需要注意的是环境变量必须配置：MAVEN_HOME\n\n## 背景\n从今年开始，内网很多项目开始使用 Maven 进行 Java 工程的 Jar 包管理，使用 Maven 自然比以前的 lib 文件夹要方便很多，其优点在这里就不罗列了，谁用谁知道。\n\n但是在没有网络的情况下使用 Maven 还是一件很艰难的事情，还好可以在内网搭建一个 Maven 私服。但是想要把整个 Maven 仓库同步到内网也是不可能的，因此一般是需要开发的适合把其依赖项添加到 Maven 仓库。\n\n例如我需要开发 Elasticsearch 工具包，需要用到 ES 相关的 Jar 包，我可以在外网新建一个项目，然后添加我的依赖项，最后将依赖打包到内网。\n\n这里存在的问题就是，全量打包是很简单的，增量打包很困难，你可以`通过每次改变本地仓库地址来实现增量打包`。但是每次手动修改 Maven 的配置文件也是一件很繁琐的事情，那么是否有工具可以帮我们实现增量打包呢？\n\n答案当然是有的，本文介绍的工具将解决增量打包的问题：\n1. 根据 pom.xml 文件将其全部依赖下载到指定的文件夹；\n2. 根据 Jar 信息（`groupId:artifactId:version`）将其全部依赖下载到指定的文件夹。\n\n## 根据 pom 文件获取其全部依赖\n### Apache Maven Invoker\n先看一下官方对该 API 的描述：在很多情况下，我们为了避免对系统的 Maven 环境造成污染，亦或是我们想使用用户目录作为 Maven 的工作目录进行项目构建，总之，`我们希望在一个全新的环境中启动 Maven 构建`。我们可以使用此 API 触发 Maven 构建，此 API 可以执行用户提供的命令行，可以捕获命令行运行中的错误信息，同时支持用户自定义输出（InvocationOutputHandler）和输入（InputStream）类。\n\n翻译的效果很差，举个例子：我想根据pom.xml文件获取该文件的全部依赖，借助 Maven 工具，我们只需要在 pom.xml 所在文件夹下使用命令行执行`mvn dependency:tree`即可获取其全部依赖。\n\n现在如果我们想通过程序的方式来实现，借助`Apache Maven Invoker`即可，下面代码展示了如何根据 pom.xml 获取其全部依赖：\n```\n/**\n * 根据POM文件获取全部依赖信息\n * @param pomFilePath POM文件路径\n * @return 全部依赖信息\n * @throws FileNotFoundException MAVEN_HOME或者POM文件不存在\n */\npublic static List\u003cDependenceInfo\u003e getDependenceListByPom(String pomFilePath) throws FileNotFoundException\n{\n    InvocationRequest request = new DefaultInvocationRequest();\n    File file = new File(pomFilePath);\n    if (!file.exists())\n    {\n        throw new FileNotFoundException(\"pom文件路径有误：\" + pomFilePath);\n    }\n    request.setPomFile(file);\n    request.setGoals(Collections.singletonList(\"dependency:tree\"));\n    String output = getInvokeOutput(request);\n    if (StrUtil.isBlank(output))\n    {\n        return null;\n    }\n    Matcher matcher = depPattern.matcher(output);\n    List\u003cDependenceInfo\u003e result = new ArrayList\u003cDependenceInfo\u003e();\n    while (matcher.find())\n    {\n        DependenceInfo dependenceInfo = new DependenceInfo(matcher.group(1),matcher.group(2),matcher.group(3),matcher.group(4));\n        result.add(dependenceInfo);\n    }\n    return result;\n}\n\n/**\n * 根据请求获取最终的控制台输出文本信息\n * @param request 请求\n * @return 控制台输出文本\n */\nprivate static String getInvokeOutput(InvocationRequest request) throws FileNotFoundException\n{\n    Invoker invoker = new DefaultInvoker();\n    String mavenHome = getMavenHome();\n    if (StrUtil.isBlank(mavenHome))\n    {\n        throw new FileNotFoundException(\"未检测到MAVEN_HOME，请在环境变量中进行配置。\");\n    }\n    invoker.setMavenHome(new File(mavenHome));\n    StringBuilderOutputHandler outputHandler = new StringBuilderOutputHandler();\n    invoker.setOutputHandler(outputHandler);\n    try\n    {\n        InvocationResult result = invoker.execute(request);\n        if (result.getExitCode() != 0)\n        {\n            StaticLog.error(\"Build failed.--------------\u003e\");\n            StaticLog.error(outputHandler.getOutput());\n            return null;\n        }\n        return outputHandler.getOutput();\n    }\n    catch (Exception ex)\n    {\n        StaticLog.error(ex);\n    }\n    return null;\n}\n```\n\n可以看到代码新建了一个`dependency:tree`的请求，然后在环境变量找到`MAVEN_HOME`，命令执行后通过自定义的输出类（`StringBuilderOutputHandler`）获取控制台文本内容：\n```\nimport org.apache.maven.shared.invoker.InvocationOutputHandler;\n\npublic class StringBuilderOutputHandler implements InvocationOutputHandler\n{\n    private StringBuilder output = new StringBuilder();\n\n    public void consumeLine(String s)\n    {\n        output.append(s).append(\"\\r\\n\");\n    }\n\n    public String getOutput()\n    {\n        return output.toString();\n    }\n}\n```\n\n通过上述代码便可获取 pom 文件的全部外部依赖，接下来根据依赖信息把依赖文件下载下来即可。\n\n### 下载依赖文件\n下载依赖文件有两种方法：\n1. 自行根据依赖信息从 Maven 仓库下载依赖项的 jar 和 pom.xml 文件，然后建立本地路径，将下载的文件放在相应的位置即可；\n2. 借助工具帮助我们下载。\n\n借助工具下载，有两种方法：\n1. 之前谷歌到的一种方法，使用`org.eclipse.aether`的一系列工具包，可以实现只需要提供 Jar 包信息即可完成全部依赖下载；\n2. 写文章到此刻，我觉得上述获取`dependency:tree`的方式应该也可以下载依赖。\n\n#### 使用 org.eclipse.aether 工具包下载全部依赖\n第一种方法整体流程就是设置一下自定义的 Maven 中央仓库地址，然后设置一下本地自定义的仓库目录，设置一下网络代理，最后调用 API 就会自动下载依赖，代码如下：\n```\n/**\n * 根据Artifact信息下载其相关依赖，并存储到指定的文件夹\n * @param artifactStr Artifact信息，例如：org.apache.maven.shared:maven-invoker:3.0.1\n * @param storePath 存储的路径\n * @param theScope Scope\n * @return 全部依赖信息\n */\npublic static List\u003cDependenceInfo\u003e downloadDependency(String artifactStr, String storePath, String theScope)\n{\n    DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();\n    RepositorySystem system = newRepositorySystem(locator);\n    RepositorySystemSession session = newSession(system, storePath);\n\n    Artifact artifact = new DefaultArtifact(artifactStr);\n    DependencyFilter theDependencyFilter = DependencyFilterUtils.classpathFilter(theScope);\n\n    RemoteRepository central = new RemoteRepository.Builder(\"central\", \"default\", \"http://central.maven.org/maven2/\").build();\n    CollectRequest theCollectRequest = new CollectRequest();\n    theCollectRequest.setRoot(new org.eclipse.aether.graph.Dependency(artifact, theScope));\n    theCollectRequest.addRepository(central);\n\n    DependencyRequest theDependencyRequest = new DependencyRequest(theCollectRequest, theDependencyFilter);\n    List\u003cDependenceInfo\u003e resultList = new ArrayList\u003cDependenceInfo\u003e();\n    try\n    {\n        DependencyResult theDependencyResult = system.resolveDependencies(session, theDependencyRequest);\n        for (ArtifactResult theArtifactResult : theDependencyResult.getArtifactResults()) {\n            Artifact theResolved = theArtifactResult.getArtifact();\n            DependenceInfo depInfo = new DependenceInfo(theResolved.getGroupId(), theResolved.getArtifactId(), theResolved.getVersion(), JavaScopes.COMPILE);\n            resultList.add(depInfo);\n        }\n    }\n    catch (Exception e)\n    {\n        e.printStackTrace();\n    }\n    return resultList;\n}\n\nprivate static RepositorySystem newRepositorySystem(DefaultServiceLocator locator) {\n    locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);\n    locator.addService(TransporterFactory.class, FileTransporterFactory.class);\n    locator.addService(TransporterFactory.class, HttpTransporterFactory.class);\n    return locator.getService(RepositorySystem.class);\n}\n\nprivate static RepositorySystemSession newSession(RepositorySystem system, String storePath) {\n    DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();\n    LocalRepository localRepo = new LocalRepository(storePath);\n    session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));\n    return session;\n}\n```\n本方法的确可以下载到全部依赖，但是有一个缺点就是会将一些可选的依赖下载下来，如下如所示：\n\n![可选的依赖会被下载](http://img.luooqi.com/FjanwBuEfm1bta1eVo6UKWmRiN-w)\n\n#### 使用 Maven Invoker 下载全部依赖\n这个方法是写文章的时候进行验证的，效果很不错，代码简洁高效，是根据 pom 文件下载全部依赖的最佳方案。\n\n其原理和上面的执行`dependency:tree`是一致的，在 Maven 官网查询到使用`dependency:resolve`可以下载到全部依赖到本地文件。那么现在只需要有个地方可以自定义本地仓库即可，幸运的是`Maven Invoker`支持自定义本地仓库：\n```\nInvoker invoker = new DefaultInvoker();\nString mavenHome = getMavenHome();\nif (StrUtil.isNotBlank(localRepo))\n{\n    //在此设置本地仓库\n    invoker.setLocalRepositoryDirectory(new File(localRepo));\n}\ninvoker.setMavenHome(new File(mavenHome));\n```\n\n## 总结\n如果根据 pom 文件下载依赖则推荐使用`Maven Invoker`方案；如果需要通过 Artifact 信息（`groupId:artifactId:version`）下载依赖则推荐使用`org.eclipse.aether`工具包；详细使用可以参考测试代码。\n\n\u003e 完整代码地址：https://github.com/AnyListen/maven-dependency-downloader\n\n---\n`追求高效、有节奏的研发过程； 打造高质量、创新的研发产品。 专注技术、钟情产品！`\n\n欢迎扫码关注『朗坤极客驿站』，遇见更优秀的自己。\n\n![](http://img.luooqi.com/Ft0jWj-Q69B67I8DE9pIBMOa6Bl5)\n\n## 参考\n- [maven-invoker](http://maven.apache.org/shared/maven-invoker/usage.html)\n- [Maven: get all dependencies programmatically\n](https://stackoverflow.com/questions/40813062/maven-get-all-dependencies-programmatically)\n- [dependency:tree](https://maven.apache.org/plugins/maven-dependency-plugin/tree-mojo.html)\n- [Find all direct dependencies of an artifact on Maven Central\n](https://stackoverflow.com/questions/39638138/find-all-direct-dependencies-of-an-artifact-on-maven-central/39641359)\n- [List of dependency jar files in Maven\n](https://stackoverflow.com/questions/278596/list-of-dependency-jar-files-in-maven)\n- [How to download Maven artifacts with Maven \u003e=3.1 and Eclipse Aether](https://www.mirkosertic.de/blog/2015/12/how-to-download-maven-artifacts-with-maven-3-1-and-eclipse-aether/)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanylisten%2Fmaven-dependency-downloader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanylisten%2Fmaven-dependency-downloader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanylisten%2Fmaven-dependency-downloader/lists"}