如何正确使用 Spring Data 中的 PagedResourcesAssembler? [英] How to correctly use PagedResourcesAssembler from Spring Data?

查看:47
本文介绍了如何正确使用 Spring Data 中的 PagedResourcesAssembler?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 Spring 4.0.0.RELEASE、Spring Data Commons 1.7.0.M1、Spring Hateoas 0.8.0.RELEASE

I'm using Spring 4.0.0.RELEASE, Spring Data Commons 1.7.0.M1, Spring Hateoas 0.8.0.RELEASE

我的资源是一个简单的 POJO:

My resource is a simple POJO:

public class UserResource extends ResourceSupport { ... }

我的资源汇编器将 User 对象转换为 UserResource 对象:

My resource assembler converts User objects to UserResource objects:

@Component
public class UserResourceAssembler extends ResourceAssemblerSupport<User, UserResource> { 
    public UserResourceAssembler() {
        super(UserController.class, UserResource.class);
    }

    @Override
    public UserResource toResource(User entity) {
        // map User to UserResource
    }
}

在我的 UserController 中,我想从我的服务中检索 Page,然后使用 PagedResourcesAssembler 将其转换为 PagedResources,就像这里显示的一样:https://stackoverflow.com/a/16794740/1321564

Inside my UserController I want to retrieve Page<User> from my service and then convert it to PagedResources<UserResource> using PagedResourcesAssembler, like displayed here: https://stackoverflow.com/a/16794740/1321564

@RequestMapping(value="", method=RequestMethod.GET)
PagedResources<UserResource> get(@PageableDefault Pageable p, PagedResourcesAssembler assembler) {
    Page<User> u = service.get(p)
    return assembler.toResource(u);
}

这不会调用 UserResourceAssembler 并且只返回 User 的内容而不是我的自定义 UserResource.

This doesn't call UserResourceAssembler and simply the contents of User are returned instead of my custom UserResource.

返回单个资源有效:

@Autowired
UserResourceAssembler assembler;

@RequestMapping(value="{id}", method=RequestMethod.GET)
UserResource getById(@PathVariable ObjectId id) throws NotFoundException {
    return assembler.toResource(service.getById(id));
}

PagedResourcesAssembler 需要一些通用参数,但是我不能使用 T toResource(T),因为我不想转换我的 Page<User>PagedResources,特别是因为 User 是一个 POJO 而没有 Resource.

The PagedResourcesAssembler wants some generic argument, but then I can't use T toResource(T), because I don't want to convert my Page<User> to PagedResources<User>, especially because User is a POJO and no Resource.

所以问题是:它是如何工作的?

So the question is: How does it work?

我的 WebMvcConfigurationSupport:

My WebMvcConfigurationSupport:

@Configuration
@ComponentScan
@EnableHypermediaSupport
public class WebMvcConfig extends WebMvcConfigurationSupport {
    @Override
    protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(pageableResolver());
        argumentResolvers.add(sortResolver());
        argumentResolvers.add(pagedResourcesAssemblerArgumentResolver());
    }

    @Bean
    public HateoasPageableHandlerMethodArgumentResolver pageableResolver() {
        return new HateoasPageableHandlerMethodArgumentResolver(sortResolver());
    }

    @Bean
    public HateoasSortHandlerMethodArgumentResolver sortResolver() {
        return new HateoasSortHandlerMethodArgumentResolver();
    }

    @Bean
    public PagedResourcesAssembler<?> pagedResourcesAssembler() {
        return new PagedResourcesAssembler<Object>(pageableResolver(), null);
    }

    @Bean
    public PagedResourcesAssemblerArgumentResolver pagedResourcesAssemblerArgumentResolver() {
        return new PagedResourcesAssemblerArgumentResolver(pageableResolver(), null);
    }

    /* ... */
}

解决方案:

@Autowired
UserResourceAssembler assembler;

@RequestMapping(value="", method=RequestMethod.GET)
PagedResources<UserResource> get(@PageableDefault Pageable p, PagedResourcesAssembler pagedAssembler) {
    Page<User> u = service.get(p)
    return pagedAssembler.toResource(u, assembler);
}

推荐答案

您似乎已经找到了正确的使用方法,但我想在这里详细介绍一些细节,供其他人找到作为好.我在 this answer 中详细介绍了关于 PagedResourceAssembler.

