Introducing KivaKit – 介绍一下KivaKit

最后修改: 2021年 9月 29日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

KivaKit is a modular Java application framework designed to make developing microservices and applications quicker and easier. KivaKit has been developed at Telenav since 2011. It is now available as an Apache Licensed, Open Source project on GitHub.

KivaKit是一个模块化的Java应用框架,旨在使开发微服务和应用程序更加快速和简单。自2011年以来,KivaKit一直在Telenav开发。它现在作为一个Apache许可的开源项目在GitHub上提供。

In this article, we’ll explore the design of KivaKit as a collection of “mini-frameworks” that work together. In addition, we’ll take a look at the essential features of each mini-framework.

在这篇文章中,我们将探讨KivaKit的设计,它是一个 “迷你框架 “的集合,可以一起工作。此外,我们将看一下每个迷你框架的基本功能。

2. KivaKit Mini-frameworks

2.KivaKit小型框架

Looking in the kivakit and kivakit-extensions repositories, we can see that KivaKit 1.0 contains 54 modules. We could find this overwhelming. However, if we take things one step at a time, it’s not so bad. For starters, we can pick and choose what we want to include in our projects. Each module in KivaKit is designed to be used on its own.

kivakitkivakit-extensions存储库中,我们可以看到KivaKit 1.0包含54个模块。我们可能会发现这让人喘不过气来。然而,如果我们一步一步来,它也不是那么糟糕。首先,我们可以挑选我们想在我们的项目中包含的内容。KivaKit中的每个模块都被设计成可以单独使用。

Some KivaKit modules contain mini-frameworks. A mini-framework is a simple, abstract design that addresses a common problem. If we examine KivaKit’s mini-frameworks, we will find that they have straightforward, broadly applicable interfaces. As a result, they are a bit like Legos™. That is to say, they are simple pieces that snap together.

一些KivaKit模块包含迷你框架。迷你框架是一个简单、抽象的设计,解决了一个共同的问题。如果我们检查KivaKit的迷你框架,我们会发现它们有直接的、广泛适用的接口。因此,它们有点像 Legos™。也就是说,它们是可以扣在一起的简单部件。

Here, we can see KivaKit’s mini-frameworks and how they relate to each other:

在这里,我们可以看到KivaKit的迷你框架以及它们之间的关系。

 

 

Mini-framework Module Description
Application kivakit-application Base components for applications and servers
Command-Line Parsing kivakit-commandline Switch and argument parsing using the conversion and validation mini-frameworks
Component kivakit-component Base functionality for implementing KivaKit components, including applications
Conversion kivakit-kernel An abstraction for implementing robust, modular type converters
Extraction kivakit-kernel Extraction of objects from a data source
Interfaces kivakit-kernel Generic interfaces used as integration points between frameworks
Logging kivakit-kernel
kivakit-logs-*
Core logging functionality, log service provider interface (SPI), and log implementations
Messaging kivakit-kernel Enables components to transmit and receive status information
Mixins kivakit-kernel An implementation of stateful traits
Resource kivakit-resource
kivakit-network-*
kivakit-filesystems-*
Abstractions for files, folders, and streamed resources
Service Locator kivakit-configuration An implementation of the service locator pattern for finding components and settings information
Settings kivakit-configuration Provides easy access to component configuration information
Validation kivakit-kernel Base functionality for checking the consistency of objects

We can find these frameworks in the kivakit repository. On the other hand, we will find less important modules like service providers in kivakit-extensions.

我们可以在kivakit资源库中找到这些框架。另一方面,我们将在kivakit-extensions中找到不太重要的模块,如服务提供者。

2.1. Messaging

2.1 信息传递

As the diagram above shows, messaging is the central point of integration. In KivaKit, messaging formalizes status reporting. As Java programmers, we’re used to status information being logged. Sometimes, we also see this information returned to callers or thrown as exceptions. By contrast, status information in KivaKit is contained in Messages. We can write components that broadcast these messages. Also, we can write components that listen to them.

如上图所示,消息传递是整合的中心点。在KivaKit中,消息传递使状态报告正规化。作为 Java 程序员,我们习惯于记录状态信息。有时,我们也会看到这些信息被返回给调用者或作为异常抛出。相比之下,KivaKit中的状态信息包含在Messages中。我们可以编写broadcast这些消息的组件。此外,我们还可以编写监听这些消息的组件。

We can see that this design allows components to focus on reporting status consistently. To a component, where status messages go is unimportant. In one case, we might direct messages to a Logger. In another, we might include them in a statistic. We could even display them to an end-user. The component doesn’t care. It just reports issues to whoever might be interested.

