26

私は本当に単純であるべきだと思うことをしようとしています。Questionspring-boot、spring-data-rest、spring-hateoas でセットアップされたオブジェクトがあります。すべての基本は正常に機能します。GET が myのURLList<Question>とまったく同じ形式でを返すカスタム コントローラーを追加して、2 つの間の応答に互換性を持たせたいと考えています。Repository/questions

これが私のコントローラーです:

@Controller
public class QuestionListController {

    @Autowired private QuestionRepository questionRepository;

    @Autowired private PagedResourcesAssembler<Question> pagedResourcesAssembler;

    @Autowired private QuestionResourceAssembler questionResourceAssembler;

    @RequestMapping(
            value = "/api/questions/filter", method = RequestMethod.GET,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody PagedResources<QuestionResource> filter(
            @RequestParam(value = "filter", required = false) String filter,
            Pageable p) {

        // Using queryDSL here to get a paged list of Questions
        Page<Question> page = 
            questionRepository.findAll(
                QuestionPredicate.findWithFilter(filter), p);

        // Option 1 - default resource assembler
        return pagedResourcesAssembler.toResource(page);

        // Option 2 - custom resource assembler
        return pagedResourcesAssembler.toResource(page, questionResourceAssembler);
    }

}

オプション 1: 提供されたものに頼るSimplePagedResourceAssembler

このオプションの問題は、必要な_linksものがレンダリングされないことです。これに対する修正があれば、それが最も簡単な解決策になります。

オプション 2: オープン リソース アセンブラーを実装する

このオプションの問題は、 Spring-Hateoas のドキュメントQuestionResourceAssemblerに従って実装すると、最終的に が のほぼ複製になるパスが導かれ、アセンブラーが 2 つのオブジェクト間でデータを手動でコピーする必要があり、すべてをビルドする必要があることです。関連するものを手で。これは多くの無駄な努力のようです。QuestionResourceQuestion_links

何をすべきか?

Spring は、QuestionRepository. コントローラーからの出力がシームレスで、生成された応答と交換可能であることを確認するために、そのコードを利用して使用する方法はありますか?

4

3 に答える 3

26

Spring Data Rest の動作を完全に模倣する方法を見つけました。PagedResourcesAssemblerその秘訣は、と の引数注入インスタンスを組み合わせて使用​​することにありますPersistentEntityResourceAssembler。次のようにコントローラーを定義するだけです...

@RepositoryRestController
@RequestMapping("...")
public class ThingController {

    @Autowired
    private PagedResourcesAssembler pagedResourcesAssembler;

    @SuppressWarnings("unchecked") // optional - ignores warning on return statement below...
    @RequestMapping(value = "...", method = RequestMethod.GET)
    @ResponseBody
    public PagedResources<PersistentEntityResource> customMethod(
            ...,
            Pageable pageable,
            // this gets automatically injected by Spring...
            PersistentEntityResourceAssembler resourceAssembler) {

        Page<MyEntity> page = ...;
        ...
        return pagedResourcesAssembler.toResource(page, resourceAssembler);
    }
}

PersistentEntityResourceAssemblerArgumentResolverこれは、Spring が を注入するために使用するの存在のおかげで機能PersistentEntityResourceAssemblerします。結果は、リポジトリ クエリ メソッドの 1 つから期待されるものとまったく同じです!

于 2015-04-28T16:03:30.560 に答える
9

この古い質問に対する更新された回答:これで、PersistentEntityResourceAssembler

@RepositoryRestController 内:

@RequestMapping(value = "somePath", method = POST)
public @ResponseBody PersistentEntityResource postEntity(@RequestBody Resource<EntityModel> newEntityResource, PersistentEntityResourceAssembler resourceAssembler)
{
  EntityModel newEntity = newEntityResource.getContent();
  // ... do something additional with new Entity if you want here ...  
  EntityModel savedEntity = entityRepo.save(newEntity);

  return resourceAssembler.toResource(savedEntity);  // this will create the complete HATEOAS response
}
于 2017-01-06T19:16:22.357 に答える
4

私は、この問題をかなり簡単な方法で解決したと信じています。

の実装を読んだ後SimplePagedResourceAssembler、ハイブリッド ソリューションが機能する可能性があることに気付きました。提供されたResource<?>クラスはエンティティを正しくレンダリングしますが、リンクは含まれていないため、追加するだけで済みます。

私のQuestionResourceAssembler実装は次のようになります。

@Component
public class QuestionResourceAssembler implements ResourceAssembler<Question, Resource<Question>> {

    @Autowired EntityLinks entityLinks;

    @Override
    public Resource<Question> toResource(Question question) {
        Resource<Question> resource = new Resource<Question>(question);

        final LinkBuilder lb = 
            entityLinks.linkForSingleResource(Question.class, question.getId());

        resource.add(lb.withSelfRel());
        resource.add(lb.slash("answers").withRel("answers"));
        // other links

        return resource;
    }
}

それが完了したら、コントローラーで上記のオプション 2を使用しました。

    return pagedResourcesAssembler.toResource(page, questionResourceAssembler);

これはうまく機能し、コードが多すぎません。唯一の面倒は、必要な参照ごとに手動でリンクを追加する必要があることです。

于 2014-10-24T16:10:12.440 に答える