# Java使用Maven及Gitlab
## Java使用Maven
### 所需依赖
```xml
org.apache.maven
maven-embedder
3.9.6
org.apache.maven
maven-compat
3.9.6
org.apache.maven.resolver
maven-resolver-transport-http
1.9.18
org.apache.maven.resolver
maven-resolver-connector-basic
1.9.18
org.apache.maven
maven-resolver-provider
3.9.6
org.apache.maven
maven-settings-builder
3.9.6
```
### 使用Archetype生成项目
```java
package org.jeecg.modules.devops.archetype;
import lombok.extern.slf4j.Slf4j;
import org.apache.maven.cli.MavenCli;
import org.jeecg.modules.devops.model.YuanMengOnlineService;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@Slf4j
public class MavenUtils {
private static final String ARCHETYPE_GROUP_ID = "com.yuanmeng.engine";
private static final String ARCHETYPE_ARTIFACT_ID = "engine-archetype-web";
private static final String ARCHETYPE_VERSION = "2.0.2-SNAPSHOT";
public static Path createProject(YuanMengOnlineService archetypeInfo) {
try {
// 配置项目目录
Path projectDir = Files.createTempDirectory(archetypeInfo.getArchetypeArtifactId());
log.info("项目生成目录: {}", projectDir);
// 创建 settings.xml 文件
Path settingsFile = createTempSettingsFile();
// 下面这行代码不能缺少,否则无法执行
configureSystemProperties(settingsFile);
// 使用 Maven Embedder 生成项目
generateMavenProject(projectDir.toFile(), settingsFile, archetypeInfo);
Path path = projectDir.resolve(archetypeInfo.getArchetypeArtifactId());
log.info("✅ 项目成功创建于: {}", path);
return path;
} catch (Exception e) {
log.error("❌ 出现错误: {}, {}", e.getMessage(), archetypeInfo, e);
throw new RuntimeException("项目初始化失败:" + e.getMessage());
}
}
private static void generateMavenProject(File baseDir, Path settingsFile, YuanMengOnlineService archetypeInfo) {
// 构建 Maven 参数
String[] mvnArgs = new String[]{
"archetype:generate",
"-DinteractiveMode=false",
"-DarchetypeGroupId=" + ARCHETYPE_GROUP_ID,
"-DarchetypeArtifactId=" + ARCHETYPE_ARTIFACT_ID,
"-DarchetypeVersion=" + ARCHETYPE_VERSION,
"-DgroupId=" + archetypeInfo.getArchetypeGroupId(),
"-DartifactId=" + archetypeInfo.getArchetypeArtifactId(),
"-Dversion=" + archetypeInfo.getArchetypeVersion(),
"-Dapp=" + archetypeInfo.getArchetypeApp(),
"-Dpackage=" + archetypeInfo.getArchetypePackage(),
"-B", // 开启批处理模式
"-s", settingsFile.toString()
};
log.info("Maven 项目生成指令:{}", String.join(" ", mvnArgs));
// 使用 Maven Embedder
MavenCli cli = new MavenCli();
int result = cli.doMain(mvnArgs, baseDir.getAbsolutePath(), System.out, System.err);
if (result != 0) {
throw new RuntimeException("Maven 项目生成失败 (退出码: " + result + ")");
}
log.info("✅ Maven 项目生成成功");
}
private static Path createTempSettingsFile() {
try {
// 创建临时 settings.xml 文件
Path settingsPath = Files.createTempFile("maven-settings", ".xml");
// 构建 settings.xml 内容
String settingsContent = buildSettingsXml();
// 写入文件
Files.write(settingsPath, settingsContent.getBytes());
// 设置文件删除钩子(程序退出时删除)
settingsPath.toFile().deleteOnExit();
return settingsPath;
} catch (IOException e) {
throw new RuntimeException("Failed to create temp settings.xml", e);
}
}
private static String buildSettingsXml() {
return "\n" +
" /tmp/repository\n" +
" \n" +
" \n" +
" private-repo\n" +
" developer\n" +
" deve@123\n" +
" \n" +
" \n" +
" \n" +
" \n" +
" private-repo\n" +
" Private Repository Mirror\n" +
" http://120.79.68.191:8081/repository/maven-public/\n" +
" *\n" +
" \n" +
" \n" +
" \n" +
" \n" +
" default\n" +
" \n" +
" \n" +
" private-repo\n" +
" http://120.79.68.191:8081/repository/maven-public/\n" +
" true\n" +
" true\n" +
" \n" +
" \n" +
" \n" +
" \n" +
" private-repo\n" +
" http://120.79.68.191:8081/repository/maven-public/\n" +
" true\n" +
" true\n" +
" \n" +
" \n" +
" \n" +
" \n" +
" \n" +
" default\n" +
" \n" +
"";
}
private static void configureSystemProperties(Path settingsPath) {
System.setProperty("maven.multiModuleProjectDirectory", System.getProperty("user.dir"));
// 使用自定义 settings.xml
System.setProperty("maven.user.settings", settingsPath.toString());
// 配置超时(可选)
System.setProperty("maven.wagon.http.readTimeout", "300000"); // 5分钟
System.setProperty("maven.wagon.http.connectionTimeout", "120000");
// 禁用 SSL 验证(如果私服使用 HTTP)
System.setProperty("maven.wagon.http.ssl.insecure", "true");
System.setProperty("maven.wagon.http.ssl.allowall", "true");
// 启用调试日志(可选)
System.setProperty("org.slf4j.simpleLogger.log.org.apache.maven.cli", "info");
}
}
```
----
## Java操作Git及Gitlab
### 依赖引入
```xml
org.eclipse.jgit
org.eclipse.jgit
6.10.1.202505221210-r
org.gitlab4j
gitlab4j-api
5.3.0
```
### Java代码调用
#### Gitlab调用工具类
```java
package org.jeecg.modules.devops.archetype;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.*;
import java.util.List;
import java.util.Objects;
/**
* insert description here
*
* @author liuxiaohua
* @since 2025-06-11
*/
@Slf4j
public class GitlabUtils {
private static volatile GitLabApi gitLabApi;
public static synchronized void init(ArchetypeProperties archetypeProperties) {
if (gitLabApi == null) {
synchronized (GitlabUtils.class) {
if (gitLabApi == null) {
gitLabApi = new GitLabApi(archetypeProperties.getGitlabUrl(), archetypeProperties.getAccessToken());
}
}
}
}
@SneakyThrows
public static void deleteProject(Long projectId) {
gitLabApi.getProjectApi().deleteProject(projectId);
}
@SneakyThrows
public static Project createProject(String group, String project, String desc) {
Group groupInfo = getGroupId(group);
if (Objects.isNull(groupInfo) || Objects.isNull(groupInfo.getId())) {
throw new RuntimeException("获取分组信息失败");
}
Project gitLabRepository = createRepository(groupInfo, project, desc);
if (gitLabRepository == null || gitLabRepository.getId() == null) {
throw new RuntimeException("创建仓库失败");
}
return gitLabRepository;
}
@SneakyThrows
public static ProtectedBranch protectedBranch(Long projectId, Integer retryTimes) {
try {
// 获取已保护的分支
List protectedBranches = gitLabApi.getProtectedBranchesApi().getProtectedBranches(projectId);
log.info("protected branches: {}", JSONObject.toJSONString(protectedBranches));
// 保护分支
if (CollUtil.isNotEmpty(protectedBranches)
&& protectedBranches.stream().map(ProtectedBranch::getName).anyMatch("master"::equalsIgnoreCase)) {
// 取消旧的配置
unprotectedBranch(projectId);
}
// 添加分支保护
return gitLabApi.getProtectedBranchesApi()
.protectBranch(projectId, "master", AccessLevel.NONE, AccessLevel.MAINTAINER);
} catch (GitLabApiException e) {
log.warn("protected branch failed: {}", e.getMessage());
}
if (retryTimes < 3) {
return protectedBranch(projectId, ++retryTimes);
}
log.warn("protected branch failure: {}", retryTimes);
throw new RuntimeException(ArchetypeUtils.WARN_MESSAGE_1);
}
private static void unprotectedBranch(Long projectId) {
try {
gitLabApi.getProtectedBranchesApi().unprotectBranch(projectId, "master");
log.info("unprotected branch master success");
} catch (Exception e) {
log.warn("unprotected branch error: {}", e.getMessage());
}
}
/**
* 根据分组路径获取分组ID
*/
private static Group getGroupId(String groupPath) throws GitLabApiException {
return gitLabApi.getGroupApi().getOptionalGroup(groupPath).orElse(null);
}
/**
* 在 GitLab 创建新仓库
*/
private static Project createRepository(Group group,
String projectName,
String desc) {
Project exists = gitLabApi.getProjectApi().getOptionalProject(group.getName(), projectName).orElse(null);
if (Objects.nonNull(exists)) {
throw new RuntimeException("项目已经存在");
}
try {
Project project = new Project()
.withName(projectName)
.withDefaultBranch("master")
.withDescription(desc)
.withNamespaceId(group.getId())
.withVisibility(Visibility.PRIVATE); // 私有库用 PRIVATE
return gitLabApi.getProjectApi().createProject(project); // 返回 HTTPS 仓库地址
} catch (Exception e) {
log.warn("create project error: {}", e.getMessage());
}
return null;
}
public static ProjectHook addWebhook(Long projectId, String webhookUrl, Integer retryTimes) {
try {
// 配置 webhook
ProjectHook projectHook = gitLabApi.getProjectApi().addHook(
projectId, webhookUrl, Boolean.FALSE, Boolean.FALSE, Boolean.TRUE);
log.info("add project hook: {}", JSONObject.toJSONString(projectHook));
return projectHook;
} catch (GitLabApiException e) {
log.warn("add project hook failed: {}", e.getMessage());
}
if (retryTimes < 3) {
return addWebhook(projectId, webhookUrl, ++retryTimes);
}
log.warn("add project hook failure: {}", retryTimes);
throw new RuntimeException(ArchetypeUtils.WARN_MESSAGE_2);
}
public static Member addMembers(Long projectId, String email, Integer retryTimes) {
try {
if (StrUtil.isBlank(email)) {
email = "liuxiaohua@keyfil.com";
}
if (!email.endsWith("@keyfil.com")) {
email += "@keyfil.com";
}
User userByEmail = gitLabApi.getUserApi().getOptionalUserByEmail(email).orElse(null);
if (userByEmail == null) {
log.warn("get user by email error");
throw new RuntimeException(ArchetypeUtils.WARN_MESSAGE_3);
}
log.info("add members user: {}", JSONObject.toJSONString(userByEmail));
Member member = gitLabApi.getProjectApi().getOptionalMember(projectId, userByEmail.getId()).orElse(null);
log.info("member exists: {}", JSONObject.toJSONString(member));
if (Objects.nonNull(member)) {
if (member.getAccessLevel().value < AccessLevel.MAINTAINER.value) {
member = gitLabApi.getProjectApi().updateMember(projectId, userByEmail.getId(), AccessLevel.MAINTAINER);
}
} else {
member = gitLabApi.getProjectApi()
.getOptionalMember(projectId, userByEmail.getId(), Boolean.TRUE)
.orElse(null);
if (Objects.isNull(member) || member.getAccessLevel().value < AccessLevel.MAINTAINER.value) {
member = gitLabApi.getProjectApi().addMember(projectId, userByEmail.getId(), AccessLevel.MAINTAINER);
}
}
return member;
} catch (GitLabApiException e) {
log.warn("add members user: failed: {}", e.getMessage());
}
if (retryTimes < 3) {
return addMembers(projectId, email, ++retryTimes);
}
log.warn("add members user failure: {}", retryTimes);
throw new RuntimeException(ArchetypeUtils.WARN_MESSAGE_3);
}
}
```
#### Git调用工具类
```java
package org.jeecg.modules.devops.archetype;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.stereotype.Component;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* insert description here
*
* @author liuxiaohua
* @since 2025-06-11
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class GitUtils {
/**
* 初始化本地仓库并推送到 GitLab
*/
public static void pushLocalCodeToGitLab(String remoteUrl,
String codePath,
ArchetypeProperties archetypeProperties) {
File localPath = new File(codePath);
CredentialsProvider credentials = new UsernamePasswordCredentialsProvider(
archetypeProperties.getUsername(), archetypeProperties.getAccessToken());
try (Git git = Git.init().setDirectory(localPath).call()) {
// 添加所有文件
git.add().addFilepattern(".").call();
// 提交更改
git.commit()
.setMessage(String.format("\uD83C\uDF89 [%s] 初始化提交",
new SimpleDateFormat("yyyy-MM-dd").format(new Date())))
.call();
// 添加远程仓库
git.remoteAdd()
.setName("origin")
.setUri(new URIish(remoteUrl))
.call();
// 推送到 GitLab
git.push()
.setRemote("origin")
.setCredentialsProvider(credentials)
.setForce(true)
.setPushAll()
.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
```