我们可以看到,这种设计允许组件专注于持续报告状态。对于一个组件来说,状态信息的去向并不重要。在一种情况下,我们可能会将消息引导到记录器。在另一种情况下,我们可能会将它们包含在一个统计数据中。我们甚至可以将它们显示给终端用户。该组件并不关心。它只是向任何可能感兴趣的人报告问题。

KivaKit components that broadcast messages can be connected to one or more message repeaters, forming a listener chain:

广播消息的KivaKit组件可以连接到一个或多个消息中继器,形成一个听众链。

 

In KivaKit, an Application is usually the end of a listener chain. Therefore, the Application class logs any messages it receives. Along the way, components in the listener chain may have other uses for these messages.

在KivaKit中,一个Application通常是一个监听器链的末端。因此,Application类会记录它收到的任何消息。一路走来,监听器链中的组件可能对这些消息有其他用途。

2.2. Mixins

2.2.混合器

Another integration feature of KivaKit is the mixins mini-framework. KivaKit mixins allow base classes to be “mixed in” to types through interface inheritance.  Sometimes, mixins are known as “stateful traits“.

KivaKit的另一个集成功能是mixins迷你框架。KivaKit混合器允许基类通过接口继承 “混入 “类型。有时,混合器被称为”stateful traits” 。

For example, the BaseComponent class in KivaKit provides a foundation for building components. BaseComponent provides convenience methods for sending messages. In addition, it offers easy access to resources, settings, and registered objects.

例如,KivaKit中的BaseComponent类为构建组件提供了一个基础。BaseComponent提供了发送消息的便利方法。此外,它还提供了对资源、设置和注册对象的简单访问。

But we quickly run into a problem with this design. As we know, in Java, a class that already has a base class cannot also extend BaseComponent. KivaKit mixins allow BaseComponent functionality to be added to a component that already has a base class. For example:

但我们很快就遇到了这种设计的问题。正如我们所知,在Java中,一个已经有基类的类不能同时扩展BaseComponent。KivaKit mixins允许将BaseComponent功能添加到已经拥有基类的组件中。比如说。

public class MyComponent extends MyBaseClass implements ComponentMixin { [...] }

We can see here that the interface ComponentMixin extends both Mixin and Component:

我们在这里可以看到,接口ComponentMixin同时扩展了MixinComponent

 

The Mixin interface provides a state() method to ComponentMixin. First, this method is used to create and associate a BaseComponent with the object implementing ComponentMixin. Second, ComponentMixin implements each method of the Component interface as a Java default method. Third, each default method delegates to the associated BaseComponent. In this way, implementing ComponentMixin provides the same methods as extending BaseComponent.

Mixin接口为ComponentMixin提供了一个state()方法。首先,这个方法被用来创建一个BaseComponent与实现ComponentMixin的对象关联。第二,ComponentMixinComponent接口的每个方法实现为Java默认方法。第三,每个默认方法都委托给相关的BaseComponent。通过这种方式,实现ComponentMixin提供了与扩展BaseComponent相同的方法。

2.3. Service Locator

2.3.服务定位器

The service locator class Registry allows us to wire components together. A Registry provides roughly the same functionality as dependency injection (DI). However, it differs from the typical use of DI in one important way. In the service locator pattern, components reach out for the interfaces that they need. On the other hand, DI pushes interfaces into components. As a result, the service locator approach improves encapsulation. It also reduces the scope of references. For example, Registry can be used neatly within a method:

服务定位器类Registry允许我们将组件连在一起Registry提供与依赖注入(DI)大致相同的功能。然而,它在一个重要方面与DI的典型使用不同。在服务定位器模式中,组件接触到它们需要的接口。另一方面,DI将接口推送到组件中。因此,服务定位器方法提高了封装性。它也减少了引用的范围。例如,Registry可以在一个方法中整齐地使用。

class MyData extends BaseComponent {

    [...]

    public void save() {
        var database = require(Database.class);
        database.save(this);
    }
}

The BaseComponent.require(Class) method here looks up objects in a Registry. When our save() method returns, the database reference leaves scope. This ensures that no external code can obtain our reference.

BaseComponent.require(Class)方法在这里查找Registry中的对象。当我们的save()方法返回时,database引用离开了范围。这确保了没有外部代码可以获得我们的引用。

When our application starts, we can register service objects with one of the BaseComponent.registerObject() methods. Later, code elsewhere in our application can look them up with require(Class).

当我们的应用程序启动时,我们可以用BaseComponent.registerObject()方法之一注册服务对象。之后,我们应用程序中其他地方的代码可以用require(Class)来查找它们。

2.4. Resources and Filesystems

2.4.资源和文件系统

