是否存在任何真实的Web服务,就Fielding的论文(内容协商,超媒体等)而言,它实际上是100%RESTful.我希望更好地掌握REST,并且需要从Restfulie等自动客户端使用的东西.到目前为止我声称是RESTful的所有东西似乎都是RPC或HTTP CRUD.
有没有人有任何使用SailsJS实现HTML5超媒体(HATEOAS)API的好例子,或者这甚至是个好主意?如果没有,为什么不呢?
我目前正在设计一种纯粹面向资源的企业服务.在阅读了几个博客,书籍等之后,我相信REST与超媒体链接是可行的方法.
但是,所有这些博客和书籍都说的一件事是在响应中使用超媒体链接时不使用application/xml作为媒体类型.他们都没有说明为什么除了通用语句之外 - 没有链接关系类型的普通URI不会将URI的语义传达给客户端.
根据我的理解,这是一种推荐的方法来定义您自己的自定义媒体类型,并使客户端知道如何阅读它.但是,如果知道连接到我的服务的客户端永远不会是浏览器,那重要吗?我不能只在application/xml类型的响应中公开这些链接吗?
我希望这里有人可以详细说明这一点.
我正在尝试找出在单页面应用程序中处理权限的正确方法,该应用程序直接与几个实现HATEOAS的RESTful API对话.
举个例子:
"作为我的应用程序的用户,我可以查看,启动和暂停作业,但不能阻止它们."
基础rest API具有以下资源:
/ jobs/{id}接受GET和PUT.GET返回作业模型,PUT接受作业模型作为请求体:
{
"_links" : {
"self" : "/jobs/12345678"
}
"id" : 12345678,
"description" : "foo job",
"state" : "STOPPED"
}
Run Code Online (Sandbox Code Playgroud)
接受的工作状态可以是:休眠| 跑步| 暂停了| 停止.
要求说在UI上我必须有按钮:
开始,暂停,停止
...并且仅基于登录用户的权限进行显示.
从API的角度来看,一切都可以作为服务器上的底层逻辑,确保用户在发出请求时无法将状态更新为STOPPED状态(可能会返回401).
通知app/UI用户权限的最佳方法是什么,因此它可以隐藏用户无权操作的任何按钮?
如果API提供权限列表,可能类似于:
{
"_links" : {
"self" : "/permissions",
"jobs" : "/jobs"
}
"permissions" : {
"job" : ["UPDATE", "DELETE"],
"job-updates" : ["START", "PAUSE"]
}
}
Run Code Online (Sandbox Code Playgroud)
或者应该更改API以便权限反映在HATEOS链接中可能类似于:
{
"_links" : {
"self" : "/jobs/12345678",
"start" : "/jobs/12345678/state?to=RUNNING",
"pause" : "/jobs/12345678/state?to=PAUSED",
}
"id" : 12345678,
"description" …Run Code Online (Sandbox Code Playgroud) 我正在开发一个RESTful webservice,其中spring-data作为其数据访问层,由JPA/Hibernate支持.在域实体之间建立关系是很常见的.例如,设想一个实体Product,其具有一个Category实体.
现在,当在客户端POSTSA Product表示到JAX-RS方法.该方法@Transactional用于在事务中包装每个存储库操作进行注释.当然,客户端只发送id一个已经存在的Category,而不是整个表示,只是一个引用(外键).
在那种方法中,如果我这样做:
entity = repository.save(entity);
Run Code Online (Sandbox Code Playgroud)
变量entity现在Category只有id字段集.这并没有让我感到惊讶.我没想到要保存(SQL插入)来检索相关对象的信息.但我需要整个Product对象和相关实体能够返回给用户.
然后我这样做了:
entity = repository.save(entity);
entity = repository.findOne(entity.getId());
Run Code Online (Sandbox Code Playgroud)
也就是说,在持久化之后,在同一个事务/会话中检索对象.
令我惊讶的是,变量entity没有改变任何东西.实际上,数据库甚至没有获得单个选择查询.这与Hibernate的缓存有关.出于某种原因,当在同一事务中时,如果该对象先前已持久化,则查找不会检索整个对象图.
使用Hibernate,解决方案似乎是使用session.refresh(entity)(参见本节和此).说得通.
但是如何通过弹簧数据实现这一目标?
我想避免创建重复的自定义存储库.我认为这个功能应该是spring数据的一部分(有些人已经在spring数据论坛中报告过:thread1,thread2).
我正在尝试编写一个可以在 Golang 中接收不同自定义类型的辅助函数,但我不知道如何完全按照我想要的方式进行。情况是这样的(顺便说一下,我正在构建一个返回 JSON 对象的 API,它实现了 HAL 协议。这只是意味着资源和关系作为链接返回,而不是简单的 ID')。
我的应用程序中有许多模型,例如学生、校长、学校等……这些模型中的每一个都有许多领域,有些相同,有些不同。理想情况下,我想要一个可以遍历结构的字段并更改结构中的另一个字段的函数。最大的挑战是这些结构可以是学生、校长、学校等类型......
楷模:
type Person struct {
halgo.Links
Id bson.ObjectId
Firstname string
Lastname string
Email string
}
type Student struct {
Person `bson:",inline"`
School mgo.DBRef
}
type School struct {
Id bson.ObjectId
Address []string
Name string
Description string
}
Run Code Online (Sandbox Code Playgroud)
然后,我想要一个函数,它基本上可以采用这些结构中的任何一个,遍历字段(使用reflect),并对每个字段执行某些操作。
我试过一个函数,interface{}但问题是你必须对参数进行类型断言才能访问任何字段。即使有了它,您仍然必须为每种类型/模型编写单独的函数。:
func GenerateLinksHelper(m interface{}) {
...
}
Run Code Online (Sandbox Code Playgroud)
最终,我试图找到一种方法来编写一个函数,该函数接受一个有点任意的结构并对可能存在或不存在的字段执行操作。
我试过了:
@BeforeClass
public static void setUpClass() {
CurieProvider curieProvider = new DefaultCurieProvider("a", new UriTemplate("a{yey}"));
RelProvider relProvider = new DefaultRelProvider();
ObjectMapper halObjectMapper = JsonUtils.mapper;
halObjectMapper.registerModule(new Jackson2HalModule());
halObjectMapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider));
}
Run Code Online (Sandbox Code Playgroud)
但仍然出现错误:
03:26:25.936 [main] ERROR org.soluvas.json.JsonUtils - Cannot serialize id.co.bippo.product.rs.commerceplug.ProductOrServiceImpl as JSON
com.fasterxml.jackson.databind.JsonMappingException: Class org.springframework.hateoas.hal.Jackson2HalModule$HalLinkListSerializer has no default (no arg) constructor
at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1042) ~[jackson-databind-2.4.3.jar:2.4.3]
at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:445) ~[jackson-databind-2.4.3.jar:2.4.3]
at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:599) ~[jackson-databind-2.4.3.jar:2.4.3]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:92) ~[jackson-databind-2.4.3.jar:2.4.3]
at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:800) ~[jackson-databind-2.4.3.jar:2.4.3]
at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:676) ~[jackson-databind-2.4.3.jar:2.4.3]
at org.soluvas.json.JsonUtils.asJson(JsonUtils.java:54) ~[classes/:na]
at id.co.bippo.product.rs.commerceplug.ProductOrServiceImplTest.productOrService(ProductOrServiceImplTest.java:41) [test-classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_20]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_20] …Run Code Online (Sandbox Code Playgroud) 我们正在寻找关于在由HATEOAS REST API支持的Web应用程序中处理URL(以及与每个URL相关的状态)的一些建议,更具体地说是
但是,首先让我提供更多背景信息:
我们正在使用超媒体约束的REST层之上构建一个Angular Web应用程序.(注意:我更喜欢在HATEOAS上使用术语'超媒体(约束)').
根据超媒体约束的规定,REST API会在任何时间点提供应用程序中的可用操作和链接.因此,Web应用程序不应包含REST API的任何硬编码URL,除了"root"(假设概念确实存在于REST API中).
另一方面,Web应用程序中的每个页面都需要是可收藏的.因此,我们无法创建一个黑盒应用程序(使用单个URL并在SPA中处理所有状态更改而不更改URL).这意味着Web应用程序还具有其URL空间,该空间需要以某种方式映射到REST API URL空间.这已经与超媒体理念发生冲突.
在Angular应用程序中,我们使用UI路由器来处理应用程序状态.以下是我们如何运作:
到目前为止这么好(或不是真的),因为这种方法有一些缺点:
因此,我们希望听到一些关于我们如何改进处理两个URL空间的方法的建议.是否有更好的方法使REST API指示Web应用程序的(可用)行为,并且仍然在Web应用程序中具有可收藏的URL?因为现在我们有某种混合方法,感觉不完全正确.
提前致谢.
问候,
吕克
有很多超媒体可用于 Restful api。我不确定哪一个适合哪种情况。这是我第一次尝试 Restful api,所以我无法预见使用它的问题和优势。我想要的是可以查询并且还支持批量(特别是对于 GET 请求)。
Odata 似乎功能齐全,也是绿洲标准,但对我来说似乎有点过分了。其查询能力灵活但复杂。更重要的是,没有任何 odata 4 的 php 实现。如果我使用它,我需要自己做。我现在正在努力避免这种情况。
哈尔似乎太简单了,无法做任何事情。
集合+json看起来不错。但貌似不具备任何批量操作能力
jsonapi:看起来很简单。兼具查询能力和批量操作(带扩展)。但不支持GET请求的批量操作。也处于稳定状态。但我还找不到任何关于它的评论。
您对此有什么经验?我应该如何在其中选择超媒体?任何见解都会有所帮助。我还想听听除此之外的任何其他超媒体。
目前我对 json-api 和 collection+json 感到困惑。
想象一下,REST端点(/employees)以JSON HAL格式提供员工页面.一名员工住在一个居住在非洲大陆的国家.
对于国家和大陆而言,也有单独的端点.
返回的页面包含_embedded具有员工数据的典型字段.员工资源还包含嵌套country资源.这个嵌套country资源也包含_links.
在这种情况下,输出将是:
GET /employees
{
"_embedded": {
"employees": [{
"employee_id": 1
"name": "Mr. X",
"place_name": "London",
"country": {
"alpha2_code": "AU",
"name": "Australia",
"continent": {
"code": "OC",
"name": "Australia",
"_links": {
"self": {
"href": "http://localhost:8077/continents/au"
}
}
},
"_links": {
"self": {
"href": "http://localhost:8077/countries/au"
}
}
},
"_links": {
"self": {
"href": "http://localhost:8077/employees/1"
}
}
},
{
..
}
]
},
"_links": {
"first": {
"href": "http://localhost:8077/employees?page=1&size=10"
}, …Run Code Online (Sandbox Code Playgroud) hypermedia ×10
rest ×8
hateoas ×4
api ×2
java ×2
angularjs ×1
go ×1
hal ×1
html5 ×1
inheritance ×1
jpa ×1
json ×1
json-api ×1
odata ×1
reflection ×1
sails.js ×1
spring ×1
web-services ×1