如何通过带有 ALPS/HATEOAS 元数据的 Spring Data MongoDB 存储库公开新的 REST 方法? [英] How do I expose a new REST method to through a Spring Data MongoDB repository with ALPS/HATEOAS metadata?

查看:69
本文介绍了如何通过带有 ALPS/HATEOAS 元数据的 Spring Data MongoDB 存储库公开新的 REST 方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将 MongoRepository 扩展类中的新方法公开给生成的 REST API 并包含相同的 ALPS/HATEOAS 元数据、链接等.

How do I expose a new method in a MongoRepository extension class to the generated REST API and include the same ALPS/HATEOAS metadata, links etc.

我有常用的 Spring Data MongoDB 存储库:

I have the usual Spring Data MongoDB repository:

public interface CollectionRepository extends Repository<Collection, String> {    
    // Simple queries
    Collection findFirstByName(@Param("name") String name);   
}

现在我想添加另一个方法并将其集成到生成的 Repository REST API 中,以便它与 QueryDSL 生成的元素一起包含在 {repository}/collection/search 响应中.

Now I want to add another method and have it integrate into the generated Repository REST API so that it is included in the {repository}/collection/search response alongside the QueryDSL generated elements.

我被两件事困住了1) 使用 PersistentEntityResourceAssembler 和 PersistentEntityResource 提供参数并将响应转换为适当的格式.2) 自动生成 HATEOAS/ALPS 元数据,以便父 URL 在 API 浏览器中显示带有参数的方法.

I'm stuck on 2 things 1) Using PersistentEntityResourceAssembler and PersistentEntityResource to provide the parameters and convert the response into the appropriate format. 2) Automating the generation of the HATEOAS/ALPS metadata so the parent URL shows the method with parameters in the API browser.

这是我的自定义控制器.请注意,我必须在模板自动装配上指定一个 @Qualifier,因为我有多个数据库并且它选择了错误的默认值.

Here's my custom controller. Note that I had to specify a @Qualifier on the template autowiring as I have multiple databases and it was picking the wrong one be default.

@Component
@RepositoryRestController
@RequestMapping(value = "{repository}/search")
public class CollectionRepositoryController implements ResourceProcessor<RepositorySearchesResource> {

    @Autowired private EntityLinks entityLinks;
    @Autowired private PagedResourcesAssembler pagedResourcesAssembler;
    @Autowired Repositories repositories;
    @Autowired
    @Qualifier("mongoTemplateCollections")
    private MongoTemplate mongoTemplate;
    private final CollectionRepository repository;
    @Autowired
    public CollectionRepositoryController(CollectionRepository repo) {
        repository = repo;
    }
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "findText", method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public PagedResources<PersistentEntityResource> findText(
            Pageable pageable, @RequestParam(value = "findText", required = false) String findText,
            PersistentEntityResourceAssembler resourceAssembler) {
        TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny(findText);
        Query query = TextQuery.queryText(criteria).sortByScore();
        List<Collection> collections = mongoTemplate.find(query, Collection.class);
        Page<Collection> page = new PageImpl<Collection>(Arrays.asList(new Collection()), pageable, pageable.getOffset());

       // What goes below here to convert List<Collections> into PersistentEntityResource ?

        PersistentEntity<?, ?> persistentEntity = repositories.getPersistentEntity(Collection.class);
        for(Collection collection : collections) {
            PersistentEntityResource collectionResource = PersistentEntityResource.build(collection, persistentEntity).
                    withLink(new Link("/collection/" + collection.getId())).build();
            Log.info("collections resource: " + collectionResource);
        }

        return pagedResourcesAssembler.toResource(page, resourceAssembler);
    }

    // https://stackoverflow.com/questions/29570962/how-to-add-custom-methods-to-spring-data-rest-jpa-implementation-and-leverage-ha
    @Override
    public RepositorySearchesResource process(RepositorySearchesResource resource) {
        LinkBuilder lb = entityLinks.linkFor(Collection.class, "name");
        resource.add(new Link(lb.toString() + "/search/findText{?findText}", "findText"));
        return resource;
    }
}

我也创建了这个,但我不确定如何/在哪里连接它:

I also created this, but I'm not sure how/where to wire it in:

@Component
public class CollectionResourceAssembler implements ResourceAssembler<Collection, Resource<Collection>> {

