GitLab4J API(gitlab4j-api)5.0.1 使用详解
基于 Maven 坐标
org.gitlab4j:gitlab4j-api:5.0.1本文全面解读该库的常用接口,并给出可直接使用的 Java 代码示例。
1. 库简介与架构
GitLab4J API(gitlab4j-api)是一个功能完整、使用简单的 Java 客户端库,用于通过 GitLab REST API 操作 GitLab 仓库及其相关功能(项目、议题、合并请求、CI/CD、用户、群组、Webhook 等)。
- 支持 GitLab Community Edition (CE) 和 Enterprise Edition (EE)。
- 内部基于 Jersey (JAX-RS) 实现 HTTP 请求,使用 Jackson 完成 JSON 序列化/反序列化。
- 从 5.x 开始仅支持 GitLab API v4(v3 已在 2025 年 4 月从库中移除)。
- 建议 Java 8+(5.0.1 版本兼容 Java 8;6.0.0 起要求 Java 11+)。
架构设计:子 API 类(Sub API)
该库采用"一个子 API 类对应 GitLab 官方文档的一个 API 分组"的设计,通过 GitLabApi 实例统一获取。常用映射关系如下:
| GitLab4J 子 API 类 | 对应 GitLab API 文档 | 说明 |
|---|---|---|
ProjectApi | /api/projects | 项目管理 |
UserApi | /api/users | 用户管理 |
GroupApi | /api/groups | 群组管理 |
RepositoryApi | /api/repositories | 分支、标签、树 |
RepositoryFileApi | /api/repository_files | 仓库文件 CRUD |
CommitsApi | /api/commits | 提交(Commit) |
IssuesApi | /api/issues | 议题(Issue) |
MergeRequestApi | /api/merge_requests | 合并请求(MR/PR) |
NotesApi | /api/notes | 评论 |
PipelineApi | /api/pipelines | CI 流水线 |
JobApi | /api/jobs | CI 任务 |
MilestonesApi | /api/milestones | 里程碑 |
LabelsApi | /api/labels | 标签 |
TagsApi | /api/tags | 仓库 Tag |
ReleasesApi | /api/releases | 版本发布 |
RunnersApi | /api/runners | CI Runner |
SearchApi | /api/search | 全局搜索 |
SystemHooksApi | /api/system_hooks | 系统钩子 |
TodosApi | /api/todos | 待办事项 |
获取方式:gitLabApi.getXxxApi()。例如 gitLabApi.getProjectApi()。
graph LR
App[你的 Java 应用] --> GLA[GitLabApi 实例]
GLA --> PA[ProjectApi]
GLA --> UA[UserApi]
GLA --> GA[GroupApi]
GLA --> RA[RepositoryApi]
GLA --> RFA[RepositoryFileApi]
GLA --> CA[CommitsApi]
GLA --> IA[IssuesApi]
GLA --> MRA[MergeRequestApi]
GLA --> NA[NotesApi]
GLA --> PL[PipelineApi]
GLA --> TA[TagsApi]
GLA --> ...[...其他子API]
PA --> HTTP[(GitLab REST API /api/v4)]2. 环境搭建与认证连接
2.1 添加 Maven 依赖
<dependency>
<groupId>org.gitlab4j</groupId>
<artifactId>gitlab4j-api</artifactId>
<version>5.0.1</version>
</dependency>Gradle:
implementation group: 'org.gitlab4j', name: 'gitlab4j-api', version: '5.0.1'2.2 创建连接(Personal Access Token 推荐)
最常用的方式:使用 GitLab 服务器地址 + 个人访问令牌(Personal Access Token,在 GitLab 账户 Settings → Access Tokens 中生成)。
import org.gitlab4j.api.GitLabApi;
// 创建 GitLabApi 实例
GitLabApi gitLabApi = new GitLabApi("http://your.gitlab.server.com", "YOUR_PERSONAL_ACCESS_TOKEN");
// 获取你有权访问的项目列表
List<Project> projects = gitLabApi.getProjectApi().getProjects();提示:token 建议放在环境变量或配置中心,避免硬编码。也可以在 token 前加
oauth2:前缀以 OAuth 方式认证。
2.3 用户名/密码登录(OAuth2)
// 使用用户名密码登录(内部转换为 OAuth2 登录)
GitLabApi gitLabApi = GitLabApi.oauth2Login("http://your.gitlab.server.com", "username", "password");2.4 指定 API 版本
// 显式指定使用 GitLab API v4
GitLabApi gitLabApi = new GitLabApi(GitLabApi.ApiVersion.V4, "http://your.gitlab.server.com", "YOUR_PRIVATE_TOKEN");2.5 以管理员身份模拟其他用户(sudo)
自 4.6.6 起支持:只要你是管理员,就可以让所有 API 调用"以另一个用户的身份"执行。
// 创建实例(必须是管理员)
GitLabApi gitLabApi = new GitLabApi("http://your.gitlab.server.com", "YOUR_PERSONAL_ACCESS_TOKEN");
// sudo 切换为 johndoe,之后的调用都以 johndoe 身份执行
gitLabApi.sudo("johndoe");
// 关闭 sudo 模式
gitLabApi.unsudo();2.6 关闭连接
GitLabApi 持有 HTTP 客户端资源,使用完应关闭:
gitLabApi.close(); // 释放底层 Jersey Client 资源3. 核心类 GitLabApi
GitLabApi 是唯一入口对象,提供连接配置、子 API 获取、请求日志、代理、超时等能力。
3.1 设置请求超时
GitLabApi gitLabApi = new GitLabApi("http://your.gitlab.com", "YOUR_PERSONAL_ACCESS_TOKEN");
// 连接超时 1 秒,读取超时 5 秒
gitLabApi.setRequestTimeout(1000, 5000);3.2 通过代理服务器连接
import org.gitlab4j.api.utils.ProxyClientConfig;
import java.util.Map;
// 使用带基本认证的代理
Map<String, Object> proxyConfig = ProxyClientConfig.createProxyClientConfig(
"http://your-proxy-server", "proxy-username", "proxy-password");
GitLabApi gitLabApi = new GitLabApi("http://your.gitlab.com", "YOUR_PERSONAL_ACCESS_TOKEN", null, proxyConfig);
// 使用 NTLM(Windows 域控制器)代理
Map<String, Object> ntlmProxyConfig = ProxyClientConfig.createNtlmProxyClientConfig(
"http://your-proxy-server", "windows-username", "windows-password", "windows-workstation", "windows-domain");
GitLabApi gitLabApi2 = new GitLabApi("http://your.gitlab.com", "YOUR_PERSONAL_ACCESS_TOKEN", null, ntlmProxyConfig);3.3 开启请求/响应日志
// 使用默认 Logger 和 FINE 级别
gitLabApi.enableRequestResponseLogging();
// 指定级别
gitLabApi.enableRequestResponseLogging(java.util.logging.Level.INFO);
// 指定 Logger 和级别
gitLabApi.enableRequestResponseLogging(yourLoggerInstance, java.util.logging.Level.INFO);
// 指定级别并最多记录 1024 字节实体内容
gitLabApi.enableRequestResponseLogging(java.util.logging.Level.INFO, 1024);3.4 校验连通性
// 检查是否能连接 GitLab 服务器并校验 token 有效性
boolean ok = gitLabApi.isUserAuthenticated();4. 分页机制 Pager
GitLab API 对列表类接口默认分页返回。GitLab4J 提供了 Pager<T> 轻松遍历所有结果。
4.1 使用 Pager 逐页遍历
import org.gitlab4j.api.Pager;
// 每页 10 个项目
Pager<Project> projectPager = gitLabApi.getProjectApi().getProjects(10);
// 逐页遍历
while (projectPager.hasNext()) {
for (Project project : projectPager.next()) {
System.out.println(project.getName() + " - " + project.getDescription());
}
}4.2 一次性获取全部结果
Pager<Project> projectPager = gitLabApi.getProjectApi().getProjects(10);
List<Project> allProjects = projectPager.all(); // 自动翻页,聚合为单列表4.3 Pager 常用方法
| 方法 | 说明 |
|---|---|
hasNext() | 是否还有下一页 |
next() | 返回当前页列表并前进到下一页 |
previous() | 返回上一页 |
page(int n) | 跳到指定页 |
getTotalItems() | 获取总条数 |
getTotalPages() | 获取总页数 |
all() | 拉取所有结果为单列表 |
lazyStream() | 惰性求值的 Stream(见下节) |
current() | 返回当前页不翻页 |
5. Stream 与 Optional 支持
5.1 Java 8 Stream 支持
所有返回 List 的方法都有对应的 getXxxStream() 方法。
急切求值(默认):
import java.util.stream.Stream;
// 输出所有可见项目名
Stream<Project> projectStream = gitLabApi.getProjectApi().getProjectsStream();
projectStream.map(Project::getName).forEach(name -> System.out.println(name));
// 并行处理(注意:数据获取不是并行的,只有流的后续处理是并行)
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;
Stream<User> stream = gitLabApi.getUserApi().getUsersStream();
List<User> users = stream.parallel().sorted(comparing(User::getUsername)).collect(toList());注意:急切求值的 Stream 不支持从服务器并行读取,但支持获取后的并行处理。
惰性求值(配合 Pager):
Pager<Project> projectPager = gitLabApi.getProjectApi().getProjects(10);
projectPager.lazyStream().limit(5).map(Project::getName).forEach(name -> System.out.println(name));惰性 Stream 不支持并行操作和
skip。
5.2 Java 8 Optional 支持
对于返回单个对象的方法,库提供了 getOptionalXxx() 版本,避免空指针。
import java.util.Optional;
Optional<Group> optionalGroup = gitLabApi.getGroupApi().getOptionalGroup("my-group-path");
if (optionalGroup.isPresent()) {
return optionalGroup.get();
}
return gitLabApi.getGroupApi().addGroup("my-group-name", "my-group-path");6. 项目接口 ProjectApi
项目管理是最常用的接口。项目 ID 是整数(Integer),也可用 URL 编码的项目路径(String,如 group/project)作为参数。
6.1 获取项目列表
// 获取当前用户有权访问的所有项目
List<Project> projects = gitLabApi.getProjectApi().getProjects();
// 获取单个项目(按 ID)
Project project = gitLabApi.getProjectApi().getProject(1234);
// 获取单个项目(按路径,url-encoded)
Project project = gitLabApi.getProjectApi().getProject("group/project-name");6.2 创建项目
import org.gitlab4j.api.models.Project;
Project projectSpec = new Project()
.withName("my-project")
.withDescription("My project for demonstration.")
.withIssuesEnabled(true)
.withMergeRequestsEnabled(true)
.withWikiEnabled(true)
.withSnippetsEnabled(true)
.withPublic(true);
Project newProject = gitLabApi.getProjectApi().createProject(projectSpec);
System.out.println("New project ID: " + newProject.getId());6.3 更新 / 删除项目
// 更新项目属性
Project projectSpec = new Project()
.withDescription("Updated description");
Project updated = gitLabApi.getProjectApi().updateProject(1234, projectSpec);
// 删除项目
gitLabApi.getProjectApi().deleteProject(1234);
// 删除项目(带删除后重命名保留期的说明,可选参数)
gitLabApi.getProjectApi().deleteProject(1234, true);6.4 星标 / 关注
// 给项目加星
gitLabApi.getProjectApi().starProject(1234);
// 取消星标
gitLabApi.getProjectApi().unstarProject(1234);
// 订阅/取消订阅项目通知
gitLabApi.getProjectApi().subscribeProject(1234);
gitLabApi.getProjectApi().unsubscribeProject(1234);6.5 成员管理
import org.gitlab4j.api.models.AccessLevel;
import org.gitlab4j.api.models.Member;
// 添加成员(指定访问级别)
Member member = gitLabApi.getProjectApi().addMember(1234, 100, AccessLevel.DEVELOPER);
// 或按用户名添加:addMember(projectIdOrPath, userId, AccessLevel)
// 获取项目成员列表
List<Member> members = gitLabApi.getProjectApi().getMembers(1234);
// 修改成员级别
Member updated = gitLabApi.getProjectApi().updateMember(1234, 100, AccessLevel.MAINTAINER);
// 移除成员
gitLabApi.getProjectApi().removeMember(1234, 100);
AccessLevel枚举:GUEST(10),REPORTER(20),DEVELOPER(30),MAINTAINER(40),OWNER(50)。
6.6 变量 / 环境变量
import org.gitlab4j.api.models.Variable;
// 新增环境变量
Variable var = new Variable()
.withKey("MY_VAR")
.withValue("my-value")
.withProtected(false)
.withMasked(false);
gitLabApi.getProjectApi().addVariable(1234, var);
// 获取/更新/删除变量
List<Variable> vars = gitLabApi.getProjectApi().getVariables(1234);
Variable v = gitLabApi.getProjectApi().getVariable(1234, "MY_VAR");
gitLabApi.getProjectApi().updateVariable(1234, "MY_VAR", "new-value");
gitLabApi.getProjectApi().removeVariable(1234, "MY_VAR");6.7 其他常用
// 分页获取
Pager<Project> pager = gitLabApi.getProjectApi().getProjects(10);
// 模糊搜索项目(按名称)
List<Project> found = gitLabApi.getProjectApi().getProjects("keyword");
// 获取当前登录用户
User currentUser = gitLabApi.getUserApi().getCurrentUser();7. 用户接口 UserApi
7.1 查询用户
// 获取用户 ID=1 的信息
User user = gitLabApi.getUserApi().getUser(1);
// 按用户名查询
List<User> users = gitLabApi.getUserApi().getUsers("johndoe");
// 获取当前登录用户
User currentUser = gitLabApi.getUserApi().getCurrentUser();
// 获取所有用户(需管理员权限)
List<User> allUsers = gitLabApi.getUserApi().getUsers();7.2 创建 / 更新 / 删除用户(需管理员)
import org.gitlab4j.api.models.User;
// 创建用户(不设密码,发送重置密码邮件)
User userConfig = new User()
.withEmail("jdoe@example.com")
.withName("Jane Doe")
.withUsername("jdoe");
String password = null;
boolean sendResetPasswordEmail = true;
User newUser = gitLabApi.getUserApi().createUser(userConfig, password, sendResetPasswordEmail);
// 创建带密码的用户
User userWithPwd = new User()
.withEmail("jdoe@example.com")
.withName("Jane Doe")
.withUsername("jdoe2");
User created = gitLabApi.getUserApi().createUser(userWithPwd, "S3curePass!", false);
// 更新用户
User userUpdate = new User().withName("Jane Q. Doe");
User updated = gitLabApi.getUserApi().updateUser(created.getId(), userUpdate);
// 删除用户
gitLabApi.getUserApi().deleteUser(created.getId());7.3 用户 SSH Keys / Emails
// 获取用户 SSH Keys
List<SSHKey> sshKeys = gitLabApi.getUserApi().getSSHKeys(1);
// 给用户添加 SSH Key
SSHKey key = new SSHKey()
.withTitle("my-laptop")
.withKey("ssh-rsa AAAAB3NzaC1yc2E...");
SSHKey newKey = gitLabApi.getUserApi().addSSHKey(1, key);
// 获取用户邮箱
List<Email> emails = gitLabApi.getUserApi().getEmails(1);7.4 修改当前用户状态
// 设置当前用户的状态(emoji + message)
UserStatus status = new UserStatus()
.withEmoji("coffee")
.withMessage("Busy coding");
gitLabApi.getUserApi().setUserStatus(status);8. 群组接口 GroupApi
8.1 查询群组
// 获取有权限访问的所有群组
List<Group> groups = gitLabApi.getGroupApi().getGroups();
// 获取单个群组(按路径)
Group group = gitLabApi.getGroupApi().getGroup("my-group-path");
// 获取单个群组(带子群组)
Group groupWithSubgroups = gitLabApi.getGroupApi().getGroup("my-group-path", true);
// Optional 版本,避免空指针
Optional<Group> optionalGroup = gitLabApi.getGroupApi().getOptionalGroup("my-group-path");8.2 创建 / 更新 / 删除群组
// 创建群组
Group newGroup = gitLabApi.getGroupApi().addGroup("my-group-name", "my-group-path");
// 带更多属性
Group groupSpec = new Group()
.withName("My Group")
.withPath("my-group")
.withDescription("A group for team A");
Group created = gitLabApi.getGroupApi().addGroup(groupSpec);
// 更新群组
Group updateSpec = new Group().withDescription("Updated desc");
Group updated = gitLabApi.getGroupApi().updateGroup("my-group-path", updateSpec);
// 删除群组
gitLabApi.getGroupApi().deleteGroup("my-group-path");8.3 群组成员与子群组
// 添加成员
Member member = gitLabApi.getGroupApi().addMember("my-group-path", 100, AccessLevel.DEVELOPER);
// 获取成员
List<Member> members = gitLabApi.getGroupApi().getMembers("my-group-path");
// 添加子群组
Group subgroup = new Group()
.withName("Sub Group")
.withPath("sub-group")
.withParentId(created.getId());
gitLabApi.getGroupApi().addSubGroup(subgroup);
// 获取子群组
List<Group> subgroups = gitLabApi.getGroupApi().getSubGroups("my-group-path");9. 仓库接口 RepositoryApi
9.1 分支(Branch)
// 获取项目所有分支(按名称排序)
List<Branch> branches = gitLabApi.getRepositoryApi().getBranches(1234);
// 按关键词搜索分支
List<Branch> branches = gitLabApi.getRepositoryApi().getBranches(1234, "feature");
// 获取单个分支
Branch branch = gitLabApi.getRepositoryApi().getBranch(1234, "main");
// 创建分支
Branch newBranch = gitLabApi.getRepositoryApi().createBranch(1234, "feature/new", "main");
// 删除分支
gitLabApi.getRepositoryApi().deleteBranch(1234, "feature/new");
// 保护/取消保护分支
gitLabApi.getRepositoryApi().protectBranch(1234, "main");
gitLabApi.getRepositoryApi().unprotectBranch(1234, "main");9.2 标签(Tag)—— TagsApi
import org.gitlab4j.api.models.Tag;
// 获取项目标签
List<Tag> tags = gitLabApi.getTagsApi().getTags(1234);
// 创建标签
Tag tag = gitLabApi.getTagsApi().createTag(1234, "v1.0.0", "main", "Release 1.0.0", "release-notes");
// 参数:projectIdOrPath, tagName, ref(branch/commit), message, releaseDescription
// 删除标签
gitLabApi.getTagsApi().deleteTag(1234, "v1.0.0");9.3 仓库树 / 归档
// 获取仓库根目录树结构
List<TreeItem> tree = gitLabApi.getRepositoryApi().getTree(1234);
// 获取指定路径的树
List<TreeItem> tree = gitLabApi.getRepositoryApi().getTree(1234, "src/main/java", "main", true);
// 下载项目归档(zip/tar.gz)
java.io.File archive = gitLabApi.getRepositoryApi().getArchive(1234, "main");9.4 比较 / Merge Base
// 比较两个分支(ref 间的差异)
List<Diff> diffs = gitLabApi.getRepositoryApi().compare(1234, "main", "feature/new");
// 获取两个 ref 的合并基准(common ancestor)
String mergeBase = gitLabApi.getRepositoryApi().getMergeBase(1234, "main", "feature/new");10. 仓库文件接口 RepositoryFileApi
用于读取、创建、更新、删除仓库内的文件内容。
import org.gitlab4j.api.models.RepositoryFile;
// 读取文件(path, projectId, ref)
RepositoryFile file = gitLabApi.getRepositoryFileApi().getFile("src/main/java/App.java", 1234, "main");
String content = file.getContent(); // Base64 编码,需解码
byte[] decoded = java.util.Base64.getDecoder().decode(content);注意:
getContent()返回的是 Base64 编码的内容,通常需要解码后使用。
创建文件:
RepositoryFile fileSpec = new RepositoryFile()
.withFilePath("README.md")
.withContent("Hello GitLab4J!")
.withBranch("main")
.withCommitMessage("Add README.md");
RepositoryFile created = gitLabApi.getRepositoryFileApi().createFile(1234, fileSpec);更新文件:
RepositoryFile updateSpec = new RepositoryFile()
.withFilePath("README.md")
.withContent("Updated content")
.withBranch("main")
.withCommitMessage("Update README.md");
RepositoryFile updated = gitLabApi.getRepositoryFileApi().updateFile(1234, updateSpec);删除文件:
gitLabApi.getRepositoryFileApi().deleteFile(1234, "README.md", "main", "Remove README.md");11. 提交接口 CommitsApi
11.1 查询提交
import org.gitlab4j.api.models.Commit;
import org.gitlab4j.api.utils.ISO8601;
import java.util.Date;
// 获取分支上的所有提交
List<Commit> commits = gitLabApi.getCommitsApi().getCommits(1234, "main");
// 指定时间窗口内的提交
Date since = ISO8601.toDate("2026-01-01T00:00:00Z");
Date until = new Date();
List<Commit> commits = gitLabApi.getCommitsApi().getCommits(1234, "new-feature", since, until);
// 获取单个提交详情
Commit commit = gitLabApi.getCommitsApi().getCommit(1234, "abcdef1234567890");
// 获取提交对应的差异
List<Diff> diffs = gitLabApi.getCommitsApi().getDiff(1234, "abcdef1234567890");11.2 创建提交(含多文件)
import org.gitlab4j.api.models.CommitAction;
import org.gitlab4j.api.models.CommitPayload;
CommitAction action = new CommitAction()
.withAction(CommitAction.Action.UPDATE)
.withFilePath("README.md")
.withContent("New content");
CommitPayload payload = new CommitPayload()
.withBranch("main")
.withCommitMessage("Update README via API")
.withActions(java.util.Collections.singletonList(action));
Commit created = gitLabApi.getCommitsApi().createCommit(1234, payload);
CommitAction.Action支持:CREATE、DELETE、UPDATE、MOVE、CHMOD。
11.3 合并请求中的提交
// 获取合并请求的提交列表
List<Commit> mrCommits = gitLabApi.getCommitsApi().getMergeRequestCommits(1234, 10);12. 议题接口 IssuesApi
12.1 查询议题
import org.gitlab4j.api.models.Issue;
// 获取项目所有议题
List<Issue> issues = gitLabApi.getIssuesApi().getIssues(1234);
// 获取当前用户分配给他的议题
List<Issue> assignedIssues = gitLabApi.getIssuesApi().getIssues(
GitLabApi.ApiVersion.V4, null, null, null, null, null, null, null, null, null, null, null, null);
// 获取单个议题(projectId, issueIid)
Issue issue = gitLabApi.getIssuesApi().getIssue(1234, 10);注意:GitLab 中议题用的是 IID(内部编号) 而非全局 ID。getIssue 第二参数是 IID。
12.2 创建 / 更新 / 删除议题
// 创建议题
Issue issueSpec = new Issue()
.withTitle("Bug: NPE when parsing empty input")
.withDescription("Steps to reproduce...")
.withLabels(java.util.Arrays.asList("bug", "priority:high"));
Issue newIssue = gitLabApi.getIssuesApi().createIssue(1234, issueSpec);
// 更精确:createIssue(projectId, title, description, labels, assigneeIds, milestoneId)
// 更新议题
Issue updateSpec = new Issue()
.withTitle("Updated title")
.withStateEvent("close"); // 或 "reopen"
Issue updated = gitLabApi.getIssuesApi().updateIssue(1234, newIssue.getIid(), updateSpec);
// 关闭/重新打开议题
gitLabApi.getIssuesApi().closeIssue(1234, newIssue.getIid());
gitLabApi.getIssuesApi().reopenIssue(1234, newIssue.getIid());
// 删除议题
gitLabApi.getIssuesApi().deleteIssue(1234, newIssue.getIid());12.3 议题搜索与订阅
// 按关键词搜索议题
List<Issue> found = gitLabApi.getIssuesApi().getIssues(1234, null, "NPE", null, null, null, null, null, null);
// 订阅/取消订阅议题
gitLabApi.getIssuesApi().subscribeToIssue(1234, newIssue.getIid());
gitLabApi.getIssuesApi().unsubscribeFromIssue(1234, newIssue.getIid());13. 合并请求接口 MergeRequestApi
13.1 查询 MR
import org.gitlab4j.api.models.MergeRequest;
// 获取项目所有 MR
List<MergeRequest> mergeRequests = gitLabApi.getMergeRequestApi().getMergeRequests(1234);
// 获取单个 MR(projectId, mrIid)
MergeRequest mr = gitLabApi.getMergeRequestApi().getMergeRequest(1234, 10);13.2 创建 MR
MergeRequest mrSpec = new MergeRequest()
.withSourceBranch("feature/new")
.withTargetBranch("main")
.withTitle("Merge feature/new into main")
.withDescription("This MR adds the new feature");
MergeRequest newMr = gitLabApi.getMergeRequestApi().createMergeRequest(1234, mrSpec);
// 或直接指定分支:createMergeRequest(projectId, sourceBranch, targetBranch, title, description, ...)13.3 更新 / 接受(合并)/ 关闭 MR
// 更新 MR
MergeRequest updateSpec = new MergeRequest().withTitle("New title");
MergeRequest updated = gitLabApi.getMergeRequestApi().updateMergeRequest(1234, newMr.getIid(), updateSpec);
// 接受(合并)MR
MergeRequest merged = gitLabApi.getMergeRequestApi().acceptMergeRequest(1234, newMr.getIid(), "Merge commit message");
// 关闭 / 重新打开 MR
gitLabApi.getMergeRequestApi().closeMergeRequest(1234, newMr.getIid());
gitLabApi.getMergeRequestApi().reopenMergeRequest(1234, newMr.getIid());
// 删除 MR(仅能删除 source 分支尚未合并的 MR)
gitLabApi.getMergeRequestApi().deleteMergeRequest(1234, newMr.getIid());13.4 获取 MR 变更与审批
// 获取 MR 的文件变更
MergeRequestDiff diffs = gitLabApi.getMergeRequestApi().getMergeRequestChanges(1234, newMr.getIid());
// 获取 MR 的审批信息
Approvals approvals = gitLabApi.getMergeRequestApi().getApprovals(1234, newMr.getIid());13.5 提交评论到 MR
import org.gitlab4j.api.models.Note;
// 给 MR 添加评论(备注)
Note note = gitLabApi.getNotesApi().createMergeRequestNote(1234, newMr.getIid(), "Looks good to me!");14. 评论接口 NotesApi
评论(Note)可附加在议题、MR 或代码行上。
14.1 获取评论
import org.gitlab4j.api.models.Note;
// 获取议题的评论(projectId, issueIid)
List<Note> notes = gitLabApi.getNotesApi().getNotes(1234, 1);
// 获取 MR 的评论
List<Note> mrNotes = gitLabApi.getNotesApi().getMergeRequestNotes(1234, 1);
// 获取单个评论
Note note = gitLabApi.getNotesApi().getIssueNote(1234, 1, 100);14.2 创建 / 修改 / 删除评论
// 给议题添加评论
Note issueNote = gitLabApi.getNotesApi().createIssueNote(1234, 1, "This is a comment.");
// 给 MR 添加评论
Note mrNote = gitLabApi.getNotesApi().createMergeRequestNote(1234, 10, "LGTM");
// 更新评论
Note updated = gitLabApi.getNotesApi().updateIssueNote(1234, 1, issueNote.getId(), "Updated comment.");
// 删除评论
gitLabApi.getNotesApi().deleteIssueNote(1234, 1, issueNote.getId());14.3 代码行评论(Discussion)
// 获取 MR 的讨论线程
List<Discussion> discussions = gitLabApi.getDiscussionsApi().getMergeRequestDiscussions(1234, 10);15. 里程碑与标签接口
15.1 里程碑 MilestonesApi
import org.gitlab4j.api.models.Milestone;
// 获取项目里程碑
List<Milestone> milestones = gitLabApi.getMilestonesApi().getMilestones(1234);
// 创建里程碑
Milestone msSpec = new Milestone()
.withTitle("Sprint 24")
.withDescription("Q3 sprint 24")
.withDueDate("2026-11-15");
Milestone ms = gitLabApi.getMilestonesApi().createMilestone(1234, msSpec);
// 更新/激活/关闭里程碑
gitLabApi.getMilestonesApi().updateMilestone(1234, ms.getId(), msSpec);
gitLabApi.getMilestonesApi().activateMilestone(1234, ms.getId());
gitLabApi.getMilestonesApi().closeMilestone(1234, ms.getId());15.2 标签 LabelsApi
import org.gitlab4j.api.models.Label;
// 获取项目标签
List<Label> labels = gitLabApi.getLabelsApi().getLabels(1234);
// 创建标签
Label labelSpec = new Label()
.withName("bug")
.withColor("#FF0000")
.withDescription("Bugs");
Label newLabel = gitLabApi.getLabelsApi().createLabel(1234, labelSpec);
// 更新 / 删除标签
gitLabApi.getLabelsApi().updateLabel(1234, "bug", newLabel);
gitLabApi.getLabelsApi().deleteLabel(1234, "bug");16. CI/CD 流水线与任务接口
16.1 流水线 PipelineApi
import org.gitlab4j.api.models.Pipeline;
// 获取项目所有流水线
List<Pipeline> pipelines = gitLabApi.getPipelineApi().getPipelines(1234);
// 获取单个流水线
Pipeline pipeline = gitLabApi.getPipelineApi().getPipeline(1234, 100);
// 触发/创建新流水线(在指定分支/ref 上)
Pipeline created = gitLabApi.getPipelineApi().createPipeline(1234, "main");
// 重试 / 取消流水线
Pipeline retried = gitLabApi.getPipelineApi().retryPipeline(1234, 100);
Pipeline cancelled = gitLabApi.getPipelineApi().cancelPipeline(1234, 100);16.2 任务 JobApi
import org.gitlab4j.api.models.Job;
// 获取流水线中的任务
List<Job> jobs = gitLabApi.getJobApi().getJobs(1234, 100);
// 获取项目所有任务
List<Job> allJobs = gitLabApi.getJobApi().getJobs(1234);
// 重试/取消某个任务
Job retriedJob = gitLabApi.getJobApi().retryJob(1234, 500);
Job cancelledJob = gitLabApi.getJobApi().cancelJob(1234, 500);16.3 Runner RunnersApi
import org.gitlab4j.api.models.Runner;
// 获取所有 Runner
List<Runner> runners = gitLabApi.getRunnersApi().getAllRunners();
// 获取项目的 Runner
List<Runner> projectRunners = gitLabApi.getRunnersApi().getRunners(1234);16.4 环境 EnvironmentsApi
import org.gitlab4j.api.models.Environment;
// 获取项目的环境
List<Environment> environments = gitLabApi.getEnvironmentsApi().getEnvironments(1234);17. 发布与版本接口 ReleasesApi
import org.gitlab4j.api.models.Release;
// 获取项目发布列表
List<Release> releases = gitLabApi.getReleasesApi().getReleases(1234);
// 创建发布
Release releaseSpec = new Release()
.withName("v1.0.0")
.withTagName("v1.0.0")
.withDescription("First stable release");
Release newRelease = gitLabApi.getReleasesApi().createRelease(1234, releaseSpec);
// 更新发布
Release updateSpec = new Release().withDescription("Updated notes");
Release updated = gitLabApi.getReleasesApi().updateRelease(1234, "v1.0.0", updateSpec);
// 删除发布
gitLabApi.getReleasesApi().deleteRelease(1234, "v1.0.0");18. Webhook 与系统钩子
18.1 项目 Webhook(ServicesApi / ProjectHookApi)
项目 Webhook 通过 ProjectApi 或专门的 Hook API 管理:
import org.gitlab4j.api.models.ProjectHook;
// 添加项目 Webhook
ProjectHook hookSpec = new ProjectHook()
.withUrl("https://example.com/gitlab-hook")
.withPushEvents(true)
.withMergeRequestsEvents(true)
.withIssuesEvents(true)
.withPipelineEvents(true)
.withEnableSslVerification(true);
ProjectHook newHook = gitLabApi.getProjectApi().addHook(1234, hookSpec);
// 获取项目 Webhook 列表
List<ProjectHook> hooks = gitLabApi.getProjectApi().getHooks(1234);
// 删除 Webhook
gitLabApi.getProjectApi().deleteHook(1234, newHook.getId());18.2 服务集成(如 Slack)
import org.gitlab4j.api.models.SlackService;
// 配置 Slack 通知服务
SlackService slackService = new SlackService()
.withMergeRequestsEvents(true)
.withWebhook("https://hooks.slack.com/services/ABC/DEF/key")
.withUsername("GitLab4J");
gitLabApi.getServicesApi().updateSlackService("project-path", slackService);18.3 系统钩子 SystemHooksApi(需管理员)
import org.gitlab4j.api.models.SystemHook;
// 获取系统钩子
List<SystemHook> hooks = gitLabApi.getSystemHooksApi().getSystemHooks();
// 添加系统钩子
SystemHook hook = gitLabApi.getSystemHooksApi().addSystemHook(
"https://example.com/system-hook", true, false, true);19. 其他常用接口速查
19.1 搜索 SearchApi
import org.gitlab4j.api.models.SearchScope;
// 全局搜索项目
List<Project> projects = gitLabApi.getSearchApi().globalSearch(SearchScope.PROJECTS, "text-to-search-for");
// 在项目内搜索
List<Issue> issues = gitLabApi.getSearchApi().projectSearch(SearchScope.ISSUES, 1234, "keyword");19.2 待办 TodosApi
import org.gitlab4j.api.models.Todo;
// 获取当前用户待办
List<Todo> todos = gitLabApi.getTodosApi().gePendingTodos();
// 将某待办标记为完成
gitLabApi.getTodosApi().markTodoAsDone(todo.getId());19.3 命名空间 NamespaceApi
import org.gitlab4j.api.models.Namespace;
// 查找名称/路径包含 "foobar" 的命名空间
List<Namespace> namespaces = gitLabApi.getNamespaceApi().findNamespaces("foobar");19.4 导入导出 ImportExportApi
// 调度项目导出
gitLabApi.getImportExportApi().scheduleExport(1234);
// 获取导出状态
ExportStatus status = gitLabApi.getImportExportApi().getExportStatus(1234);19.5 讨论 DiscussionsApi
import org.gitlab4j.api.models.Discussion;
// 获取 MR 的讨论线程
List<Discussion> discussions = gitLabApi.getDiscussionsApi().getMergeRequestDiscussions(1234, 10);
// 获取议题的讨论线程
List<Discussion> issueDiscussions = gitLabApi.getDiscussionsApi().getIssueDiscussions(1234, 10);20. 异常处理与最佳实践
20.1 异常体系
GitLab4J 统一抛出 GitLabApiException(继承自 RuntimeException,无需强制捕获)。
import org.gitlab4j.api.GitLabApiException;
try {
Project project = gitLabApi.getProjectApi().getProject(1234);
} catch (GitLabApiException e) {
System.err.println("HTTP status: " + e.getHttpStatus());
System.err.println("Message: " + e.getMessage());
if (e.getHttpStatus() == 404) {
System.err.println("Project not found (or no access).");
} else if (e.getHttpStatus() == 401) {
System.err.println("Authentication failed.");
}
}常用判断:
e.getHttpStatus():HTTP 状态码e.getValidationErrors():创建类接口的字段校验错误e.isNotFound()、e.isUnauthorized()、e.isForbidden():便捷判断
20.2 最佳实践清单
- Token 安全:token 放环境变量/配置中心,绝不硬编码进代码或提交仓库。
- 连接复用:
GitLabApi是重量级对象(内含 HTTP 客户端),应作为单例或长期持有,避免频繁创建;程序结束时调用close()。 - 善用分页:列表接口务必用
Pager或getXxxStream(),避免一次拉取过多数据。 - 多线程:
GitLabApi是线程安全的,可被多线程共享;但Pager是有状态的,不要在多线程间共享同一个Pager。 - 文件内容解码:
RepositoryFile.getContent()返回 Base64,使用前先解码。 - IID 与 ID 区分:议题/MR 的操作多用 IID(项目内编号),用户/群组用全局 ID。
- 权限最小化:token 授予执行任务所需的最小 scopes(如
api、read_repository、write_repository)。 - 异常兜底:所有网络/API 调用捕获
GitLabApiException,按 HTTP 状态码分类处理。 - 开启请求日志:排查问题时调用
enableRequestResponseLogging()。 - 版本匹配:不同 GitLab 服务器版本的 API 存在差异,生产前在目标服务器版本上验证。
20.3 完整可运行示例
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.models.Project;
import java.util.List;
public class GitLab4JDemo {
public static void main(String[] args) throws Exception {
// 1. 创建连接
String url = System.getenv("GITLAB_URL"); // e.g. http://your.gitlab.com
String token = System.getenv("GITLAB_TOKEN"); // personal access token
GitLabApi gitLabApi = new GitLabApi(url, token);
try {
// 2. 校验连接
System.out.println("Authenticated: " + gitLabApi.isUserAuthenticated());
// 3. 列出项目
List<Project> projects = gitLabApi.getProjectApi().getProjects();
projects.forEach(p -> System.out.println(p.getId() + " - " + p.getName()));
// 4. 分页遍历
Pager<Project> pager = gitLabApi.getProjectApi().getProjects(5);
while (pager.hasNext()) {
pager.next().forEach(p -> System.out.println("Page item: " + p.getName()));
}
// 5. 创建议题(示例项目 ID 1234)
Issue issue = gitLabApi.getIssuesApi().createIssue(
1234, "Hello from GitLab4J", "Created via gitlab4j-api demo", null, null, null);
// 6. 给议题添加评论
gitLabApi.getNotesApi().createIssueNote(1234, issue.getIid(), "Auto comment from demo");
// 7. 创建 MR
MergeRequest mr = gitLabApi.getMergeRequestApi().createMergeRequest(
1234, "feature/demo", "main", "Demo MR", null, null, null, null);
System.out.println("Created MR: " + mr.getWebUrl());
} finally {
gitLabApi.close();
}
}
}附录:常见方法签名速查表
| 子 API | 常用方法 | 说明 |
|---|---|---|
| ProjectApi | getProjects() / getProjects(int perPage) | 列出项目 |
| ProjectApi | getProject(id) / getProject(path) | 获取项目 |
| ProjectApi | createProject(Project) / deleteProject(id) | 创建/删除项目 |
| ProjectApi | addMember(id, userId, AccessLevel) | 添加成员 |
| ProjectApi | addVariable(id, Variable) | 添加环境变量 |
| UserApi | getUser(id) / getCurrentUser() | 查询用户 |
| UserApi | createUser(User, password, reset) | 创建用户 |
| GroupApi | getGroups() / getGroup(path) | 查询群组 |
| GroupApi | addGroup(name, path) / deleteGroup(path) | 创建/删除群组 |
| RepositoryApi | getBranches(id) / createBranch(id, name, ref) | 分支操作 |
| TagsApi | getTags(id) / createTag(id, name, ref, msg, desc) | 标签操作 |
| RepositoryFileApi | getFile(path, id, ref) / createFile(id, file) | 文件读写 |
| CommitsApi | getCommits(id, branch) / getCommit(id, sha) | 提交查询 |
| IssuesApi | getIssues(id) / createIssue(id, Issue) | 议题操作 |
| MergeRequestApi | getMergeRequests(id) / createMergeRequest(id, mr) | MR 操作 |
| MergeRequestApi | acceptMergeRequest(id, iid, msg) | 合并 MR |
| NotesApi | createIssueNote(id, iid, msg) | 添加评论 |
| PipelineApi | getPipelines(id) / createPipeline(id, ref) | 流水线 |
| JobApi | getJobs(id, pipelineId) | 任务查询 |
| ReleasesApi | getReleases(id) / createRelease(id, rel) | 版本发布 |
| ProjectApi | addHook(id, ProjectHook) | Webhook |
文档基于 gitlab4j-api 5.0.1 编写,接口方法以官方 Javadoc 为准。官方项目主页:https://gitlab4j.github.io/gitlab4j-api/
使用中如遇具体方法参数细节,可查看对应子 API 类的 Javadoc:gitLabApi.getProjectApi() 等方法返回类型的在线文档。