在我以前的博客文章中,我展示了如何使用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 Resource
和Resources
助手。 后者包装了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"}}]
}
使用
Resource
, Resources
, PagedResources
帮助器非常方便,但是在某些情况下,需要对创建的资源进行更多控制。
要从实体创建自定义传输对象,可以使用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