1. 概述
KivaKit是一个模块化Java应用程序框架,旨在让微服务和应用程序的开发更快、更轻松。KivaKit自2011年起由Telenav开发。目前,它已在GitHub上以Apache许可的开源项目形式提供。
在本文中,我们将探讨KivaKit作为一系列可协同工作的“迷你框架”的设计理念。此外,我们还将介绍每个迷你框架的基本功能。
2. KivaKit迷你框架
查看kivakit和kivakit-extensions仓库,我们发现KivaKit 1.0包含54个模块,这或许会让人眼花缭乱。不过,如果我们一步步来,情况就不会那么糟糕。首先,我们可以选择想要添加到项目中的模块,KivaKit中的每个模块都设计为可独立使用。
一些KivaKit模块包含迷你框架,迷你框架是一种简单、抽象的设计,用于解决一个常见问题。如果我们仔细研究KivaKit的迷你框架,就会发现它们拥有简单易用且适用范围广泛的接口。因此,它们有点像乐高积木,也就是说,它们是由简单的零件拼凑而成的。
在这里,我们可以看到KivaKit的迷你框架以及它们之间的关系:
迷你框架 | 模块 | 描述 |
---|---|---|
应用程序 | kivakit-application | 应用程序和服务器的基础组件 |
命令行解析 | kivakit-commandline | 使用转换和验证迷你框架进行开关和参数解析 |
组件 | kivakit-component | 实现KivaKit组件(包括应用程序)的基本功能 |
转换 | kivakit-kernel | 用于实现健壮的模块化类型转换器的抽象 |
提取 | kivakit-kernel | 从数据源提取对象 |
接口 | kivakit-kernel | 用作框架之间集成点的通用接口 |
日志记录 | kivakit-kernel kivakit-logs-* | 核心日志功能、日志服务提供商接口(SPI)和日志实现 |
消息传递 | kivakit-kernel | 使组件能够传输和接收状态信息 |
混合 | kivakit-kernel | 状态特征的实现 |
资源 | kivakit-resource kivakit-network-*kivakit-filesystems-* | 文件、文件夹和流资源的抽象 |
服务定位器 | kivakit-configuration | 用于查找组件和设置信息的服务定位器模式的实现 |
设置 | kivakit-configuration | 轻松访问组件配置信息 |
验证 | kivakit-kernel | 检查对象一致性的基本功能 |
我们可以在Kivakit仓库中找到这些框架,另一方面,我们会在kivakit-extensions中找到一些不太重要的模块,例如服务提供者。
2.1 消息传递
如上图所示,消息传递是集成的核心。在KivaKit中,消息传递使状态报告正式化,作为Java程序员,我们习惯于记录状态信息。有时,我们也会看到这些信息返回给调用者或作为异常抛出。相比之下,KivaKit中的状态信息包含在消息中,我们可以编写组件来广播这些消息。此外,我们还可以编写组件来监听这些消息。
我们可以看到,这种设计允许组件专注于一致地报告状态。对于组件来说,状态消息的去向并不重要。在一种情况下,我们可能会将消息定向到Logger。在另一种情况下,我们可能会将它们包含在统计信息中,我们甚至可以将它们显示给最终用户,组件并不关心,它只会向可能感兴趣的人报告问题。
广播消息的KivaKit组件可以连接到一个或多个消息中继器,形成监听器链:
在KivaKit中,Application通常是监听器链的末端。因此,Application类会记录它收到的所有消息。在此过程中,监听器链中的组件可能会将这些消息用于其他用途。
2.2 混合
KivaKit的另一个集成功能是mixins迷你框架,KivaKit mixins允许通过接口继承将基类“混合”到类型中。有时,mixins也被称为“有状态特征”。
例如,KivaKit中的BaseComponent类提供了构建组件的基础,BaseComponent提供了发送消息的便捷方法。此外,它还提供了对资源、设置和注册对象的轻松访问。
但我们很快就遇到了这种设计的问题,众所周知,在Java中,已经有基类的类不能扩展BaseComponent。KivaKit mixins允许将BaseComponent功能添加到已经有基类的组件中。例如:
public class MyComponent extends MyBaseClass implements ComponentMixin { [...] }
我们可以在这里看到接口ComponentMixin同时扩展了Mixin和Component:
Mixin接口为ComponentMixin提供了一个state()方法,首先,该方法用于创建一个BaseComponent并将其与实现ComponentMixin的对象关联起来。其次,ComponentMixin将Component接口的每个方法实现为Java默认方法。第三,每个默认方法都委托给关联的BaseComponent,这样,实现ComponentMixin提供的方法与扩展BaseComponent相同。
2.3 服务定位器
服务定位器类Registry允许我们将组件连接在一起,Registry提供的功能与依赖注入(DI)大致相同,但是,它与DI的典型用法在一个重要方面有所不同。在服务定位器模式中,组件会主动获取所需的接口,而DI则会将接口推送到组件中。因此,服务定位器方法改进了封装性,并减少了引用的范围。例如,Registry可以在方法中简洁地使用:
class MyData extends BaseComponent {
[...]
public void save() {
var database = require(Database.class);
database.save(this);
}
}
这里的BaseComponent.require(Class)方法会在Registry中查找对象,当我们的save()方法返回时,数据库引用就会离开作用域,这确保了没有外部代码能够获取我们的引用。
应用启动时,我们可以使用BaseComponent.registerObject()方法注册服务对象。之后,应用中其他位置的代码可以通过require(Class)查找它们。
2.4 资源和文件系统
kivakit-resource模块提供了读写流资源和访问文件系统的抽象,我们可以在这里看到KivaKit包含的一些比较重要的资源类型:
- 文件(本地、Zip、S3和HDFS)
- 包资源
- 网络协议(套接字、HTTP、HTTPS和FTP)
- 输入和输出流
我们从这种抽象中获得了两个宝贵的好处,可以:
- 通过一致的、面向对象的API访问任何流资源
- 使用Resource和WritableResource接口允许使用未知的资源类型
2.5 组件
kivakit-component模块让我们可以轻松访问常用功能,我们可以:
- 发送和接收消息
- 访问包和打包资源
- 注册和查找对象、组件和设置
BaseComponent和ComponentMixin都实现了Component接口,因此,我们可以为任何对象添加“组件特性”。
2.6 日志记录
KivaKit组件形成的监听器链通常终止于一个Logger,Logger将接收到的消息写入一个或多个Log中。此外,kivakit-kernel模块提供了一个用于实现Log的服务提供者接口(SPI)。
使用日志记录SPI,kivakit-extensions仓库为我们提供了一些日志实现:
提供者 | 模块 |
---|---|
ConsoleLog | kivakit-kernel |
FileLog | kivakit-logs-file |
EmailLog | kivakit-logs-email |
可以从命令行选择并配置一个或多个日志,这通过定义KIVAKIT_LOG系统属性来实现。
2.7 转换和验证
kivakit-kernel模块包含用于类型转换和对象验证的微型框架,这些框架与KivaKit消息传递功能集成,这使得它们能够一致地报告问题,并简化了使用。要实现像StringConverter这样的类型转换器,我们需要编写转换代码,我们无需担心异常、空字符串或Null值。
我们可以在KivaKit的许多地方看到转换器的使用,包括:
- 开关和参数解析
- 从属性文件加载设置对象
- 将对象格式化为调试字符串
- 从CSV文件读取对象
Validatable广播的消息会被验证微框架捕获,随后,这些消息会被分析,以便我们轻松获取错误统计信息和验证问题。
2.8 应用程序、命令行和设置
kivakit-application、kivakit-configuration和kivakit-commandline模块为开发应用程序提供了一个简单、一致的模型。
kivakit-application项目提供了Application基类,Application是一个组件,它使用kivakit-configuration提供设置信息。此外,它还使用kivakit-commandline提供命令行解析。
kivakit-configuration项目使用kivakit-resource模块从.properties资源(以及将来的其他来源)加载设置信息,它使用kivakit-kernel转换器将这些资源中的属性转换为对象,然后使用Validation迷你框架对转换后的对象进行验证。
应用程序的命令行参数和开关由kivakit-commandline模块使用KivaKit转换器和验证器进行解析,我们可以在应用程序的ConsoleLog中看到出现的问题。
2.9 微服务
到目前为止,我们已经讨论了KivaKit中对任何应用程序都有用的功能。此外,KivaKit还在kivakit-extensions中提供了专门针对微服务的功能,让我们快速浏览一下kivakit-web。
kivakit-web项目包含用于快速开发简单的REST和Web微服务接口的模块,JettyServer类为我们提供了一种轻松插入Servlet和过滤器的方法,JettyServer可以使用的插件包括:
插件 | 描述 |
---|---|
JettyJersey | REST应用程序支持 |
JettySwagger | Swagger自动REST文档 |
JettyWicket | 支持Apache Wicket Web框架 |
这些插件可以组合起来提供带有Swagger文档和Web界面的RESTful微服务:
var application = new MyRestApplication();
listenTo(new JettyServer())
.port(8080)
.add("/*", new JettyWicket(MyWebApplication.class))
.add("/open-api/*", new JettySwaggerOpenApi(application))
.add("/docs/*", new JettySwaggerIndex(port))
.add("/webapp/*", new JettySwaggerStaticResources())
.add("/webjar/*", new JettySwaggerWebJar(application))
.add("/*", new JettyJersey(application))
.start();
KivaKit 1.1将包含一个专用的微服务迷你框架,这将使我们更轻松地构建微服务。
3. 文档和Lexakai
KivaKit的文档由Lexakai生成,Lexakai创建UML图(可根据需要使用注释引导)并更新README.md Markdown文件。在每个项目的README文件中,Lexakai都会更新标准的页眉和页脚。此外,它还维护生成的UML图和Javadoc文档的索引。
4. 构建KivaKit
KivaKit的目标是Java 11或更高版本的虚拟机(但可以从Java 8源代码中使用),我们可以在Maven Central上找到KivaKit模块的所有构件。但是,我们可能想要修改KivaKit或为开源项目做出贡献,在这种情况下,我们需要构建它。
首先,让我们设置Git、Git Flow、Java 16 JDK和Maven 3.8.1或更高版本。
首先,我们将kivakit仓库克隆到我们的工作区中:
mkdir ~/Workspace
cd ~/Workspace
git clone --branch develop https://github.com/Telenav/kivakit.git
接下来,我们将示例bash配置文件复制到我们的主文件夹:
cp kivakit/setup/profile ~/.profile
然后我们修改~/.profile以指向我们的工作区以及我们的Java和Maven安装:
export KIVAKIT_WORKSPACE=$HOME/Workspace
export JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-16.jdk/Contents/Home
export M2_HOME=$HOME/Developer/apache-maven-3.8.2
设置好配置文件后,我们确保正在运行bash(在macOS上,zsh现在是默认设置):
chsh -s /bin/bash
最后,我们重新启动终端程序并执行命令:
$KIVAKIT_HOME/setup/setup.sh
安装脚本会克隆kivakit-extensions和其他一些相关的仓库,之后,它会初始化git-flow并构建所有KivaKit项目。
5. 总结
在本文中,我们简要介绍了KivaKit的设计,并介绍了它提供的一些重要功能。KivaKit非常适合开发微服务,它被设计成易于理解、独立的组件,方便学习和使用。
Post Directory
