使用JAX-RS和Spring构建HATEOAS API

在我以前的博客文章中,我展示了如何使用Spring Boot配置Jersey多么容易。 我对Spring Boot和Jersey的探索并没有结束,我研究了在Spring Boot应用程序中将Spring HATEOAS和Jersey一起使用的可能性。 Spring HATEOS允许创建遵循HATEOAS原理的REST表示形式,并且(截至撰写本文时)具有使用链接的基本JAX-RS支持。 在这篇博客中,我将分享一些示例,说明如何将Spring HATEOAS与Jersey集成到Spring Boot应用程序中。

介绍

作为本文的基础,我使用了之前创建的示例:( https://github.com/kolorobot/spring-boot-jersey-demo )。

为了开始使用Spring HATEOAS,我在build.gradle中添加了有效的依赖build.gradle

compile("org.springframework.hateoas:spring-hateoas:0.16.0.RELEASE")

使用

生成实体对象( Customer )表示的最快方法是使用Spring HATEOAS ResourceResources助手。 后者包装了CustomerRepository返回的实体的集合。 为了生成链接,我使用了JaxRsLinkBuilder ,它通过基于@Path注释发现路径来帮助构建到JAX-RS资源的资源链接。

@Component
@Path("/customer")
@Produces(MediaType.APPLICATION_JSON)
public class CustomerController {@Injectprivate CustomerRepository customerRepository;@GETpublic Response findAll() {Resources<Customer> resources = new Resources<>(customerRepository.findAll(),JaxRsLinkBuilder.linkTo(CustomerController.class).withSelfRel());return Response.ok(resources).build();}

调用上述方法的结果将是带有自相关链接的收集资源:

{"links": [{"rel": "self","href": "http://localhost:8080/customer"}],"content": [{"id": 1,"firstname": "Dave","lastname": "Matthews","emailAddress": {"value": "dave@dmband.com"}}]
}

使用

ResourceResourcesPagedResources帮助器非常方便,但是在某些情况下,需要对创建的资源进行更多控制。

要从实体创建自定义传输对象,可以使用ResourceSupport基类:

public class CustomerResource extends ResourceSupport {private String fullName;private String email;}

要从实体组装CustomerResource并自动向其添加自相关链接,应使用ResourceAssemblerSupport类。 基本上,此类负责实例化资源并添加具有rel自指向该资源的链接:

public class CustomerResourceAssembler extends ResourceAssemblerSupport<Customer, CustomerResource> {public CustomerResourceAssembler() {super(CustomerController.class, CustomerResource.class);}@Overridepublic CustomerResource toResource(Customer entity) {CustomerResource resource = createResourceWithId(entity.getId(),entity);// initialize the resource        return resource;}
}

我在上面的代码中遇到的问题是ResourceAssemblerSupport类在内部使用链接构建器来构建到Spring MVC控制器( ControllerLinkBuilder )的链接。 这导致链接无效。

除了创建从ResourceAssemblerSupport扩展并覆盖其父级行为的新支持类外,我没有发现其他方法:

public abstract class JaxRsResourceAssemblerSupport<T, D extends ResourceSupport>extends ResourceAssemblerSupport<T, D> {private final Class<?> controllerClass;public JaxRsResourceAssemblerSupport(Class<?> controllerClass, Class<D> resourceType) {super(controllerClass, resourceType);this.controllerClass = controllerClass;}@Overrideprotected D createResourceWithId(Object id, T entity, Object... parameters) {Assert.notNull(entity);Assert.notNull(id);D instance = instantiateResource(entity);instance.add(JaxRsLinkBuilder.linkTo(controllerClass, parameters).slash(id).withSelfRel());return instance;}
}

我真的不喜欢上面的解决方案,因为我需要复制和粘贴一些代码,但是我没有找到实现我想要的更好的方法。

我的汇编器现在从新创建的JaxRsResourceAssemblerSupport

public class CustomerResourceAssembler extends JaxRsResourceAssemblerSupport<Customer, CustomerResource> {}

最后,我可以修改控制器的方法以返回由我的汇编器汇编的资源。 请注意, ResourceAssemblerSupport提供了方便的方法来将所有给定的实体转换为资源:

@GET
@Path("/resources")
public Response findAll() {Iterable<Customer> customers = customerRepository.findAll();CustomerResourceAssembler assembler = new CustomerResourceAssembler();List<CustomerResource> resources = assembler.toResources(customers);return Response.ok(wrapped).build();
}

要添加具有自相关链接的集合资源链接,我需要使用前面提到的Resources类包装它:

// wrap to add link
Resources<CustomerResource> wrapped = new Resources<>(resources);
wrapped.add(JaxRsLinkBuilder.linkTo(CustomerController.class).withSelfRel()
);

现在返回的表示看起来更像是HATEOAS:

{"links": [{"rel": "self","href": "http://localhost:8080/customer"}],"content": [{"fullName": "Matthews, Dave","email": "dave@dmband.com","links": [{"rel": "self","href": "http://localhost:8080/customer/1"}]}]
}

使用

EntityLinks接口提供API以根据实体类型创建链接,并且@EnableEntityLinks@EnableHypermadiaSupport@ExposesResourceFor一起使用时,可用于依赖项注入。 @ExposesResourceFor公开Spring MVC控制器或JAX-RS资源管理的实体类型。

在配置类中,我们需要激活实体链接:

@SpringBootApplication
@EnableEntityLinks
public class Application {}

注意:请注意,使用实体链接和@EnableEntityLinks ,以下依赖项必须位于类路径上:

compile("org.springframework.plugin:spring-plugin-core:1.1.0.RELEASE")

任何支持实体类型的JAX-RS资源都必须使用@ExposesResourceFor进行标记,以便可以注入EntityLinks

@ExposesResourceFor(Customer.class)
public class CustomerController {@Injectprivate EntityLinks entityLinks;
}

基本上, EntityLinks接口提供了返回链接到集合资源或单个资源的方法。 例:

Link selfRel = entityLinks.linkToSingleResource(Customer.class, customer.getId()
).withSelfRel();

摘要

Spring HATEOAS不是使用JAX-RS和Jersey构建HATEOAS API的唯一选择,但是有可能在Spring Boot应用程序中使用Jersey,Spring HATEOAS可能是不错的补充,尤其是考虑到JAX-RS的设计。

注意:本文只是我针对所述主题进行的一项研究。 我尚未在任何项目中使用该方法。

资源资源

  • 项目源代码: https : //github.com/kolorobot/spring-boot-jersey-demo
  • SpringHATEOAS项目页面: https : //github.com/spring-projects/spring-hateoas和示例: https : //github.com/olivergierke/spring-hateoas-sample

翻译自: https://www.javacodegeeks.com/2015/01/building-a-hateoas-api-with-jax-rs-and-spring.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360968.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业中的微服务:敌是友?

宏观问题的微观解决方法&#xff1f; 微服务的炒作无处不在&#xff0c;尽管业界似乎无法就确切的定义达成共识&#xff0c;但我们一再被告知&#xff0c;从单一应用程序转向由小型服务组成的面向服务的架构&#xff08;SOA&#xff09;是正确的方法。构建和发展软件系统。 但是…

自定义百度地图气泡

自定义百度地图气泡 http://www.cnblogs.com/jz1108/archive/2011/09/15/2152122.html 转载于:https://www.cnblogs.com/ygm900/archive/2013/02/26/2933000.html

使用Bean验证扩展PrimeFaces CSV

你们中有些人已经知道我和我的合著者Mertalışkan正在研究PrimeFaces Cookbook的2.版。 Packt Publishing允许我从新章节“客户端验证”的一个食谱中摘录一小部分摘录。 这将有助于使读者知道这本书的内容。 在此博客文章中&#xff0c;我想讨论使用Bean验证扩展的PrimeFaces客…

ASP.NET.CORE发布后启动网站出现500.19-0x8007000d错误解决方法

本项目使用的是netcoreapp2.2&#xff0c;缺少的XML文件是swagger。发布采用的是文件系统、依赖框架。 我第一次发布asp.net.core的后台&#xff0c;发布后启动网站出现500.19错误-0x8007000d。百度查了一下原因&#xff0c;2其中大多数人说是因为没有权限&#xff0c;需要编辑…

Java持久性锁定初学者指南

隐式锁定 在并发理论中&#xff0c;锁定用于保护可变共享数据免受危险数据完整性异常的影响。 因为锁管理是一个非常复杂的问题&#xff0c;所以大多数应用程序都依赖于其数据提供程序隐式锁定技术。 将整个锁定职责委托给数据库系统既可以简化应用程序开发&#xff0c;又可以…

负载均衡的集中实现方式

1&#xff0c; 软件 &#xff08;安装第三方软件做双机&#xff0c;缺点是切换速度&#xff0c;以及故障转移会有问题&#xff09;2&#xff0c; 硬件&#xff08;采用第三方硬件设备&#xff0c;缺点是费用贵&#xff09;3&#xff0c; DNS&#xff08;价格最便宜&#xff0c;…

uni-app之新建项目无模板选择以及点击创建后一直卡住不动

uni-app&#xff1a;新建项目无模板选择以及点击创建后一直卡住不动 原因&#xff1a;无权限 解决方法&#xff1a;退出HBuilderX&#xff0c;然后以管理员身份启动HBuilderX.exe。解决问题

WildFly和Docker上的Java EE 7动手实验室

Java EE 7动手实验室已在全球范围内交付&#xff0c;它是一个非常标准的应用程序&#xff0c;显示了典型Java EE 7应用程序的设计模式和反模式。 它显示了如何在接近现实的应用程序中使用以下技术&#xff1a; WebSocket 1.0 JSON处理1.0 批次1.0 上下文和依赖注入1.1 Jav…

JSONP跨域的原理解析

转自 http://www.nowamagic.net/librarys/veda/detail/224 JavaScript是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中&#xff0c;有一个很重要的安全性限制&#xff0c;被称为“Same-Origin Policy”&#xff08;同源策略&#xff09;。这一策略对于JavaScript…

uni-app运行编译报错

uni-app运行编译失败&#xff1b; 原因&#xff1a;安装目录问题 解决方案&#xff1a;将下载的安装包放在英文目录下&#xff0c;路径中不要出现中文

一罐将其全部统治:Arquillian + Java 8

借助Java 8 &#xff0c;已实现了许多新的语言改进&#xff0c;以简化开发人员的生活。 在我看来&#xff0c; Java 8的最大优点之一是&#xff0c;在某些情况下&#xff0c;已开发的代码看起来比使用以前的方法更漂亮&#xff0c;我指的是Lambdas和Method引用。 这篇文章不是要…

Gentoo使用sudo

安装app-admin/sudo包 emerge sudo 设置环境变量EDITOR echo EDITOR\"/usr/bin/vim\" >/etc/env.d/99editor env-update 然后注销重新登陆编辑sudo配置文件/etc/sudoer&#xff0c;启用wheel组特权&#xff0c;/etc/sudoer不能用编辑器直接编辑&#xff0c;只能使…

uni-app引入阿里巴巴矢量库图标后,顶部导航栏显示小方块

引入阿里巴巴矢量图标库 首先在阿里巴巴创建项目&#xff0c;拥有图标 具体引入方法参考&#xff1a; [https://blog.csdn.net/Dream_Weave/article/details/88550978?depth_1-utm_sourcedistribute.pc_relevant.none-task&utm_sourcedistribute.pc_relevant.none-task]在…

使用Spring Integration进行消息处理

Spring Integration提供了Spring框架的扩展&#xff0c;以支持著名的企业集成模式。 它在基于Spring的应用程序中启用轻量级消息传递&#xff0c;并支持与外部系统的集成。 Spring Integration的最重要目标之一是为构建可维护且可测试的企业集成解决方案提供一个简单的模型。 …

mysql中的字段类型

Mysql中的字段类型 MySQL支持大量的列类型&#xff0c;它可以被分为3类&#xff1a;数字类型、日期和时间类型以及字符串(字符)类型。本节首先给出可用类型的一个概述&#xff0c;并且总结每个列类型的存储需求&#xff0c;然后提供每个类中的类型性质的更详细的描述。概述有意…

js 编码

编码 let url encodeURIComponent(this.url);

使用RxNetty访问Meetup的流API

本文将涉及多个主题&#xff1a;响应式编程&#xff0c;HTTP&#xff0c;解析JSON以及与社交API集成。 完全在一个用例中&#xff1a;我们将通过非夸张的RxNetty库实时加载和处理新的metup.com事件&#xff0c;结合Netty框架的强大功能和RxJava库的灵活性。 Meetup提供了公开可…

SQL Server 2005/2008 导入导出数据常见报错

数据库导入导出时总失败&#xff0c;错误信息如下&#xff1a; 正在验证 (错误) 消息 错误 0xc0202049: 数据流任务 1: 无法在只读列“ID”中插入数据。 (SQL Server 导入和导出向导) 错误 0xc0202045: 数据流任务 1: 验证列元数据失败。 (SQL Server 导入和导出向导) 错…

js、react对象名和对象属性赋值

const resValue {}; resValue[standards${standardsNumber}] ""; Console.log(:test"&#xff0c;resValue )//

TIBCO产品的微服务和DevOps

如今&#xff0c;每个人都在谈论微服务。 您可以在数百篇文章和博客文章中读到很多有关微服务的信息。 马丁福勒 &#xff08; Martin Fowler &#xff09;的文章是一个很好的起点&#xff0c;该文章引发了有关这种新架构概念的大量讨论。 另一个很棒的资源是独立于供应商的分…