JGit实现Git Http服务器
使用过git的同学应该特别清楚github的http服务,今天就让我们学习一下如何通过JGit自己搭建一个自己的Git Http服务器吧。
Git协议
在使用Git的过程中,往往需要与其他人进行协作——也就是需要为本地的仓库设置远程(Remote)仓库。我们经常使用的pull/push/fetch
操作,实际上都是与远程仓库进行的数据交互。Git支持4种传输协议:
- 本地文件
- HTTP协议
- SSH协议
- Git协议
GitHub是世界上最大的Git仓库托管系统,它支持后三种协议,通常我们如果想要从GitHub上获取代码,可以这样操作:
$ git clone https://github.com/jquery/jquery.git
Cloning into 'jquery'...
remote: Counting objects: 37065, done.
remote: Compressing objects: 100% (48/48), done.
remote: Total 37065 (delta 28), reused 0 (delta 0), pack-reused 37017
Receiving objects: 100% (37065/37065), 22.58 MiB | 709.00 KiB/s, done.
Resolving deltas: 100% (26132/26132), done.
Checking connectivity... done.
上例就是通过HTTP协议获取了GitHub服务器上的一个仓库,如果拥有仓库写权限,那么可以在本地修改提交后,push到GitHub服务器,push过程也是通过HTTP协议完成的。
Git HTTP服务器
为了支持客户端Git程序pull/push
操作,GitHub服务器上运行着能够处理响应HTTP请求的应用程序。Git本身自带的应用程序git-http-backend
可以处理这些HTTP请求,通过HTTP服务器(例如Nginx, Apache)我们可以很容易的架设一个Git HTTP服务器,详细方法可以参考。
但是这样做的方法也有一定的局限性:
git-http-backend
本身是用C语言编写并编译的可执行应用程序,与其他开发语言(例如Java,PHP等等)集成难度大- 可扩展性有限,例如很难实现诸如动态权限验证、动态钩子等作为托管仓库的必要功能
在本文中我们将以Git的一个纯Java实现为例,介绍如何在应用中嵌入JGit并实现一个Git HTTP服务器。
使用JGit实现Git HTTP服务器
JGit是Git的Java实现,它即提供了类似Git命令行工具的操作接口:
$ jgit clone https://github.com/jquery/jquery.git
也提供了非常友好的API,Java应用程序能够非常容易的引入它。同时它还提供一个HTTP Server模块能够方便的帮助我们建立HTTP服务器来提供Git仓库托管服务。
引入Maven依赖
<dependencies>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.http.server</artifactId>
<version>4.0.1.201506240215-r</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
实现处理HTTP请求的Servlet
org.eclipse.jgit.http.server
模块提供的GitServlet
类,实现了Git Smart HTTP Protocol:
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
@WebServlet(name = "gitServlet", urlPatterns = {"/*"},
loadOnStartup = 1,
initParams = {
@WebInitParam(name = "base-path", value = "/Users/luoruici/tmy-data/users/"),
@WebInitParam(name = "export-all", value = "true")
})
public class GitServlet extends org.eclipse.jgit.http.server.GitServlet {
}
这里扩展了org.eclipse.jgit.http.server.GitServlet
实现一个最简单的Git HTTP服务器,无需配置。只需要指定两个参数:
base-path
指定Git仓库的基本目录——这个目录存放的是Git仓库列表(Bare仓库),允许嵌套export-all
设为true
另外,这里使用的是Servlet 3.0规范中的注解@WebServelt
,并设置好urlPatterns
。
运行Git HTTP服务器
在编写完Servlet后,我们需要将它放在Servlet Container中运行。这里为了测试方便,引入(Maven Jetty Plugin):
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.1.v20150714</version>
</plugin>
</plugins>
</build>
在命令行中运行:
$ mvn jetty:run
过一会Jetty就启动起来了,假设现在在base-path
参数对应的目录中包含一个仓库jquery.git
,那么可以通过git clone http://localhost:8080/jquery.git
来获取仓库了。
自定义仓库获取方式
在上例中使用的是GitServlet
的默认行为来根据url获取仓库——将base-path
与url中的path
部分连接在一起,作为本地文件系统的访问路径获取一个Repository
对象。但是业务系统很多时候并没有这么简单。以GitHub为例,url模式/{owner}/{repo}.git
中的owner可能是一个个人用户,也可能是一个组织(organization),那么他们的仓库路径便不在文件系统的同一个目录中(仅仅是假设,并非GitHub的内部实现方式),那么这个时候我们需要扩展RepositoryResolver
这个接口:
public class GitHttpResolver implements RepositoryResolver<HttpServletRequest> {
Repository open(HttpServletRequest req, String name)
throws RepositoryNotFoundException,ServiceNotAuthorizedException,ServiceNotEnabledException,
ServiceMayNotContinueException {
//TODO: implement this method
}
}
open
方法描述了如何通过Request
以及仓库的名字来获取一个需要serve出去的仓库对象Repository
。同时还需要在GitServlet
初始化时配置它使用改Resolver:
public class GitServlet extends org.eclipse.jgit.http.server.GitServlet {
@Override
public void init(ServletConfig config) throws ServletException {
setRepositoryResolver(new GitHttpResolver());
}
}
要获取本文的参考代码,请访问:< https://www.tianmaying.com/tutorial/jgit-http-server-guides/repo>
本文由 创作,采用 知识共享署名4.0 国际许可协议进行许可。本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为: 2020/07/15 07:14