web-dev-qa-db-ja.com

Spring DataからPagedResourcesAssemblerを正しく使用する方法は?

Spring 4.0.0.RELEASE、Spring Data Commons 1.7.0.M1、Spring Hateoas 0.8.0.RELEASEを使用しています

私のリソースは単純なPOJOです:

_public class UserResource extends ResourceSupport { ... }
_

私のリソースアセンブラーは、ユーザーオブジェクトを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
    }
}
_

UserController内で、サービスから_Page<User>_を取得し、次に示すようにPagedResourcesAssemblerを使用して_PagedResources<UserResource>_に変換します。 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の代わりに返されます。

単一のリソースを返すことができます:

_@Autowired
UserResourceAssembler assembler;

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

PagedResourcesAssemblerはいくつかの汎用引数を必要としますが、_Page<User>_を_PagedResources<User>_に変換したくないため、T toResource(T)を使用できません。特に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);
    }

    /* ... */
}
_

解決:

_@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);
}
_
34
Benjamin M

あなたはすでに適切な使用方法を知っているようですが、他の人にも見つけてもらうために、ここでいくつかの詳細に触れたいと思います。 この回答PagedResourceAssemblerについても同様の詳細を説明しました。

表現モデル

Spring HATEOASには、リンク付きのリプレゼンテーションを簡単に作成できるリプレゼンテーションモデルのさまざまな基本クラスが付属しています。すぐに使用できるクラスには3つのタイプがあります。

  • Resource-アイテムリソース。 singleアイテムをキャプチャし、それをリンクで強化するDTOまたはエンティティを効果的にラップします。
  • Resources-コレクションリソース。何かのコレクションでもかまいませんが、通常はResourceインスタンスのコレクションです。
  • PagedResources-総ページ数などの追加のページネーション情報をキャプチャするResourcesの拡張.

これらのクラスはすべて、ResourceSupportインスタンスの基本コンテナであるLinkから派生しています。

リソースアセンブラー

ResourceAssemblerは、ドメインオブジェクトまたはDTOをそのようなリソースインスタンスに変換する緩和コンポーネントです。ここで重要な部分は、oneソースオブジェクトをoneに変えることです。ターゲットオブジェクト。

したがって、PagedResourcesAssemblerは、Spring Data Pageインスタンスを取得し、PagedResourcesを評価して必要なPageを作成することにより、PageMetadataインスタンスに変換します。ページをナビゲートするためのprevおよびnextリンク。デフォルトでは-これはおそらくここで興味深い部分です-プレーンSimplePagedResourceAssemblerPRAの内部クラス)を使用して、ページの個々の要素をネストされたResourceインスタンスに変換します。

これをカスタマイズできるようにするため、PRAには、個々のアイテムを処理するためにデリゲートResourceAssemblerを受け取る追加のtoResource(…)メソッドがあります。したがって、次のような結果になります。

 class UserResource extends ResourceSupport { … }

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

クライアントコードは次のようになります。

 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の推移的)の時点で、prevおよびnextリンクが RFC654 準拠のURIテンプレートとして生成され、ページネーション要求パラメーターが公開されます。 HandlerMethodArgumentResolversおよびPageableSortで構成されます。

上記で示した構成は、構成クラスに@EnableSpringDataWebSupportこれにより、明示的なBean宣言をすべて取り除くことができます。

70
Oliver Drotbohm

リソースのリストをページに変換したかった。しかし、PagedResourcesAssemblerを指定すると、内部リンクを食い尽くしていました。

これにより、リストがページングされます。

 public class JobExecutionInfoResource extends ResourceSupport {
    private final JobExecutionInfo jobExecution;

    public JobExecutionInfoResource(final JobExecutionInfo jobExecution) {
        this.jobExecution = jobExecution;        
        add(ControllerLinkBuilder.linkTo(methodOn(JobsMonitorController.class).get(jobExecution.getId())).withSelfRel()); // add your own links.          
    }

    public JobExecutionInfo getJobExecution() {
        return jobExecution;
    }
}

PagedリソースResourceAssemblerを使用して、Pagedリソースにそれを使用するように指示します。これは、既に渡されたリソースリストであるため、単に何も返しません。

    private final PagedResourcesAssembler<JobExecutionInfoResource> jobExecutionInfoResourcePagedResourcesAssembler;
    public static final PageRequest DEFAULT_PAGE_REQUEST = new PageRequest(0, 20);
    public static final ResourceAssembler<JobExecutionInfoResource, JobExecutionInfoResource> SIMPLE_ASSEMBLER = entity -> entity;

@GetMapping("/{clientCode}/{propertyCode}/summary")
    public PagedResources<JobExecutionInfoResource> getJobsSummary(@PathVariable String clientCode, @PathVariable String propertyCode,
                                                                   @RequestParam(required = false) String exitStatus,
                                                                   @RequestParam(required = false) String jobName,
                                                                   Pageable pageRequest) {
        List<JobExecutionInfoResource> listOfResources = // your code to generate the list of resource;
        int totalCount = 10// some code to get total count;
        Link selfLink = linkTo(methodOn(JobsMonitorController.class).getJobsSummary(clientCode, propertyCode, exitStatus, jobName, DEFAULT_PAGE_REQUEST)).withSelfRel();
        Page<JobExecutionInfoResource> page = new PageImpl<>(jobExecutions, pageRequest, totalCount);
        return jobExecutionInfoResourcePagedResourcesAssembler.toResource(page, SIMPLE_ASSEMBLER, selfLink);
    }
0