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

查看:142
本文介绍了如何从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<User>,然后使用PagedResourcesAssembler将其转换为PagedResources<UserResource>,如下所示:

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.

返回单个资源的工作原理:

Returning a single resource works:

@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>,尤其是因为User是POJO且没有资源.

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

推荐答案

您似乎已经找到了正确的使用方法,但是我想在这里详细介绍一些细节,以供其他人查找出色地.在此答案中,我对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.

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

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并创建必要的PageMetadata以及prevnext,将其转换为PagedResources实例.链接以浏览页面.默认情况下-这可能是这里有趣的部分-它将使用普通的SimplePagedResourceAssembler(PRA的内部类)将页面的各个元素转换为嵌套的Resource实例.

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

Outlook

从即将到来的Spring Data Commons 1.7 RC1(和Spring HATEOAS 0.9过渡)起,prevnext链接将生成为

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注释config类来简化,这将使您摆脱所有显式的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天全站免登陆