Skip to content

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/pipelinesCI 流水线
JobApi/api/jobsCI 任务
MilestonesApi/api/milestones里程碑
LabelsApi/api/labels标签
TagsApi/api/tags仓库 Tag
ReleasesApi/api/releases版本发布
RunnersApi/api/runnersCI Runner
SearchApi/api/search全局搜索
SystemHooksApi/api/system_hooks系统钩子
TodosApi/api/todos待办事项

获取方式:gitLabApi.getXxxApi()。例如 gitLabApi.getProjectApi()。

mermaid
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 依赖 ​

xml
<dependency>
    <groupId>org.gitlab4j</groupId>
    <artifactId>gitlab4j-api</artifactId>
    <version>5.0.1</version>
</dependency>

Gradle:

groovy
implementation group: 'org.gitlab4j', name: 'gitlab4j-api', version: '5.0.1'

2.2 创建连接(Personal Access Token 推荐) ​

最常用的方式:使用 GitLab 服务器地址 + 个人访问令牌(Personal Access Token,在 GitLab 账户 Settings → Access Tokens 中生成)。

java
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) ​

java
// 使用用户名密码登录(内部转换为 OAuth2 登录)
GitLabApi gitLabApi = GitLabApi.oauth2Login("http://your.gitlab.server.com", "username", "password");

2.4 指定 API 版本 ​

java
// 显式指定使用 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 调用"以另一个用户的身份"执行。

java
// 创建实例(必须是管理员)
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 客户端资源,使用完应关闭:

java
gitLabApi.close();   // 释放底层 Jersey Client 资源

3. 核心类 GitLabApi ​

GitLabApi 是唯一入口对象,提供连接配置、子 API 获取、请求日志、代理、超时等能力。

3.1 设置请求超时 ​

java
GitLabApi gitLabApi = new GitLabApi("http://your.gitlab.com", "YOUR_PERSONAL_ACCESS_TOKEN");

// 连接超时 1 秒,读取超时 5 秒
gitLabApi.setRequestTimeout(1000, 5000);

3.2 通过代理服务器连接 ​

java
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 开启请求/响应日志 ​

java
// 使用默认 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 校验连通性 ​

java
// 检查是否能连接 GitLab 服务器并校验 token 有效性
boolean ok = gitLabApi.isUserAuthenticated();

4. 分页机制 Pager ​

GitLab API 对列表类接口默认分页返回。GitLab4J 提供了 Pager<T> 轻松遍历所有结果。

4.1 使用 Pager 逐页遍历 ​

java
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 一次性获取全部结果 ​

java
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() 方法。

急切求值(默认):

java
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):

java
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() 版本,避免空指针。

java
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 获取项目列表 ​

java
// 获取当前用户有权访问的所有项目
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 创建项目 ​

java
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 更新 / 删除项目 ​

java
// 更新项目属性
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 星标 / 关注 ​

java
// 给项目加星
gitLabApi.getProjectApi().starProject(1234);

// 取消星标
gitLabApi.getProjectApi().unstarProject(1234);

// 订阅/取消订阅项目通知
gitLabApi.getProjectApi().subscribeProject(1234);
gitLabApi.getProjectApi().unsubscribeProject(1234);

6.5 成员管理 ​

java
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 变量 / 环境变量 ​

java
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 其他常用 ​

java
// 分页获取
Pager<Project> pager = gitLabApi.getProjectApi().getProjects(10);

// 模糊搜索项目(按名称)
List<Project> found = gitLabApi.getProjectApi().getProjects("keyword");

// 获取当前登录用户
User currentUser = gitLabApi.getUserApi().getCurrentUser();

7. 用户接口 UserApi ​

7.1 查询用户 ​

java
// 获取用户 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 创建 / 更新 / 删除用户(需管理员) ​

java
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 ​

java
// 获取用户 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 修改当前用户状态 ​

java
// 设置当前用户的状态(emoji + message)
UserStatus status = new UserStatus()
        .withEmoji("coffee")
        .withMessage("Busy coding");
gitLabApi.getUserApi().setUserStatus(status);

8. 群组接口 GroupApi ​

8.1 查询群组 ​

java
// 获取有权限访问的所有群组
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 创建 / 更新 / 删除群组 ​

java
// 创建群组
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 群组成员与子群组 ​

java
// 添加成员
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) ​

java
// 获取项目所有分支(按名称排序)
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 ​

java
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 仓库树 / 归档 ​

java
// 获取仓库根目录树结构
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 ​

java
// 比较两个分支(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 ​

用于读取、创建、更新、删除仓库内的文件内容。

java
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 编码的内容,通常需要解码后使用。

创建文件:

java
RepositoryFile fileSpec = new RepositoryFile()
        .withFilePath("README.md")
        .withContent("Hello GitLab4J!")
        .withBranch("main")
        .withCommitMessage("Add README.md");

RepositoryFile created = gitLabApi.getRepositoryFileApi().createFile(1234, fileSpec);

更新文件:

java
RepositoryFile updateSpec = new RepositoryFile()
        .withFilePath("README.md")
        .withContent("Updated content")
        .withBranch("main")
        .withCommitMessage("Update README.md");

RepositoryFile updated = gitLabApi.getRepositoryFileApi().updateFile(1234, updateSpec);

删除文件:

java
gitLabApi.getRepositoryFileApi().deleteFile(1234, "README.md", "main", "Remove README.md");

11. 提交接口 CommitsApi ​

11.1 查询提交 ​

java
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 创建提交(含多文件) ​

java
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 合并请求中的提交 ​

java
// 获取合并请求的提交列表
List<Commit> mrCommits = gitLabApi.getCommitsApi().getMergeRequestCommits(1234, 10);

12. 议题接口 IssuesApi ​

