Spring 数据休息 / Spring Hateoas 自定义控制器 - PersistentEntityResourceAssembler
Spring Data Rest / Spring Hateoas Custom Controller - 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);
}
}
我看过以下两篇 Whosebug 文章:
- Can I make a custom controller mirror the formatting of Spring-Data-Rest / Spring-Hateoas generated classes?
我觉得我很接近,但我面临的问题是:
return pagedResourcesAssembler.toResource(events, persistentEntityResourceAssembler);
returns 错误提示:
"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 的目的。另一种方法是使用在创建、保存、删除操作之后 and/or 之前调用的事件处理程序。
@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
。在您的情况下,您尝试 return 的资源似乎是 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
.
来组合它们
最终结果可以像上面的 body 一样简单地 returned。您还可以使用 HttpEntity
之类的东西来更好地控制状态代码和 headers.
注意:您提供的 ResourceAssembler
字面上可以是简单的包装资源,例如 Event
,带有 Resource
object。不过,通常您会想要添加任何相关链接。
要破解它,您只需使用 PagedResourcesAssembler<Object>
,例如:
@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
);
}
我正在尝试向 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);
}
}
我看过以下两篇 Whosebug 文章:
- Can I make a custom controller mirror the formatting of Spring-Data-Rest / Spring-Hateoas generated classes?
我觉得我很接近,但我面临的问题是:
return pagedResourcesAssembler.toResource(events, persistentEntityResourceAssembler);
returns 错误提示:
"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 的目的。另一种方法是使用在创建、保存、删除操作之后 and/or 之前调用的事件处理程序。
@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
。在您的情况下,您尝试 return 的资源似乎是 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
.
最终结果可以像上面的 body 一样简单地 returned。您还可以使用 HttpEntity
之类的东西来更好地控制状态代码和 headers.
注意:您提供的 ResourceAssembler
字面上可以是简单的包装资源,例如 Event
,带有 Resource
object。不过,通常您会想要添加任何相关链接。
要破解它,您只需使用 PagedResourcesAssembler<Object>
,例如:
@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
);
}