You seem to have already found out about the proper way to use but I'd like to go into some of the details here a bit for others to find as well. I went into similar detail about PagedResourceAssembler in this answer.

Spring HATEOAS 为表示模型提供了各种基类,可以轻松创建配备链接的表示.开箱即用提供了三种类型的类:

Spring HATEOAS ships with a variety of base classes for representation models that make it easy to create representations equipped with links. There are three types of classes provided out of the box:

  • Resource - 项目资源.有效地环绕一些 DTO 或实体,这些实体捕获单个项目并通过链接对其进行丰富.
  • Resources - 一个集合资源,可以是一些东西的集合,但通常是一个 Resource 实例的集合.
  • PagedResources - Resources 的扩展,用于捕获额外的分页信息,例如总页数等.
  • Resource - an item resource. Effectively to wrap around some DTO or entity that captures a single item and enriches it with links.
  • Resources - a collection resource, that can be a collection of somethings but usually are a collection of Resource instances.
  • PagedResources - an extension of Resources that captures additional pagination information like the number of total pages etc.

所有这些类都源自 ResourceSupport,它是 Link 实例的基本容器.

All of these classes derive from ResourceSupport, which is a basic container for Link instances.

ResourceAssembler 现在是将域对象或 DTO 转换为此类资源实例的缓解组件.这里的重要部分是,它将一个源对象变成了一个目标对象.

A ResourceAssembler is now the mitigating component to convert your domain objects or DTOs into such resource instances. The important part here is, that it turns one source object into one target object.

因此 PagedResourcesAssembler 将获取 Spring Data Page 实例并通过评估 Page 将其转换为 PagedResources 实例code> 并创建必要的 PageMetadata 以及 prevnext 链接来导航页面.默认情况下 - 这可能是这里有趣的部分 - 它将使用一个普通的 SimplePagedResourceAssembler(PRA 的内部类)将页面的各个元素转换为嵌套的 SimplePagedResourceAssembler代码>资源实例.

So the PagedResourcesAssembler will take a Spring Data Page instance and transform it into a PagedResources instance by evaluating the Page and creating the necessary PageMetadata as well as the prev and next links to navigate the pages. By default - and this is probably the interesting part here - it will use a plain SimplePagedResourceAssembler (an inner class of PRA) to transform the individual elements of the page into nested Resource instances.

为了允许对此进行自定义,PRA 有额外的 toResource(…) 方法,这些方法采用委托 ResourceAssembler 来处理各个项目.所以你最终会得到这样的结果:

To allow to customize this, PRA has additional toResource(…) methods that take a delegate ResourceAssembler to process the individual items. So you end up with something like this:

 class UserResource extends ResourceSupport { … }

 class UserResourceAssembler extends ResourceAssemblerSupport<User, UserResource> { … }

客户端代码现在看起来像这样:

And the client code now looking something like this:

 PagedResourcesAssembler<User> parAssembler = … // obtain via DI
 UserResourceAssembler userResourceAssembler = … // obtain via DI

 Page<User> users = userRepository.findAll(new PageRequest(0, 10));

 // Tell PAR to use the user assembler for individual items.
 PagedResources<UserResource> pagedUserResource = parAssembler.toResource(
   users, userResourceAssembler);

展望

从即将发布的 Spring Data Commons 1.7 RC1(和 Spring HATEOAS 0.9 传递)开始,prevnext 链接将生成为 RFC6540 兼容 URI 模板,用于公开 HandlerMethodArgumentResolvers 中配置的分页请求参数,用于PageableSort.

Outlook

As of the upcoming Spring Data Commons 1.7 RC1 (and Spring HATEOAS 0.9 transitively) the prev and next links will be generated as RFC6540 compliant URI templates to expose the pagination request parameters configured in the HandlerMethodArgumentResolvers for Pageable and Sort.

上面显示的配置可以通过使用 @EnableSpringDataWebSupport 注释配置类来简化,这将使您摆脱所有显式的 bean 声明.

The configuration you've shown above can be simplified by annotating the config class with @EnableSpringDataWebSupport which would let you get rid off all the explicit bean declarations.

这篇关于如何正确使用 Spring Data 中的 PagedResourcesAssembler?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