【问题标题】:Spring Data Rest / Spring Hateoas Custom Controller - PersistentEntityResourceAssemblerSpring Data Rest / Spring Hateoas 自定义控制器 - PersistentEntityResourceAssembler
【发布时间】:2016-02-07 21:40:00
【问题描述】:

我正在尝试从 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);
  }
}

我看过以下两篇 stackoverflow 文章:

我觉得我很接近,但我面临的问题是:

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

提前致谢, - 布赖恩

编辑

我的问题是我认为我可以覆盖从 @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 扩展自动生成的控制器方法的问题。

【问题讨论】:

标签: java spring spring-mvc spring-data-rest spring-hateoas


【解决方案1】:

要破解它,您可以使用 PagedResourcesAssembler&lt;Object&gt; 像:

@RequestMapping(method = RequestMethod.GET, value = "")
@ResponseBody
public PagedModel<PersistentEntityResource> getEvents(
    Pageable pageable,
    PersistentEntityResourceAssembler persistentAssembler,
    PagedResourcesAssembler<Object> pageableAssembler
) {
    return pageableAssembler.toModel(
        (Page<Object>) repository.findAll(pageable),
        persistentAssembler
    );
  }

【讨论】:

    【解决方案2】:

    它需要一个 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&lt;Event&gt;,告诉Spring 如何将Event 转换为Resource。 Spring 将PagedResourcesAssembler&lt;Event&gt; 注入到您的控制器方法中以处理分页链接。通过调用toResource 并传入注入的pageAssembler 来组合它们。

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

    注意:您提供的ResourceAssembler 实际上可以像用Resource 对象包装资源一样简单,例如Event。不过,通常您会希望添加任何相关链接。

    【讨论】:

    • 感谢您的回复。我认为也许可以覆盖 RepositoryRestResource 注释中自动生成的端点,而无需创建 EventResource 和 EventResourceAssembler。认为最好的解决方案可能是使用带有 RepositoryEventHandler 注释的类并使用 REST 导出器发出的事件。这样我就不必接触我的 EventRepository,我可以将我的业务逻辑添加到这些端点。
    猜你喜欢
    • 2015-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 2014-03-07
    • 1970-01-01
    • 2014-12-19
    • 2015-12-27
    相关资源
    最近更新 更多