    @Autowired
    EntityLinks entityLinks;

    @Override
    public Resource<Collection> toResource(Collection collection) {
        Resource<Collection> resource = new Resource<Collection>(collection);

        final LinkBuilder lb = entityLinks.linkForSingleResource(Collection.class, collection.getId());
        resource.add(lb.withSelfRel());
        resource.add(lb.slash("answers").withRel("answers"));
        // other links

        return resource;
    }
}

我遇到的问题是下面是什么",就像奥利弗建议的那样:

The bit I'm having trouble with is the "what goes below here", such that it does as Oliver suggested:

调用存储库并使用 PersistentEntityResourceAssembler可注入到处理程序方法中以产生一个要返回的 PersistentEntityResource.

calling the repository and using a PersistentEntityResourceAssembler injectable into the handler method to produce a PersistentEntityResource to return.

而且,我真的必须使用 ResourceProcessor.process() 方法手动设置 ALPS/HATEOAS 数据还是有自动设置的技巧?

And, do I really have to manually set the ALPS/HATEOAS data using the ResourceProcessor.process() method or is there a trick to automating that?

这是一个无价的例子.我很确定 SO 中没有任何内容显示如何执行此操作,至少在我需要的手持级别上.这个也很接近:为一个 REST Spring HATEOAS 控制器,但也假设比我知道的更多.

This is where an example would be priceless. I'm pretty sure there's nothing in SO that shows how to do this, at least at the level of handholding I need. This one is also pretty close: Defining a resource assembler for a REST Spring HATEOAS controller but also assumes more than I know.

推荐答案

tl;dr

它将需要存储库和控制器的自定义实现.

tl;dr

It will need custom implementations for the repository and the controller.

我们必须确保我们不会在您在这里提到的所有不同方面迷失方向.我会试着从下往上解开树枝:

We have to make sure we're not getting lost in all the different aspects you're mentioning here. I'll try to untangle the branches bottom up:

作为 使用 MongoDB 执行脚本的参考文档 指出(并且您已经发现),该功能由 MongoTemplateScriptOperations 提供.因此,应该清楚如何使用该 API.有关详细信息,请参阅 Javadoc.

As the reference documentation on executing scripts with MongoDB states (and you already discovered), the functionality is provided by MongoTemplate's ScriptOperations. Thus how to use that API should be clear. Consult the Javadoc for more information.

您要求的下一件事是通过存储库抽象执行这些脚本.为了不把婴儿和洗澡水一起扔出去,请确保我们了解存储库的用途:它模拟聚合根的集合并对其进行访问而不会暴露底层的持久性机制.在存储库中公开像 ExecutableMongoScript 这样的类型会破坏后一个特性.因此,这里的正确方法是为该特定功能制作自定义实现,如 有关 Spring Data 存储库的参考文档.

The next thing you're asking for is executing those scripts through the repository abstraction. To not throw the baby out with the bath water here, make sure we understand the purpose of a repository: it simulates a collection of aggregate roots and access to it without exposing the underlying persistence mechanism. Exposing types like ExecutableMongoScript on the repository would break the latter trait. Thus the correct approach here is to craft a custom implementation for that particular functionality as described in the reference documentation on Spring Data repositories.

我假设您指的是 Spring Data REST 的功能,以便为您的问题中的存储库查询方法公开专用资源.Spring Data REST 目前仅自动公开声明性查询方法,主要是因为我们无法猜测方法内部发生了什么,因此很难推断正确的 HTTP 方法来支持自定义实现.

I am assuming you're referring to Spring Data REST's feature to expose a dedicated resource for the repository query method in your question. Spring Data REST currently only exposes declarative query methods automatically, mostly for the reason that it's hard to reason about the correct HTTP method to support for custom implementations as we cannot guess what's happening inside the method.

使用自定义控制器和适合您目的的 @RequestMapping 公开自定义存储库查询方法的推荐方法,调用存储库并使用可注入处理程序方法的 PersistentEntityResourceAssembler生成要返回的 PersistentEntityResource.

The recommended way to expose custom repository query methods using a custom controller with an @RequestMapping suiting your purpose, calling the repository and using a PersistentEntityResourceAssembler injectable into the handler method to produce a PersistentEntityResource to return.

这篇关于如何通过带有 ALPS/HATEOAS 元数据的 Spring Data MongoDB 存储库公开新的 REST 方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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