当前位置:Java -> 介绍Kilo

介绍Kilo

Kilo 是一个用于在Java中创建和消费RESTful和类RESTful网络服务的开源框架。它非常轻量级,只需要一个Java运行环境和一个Servlet容器。项目的名称来自航海中的K或Kilo旗,代表“我想与你通信”。

Kilo原先被称为“HTTP-RPC”,被创建作为其他占用更大空间且学习曲线更陡峭的框架的替代品。最近更改了名称以更好地反映项目当前的重点和意图。

本文概述了两个核心Kilo类,WebServiceWebServiceProxy

WebService

WebService 是用于网络服务的抽象基类。它扩展了类似的抽象HttpServlet类,并在标准servlet API之上提供了一个薄的、面向REST的层。

例如,以下服务实现了一些简单的数学运算:

@WebServlet(urlPatterns = {"/math/*"}, loadOnStartup = 1)
@Description("Math example service.")
public class MathService extends WebService {
    @RequestMethod("GET")
    @ResourcePath("sum")
    @Description("Calculates the sum of two numbers.")
    public double getSum(
        @Description("The first number.") double a,
        @Description("The second number.") double b
    ) {
        return a + b;
    }

    @RequestMethod("GET")
    @ResourcePath("sum")
    @Description("Calculates the sum of a list of numbers.")
    public double getSum(
        @Description("The numbers to add.") List<Double> values
    ) {
        double total = 0;

        for (double value : values) {
            total += value;
        }

        return total;
    }
}


RequestMethod 注解将HTTP动词(例如GETPOST)与服务方法或“处理程序”相关联。可选的ResourcePath 注解将处理程序与相对于Servlet的特定路径或“端点”相关联。如果未指定,则处理程序与Servlet自身相关。可选的Description 注解用于自动生成的服务文档中。

参数可以通过查询字符串、资源路径或请求体提供。它们也可以以表单数据的形式提交。 WebService 将值转换为预期类型,调用方法,并将返回值(如果有)以JSON形式写入输出流。

可以将多个方法与同一动词和路径相关联。 WebService 根据提供的参数值选择要执行的最佳方法。例如,这个请求将调用第一个方法:

GET /math/sum?a=2&b=4


而这个请求将调用第二个:

GET /math/sum?values=1&values=2&values=3


无论哪种情况,服务都会以响应返回值6。

路径变量

路径变量(或“键”)在处理程序的资源路径中由“?”字符指定。例如,下面方法中的itemID参数是由路径变量提供的:

@RequestMethod("GET")
@ResourcePath("items/?")
@Description("Returns detailed information about a specific item.")
public ItemDetail getItem(
    @Description("The item ID.") Integer itemID
) throws SQLException { ... }


路径参数必须在方法签名中的查询参数之前。值根据声明顺序映射到方法参数。

请求体内容

请求体内容可以在POSTPUT处理程序的最后一个参数中声明。例如,该方法接受作为路径变量和ItemDetail实例的请求体参数:

@RequestMethod("PUT")
@ResourcePath("items/?")
@Description("Updates an item.")
public void updateItem(
    @Description("The item ID.") Integer itemID,
    @Description("The updated item.") ItemDetail item
) throws SQLException { ... }


返回值

返回值转换成JSON格式如下:

  • String: string
  • Number/数值类型: number
  • Boolean/boolean: boolean
  • java.util.Date: 表示毫秒数的数值
  • Iterable: array
  • java.util.Map: object

此外,以下类型的实例会自动转换为它们的字符串表示形式:

  • Character/char
  • Enum
  • java.time.TemporalAccessor
  • java.time.TemporalAmount
  • java.util.UUID
  • java.net.URL

所有其他值被假设为bean并被序列化为对象。

WebServiceProxy

WebServiceProxy 类用于向服务器提交API请求。它提供以下两个构造函数:

public WebServiceProxy(String method, URL url) { ... }
public WebServiceProxy(String method, URL baseURL, String path, Object... arguments) throws MalformedURLException { ... }


第一个版本接受表示要执行的HTTP方法和所请求资源的URL的字符串。第二个版本接受HTTP方法、基本URL和相对路径(作为格式字符串,对其应用了可选的尾随参数)。

请求参数通过传递给setArguments()方法的映射来指定。可以使用任何值作为参数,并通常使用其字符串表示形式进行编码。然而,Date实例会自动转换为表示毫秒数的长整型值。此外,Collection或数组实例表示多值参数,并且类似于HTML中的<select multiple>标签。请求体内容可以通过setBody()方法提供。

服务操作通过以下方法之一被调用:

public Object invoke() throws IOException { ... }
public <T> T invoke(Function<Object, ? extends T> transform) throws IOException { ... }
public <T> T invoke(ResponseHandler<T> responseHandler) throws IOException { ... }


第一个版本反序列化一个成功的JSON响应(如果有)。第二个应用一个转换到反序列化响应。第三个版本允许调用者提供自定义响应处理程序:

public interface ResponseHandler<T> {
    T decodeResponse(InputStream inputStream, String contentType) throws IOException;
}


下面的代码演示了如何使用WebServiceProxy来访问前面讨论的简单数学服务的操作:

// GET /math/sum?a=2&b=4
var webServiceProxy = new WebServiceProxy("GET", new URL("http://localhost:8080/kilo-test/math/sum"));

webServiceProxy.setArguments(mapOf(
    entry("a", 4),
    entry("b", 2)
));

System.out.println(webServiceProxy.invoke()); // 6.0
// GET /math/sum?values=1&values=2&values=3
var webServiceProxy = new WebServiceProxy("GET", new URL("http://localhost:8080/kilo-test/math/sum"));

webServiceProxy.setArguments(mapOf(
    entry("values", listOf(1, 2, 3))
));

System.out.println(webServiceProxy.invoke()); // 6.0


还支持POSTPUTDELETE操作。

Typed Invocation

WebServiceProxy还提供了以下方法,以便方便、类型安全地访问Web API:

public static <T> T of(Class<T> type, URL baseURL) { ... }
public static <T> T of(Class<T> type, URL baseURL, Consumer<WebServiceProxy> initializer) { ... }


两个版本都返回一个实现了给定接口的对象,用于向提供的URL提交请求。第二个版本接受的可选的初始化器将在每次服务调用之前被调用;例如,用于应用常见的请求头。

RequestMethodResourcePath注解如前面所述使用。代理方法必须包括一个throws子句,声明IOException,以便调用者可以处理意外失败。例如:

public interface MathServiceProxy {
    @RequestMethod("GET")
    @ResourcePath("sum")
    double getSum(double a, double b) throws IOException;

    @RequestMethod("GET")
    @ResourcePath("sum")
    double getSum(List<Double> values) throws IOException;
}


下面展示了示例用法:

var mathServiceProxy = WebServiceProxy.of(MathServiceProxy.class, new URL("http://localhost:8080/kilo-test/math/"));

System.out.println(mathServiceProxy.getSum(4, 2)); // 6.0
System.out.println(mathServiceProxy.getSum(listOf(1.0, 2.0, 3.0))); // 6.0


附加信息

本文介绍了Kilo框架,并简要概述了两个Kilo类WebServiceWebServiceProxy。有关更多信息,请查看项目的 README

推荐阅读: 百度面经(20)

本文链接: 介绍Kilo