如何正确使用Spring Data中的PagedResourcesAssembler?

Ben*_*n M 35 spring pagination spring-mvc spring-data spring-hateoas

我正在使用Spring 4.0.0.RELEASE,Spring Data Commons 1.7.0.M1,Spring Hateoas 0.8.0.RELEASE

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

public class UserResource extends ResourceSupport { ... }
Run Code Online (Sandbox Code Playgroud)

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

@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
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的UserController中,我想Page<User>从我的服务中检索然后将其转换为PagedResources<UserResource>使用PagedResourcesAssembler,如下所示: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);
}
Run Code Online (Sandbox Code Playgroud)

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

返回单个资源有效:

@Autowired
UserResourceAssembler assembler;

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

PagedResourcesAssembler想一些通用的说法,但我不能使用T toResource(T),因为我不想将我Page<User>PagedResources<User>,特别是因为User是一个POJO,没有资源.

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

编辑:

我的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);
    }

    /* ... */
}
Run Code Online (Sandbox Code Playgroud)

解:

@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);
}
Run Code Online (Sandbox Code Playgroud)

Oli*_*ohm 71

你似乎已经发现了正确的使用方法,但我想在这里详细介绍一些细节,供其他人查找.我PagedResourceAssembler这个答案中谈到了类似的细节.

表示模型

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

  • Resource - 项目资源.有效地包装一些DTO或实体,捕获单个项目并通过链接丰富它.
  • Resources- 集合资源,可以是某些东西的集合,但通常是Resource实例的集合.
  • PagedResources- 其扩展名Resources捕获额外的分页信息,如总页数等.

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

资源组装商

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

因此,PagedResourcesAssembler将采取一个Spring数据Page实例,并将它转换成PagedResources通过对实例Page和创造必要的PageMetadata还有prevnext链接进行浏览的页面.默认情况下 - 这可能是这里有趣的部分 - 它将使用plain SimplePagedResourceAssembler(内部类PRA)将页面的各个元素转换为嵌套Resource实例.

要允许自定义此选项,PRA还有其他toResource(…)方法可以让委托ResourceAssembler处理单个项目.所以你最终得到这样的东西:

 class UserResource extends ResourceSupport { … }

 class UserResourceAssembler extends ResourceAssemblerSupport<User, UserResource> { … }
Run Code Online (Sandbox Code Playgroud)

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

 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);
Run Code Online (Sandbox Code Playgroud)

外表

截至即将发布的Spring Data Commons 1.7 RC1(以及Spring HATEOAS 0.9)prev,next链接将生成为符合RFC6540的 URI模板,以显示HandlerMethodArgumentResolversfor Pageable和for中配置的分页请求参数Sort.

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

  • 我在上面的答案中添加了`PagedResourcesAssembler`的泛型.如果您提供自定义`UserResourceAssembler`这是一个'ResourceAssembler <用户,UserResource>`,你需要得到一个`PagedResourcesAssembler <用户名>`注入,最终创造`PagedResources <UserResource>`.我只是增加了一个[测试例](https://github.com/spring-projects/spring-data-commons/commit/30a63f5546e51f1496efaefe4314ca3b90b3e1e0#diff-689e2ccfdbb815599f1a6b2e7b5c00f9R145)到代码库给出一个工作示例. (2认同)