The kivakit-resource module provides abstractions for reading and writing streamed resources and accessing filesystems. We can see here a few of the more important resource types that KivaKit includes:

kivakit-resource模块为读写流式资源和访问文件系统提供了抽象。我们可以在这里看到KivaKit包括的几个比较重要的资源类型。

  • Files (local, Zip, S3, and HDFS)
  • Package resources
  • Network protocols (sockets, HTTP, HTTPS, and FTP)
  • Input and output streams

We get two valuable benefits from this abstraction. We can:

我们从这种抽象中得到两个宝贵的好处。我们可以。

2.5. Components

2.5.组成部分

The kivakit-component module gives us ready access to common functionality. We can:

kivakit-component模块让我们可以随时访问常用功能。我们可以。

  • Send and receive messages
  • Access packages and packaged resources
  • Register and lookup objects, components, and settings

The Component interface is implemented by both BaseComponent and ComponentMixin. As a result, we can add “component nature” to any object.

Component接口由BaseComponentComponentMixin实现。因此,我们可以为任何对象添加 “组件性质”。

2.6. Logging

2.6.记录

Listener chains formed by KivaKit components often terminate in a Logger. A Logger writes the messages it receives to one or more Logs. In addition, the kivakit-kernel module provides a service provider interface (SPI) for implementing Logs. We can see the full design of the logging mini-framework in UML here.

KivaKit组件形成的监听器链通常终止于Logger。一个Logger将其收到的消息写入一个或多个Logs。此外,kivakit-kernel模块提供了一个服务提供者接口(SPI)来实现Logs。我们可以在UML这里看到日志小框架的完整设计。

Using the logging SPI, the kivakit-extensions repository provides us with some Log implementations:

使用日志SPI,kivakit-extensions 资源库为我们提供了一些Log实现。

Provider Module
ConsoleLog kivakit-kernel
FileLog kivakit-logs-file
EmailLog kivakit-logs-email

One or more logs can be selected and configured from the command line. This is done by defining the KIVAKIT_LOG system property.

可以从命令行选择和配置一个或多个日志。这是通过定义KIVAKIT_LOG系统属性实现的。

2.7. Conversion and Validation

2.7.转换和验证

The kivakit-kernel module contains mini-frameworks for type conversion and object validation. These frameworks are integrated with KivaKit messaging. This allows them to report problems consistently. It also simplifies usage. To implement a type Converter like a StringConverter, we need to write the conversion code. We don’t need to worry about exceptions, empty strings, or null values.

kivakit-kernel模块包含用于类型转换和对象验证的迷你框架。这些框架与KivaKit消息传递集成。这使得它们能够一致地报告问题。它也简化了使用。要实现像StringConverter这样的类型转换器,我们需要编写转换代码。我们不需要担心异常、空字符串或空值的问题。

 

We can see converters in use in many places in KivaKit, including:

我们可以在KivaKit的许多地方看到转换器的使用,包括。

  • Switch and argument parsing
  • Loading settings objects from properties files
  • Formatting objects as debug strings
  • Reading objects from CSV files

Messages broadcast by Validatables are captured by the validation mini-framework. Subsequently, they are analyzed to provide us with easy access to error statistics and validation problems.

Validatables广播的信息被验证小框架捕获。随后,它们被分析,为我们提供了对错误统计和验证问题的轻松访问。

 

2.8. Applications, Command Lines, and Settings

2.8.应用程序、命令行和设置

The kivakit-application, kivakit-configuration, and kivakit-commandline modules provide a simple, consistent model for developing applications.

kivakit-applicationkivakit-configurationkivakit-commandline模块为开发应用程序提供了一个简单、一致的模型。

The kivakit-application project supplies the Application base class. An Application is a Component. It provides settings information using kivakit-configuration. In addition, it provides command-line parsing with kivakit-commandline.

kivakit-application项目提供Application基类。Application是一个组件它使用kivakit-configuration提供设置信息。此外,它使用kivakit-commandline提供命令行解析。

The kivakit-configuration project uses the kivakit-resource module to load settings information from .properties resources (and other sources in the future). It converts the properties in these resources to objects using kivakit-kernel converters. The converted objects are then validated with the validation mini-framework.

kivakit-configuration项目使用kivakit-resource模块从.properties资源(以及将来的其他来源)加载设置信息。它使用kivakit-kernel转换器将这些资源中的属性转换为对象。然后用验证mini-framework对转换后的对象进行验证。

Command-line arguments and switches for an application are parsed by the kivakit-commandline module using KivaKit converters and validators. We can see issues that arise in the application’s ConsoleLog.

