如何将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浏览器中显示带参数的方法。
这是我的自定义控制器。 请注意,我必须在自动装配的模板上指定一个@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;
}
}
我遇到麻烦的是“这里有什么东西”,这样就像奥利弗建议的那样:
调用存储库并使用PersistentEntityResourceAssembler 可注入到handler方法中来生成一个 PersistentEntityResource返回。
并且,我是否真的必须使用ResourceProcessor.process()方法手动设置ALPS / HATEOAS数据,还是有自动化的技巧?
这是一个无价的例子。我很确定SO中没有任何内容可以说明如何做到这一点,至少在我需要的手持水平上。 这个也很接近:Defining a resource assembler for a REST Spring HATEOAS controller但也假设比我知道的更多。
答案 0 :(得分:2)
它需要存储库和控制器的自定义实现。
我们必须确保我们不会在您提到的所有不同方面迷失方向。我试着从下到上解开树枝:
作为reference documentation on executing scripts with MongoDB状态(您已经发现),功能已提供by MongoTemplate
&#39; s ScriptOperations
。因此,应该清楚如何使用该API。有关更多信息,请咨询Javadoc。
您要求的下一件事是通过存储库抽象执行这些脚本。为了不让宝宝在这里洗澡,请确保我们了解存储库的用途:它模拟聚合根的集合并访问它,而不暴露底层持久性机制。在存储库中公开类似ExecutableMongoScript
的类型会破坏后者的特征。因此,正确的方法是为reference documentation on Spring Data repositories。
我假设您正在引用Spring Data REST的功能,以便在您的问题中为存储库查询方法公开专用资源。 Spring Data REST目前仅自动公开声明性查询方法,主要是因为我们很难推断出支持自定义实现的正确HTTP方法,因为我们无法猜测方法内部发生了什么。
使用符合您目的的@RequestMapping
自定义控制器公开自定义存储库查询方法的推荐方法,调用存储库并在处理程序方法中使用PersistentEntityResourceAssembler
注入来生成{{1}返回。