jax-ws和jax-rs
在我以前的博客文章中,我展示了如何使用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
:
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 {
@Inject
private CustomerRepository customerRepository;
@GET
public 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);
}
@Override
public 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;
}
@Override
protected 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 {
@Inject
private 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
jax-ws和jax-rs