当前位置: 首页 > 知识库问答 >
问题:

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

公冶渝
2023-03-14

我试图向RepositoryRestResource中自动生成的endpoint添加一些额外的业务逻辑。请参见下面的代码:

资源:

@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的文章:

  • 我可以让自定义控制器镜像Spring-Data-Rest / Spring-Hateoas生成的类的格式吗?
  • 在自定义控制器方法的 Spring Boot 中启用 HAL 序列化

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

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)".

toResources方法有一个接受ResourceAssembler的方法签名,但我不确定如何正确实现它,也找不到任何关于此事的留档。

提前感谢-布莱恩

编辑

我的问题是我认为我可以覆盖从@RepositoryRestResources注释自动创建的控制器方法,而无需创建我自己的资源和资源汇编器。创建资源和资源汇编器后,我能够将我的业务逻辑添加到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);
  }
}

我不喜欢的是,它似乎违背了拥有RepositoryRestResources的目的。另一种方法是使用在创建、保存、删除操作之前和/或之后调用的事件处理程序。

@RepositoryEventHandler(Event.class)
public class EventRepositoryEventHandler {

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

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

共有2个答案

陆弘光
2023-03-14

要破解它,你可以只使用PagedResourcesAssembler

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

简意
2023-03-14

它需要一个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);
}

您提供资源汇编程序

最终结果可以简单地作为上述主体返回。您还可以使用像 HttpEntity 这样的东西来更好地控制状态代码和标头。

注意:您提供的< code>ResourceAssembler实际上可以像用< code>Resource对象包装资源一样简单,比如< code>Event。一般来说,你会想要添加任何相关的链接。

 类似资料:
  • 控制器定义 ThinkCMF5的控制器完全按 TP5的控制器用法来,但 CMF 封装了几个重要控制器基类,为了更方便开发者,我们建议如果没有特殊需求,自己创建的控制器请最好继承一个基类控制器; 用于 WEB 项目的基类控制器有四个,分别是:BaseController,HomeBaseController,UserBaseController,AdminBaseController 继承关系 th

  • 控制器定义 ThinkCMF6.0的控制器完全按 TP6.0的控制器用法来,但 CMF 封装了几个重要控制器基类,为了更方便开发者,我们建议如果没有特殊需求,自己创建的控制器请最好继承一个基类控制器; 用于 WEB 项目的基类控制器有四个,分别是:BaseController,HomeBaseController,UserBaseController,AdminBaseController, Re

  • 控制器定义 控制器文件通常放在application/module/controller下面,类名和文件名保持大小写一致,并采用驼峰命名(首字母大写)。 一个典型的控制器类定义如下: <?php namespace app\index\controller; use think\Controller; class Index extends Controller { public fu

  • 我尝试用自定义控制器制作一个自定义组件。自定义组件已经显示在应用程序上,但我未能向其添加属性。 项目结构: null 布尔马尔科 完全错误: 原因:java.lang.nullPointerException:无法调用“javafx.scene.image.imageeview.setimage(javafx.scene.image.image)”,因为“controller.topbarbtn.

  • 自定义路由 easySwoole支持路由拦截。其路由利用fastRoute实现,因此其路由规则与其保持一致,该组件的详细文档请参考 GitHub文档 路由定义 若需要再easySwoole使用路由拦截功能,请在应用目录(默认为App)下,建立Router类,井继承Core\AbstractInterface\AbstractRouter实现addRouter方法,如果在类UNIX系统下请严格注意文

  • 控制器是放在Controller下的,如果有分组的情况,控制器是放在分组下的,默认分组可以通过Config.php指定。 那么Home分组下的控制器的文件位置就应该是App1/Controller/Home/****Controller.php ,比如:IndexController.php。 那么控制器类要如何定义呢? 首先所有的控制器是继承自GF_Controller类的,如果有分组的情况下,