使用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 {

    @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"
      }
    }
  ]
}

使用

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);
    }

    @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://www.javacodegeeks.com/2015/01/building-a-hateoas-api-with-jax-rs-and-spring.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值