SpringBoot 2 构建 REST 服务 - 简化链接创建过程

我们是否注意到在创建单个雇员链接时的重复?两次显示了提供指向雇员的单个链接以及指向聚合根的 “雇员” 的链接的代码。如果那引起我们的关注,那就好!有一个解决方案。

简而言之,我们需要定义一个将 Employee 对象转换为 EntityModel<Employee> 对象的函数。尽管我们可以自己轻松地编写该方法,但在实现 Spring HATEOAS 的 RepresentationModelAssember 接口的过程中会有很多好处。

evolution/src/main/java/payroll/EmployeeResourceAssembler.java

package payroll;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;

import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.server.RepresentationModelAssembler;
import org.springframework.stereotype.Component;

@Component
class EmployeeModelAssembler implements RepresentationModelAssembler<Employee, EntityModel<Employee>> {

  @Override
  public EntityModel<Employee> toModel(Employee employee) {

    return new EntityModel<>(employee,
      linkTo(methodOn(EmployeeController.class).one(employee.getId())).withSelfRel(),
      linkTo(methodOn(EmployeeController.class).all()).withRel("employees"));
  }
}

该简单的接口有一个方法:toModel()。它基于将非资源对象(Employee)转换为基于资源的对象(EntityModel<Employee>)。

我们之前在控制器中看到的所有代码都可以移入该类。通过应用 Spring 框架的 @Component,该组件将在应用启动时自动创建。

Spring HATEOAS 针对所有资源的抽象基类是 RepresentationModel。但是为简单起见,教程建议使用 EntityModel<T> 作为我们的机制来轻松包装所有 POJO 作为资源。

要利用该组装器,只需要将其注入 EmployeeController 的构造器中即可对其进行变更。

将 EmployeeResourceAssembler 注入控制器。

@RestController
class EmployeeController {

  private final EmployeeRepository repository;

  private final EmployeeModelAssembler assembler;

  EmployeeController(EmployeeRepository repository,
             EmployeeModelAssembler assembler) {

    this.repository = repository;
    this.assembler = assembler;
  }

  ...

}

在这里,我们可以在单项雇员方法中使用它:

使用组装器获取单项资源。

@GetMapping("/employees/{id}")
EntityModel<Employee> one(@PathVariable Long id) {

  Employee employee = repository.findById(id)
    .orElseThrow(() -> new EmployeeNotFoundException(id));

  return assembler.toModel(employee);
}

该段代码几乎是相同的,除了我们不是在这里创建 EntityModel<Employee> 示例,而是将其委托给了组装器。也许看起来不多?

在聚合根控制器方法中应用相同的内容会更加令人印象深刻:

使用组装器获取聚合根资源。

@GetMapping("/employees")
CollectionModel<EntityModel<Employee>> all() {

  List<EntityModel<Employee>> employees = repository.findAll().stream()
    .map(assembler::toModel)
    .collect(Collectors.toList());

  return new CollectionModel<>(employees,
    linkTo(methodOn(EmployeeController.class).all()).withSelfRel());
}

再次,代码几乎相同,但是我们可以将所有 EntityModel<Employee> 创建逻辑替换为 map(assembler::toModel)。借助 Java 8 方法引用,可以非常轻松地将其插入并简化我们的控制器。

Spring HATEOAS 的主要涉及目标是使做 “The Right Thing™” 变得容易。在该情况下,无需对事物进行硬编码即可将超媒体添加到我们的服务器中。

在该阶段,我们已经创建了一个 Spring MVC REST 控制器,该控制器实际上可以生成超媒体支持的内容!不使用 HAL 的客户端在使用纯数据时可以忽略多余的比特。会 HAL 的客户端可以浏览我们的授权 API。

但这并不是用 Spring 构建真正 RESTful 服务的唯一方式。

发布了232 篇原创文章 · 获赞 14 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/stevenchen1989/article/details/105586569