一、前言
功能:根据一个pom.xml
文件,将本地maven仓库中相关的依赖文件导出到一个文件夹下,并保留目录原有的层级结构。
该节废话偏多,没心情看的兄弟们直接看第二、三节。
在内网开发过程中,基于maven构建的项目时常会遇到缺依赖的情况,即使在内网环境中有maven私仓环境也无法避免依赖不全的问题,maven给我们提供了依赖管理的功能,通过Maven的中央仓库或国内的镜像服务,我们可以轻松下载和安装第三方库,而无需手动下载和管理添加第三方jar包。这解决了添加第三方jar包、处理jar包之间的依赖关系以及解决jar包之间的冲突等问题,由于内网无法链接互联网,导致我们在需要添加新依赖时就变得无比麻烦,一个依赖可能会存在多个依赖,如此循环往复下去无疑会消耗我们很多时间,如果多来几次或不成功的时候甚至会把我们心态搞崩溃。
二、效果
pom.xml中的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.6</version>
</dependency>
</dependencies>
程序执行信息
copy groupId:org.springframework.boot artifactId:spring-boot-starter-web version:3.3.2
copy groupId:org.springframework.boot artifactId:spring-boot-starter version:3.3.2
copy groupId:org.springframework.boot artifactId:spring-boot version:3.3.2
copy groupId:org.springframework.boot artifactId:spring-boot-starter-logging version:3.3.2
copy groupId:ch.qos.logback artifactId:logback-classic version:1.5.6
copy groupId:ch.qos.logback artifactId:logback-core version:1.5.6
copy groupId:org.apache.logging.log4j artifactId:log4j-to-slf4j version:2.23.1
copy groupId:org.apache.logging.log4j artifactId:log4j-api version:2.23.1
copy groupId:org.slf4j artifactId:jul-to-slf4j version:2.0.13
copy groupId:jakarta.annotation artifactId:jakarta.annotation-api version:2.1.1
copy groupId:org.springframework artifactId:spring-core version:6.1.11
copy groupId:org.springframework artifactId:spring-jcl version:6.1.11
copy groupId:org.yaml artifactId:snakeyaml version:2.2
copy groupId:org.springframework.boot artifactId:spring-boot-starter-json version:3.3.2
copy groupId:com.fasterxml.jackson.core artifactId:jackson-databind version:2.17.2
copy groupId:com.fasterxml.jackson.core artifactId:jackson-annotations version:2.17.2
copy groupId:com.fasterxml.jackson.core artifactId:jackson-core version:2.17.2
copy groupId:com.fasterxml.jackson.datatype artifactId:jackson-datatype-jdk8 version:2.17.2
copy groupId:com.fasterxml.jackson.datatype artifactId:jackson-datatype-jsr310 version:2.17.2
copy groupId:com.fasterxml.jackson.module artifactId:jackson-module-parameter-names version:2.17.2
copy groupId:org.springframework.boot artifactId:spring-boot-starter-tomcat version:3.3.2
copy groupId:org.apache.tomcat.embed artifactId:tomcat-embed-core version:10.1.26
copy groupId:org.apache.tomcat.embed artifactId:tomcat-embed-el version:10.1.26
copy groupId:org.apache.tomcat.embed artifactId:tomcat-embed-websocket version:10.1.26
copy groupId:org.springframework artifactId:spring-web version:6.1.11
copy groupId:org.springframework artifactId:spring-beans version:6.1.11
copy groupId:io.micrometer artifactId:micrometer-observation version:1.12.8
copy groupId:io.micrometer artifactId:micrometer-commons version:1.12.8
copy groupId:org.springframework artifactId:spring-webmvc version:6.1.11
copy groupId:org.springframework artifactId:spring-aop version:6.1.11
copy groupId:org.springframework artifactId:spring-context version:6.1.11
copy groupId:org.springframework artifactId:spring-expression version:6.1.11
copy groupId:com.baomidou artifactId:mybatis-plus-boot-starter version:3.5.6
copy groupId:com.baomidou artifactId:mybatis-plus version:3.5.6
copy groupId:com.baomidou artifactId:mybatis-plus-core version:3.5.6
copy groupId:com.baomidou artifactId:mybatis-plus-annotation version:3.5.6
copy groupId:com.baomidou artifactId:mybatis-plus-extension version:3.5.6
copy groupId:org.mybatis artifactId:mybatis version:3.5.16
copy groupId:com.github.jsqlparser artifactId:jsqlparser version:4.9
copy groupId:org.mybatis artifactId:mybatis-spring version:2.1.2
copy groupId:com.baomidou artifactId:mybatis-plus-spring-boot-autoconfigure version:3.5.6
copy groupId:org.springframework.boot artifactId:spring-boot-autoconfigure version:2.7.15
copy groupId:org.springframework.boot artifactId:spring-boot-starter-jdbc version:2.7.15
copy groupId:com.zaxxer artifactId:HikariCP version:4.0.3
copy groupId:org.slf4j artifactId:slf4j-api version:2.0.0-alpha1
copy groupId:org.springframework artifactId:spring-jdbc version:5.3.29
copy groupId:org.springframework artifactId:spring-tx version:5.3.29
导出依赖到其它目录的内容及结构,内容太长,这里只贴部分内容示意。
├─ch
│ └─qos
│ └─logback
│ ├─logback-classic
│ │ └─1.5.6
│ │ logback-classic-1.5.6.jar
│ │ logback-classic-1.5.6.jar.sha1
│ │ logback-classic-1.5.6.pom
│ │ logback-classic-1.5.6.pom.sha1
│ │ _remote.repositories
│ │
│ └─logback-core
│ └─1.5.6
│ logback-core-1.5.6.jar
│ logback-core-1.5.6.jar.sha1
│ logback-core-1.5.6.pom
│ logback-core-1.5.6.pom.sha1
│ _remote.repositories
│
├─com
│ ├─baomidou
│ │ ├─mybatis-plus
│ │ │ └─3.5.6
│ │ │ mybatis-plus-3.5.6.jar
│ │ │ mybatis-plus-3.5.6.jar.sha1
│ │ │ mybatis-plus-3.5.6.pom
│ │ │ mybatis-plus-3.5.6.pom.sha1
│ │ │ _remote.repositories
│ │ │
│ │ ├─mybatis-plus-annotation
│ │ │ └─3.5.6
│ │ │ mybatis-plus-annotation-3.5.6.jar
│ │ │ mybatis-plus-annotation-3.5.6.jar.sha1
│ │ │ mybatis-plus-annotation-3.5.6.pom
│ │ │ mybatis-plus-annotation-3.5.6.pom.sha1
│ │ │ _remote.repositories
│ │ │
│ │ ├─mybatis-plus-boot-starter
│ │ │ └─3.5.6
│ │ │ mybatis-plus-boot-starter-3.5.6.jar
│ │ │ mybatis-plus-boot-starter-3.5.6.jar.sha1
│ │ │ mybatis-plus-boot-starter-3.5.6.pom
│ │ │ mybatis-plus-boot-starter-3.5.6.pom.sha1
│ │ │ _remote.repositories
│ │ │
│ │ ├─mybatis-plus-core
│ │ │ └─3.5.6
│ │ │ mybatis-plus-core-3.5.6.jar
│ │ │ mybatis-plus-core-3.5.6.jar.sha1
│ │ │ mybatis-plus-core-3.5.6.pom
│ │ │ mybatis-plus-core-3.5.6.pom.sha1
│ │ │ _remote.repositories
│ │ │
│ │ ├─mybatis-plus-extension
│ │ │ └─3.5.6
│ │ │ mybatis-plus-extension-3.5.6.jar
│ │ │ mybatis-plus-extension-3.5.6.jar.sha1
│ │ │ mybatis-plus-extension-3.5.6.pom
│ │ │ mybatis-plus-extension-3.5.6.pom.sha1
│ │ │ _remote.repositories
│ │ │
│ │ └─mybatis-plus-spring-boot-autoconfigure
│ │ └─3.5.6
│ │ mybatis-plus-spring-boot-autoconfigure-3.5.6.jar
│ │ mybatis-plus-spring-boot-autoconfigure-3.5.6.jar.sha1
│ │ mybatis-plus-spring-boot-autoconfigure-3.5.6.pom
│ │ mybatis-plus-spring-boot-autoconfigure-3.5.6.pom.sha1
│ │ _remote.repositories
│ │
三、代码
package org.example;
import org.apache.commons.io.FileUtils;
import java.io.*;
import java.text.MessageFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) throws IOException {
//读取的pom文件
String pom = "D:\\projects\\test\\dependency-module\\pom.xml";
//maven仓库地址
String rep = "D:\\source\\maven\\repository";
//文件存储的位置
String out = "D:\\source\\maven\\rep_target";
//是否覆写_remote.repositories文件
boolean overwriteRemoteFile = true;
Process exec = Runtime.getRuntime().exec("cmd /c mvn dependency:list -f " + pom);
InputStream is = exec.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
//源
File repFile = new File(rep);
//目标
File outFile = new File(out);
if(!outFile.exists()) {
outFile.mkdirs();
}
Pattern pattern = Pattern.compile(".*?\\s+(.*?):(.*):(jar|pom|war):(.*?):.*");
String content = null;
while (null != (content = br.readLine())) {
//System.out.println(content);
Matcher matcher = pattern.matcher(content);
boolean matches = matcher.matches();
if(matches) {
Dependency dependency = new Dependency(matcher.group(1), matcher.group(2), matcher.group(4));
System.out.println("copy " + dependency);
dependency.copy(repFile,outFile,overwriteRemoteFile);
}
}
br.close();
isr.close();
is.close();
System.out.println("final...");
}
static class Dependency {
public Dependency (String groupId,String artifactId,String version) {
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
}
private String groupId;
private String artifactId;
private String version;
@Override
public String toString() {
return MessageFormat.format("groupId:{0} artifactId:{1} version:{2}",groupId,artifactId,version);
}
public void copy(File source,File target,boolean overwrite) throws IOException {
String path = groupId.replace(".","\\") + "\\" + artifactId + "\\" + version;
//System.out.println(path);
File s = new File(source,path);
if(s.exists()) {
File t = new File(target,path);
if(!t.exists()) {
t.mkdirs();
}
FileUtils.copyDirectory(s,t);
if(overwrite) {
File[] files = t.listFiles(file -> file.getName().equals("_remote.repositories"));
if(null != files && files.length != 0) {
File file = files[0];
FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fos);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(artifactId + "-" + version + ".pom>central=");
bw.newLine();
bw.write(artifactId + "-" + version + ".jar>central=");
bw.flush();
bw.close();
osw.close();
fos.close();
}
}
} else {
System.err.println("file not fond ... ,please manual handle");
}
}
}
}
四、解释
通过mvn dependency
命令获取pom.xml
中的依赖项,通过正则匹配每个依赖的groupId
、artifactId
、version
,通过这三个内容可以定位maven仓库中的位置,将文件按照目录复制到目标文件夹下,如果需要覆写_remote.repositories
,则重新生成内容写入到_remote.repositories
文件中。
cmd /c mvn dependency:list -f D:\projects\test\dependency-module\pom.xml
命令可以打印一个pom.xml中的所有依赖内容,效果如下。
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< org.example:dependency-module >--------------------
[INFO] Building dependency-module 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- dependency:3.7.0:list (default-cli) @ dependency-module ---
[INFO]
[INFO] The following files have been resolved:
[INFO] org.springframework.boot:spring-boot-starter-web:jar:3.3.2:compile -- module spring.boot.starter.web [auto]
[INFO] org.springframework.boot:spring-boot-starter:jar:3.3.2:compile -- module spring.boot.starter [auto]
[INFO] org.springframework.boot:spring-boot:jar:3.3.2:compile -- module spring.boot [auto]
[INFO] org.springframework.boot:spring-boot-starter-logging:jar:3.3.2:compile -- module spring.boot.starter.logging [auto]
[INFO] ch.qos.logback:logback-classic:jar:1.5.6:compile -- module ch.qos.logback.classic
[INFO] ch.qos.logback:logback-core:jar:1.5.6:compile -- module ch.qos.logback.core
[INFO] org.apache.logging.log4j:log4j-to-slf4j:jar:2.23.1:compile -- module org.apache.logging.log4j.to.slf4j
[INFO] org.apache.logging.log4j:log4j-api:jar:2.23.1:compile -- module org.apache.logging.log4j
[INFO] org.slf4j:jul-to-slf4j:jar:2.0.13:compile -- module jul.to.slf4j
[INFO] jakarta.annotation:jakarta.annotation-api:jar:2.1.1:compile -- module jakarta.annotation
[INFO] org.springframework:spring-core:jar:6.1.11:compile -- module spring.core [auto]
[INFO] org.springframework:spring-jcl:jar:6.1.11:compile -- module spring.jcl [auto]
[INFO] org.yaml:snakeyaml:jar:2.2:compile -- module org.yaml.snakeyaml
[INFO] org.springframework.boot:spring-boot-starter-json:jar:3.3.2:compile -- module spring.boot.starter.json [auto]
[INFO] com.fasterxml.jackson.core:jackson-databind:jar:2.17.2:compile -- module com.fasterxml.jackson.databind
[INFO] com.fasterxml.jackson.core:jackson-annotations:jar:2.17.2:compile -- module com.fasterxml.jackson.annotation
[INFO] com.fasterxml.jackson.core:jackson-core:jar:2.17.2:compile -- module com.fasterxml.jackson.core
[INFO] com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.17.2:compile -- module com.fasterxml.jackson.datatype.jdk8
[INFO] com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.17.2:compile -- module com.fasterxml.jackson.datatype.jsr310
[INFO] com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.17.2:compile -- module com.fasterxml.jackson.module.paramnames
[INFO] org.springframework.boot:spring-boot-starter-tomcat:jar:3.3.2:compile -- module spring.boot.starter.tomcat [auto]
[INFO] org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.26:compile -- module tomcat.embed.core (auto)
[INFO] org.apache.tomcat.embed:tomcat-embed-el:jar:10.1.26:compile -- module tomcat.embed.el (auto)
[INFO] org.apache.tomcat.embed:tomcat-embed-websocket:jar:10.1.26:compile -- module tomcat.embed.websocket (auto)
[INFO] org.springframework:spring-web:jar:6.1.11:compile -- module spring.web [auto]
[INFO] org.springframework:spring-beans:jar:6.1.11:compile -- module spring.beans [auto]
[INFO] io.micrometer:micrometer-observation:jar:1.12.8:compile -- module micrometer.observation [auto]
[INFO] io.micrometer:micrometer-commons:jar:1.12.8:compile -- module micrometer.commons [auto]
[INFO] org.springframework:spring-webmvc:jar:6.1.11:compile -- module spring.webmvc [auto]
[INFO] org.springframework:spring-aop:jar:6.1.11:compile -- module spring.aop [auto]
[INFO] org.springframework:spring-context:jar:6.1.11:compile -- module spring.context [auto]
[INFO] org.springframework:spring-expression:jar:6.1.11:compile -- module spring.expression [auto]
[INFO] com.baomidou:mybatis-plus-boot-starter:jar:3.5.6:compile -- module com.baomidou.mybatis.plus.boot.starter [auto]
[INFO] com.baomidou:mybatis-plus:jar:3.5.6:compile -- module com.baomidou.mybatis.plus [auto]
[INFO] com.baomidou:mybatis-plus-core:jar:3.5.6:compile -- module com.baomidou.mybatis.plus.core [auto]
[INFO] com.baomidou:mybatis-plus-annotation:jar:3.5.6:compile -- module com.baomidou.mybatis.plus.annotation [auto]
[INFO] com.baomidou:mybatis-plus-extension:jar:3.5.6:compile -- module com.baomidou.mybatis.plus.extension [auto]
[INFO] org.mybatis:mybatis:jar:3.5.16:compile -- module org.mybatis [auto]
[INFO] com.github.jsqlparser:jsqlparser:jar:4.9:compile -- module net.sf.jsqlparser [auto]
[INFO] org.mybatis:mybatis-spring:jar:2.1.2:compile -- module org.mybatis.spring [auto]
[INFO] com.baomidou:mybatis-plus-spring-boot-autoconfigure:jar:3.5.6:compile -- module com.baomidou.mybatis.plus.spring.boot.autoconfigure [auto]
[INFO] org.springframework.boot:spring-boot-autoconfigure:jar:2.7.15:compile -- module spring.boot.autoconfigure [auto]
[INFO] org.springframework.boot:spring-boot-starter-jdbc:jar:2.7.15:compile -- module spring.boot.starter.jdbc [auto][INFO] com.zaxxer:HikariCP:jar:4.0.3:compile -- module com.zaxxer.hikari
[INFO] org.slf4j:slf4j-api:jar:2.0.0-alpha1:compile -- module org.slf4j
[INFO] org.springframework:spring-jdbc:jar:5.3.29:compile -- module spring.jdbc [auto]
[INFO] org.springframework:spring-tx:jar:5.3.29:compile -- module spring.tx [auto]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.758 s
[INFO] Finished at: 2024-09-03T16:24:16+08:00
[INFO] ------------------------------------------------------------------------
".*?\\s+(.*?):(.*):(jar|pom|war):(.*?):.*"
正则可以匹配到依赖项,并通过正则表达式中的分组
提取出groupId
、artifactId
、version
。
_remote.repositories的作用,通常来说覆写是很有必要的。