Spring Data Rest / Spring Hateoas自定义控制器-PersistentEntityResourceAssembler


问题内容

我正在尝试从RepositoryRestResource向自动生成的端点添加一些其他业务逻辑。请参见下面的代码:

资源:

@RepositoryRestResource(collectionResourceRel="event", path="event")
public interface EventRepository extends PagingAndSortingRepository<Event, Long> {

}

控制器:

@RepositoryRestController
@RequestMapping(value = "/event")
public class EventController {

  @Autowired
  private EventRepository eventRepository;

  @Autowired
  private PagedResourcesAssembler<Event> pagedResourcesAssembler;

  @RequestMapping(method = RequestMethod.GET, value = "")
  @ResponseBody
  public PagedResources<PersistentEntityResource> getEvents(Pageable pageable,
      PersistentEntityResourceAssembler persistentEntityResourceAssembler) {

    Page<Event> events = eventRepository.findAll(pageable);

    return pagedResourcesAssembler.toResource(events, persistentEntityResourceAssembler);
  }
}

我感觉自己已经接近了,但是我面临的问题是:

return pagedResourcesAssembler.toResource(events, persistentEntityResourceAssembler);

返回错误信息:

"The method toResource(Page<Event>, Link) in the type PagedResourcesAssembler<Event> is not applicable 
 for the arguments (Page<Event>, PersistentEntityResourceAssembler)".

toResource方法具有一个接受ResourceAssembler的方法签名,但是我不确定如何正确实现此方法,因此找不到任何文档。

在此先感谢,-Brian

编辑

我的问题是,我认为我可以覆盖通过@RepositoryRestResource注释自动创建的控制器方法,而不必创建自己的资源和资源汇编器。创建资源和资源汇编器后,我可以将业务逻辑添加到端点。

资源:

public class EventResource extends ResourceSupport {
  private String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}

资源汇编器:

@Component
public class EventResourceAssembler extends ResourceAssemblerSupport<Event, EventResource> {

  public EventResourceAssembler() {
    super(EventController.class, EventResource.class);
  }

  @Override
  public EventResource toResource(Event entity) {
    EventResource eventResource = createResourceWithId(entity.getId(), entity);
    eventResource.setName(entity.getName());
    return eventResource;
  }
}

更新的控制器:

@RepositoryRestController
@RequestMapping(value = "/event")
public class EventController {

  @Autowired
  private EventRepository eventRepository;

  @Autowired
  private EventResourceAssembler eventResourceAssembler;

  @Autowired
  private PagedResourcesAssembler<Event> pageAssembler;

  @RequestMapping(method = RequestMethod.GET, value = "")
  @ResponseBody
  public PagedResources<EventResource> getEvents(Pageable pageable) {
    Page<Event> events = eventRepository.findAll(pageable);

    // business logic

    return pageAssembler.toResource(events, eventResourceAssembler);
  }
}

我对此不喜欢的事情是,它似乎无法实现拥有RepositoryRestResource的目的。另一种方法是使用在创建,保存,删除操作之前和/或之后调用的事件处理程序。

@RepositoryEventHandler(Event.class)
public class EventRepositoryEventHandler {

  @HandleBeforeCreate
  private void handleEventCreate(Event event) {
    System.out.println("1");
  }
}

findAll或findOne操作似乎没有任何事件。无论如何,这两种方法似乎都解决了我从RepositoryRestResource扩展自动生成的控制器方法的问题。


问题答案:

它需要一个PagedResourcesAssembler,如果您需要,Spring会为您注入一个。

public PagedResources<Foo> get(Pageable page, PagedResourcesAssembler<Foo> assembler) {
    // ...
}

在这种情况下,资源为Foo。在您的情况下,您似乎要返回的资源是Event。如果是这样,我希望您的代码看起来像这样:

private ResourceAssembler<Event> eventAssembler = ...;
public PagedResources<Event> get(Pageable page, PagedResourcesAssembler<Event> pageAssembler) {
    Event event = ...;
    return eventAssembler.toResource(event, pageAssembler);
}

您提供的内容ResourceAssembler<Event>可以告诉Spring如何Event变成Resource。Spring将注入PagedResourcesAssembler<Event>到控制器方法中以处理分页链接。通过调用toResource并传入注入将它们组合在一起pageAssembler

最终结果可以像上面一样简单地作为主体返回。您还可以使用类似的方法HttpEntity来更好地控制状态代码和标头。

注意:ResourceAssembler您提供的字面上实际上可以像EventResource对象包装资源一样简单。通常,您将需要添加任何相关链接。