KivaKit微服务
KivaKit微服务 
KivaKit旨在使微服务的编码更快、更容易。在这篇博文中,我们将研究 kivakit-microservice模块。截至目前,该模块只能通过SNAPSHOT构建和构建KivaKit来提前访问。KivaKit 1.1的最终版本将包括这个模块,并且应该在2021年10月底或更早发生。
它是做什么的?
kivakit-microservice迷你框架使得实现REST-ful GET、POST和DELETE处理程序以及将这些处理程序安装在特定路径上变得容易。大多数REST微服务的常规管道都被处理了,包括:
- Jetty网络服务器的配置和启动
- 处理GET、POST和DELETE请求
- 用Json对JSON对象进行序列化
- 使用KivaKit消息传递进行错误处理
- 生成一个OpenAPI规范
- 用Swagger查看OpenAPI规范
- 启动Apache Wicket网络应用程序
微服务
下面的DivisionMicroservice类是一个微服务,用于执行算术除法(以可以想象的最慢、最昂贵的方式)。微服务的超类提供了Jetty服务器的自动配置和启动:
public class DivisionMicroservice extends Microservice
{
public static void main(final String[] arguments)
{
new DivisionMicroservice().run(arguments);
}
@Override
public MicroserviceMetadata metadata()
{
return new MicroserviceMetadata()
.withName("divide-microservice")
.withDescription("Example microservice for division")
.withVersion(Version.parse("1.0"));
}
@Override
public void onInitialize()
{
// Register components here
}
public DivideRestApplication restApplication()
{
return new DivideRestApplication(this);
}
}
在这里,main(String[] arguments)方法创建了一个DivisionMicroservice的实例,并通过调用*run(String[] )*来启动它的运行(与任何KivaKit应用程序相同)。*metadata()*方法返回包含在REST OpenAPI规范中的服务信息(安装在/open-api/swagger.json)。*restApplication()*工厂方法为微服务创建一个REST应用程序,*webApplication()工厂方法可以选择创建一个Apache Wicket Web应用程序,用于配置服务和查看其状态。微服务的任何初始化都必须在onInitialize()*方法中进行。这是注册整个应用中使用的组件的最佳位置。
当run(String[] arguments)方法被调用时,Jetty Web服务器会在由-deployment开关加载的MicroserviceSettings对象指定的端口上启动。可以使用*-port*命令行开关来覆盖这个值。
当微服务启动时,以下资源是可用的:
| 资源路径 | 描述 |
|---|---|
| / | Apache Wicket网络应用 |
| / | KivaKit microservlet REST应用程序 |
| /资产 | 静态资源 |
| /docs | Swagger OpenAPI 文档 |
| /open-api/assets | OpenAPI资源(.yaml文件)。 |
| /open-api/swagger.json | OpenAPI规范 |
| /swagger/webapp | Swagger网络应用程序 |
| /swagger/webjar | Swagger设计资源 |
REST应用
一个REST应用程序是通过扩展MicroserviceRestApplication类来创建的:
public class DivideRestApplication extends MicroserviceRestApplication
{
public DivideRestApplication(Microservice microservice)
{
super(microservice);
}
@Override
public void onInitialize()
{
mount("divide", DivideRequest.class);
}
}
请求处理程序必须被挂载在onInitialize()方法里面的特定路径上(否则会报告错误)。如果挂载路径(在本例中为 "divide")不是以斜线("/")开头,则会自动预加路径"/api/[major-version].[minor-version]/"。因此,在上面的代码中,"divide "变成了"/api/1.0/divide",其中的1.0版本来自DivideMicroservice返回的元数据。同样的路径可以用来为每种HTTP方法(GET、POST、DELETE)装载一个请求处理程序。然而,试图在同一路径上为同一HTTP方法装载两个处理程序将导致错误。
gsonFactory()工厂方法(上面没有显示)可以选择提供一个创建配置的Gson对象的工厂。Gson工厂应该扩展MicroserviceGsonFactory类。KivaKit将在序列化和反序列化JSON对象时使用该工厂。
Microservlets
Microservlets处理 GET、POST 和 DELETE 请求。它们被安装在路径上,与请求处理程序的安装方式相同。但与请求处理程序不同的是,microservlet可以同时处理任何或所有HTTP请求方法。请求处理程序比microservlet更灵活,通常也更有用,所以这里主要是为了完整地介绍这一信息。microservlets的关键用例(到目前为止是唯一的用例)是它们被用来实现请求处理程序。你可以在MicroserviceRestApplication的*mount(String path, Class requestType)*方法中看到用于此目的的内部微服务。
请求处理程序
请求处理程序通过调用mount(String path, Class requestType)被安装到MicroserviceRestApplication上。它们有三种类型,每种类型都是MicroserviceRequest 的子类:
- MicroservletGetRequest
- MicroservletPostRequest
- MicroservletDeleteRequest
下面,我们看到一个POST请求处理程序,DivideRequest,它将两个数字分开。响应是由嵌套的DivideResponse类制定的。使用来自*@OpenApi注解的信息生成一个OpenAPI规范。最后,请求通过实现MicroservletPostRequest要求的Validatable*接口来执行自我验证:
@OpenApiIncludeType(description = "Request for divisive action")
public class DivideRequest extends MicroservletPostRequest
{
@OpenApiIncludeType(description = "Response to a divide request")
public class DivideResponse extends MicroservletResponse
{
@Expose
@OpenApiIncludeMember(description = "The result of dividing",
example = "42")
int quotient;
public DivideResponse()
{
this.quotient = dividend / divisor;
}
public String toString()
{
return Integer.toString(quotient);
}
}
@Expose
@OpenApiIncludeMember(description = "The number to be divided",
example = "84")
private int dividend;
@Expose
@OpenApiIncludeMember(description = "The number to divide the dividend by",
example = "2")
private int divisor;
public DivideRequest(int dividend, int divisor)
{
this.dividend = dividend;
this.divisor = divisor;
}
public DivideRequest()
{
}
@Override
@OpenApiRequestHandler(summary = "Divides two numbers")
public DivideResponse onPost()
{
return listenTo(new DivideResponse());
}
@Override
public Class<DivideResponse> responseType()
{
return DivideResponse.class;
}
@Override
public Validator validator(ValidationType type)
{
return new BaseValidator()
{
@Override
protected void onValidate()
{
problemIf(divisor == 0, "Cannot divide by zero");
}
};
}
}
注意,嵌套的响应类使用外层类来访问请求的字段。这使得getters和setters没有必要。当KivaKit调用onPost()时,响应对象被创建(由于调用listenTo(),它产生的任何消息都会被重复,DivideResponse对象的构造器会执行分割操作。这使得*onPost()*处理程序成为一个单行程序:
public DivideResponse onPost()
{
return listenTo(new DivideResponse());
}
请注意OO设计原则是如何改进封装、消除模板和增加可读性的。
在Java中访问KivaKit微服务
kivakit-microservice模块包括MicroserviceClient,它可以在Java中轻松访问KivaKit微服务。该客户端可以像这样使用:
public class DivisionClient extends Application
{
public static void main(String[] arguments)
{
new DivisionClient().run(arguments);
}
@Override
protected void onRun()
{
var client = listenTo(new MicroservletClient(
new MicroserviceGsonFactory(),
Host.local().https(8086),
Version.parse("1.0"));
var response = client.post("divide",
DivideRequest.DivideResponse.class,
new DivideRequest(9, 3));
Message.println(AsciiArt.box("response => $", response));
}
}
在这里,我们创建了一个MicroservletClient来访问我们上面构建的微服务。我们告诉它在本地主机的8086端口使用该服务。然后我们发送一个DivideRequest,用客户端将9除以3,然后我们读取响应。响应显示商是3:
-------------------
| response => 3 |
-------------------
路径和查询参数
一个请求处理程序不会直接访问路径和查询参数。相反,它们被自动转化为JSON对象。例如,一个POST到这个URL:
http://localhost:8086/api/1.0/divide/dividend/9/divisor/3
与上面DivisionClient代码中的POST请求完全相同。路径的dividend/9/divisor/3部分被转化为一个JSON对象,就像这样:
{
"dividend": 9,
"divisor": 3
}
microservlet处理这个JSON,就像它被发布一样。当POST-ing "平面 "请求对象(没有嵌套的对象)时,这个功能会很方便。请注意,当提供路径变量或查询参数时,请求的主体会被忽略。
OpenAPI
服务器上的"/docs "根路径通过Swagger提供了一个生成的OpenAPI规范。
OpenAPI可用的注释很少,但对简单的REST项目很有效。
| 注释 | 目的 |
|---|---|
| @OpenApiIncludeMember | 在规范中包括被注释的方法或字段。 |
| @OpenApiExcludeMember | 将注释方法或字段从规范中排除。 |
| @OpenApiIncludeMemberFromSuperType | 在规范中包括来自超类或超接口的成员。 |
| @OpenApiIncludeType | 包括规范模式中的注解类型 |
| @OpenApiRequestHandler | 提供关于请求处理方法*(onGet()*、onPost()或onDelete())的信息。 |
代码
上面讨论的代码是kivakit-examples资源库中的一个工作实例。在调试器中追踪该代码可能会有启发。
KivaKit 微服务 API 可在开发分支的 kivakit-microservice模块的开发分支中。
<dependency>
<groupId>com.telenav.kivakit</groupId>
<artifactId>kivakit-microservice</artifactId>
<version>${kivakit.version}</version>
</dependency>

