Hypertext Application Language(HAL)
Hypertext Application Language(HAL)
HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单、统一的形式,在API中引入超链接特性,使得API的可发现性(discoverable)更强,并具有自描述的特点。使用了HAL的API会更容易地被第三方开源库所调用,并且使用起来也很方便,开发者可以像处理普通JSON数据那样去处理API数据。有关HAL的更多信息,可以参考官方网站:http://stateless.co/hal_specification.html。
例子
下面就是一个典型的使用HAL的API的响应数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
{ "_links": { "self": { "href": "/orders" }, "curies": [{ "name": "ea", "href": "http://example.com/docs/rels/{rel}", "templated": true }], "next": { "href": "/orders?page=2" }, "ea:find": { "href": "/orders{?id}", "templated": true } }, "currentlyProcessing": 14, "shippedToday": 20, "_embedded": { "ea:order": [{ "_links": { "self": { "href": "/orders/123" }, "ea:basket": { "href": "/baskets/98712" }, "ea:customer": { "href": "/customers/7809" } }, "total": 30.00, "currency": "USD", "status": "shipped" }, { "_links": { "self": { "href": "/orders/124" }, "ea:basket": { "href": "/baskets/97213" }, "ea:customer": { "href": "/customers/12369" } }, "total": 20.00, "currency": "USD", "status": "processing" }] } } |
上面的JSON数据中,标注了高亮的几行其实是真正的数据部分,其它部分就是增加的一些超链接,用以定位与当前资源(对象)相关的其它资源。比如,在_embedded节点下包含了两个订单信息,在订单信息的_links节点下,就包含了与该订单相关的其它资源的访问链接,例如可以通过访问/customers/7809链接,就可以获得第一条订单的客户信息。另外,在HAL中,超链接是可以为模板的,模板链接可以给定一个名称,并指定templated为true。例如,上面,,子中的curies链接,指定了API文档的链接模板,那么,通过访问http://example.com/docs/rels/find,就可以获得有关获取某个销售订单详细信息API的文档,通过访问http://example.com/docs/rels/order,就可以获得有关销售订单API的文档。此外,上面的例子中还包含了获取下一页数据的链接(next链接),因此,客户端只需要调用一次API,就能获得与其相关的其它API的访问链接。
.NET Core实现
Java中Spring Data在新建的Data Service API都默认使用了HAL,返回数据格式是application/hal+json或者application/hal+xml(HAL可以有JSON和XML两种格式,本文只讨论JSON格式)。于是,我基于.NET Core实现了HAL的编程模型,通过这个编程模型,今后就能很方便地在.NET Core Web API中启用HAL的功能。项目的开源地址是:https://github.com/daxnet/hal。我也通过Jenkins持续集成,发布了NuGet包,可以支持.NET Framework 4.6.1以及Net Standard 1.6,这样,既可以在经典.NET Framework,又可以在.NET Core中使用HAL库。
在Visual Studio中,在NuGet Package Manager中添加NuGet Feed:https://www.myget.org/F/daxnet-utils/api/v3/index.json
然后,在控制台应用程序(Console Application)项目上选择Manage NuGet Packages,打开NuGet,Package source选择刚刚添加的那个,然后选择Hal后,点击Install进行安装。
安装完成后,输入下面代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
using System; using Hal.Builders; namespace ConsoleApp8 { public class Program { public static void Main( string [] args) { var builder = new ResourceBuilder(); var resource = builder .WithState( new { currentlyProcessing = 14, shippedToday = 20 }) .AddSelfLink().WithLinkItem( "/orders" ) .AddCuriesLink().WithLinkItem( "http://example.com/docs/rels/{rel}" , "ea" , true ) .AddLink( "next" ).WithLinkItem( "/orders?page=2" ) .AddLink( "ea:find" ).WithLinkItem( "/orders{?id}" , templated: true ) .AddEmbedded( "ea:order" ) .Resource( new ResourceBuilder() .WithState( new { total = 30.00F, currency = "USD" , status = "shipped" }) .AddSelfLink().WithLinkItem( "/orders/123" ) .AddLink( "ea:basket" ).WithLinkItem( "/baskets/98712" ) .AddLink( "ea:customer" ).WithLinkItem( "/customers/7809" )) .Resource( new ResourceBuilder() .WithState( new { total = 20.00F, currency = "USD" , status = "processing" }) .AddSelfLink().WithLinkItem( "/orders/124" ) .AddLink( "ea:basket" ).WithLinkItem( "/baskets/97213" ) .AddLink( "ea:customer" ).WithLinkItem( "/customers/12369" )) .Build(); Console.WriteLine(resource); } } } |
运行一下试试?是否已经输出了前面例子中的HAL JSON数据(如下)?
这个开发库的一个亮点就是使用了流畅接口(Fluent API)的编程风格,开发人员能够非常方便地使用此库来产生所需的HAL数据。流畅接口的实现结合了装饰器(Decorator)模式和C#的扩展方法,都定义在Hal.Builders命名空间下,有兴趣的读者可以下载源代码查看。
附上整个HAL的对象模型类图:
总结
相信本库应该是.NET Core下第一个比较完整地实现了HAL规范的开源库,它发布在MIT许可协议之下,商业友好,欢迎使用并提宝贵意见。在发现Bug后,也欢迎在Issue中提出,或者提交Pull Request。
Hypertext Application Language(HAL)的更多相关文章
- 基于.NET Core的Hypertext Application Language(HAL)开发库
HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单.统一的形式,在API中引入超链接特性,使得API的可发现性(discoverable ...
- Android源码分析二 硬件抽象层(HAL)
一 什么是HAL HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现.借助 HAL,您可以顺利实现相关功能,而不会影响或更改更高级别的系统.HAL 实现会 ...
- 在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口(老罗学习笔记4)
在上两篇文章中,我们介绍了如何为Android系统的硬件编写驱动程序,包括如何在Linux内核空间实现内核驱动程序和在用户空间实现硬件抽象层接口.实现这两者的目的是为了向更上一层提供硬件访问接口,即为 ...
- 为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口
在上两篇文章中,我们介绍了如何为Android系统的硬件编写驱动程序,包括如何在Linux内核空间实现内核驱动程序和在用户空间实现硬件抽象层接 口.实现这两者的目的是为了向更上一层提供硬件访问接口,即 ...
- 为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序
在Android硬件抽象层(HAL)概要介绍和学习计划一文中,我们简要介绍了在Android系统为为硬件编写驱动程序的方法.简单来说,硬件驱动程序一方面分布在Linux内核中,另一方面分布在用户空间的 ...
- Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析[转]
前面在介绍Android系统的开机画面时提到,Android设备的显示屏被抽象为一个帧缓冲区,而Android系统中的SurfaceFlinger服务就是通过向这个帧缓冲区写入内容来绘制应用程序的用户 ...
- Android - 硬件抽象层(HAL)
以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):http://blog.csdn.net/luosheng ...
- Azure Application Gateway(二)对后端 VM 进行负载均衡
一,引言 上一节有讲到使用 Azure Application Gateway 为我们后端类型为 Web App 的 Demo 项目提供负载均衡,Azure Application Gateway 的 ...
- 在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序(老罗学习笔记3)
简单来说,硬件驱动程序一方面分布在Linux内核中,另一方面分布在用户空间的硬件抽象层中.接着,在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)一文中举例子说明了如何在 ...
随机推荐
- darknet YOLOv2安装及数据集训练
一. YOLOv2安装使用 1. darknet YOLOv2安装 git clone https://github.com/pjreddie/darknetcd darknetmake或到网址上下载 ...
- CodeForces - 592D: Super M(虚树+树的直径)
Ari the monster is not an ordinary monster. She is the hidden identity of Super M, the Byteforces’ s ...
- java.lang.NoSuchMethodException: cn.pb.bean.Category.<init>()报错
代码如下: package cn.pb.bean; import java.util.ArrayList;import java.util.List; /** * 分类的实体类 */public cl ...
- 洛谷 P2919 [USACO08NOV]守护农场Guarding the Farm
题目描述 The farm has many hills upon which Farmer John would like to place guards to ensure the safety ...
- 【Lintcode】046.Majority Number
题目: Given an array of integers, the majority number is the number that occurs more than half of the ...
- 使用django-extension扩展django的manage――runscript命令
摘要:1.下载安装 1)$easy_installdjango-extensions 2)在INSTALLED_APP中添加'django_extensions'[python]INSTALL ...
- pytorch------cpu与gpu load时相互转化 torch.load(map_location=)
将gpu改为cpu时,遇到一个报错: RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is ...
- float浮动改变display类型
position:absolute和float都会隐式的改变display类型. 也就是说,不论之前是什么类型的元素(display:none除外),只要设置了position:absolute或fl ...
- poj3013Big Chrismas Tree——树转换spfa
题目:http://poj.org/problem?id=3013 看似生成树,实则最短路,可以将题意转化为点权*根到此点的边权和(最短路使其最小). 代码如下: #include<iostre ...
- javascript 中的深复制 和 其实现方法
首先,我们需要明白什么是深复制(侧重指对象方面)? 在javascript中,复制分为浅复制和深复制,个人理解,浅复制就是直接将引用复制,复制前后的两个对象指向同一个内存地址,对其中一个进行操作,另外 ...