几个星期前几个月前,我正在寻找如何为Oracle Cloud项目设计新的REST API。 我计划要做的事情之一就是使用Marc Hadley在Jersey 1.x中创建的声明性链接注入。 可悲的是这并没有被转发移植然而,这样一个快速的聊天项目带动和我承担了使代码最新的小中型工作。
新版本中发生的更改之一是,在JAX-RS 2.0中,存在一个Link
对象,因此除了只能注入String和URI之外,还可以注入正确的rel属性。 这意味着,由Marc编码的现有注释已合并到用于Link标头和注入属性的简单注释集中。
现在可以使用此功能以及一个简单的示例。 我提交的功能的原始版本有一些严重的限制,稍后将进行介绍,您将需要版本2.8的Jersey Jersey,或者可以构建包含当前更改的2.9-SNAPSHOT映像以实现此博客中的示例。
该博客着眼于使用这个新的API为collections API提供简单的注入。 RESTful服务(尤其是基于JSON的服务)中的常见模式之一是在结构的顶层具有一系列结构链接。 就本博客而言,我将遵循Collection + JSON超媒体类型的形式。
{ "collection" :{"version" : "1.0","href" : "http://example.org/friends/?offset=10&limit=10","links" : [{"rel" : "create", "href" : "http://example.org/friends/"}{"rel" : "next", "href" : "http://example.org/friends/?offset=20&limit=10"}{"rel" : "previous", "href" : "http://example.org/friends/?offset=0&limit=10"}],"items" : [...]}
}
因此,我可以按以下形式插入链接,为清楚起见,这里没有一堆锅炉板。 这不是最整齐的代码; 但在以后的周期中,应该可以对它们进行一些简单的设置。 该设计当前使用EL来访问属性-这样做的优点是可以在表示属性时写回值。 我可以理解有些人不喜欢它。 但我不确定目前是否可以转向JavaScript。 也不要被@Xml注释所代替,我使用MOXy进行JSON生成–这不是XML唯一的事情。
{@XmlTransientprivate int limit, offset; // Getters for these@XmlTransientprivate int modelLimit; // Getters for these@InjectLink(resource = ItemsResource.class,method = "query",style = Style.ABSOLUTE,bindings = {@Binding(name = "offset", value="${instance.offset}"),@Binding(name = "limit", value="${instance.limit}")},rel = "self")@XmlElement(name="link")private String href;@InjectLinks({@InjectLink(resource = ItemsResource.class,style = Style.ABSOLUTE,method = "query",condition = "${instance.offset + instance.limit < instance.modelLimit}",bindings = {@Binding(name = "offset", value = "${instance.offset + instance.limit}"),@Binding(name = "limit", value = "${instance.limit}")},rel = "next"),@InjectLink(resource = ItemsResource.class,style = Style.ABSOLUTE,method = "query",condition = "${instance.offset - instance.limit >= 0}",bindings = {@Binding(name = "offset", value = "${instance.offset - instance.limit}"),@Binding(name = "limit", value = "${instance.limit}")},rel = "prev")})@XmlElement(name="link")@XmlElementWrapper(name = "links")@XmlJavaTypeAdapter(Link.JaxbAdapter.class)List<Link> links;....
}
声明性链接代码的原始移植存在于2.8之前的Jersey版本中,它具有很幼稚的代码,可以计算出特定资源的URI应该是什么,它不能处理不在应用程序根目录下的任何资源。 ,也无法应付在处理集合时非常重要的查询参数。
从理论上讲,一个特定的资源类可以有多个URI。 但是此代码确实需要假设1:1映射,当前的实现包含一个简单的算法,该算法会遍历Jersey元模型以尝试计算结构,这对您不起作用,您可以简单地提供另一个实现ResourceMappingContext 。
有人可能会问,当我自己注入URI更容易时,为什么应该使用这些丑陋的注释? 原因是提供其他工具可以使用的元数据。 我的下一个工作之一是扩展这项工作以生成超媒体扩展,为此,我需要上面的元数据。 (等待拉动请求在我真正加入之前得到批准)。
最后,值得注意的是,分页模型有其自身的问题,如果您将REST集合视为可以安全地分页的某种数组,则这些问题就变得显而易见。 并发更新以及缺少状态意味着客户端永远无法确定自己拥有完整的模型,并且应该期望在更新模型时多次看到某些项目。 应该考虑使用基于游标或链接的方案,这再次提醒了您为什么总是将URI视为不透明–服务器将来可能需要更改其结构。 但这是另一天完全不同的博客…..
翻译自: https://www.javacodegeeks.com/2014/05/declarative-linking-in-jersey-2-9-and-up.html