mongodb - 如何通过带有 ALPS/HATEOAS 元数据的 Spring Data MongoDB 存储库公开新的 REST 方法?

标签 mongodb spring-data spring-data-mongodb spring-hateoas

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

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

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

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

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

这是我的自定义 Controller 。 请注意,我必须在模板 Autowiring 上指定一个 @Qualifier,因为我有多个数据库,它选择了错误的默认值。

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

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

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

我遇到的问题是“这里下面发生了什么”,就像奥利弗建议的那样:

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

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

这是一个例子是无价的地方。我很确定 SO 中没有任何内容可以说明如何执行此操作,至少在我需要的手持级别上是这样。 这个也很接近:Defining a resource assembler for a REST Spring HATEOAS controller但也假设了比我知道的更多。

最佳答案

tl;dr

它将需要存储库和 Controller 的自定义实现。

详情

我们必须确保我们不会迷失在您在这里提到的所有不同方面。我将尝试从下到上理清 Twig :

执行 MongoDB 脚本

作为reference documentation on executing scripts with MongoDB状态(您已经发现),该功能由 MongoTemplateScriptOperations 提供。因此应该清楚如何使用该 API。有关详细信息,请参阅 Javadoc。

通过 Spring Data 存储库执行脚本

接下来您需要的是通过存储库抽象执行这些脚本。为了不把婴儿和洗澡水一起扔掉,请确保我们了解存储库的目的:它模拟聚合根的集合并访问它而不暴露底层持久性机制。在存储库中公开诸如 ExecutableMongoScript 之类的类型会破坏后一个特征。因此,这里正确的方法是按照 reference documentation on Spring Data repositories 中所述为该特定功能制作自定义实现。 .

通过 REST 公开功能

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

推荐的公开自定义存储库查询方法的方法是使用带有适合您目的的 @RequestMapping 的自定义 Controller ,调用存储库并使用可注入(inject)处理程序方法的 PersistentEntityResourceAssembler生成要返回的 PersistentEntityResource

关于mongodb - 如何通过带有 ALPS/HATEOAS 元数据的 Spring Data MongoDB 存储库公开新的 REST 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31575259/

相关文章:

java - Spring 数据 : JPA Repository in abstract base service to call findAll with specification

Spring 数据存储库无需注释即可工作

MongoDB 唯一索引不允许覆盖

node.js - 当我使用带有 .stream() 的 mongo tailable 光标时,我的 CPU 过热

c# - SQL Server 与 MongoDB : Speed test?

node.js - 在 Mongoose 3 中节省麻烦

mongodb - 带有可选参数的 MongoDB runCommand 引用

spring-data - 如何将 spring 数据排序转换为 querydsl OrderSpecifier?

java - Play-Framework 2.4 未选择 Spring-Data-Mongodb depedencies

mongodb - org.bson.codecs.configuration.CodecConfigurationException : Can't find a codec for class org. springframework.data.mongodb.core.query.GeoCommand