应用程序的命令行参数和开关由kivakit-commandline模块使用KivaKit转换器和验证器进行解析。我们可以看到在应用程序的ConsoleLog中出现的问题。

 

2.9. Microservices

2.9.微服务

So far, we’ve discussed KivaKit features that are generally useful to any application. In addition, KivaKit also provides functionality in kivakit-extensions that is explicitly targeted at microservices. Let’s take a quick look at kivakit-web.

到目前为止,我们已经讨论了对任何应用程序普遍有用的KivaKit功能。此外,KivaKit还在kivakit-extensions中提供明确针对微服务的功能。让我们快速浏览一下kivakit-web

The kivakit-web project contains modules for rapidly developing a simple REST and web interface to a microservice. The JettyServer class provides us with a way to plug in servlets and filters with a minimum of hassle. Plugins that we can use with JettyServer include:

kivakit-web项目包含了一些模块,用于快速开发一个简单的REST和Web界面的微服务。JettyServer类为我们提供了一种方法,以最小的麻烦插入Servlet和过滤器。我们可以与JettyServer一起使用的插件包括。

Plugin Description
JettyJersey REST application support
JettySwagger Swagger automatic REST documentation
JettyWicket Support for the Apache Wicket web framework

These plugins can be combined to provide a RESTful microservice with Swagger documentation and a web interface:

这些插件可以结合起来,提供一个带有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 will include a dedicated microservices mini-framework. This will make it even easier for us to build microservices.

KivaKit 1.1将包括一个专门的微服务迷你框架。这将使我们更容易构建微服务。

3. Documentation and Lexakai

3.文件和Lexakai

The documentation for KivaKit is generated by Lexakai. Lexakai creates UML diagrams (guided by annotations when desired) and updates README.md markdown files. In the readme file for each project, Lexakai updates a standard header and footer. In addition, it maintains indexes for the generated UML diagrams and Javadoc documentation. Lexakai is an open-source project distributed under Apache License.

KivaKit的文档由Lexakai生成。 Lexakai创建UML图(在需要时由注释引导)并更新README.md标记文件。在每个项目的readme文件中,Lexakai更新了一个标准的页眉和页脚。此外,它还为生成的UML图和Javadoc文档维护索引。Lexakai是一个在Apache许可下发布的开源项目。

4. Building KivaKit

4.建设KivaKit

KivaKit targets a Java 11 or higher virtual machine (but can be used from Java 8 source code). We can find all the artifacts for KivaKit modules on Maven Central. However, we might want to modify KivaKit or contribute to the open-source project. In this case, we’ll need to build it.

KivaKit的目标是Java 11或更高的虚拟机(但也可以从Java 8源代码中使用)。我们可以在Maven Central上找到KivaKit模块的所有工件。然而,我们可能想修改KivaKit或为该开源项目做出贡献。在这种情况下,我们就需要构建它。

To get started, let’s set up Git, Git Flow, Java 16 JDK, and Maven 3.8.1 or higher.

为了开始工作,我们来设置Git、Git FlowJava 16 JDKMaven 3.8.1或更高

First, we clone the kivakit repository into our workspace:

首先,我们把kivakit资源库克隆到我们的工作区。

mkdir ~/Workspace
cd ~/Workspace
git clone --branch develop https://github.com/Telenav/kivakit.git

Next, we copy the sample bash profile to our home folder:

接下来,我们将样本bash配置文件复制到我们的主文件夹。

cp kivakit/setup/profile ~/.profile

Then we modify ~/.profile to point to our workspace, and our Java and Maven installations:

然后我们修改~/.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

After our profile is set up, we ensure that we are running bash (on macOS, zsh is the default now):

在我们的配置文件设置完成后,我们确保我们正在运行bash(在macOS上,zsh现在是默认的)。

chsh -s /bin/bash

And finally, we restart our terminal program and execute the command:

最后,我们重新启动我们的终端程序并执行命令。

$KIVAKIT_HOME/setup/setup.sh

The setup script will clone kivakit-extensions and some other related repositories. Afterward, it will initialize git-flow and build all our KivaKit projects.

设置脚本将克隆kivakit-extensions和其他一些相关的资源库。之后,它将初始化git-flow并构建我们所有的KivaKit项目。

5. Conclusion

5.总结

In this article, we took a brief look at the design of KivaKit. We also toured some of the more important functions it provides. KivaKit is ideally suited for developing microservices. It has been designed to be learned and used in easy-to-digest, independent pieces.

在这篇文章中,我们简单看了一下KivaKit的设计。我们还参观了它提供的一些比较重要的功能。KivaKit非常适用于开发微服务。它被设计成易于学习和使用的、独立的片段。