12.1 查询议题 ​

java
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 创建 / 更新 / 删除议题 ​

java
// 创建议题
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 议题搜索与订阅 ​

java
// 按关键词搜索议题
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 ​

java
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 ​

java
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 ​

java
// 更新 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 变更与审批 ​

java
// 获取 MR 的文件变更
MergeRequestDiff diffs = gitLabApi.getMergeRequestApi().getMergeRequestChanges(1234, newMr.getIid());

// 获取 MR 的审批信息
Approvals approvals = gitLabApi.getMergeRequestApi().getApprovals(1234, newMr.getIid());

13.5 提交评论到 MR ​

java
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 获取评论 ​

java
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 创建 / 修改 / 删除评论 ​

java
// 给议题添加评论
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) ​

java
// 获取 MR 的讨论线程
List<Discussion> discussions = gitLabApi.getDiscussionsApi().getMergeRequestDiscussions(1234, 10);

15. 里程碑与标签接口 ​

15.1 里程碑 MilestonesApi ​

java
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 ​

java
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 ​

java
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 ​

java
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 ​

java
import org.gitlab4j.api.models.Runner;

// 获取所有 Runner
List<Runner> runners = gitLabApi.getRunnersApi().getAllRunners();

// 获取项目的 Runner
List<Runner> projectRunners = gitLabApi.getRunnersApi().getRunners(1234);

16.4 环境 EnvironmentsApi ​

java
import org.gitlab4j.api.models.Environment;

// 获取项目的环境
List<Environment> environments = gitLabApi.getEnvironmentsApi().getEnvironments(1234);

17. 发布与版本接口 ReleasesApi ​

java
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 管理:

java
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) ​

java
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(需管理员) ​

java
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 ​

java
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 ​

java
import org.gitlab4j.api.models.Todo;

// 获取当前用户待办
List<Todo> todos = gitLabApi.getTodosApi().gePendingTodos();

// 将某待办标记为完成
gitLabApi.getTodosApi().markTodoAsDone(todo.getId());

19.3 命名空间 NamespaceApi ​

java
import org.gitlab4j.api.models.Namespace;

// 查找名称/路径包含 "foobar" 的命名空间
List<Namespace> namespaces = gitLabApi.getNamespaceApi().findNamespaces("foobar");

19.4 导入导出 ImportExportApi ​

java
// 调度项目导出
gitLabApi.getImportExportApi().scheduleExport(1234);

// 获取导出状态
ExportStatus status = gitLabApi.getImportExportApi().getExportStatus(1234);

19.5 讨论 DiscussionsApi ​

java
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,无需强制捕获)。

java
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 最佳实践清单 ​

  1. Token 安全:token 放环境变量/配置中心,绝不硬编码进代码或提交仓库。
  2. 连接复用:GitLabApi 是重量级对象(内含 HTTP 客户端),应作为单例或长期持有,避免频繁创建;程序结束时调用 close()。
  3. 善用分页:列表接口务必用 Pager 或 getXxxStream(),避免一次拉取过多数据。
  4. 多线程:GitLabApi 是线程安全的,可被多线程共享;但 Pager 是有状态的,不要在多线程间共享同一个 Pager。
  5. 文件内容解码:RepositoryFile.getContent() 返回 Base64,使用前先解码。
  6. IID 与 ID 区分:议题/MR 的操作多用 IID(项目内编号),用户/群组用全局 ID。
  7. 权限最小化:token 授予执行任务所需的最小 scopes(如 api、read_repository、write_repository)。
  8. 异常兜底:所有网络/API 调用捕获 GitLabApiException,按 HTTP 状态码分类处理。
  9. 开启请求日志:排查问题时调用 enableRequestResponseLogging()。
  10. 版本匹配:不同 GitLab 服务器版本的 API 存在差异,生产前在目标服务器版本上验证。

20.3 完整可运行示例 ​

java
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常用方法说明
ProjectApigetProjects() / getProjects(int perPage)列出项目
ProjectApigetProject(id) / getProject(path)获取项目
ProjectApicreateProject(Project) / deleteProject(id)创建/删除项目
ProjectApiaddMember(id, userId, AccessLevel)添加成员
ProjectApiaddVariable(id, Variable)添加环境变量
UserApigetUser(id) / getCurrentUser()查询用户
UserApicreateUser(User, password, reset)创建用户
GroupApigetGroups() / getGroup(path)查询群组
GroupApiaddGroup(name, path) / deleteGroup(path)创建/删除群组
RepositoryApigetBranches(id) / createBranch(id, name, ref)分支操作
TagsApigetTags(id) / createTag(id, name, ref, msg, desc)标签操作
RepositoryFileApigetFile(path, id, ref) / createFile(id, file)文件读写
CommitsApigetCommits(id, branch) / getCommit(id, sha)提交查询
IssuesApigetIssues(id) / createIssue(id, Issue)议题操作
MergeRequestApigetMergeRequests(id) / createMergeRequest(id, mr)MR 操作
MergeRequestApiacceptMergeRequest(id, iid, msg)合并 MR
NotesApicreateIssueNote(id, iid, msg)添加评论
PipelineApigetPipelines(id) / createPipeline(id, ref)流水线
JobApigetJobs(id, pipelineId)任务查询
ReleasesApigetReleases(id) / createRelease(id, rel)版本发布
ProjectApiaddHook(id, ProjectHook)Webhook

文档基于 gitlab4j-api 5.0.1 编写,接口方法以官方 Javadoc 为准。官方项目主页:https://gitlab4j.github.io/gitlab4j-api/

使用中如遇具体方法参数细节,可查看对应子 API 类的 Javadoc:gitLabApi.getProjectApi() 等方法返回类型的在线文档。