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

问题描述:

我正在尝试从RepositoryRestResource向自动生成的端点添加一些额外的业务逻辑。请参阅以下代码:

I'm attempting to add some additional business logic to the auto-generated endpoints from the RepositoryRestResource. Please see the code below:

资源:

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

我查看了以下两篇stackoverflow文章:

I've looked at the following two stackoverflow articles:

  • Can I make a custom controller mirror the formatting of Spring-Data-Rest / Spring-Hateoas generated classes?
  • Enable HAL serialization in Spring Boot for custom controller method

我觉得我很亲密,但我面临的问题是这样的:

I feel like I am close, but the problem that I am facing is that:

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的方法签名,但我不确定如何正确实现这一点,我找不到任何关于此事的文件。

The toResource method has a method signature that accepts a ResourceAssembler, but I'm not sure how to properly implement this and I can't find any documentation on the matter.

提前致谢,
- Brian

Thanks in advance, - Brian

编辑

我的问题是我认为我可以覆盖从 @RepositoryRestResource 注释,无需创建自己的资源和资源汇编程序。创建资源和资源汇编程序后,我能够将业务逻辑添加到端点。

My issue was that I thought I could override the controller methods that are auto-created from @RepositoryRestResource annotation without having to create my own resource and resource assembler. After creating the resource and resource assembler I was able to add my business logic to the endpoint.

资源:

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的目的。另一种方法是使用在创建,保存,删除操作之前和/或之后调用的事件处理程序。

The thing I don't like about this is that it seems to defeat the purpose of having a RepositoryRestResource. The other approach would be to use event handlers that would get called before and/or after the create, save, delete operations.

@RepositoryEventHandler(Event.class)
public class EventRepositoryEventHandler {

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

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

There doesn't seem to be any events for the findAll or findOne operations. Anyways, both these approaches seem to solve my problem of extending the auto generated controller methods from RepositoryRestResource.

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

It requires a PagedResourcesAssembler, Spring will inject one for you if you ask.

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

在这种情况下,资源是 Foo 。在您的情况下,您尝试返回的资源似乎是事件。如果是这样,我希望你的代码看起来像:

In this case the resource is Foo. It seems in your case the resource you're trying to return is an Event. If that's so, I would expect your code to look something like:

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

您提供 ResourceAssembler< Event> 告诉Spring如何将 Event 转换为资源。 Spring将 PagedResourcesAssembler< Event> 注入到控制器方法中以处理分页链接。通过调用 toResource 并传入注入的 pageAssembler 来组合它们。

You provide the ResourceAssembler<Event> that tells Spring how to turn Event into a Resource. Spring injects the PagedResourcesAssembler<Event> into your controller method to handle the pagination links. Combine them by calling toResource and passing in the injected pageAssembler.

最终结果可以像上面一样简单地返回。您还可以使用 HttpEntity 之类的内容来获得对状态代码和标题的更多控制。

The final result can be returned simply as a body as above. You could also use things like HttpEntity to gain more control over status codes and headers.

注意: ResourceAssembler 可以简单地包装资源,例如 Event ,带有资源对象。通常,您会想要添加任何相关链接。

Note: The ResourceAssembler you provide can literally be something as simple as wrapping the resource, such as Event, with a Resource object. Generally you'll want to add any relevant links though.