我正在尝试将自定义方法添加到我的Spring Data存储库中PersonRepository,如针对Spring Data存储库的1.3自定义实现中所述,并通过REST公开这些方法。初始代码来自使用REST示例访问JPA数据,这是添加/修改的类的代码:
interface PersonRepositoryCustom { List<Person> findByFistName(String name); } class PersonRepositoryImpl implements PersonRepositoryCustom, InitializingBean { @Override public void afterPropertiesSet() throws Exception { // initialization here } @Override public List<Person> findByFistName(String name) { // find the list of persons with the given firstname } } @RepositoryRestResource(collectionResourceRel = "people", path = "people") public interface PersonRepository extends PagingAndSortingRepository<Person, Long> { List<Person> findByLastName(@Param("name") String name); }
运行应用程序并访问时http://localhost:8080/portfolio/search/,我得到以下响应正文:
http://localhost:8080/portfolio/search/
{ "_links" : { "findByLastName" : { "href" : "http://localhost:8080/people/search/findByLastName{?name}", "templated" : true } } }
为什么findByFirstName即使在PersonRepository界面中可用也不暴露?
findByFirstName
PersonRepository
另外,有没有办法动态/以编程方式添加要通过REST公开的存储库?
这些方法未公开的原因是,你基本上可以自由地在自定义存储库方法中实现所需的任何内容,因此不可能推理出支持该特定资源的正确HTTP方法。
在你的情况下,使用Plain可能很好GET,在其他情况下,可能必须使用a,POST因为该方法的执行会产生副作用。
GET
POST
当前的解决方案是设计一个自定义控制器来调用存储库方法。
我以这种方式解决了。
Custom Repository Interface:
public interface PersonRepositoryCustom { Page<Person> customFind(String param1, String param2, Pageable pageable); }
Custom Repository Implementation
public class PersonRepositoryImpl implements PersonRepositoryCustom{ @Override public Page<Person> customFind(String param1, String param2, Pageable pageable) { // custom query by mongo template, entity manager... } }
Spring Data Repository:
@RepositoryRestResource(collectionResourceRel = "person", path = "person") public interface PersonRepository extends MongoRepository<Person, String>, PersonRepositoryCustom { Page<Person> findByName(@Param("name") String name, Pageable pageable); }
Bean Resource representation
public class PersonResource extends org.springframework.hateoas.Resource<Person>{ public PersonResource(Person content, Iterable<Link> links) { super(content, links); } }
Resource Assembler
@Component public class PersonResourceAssembler extends ResourceAssemblerSupport<Person, PersonResource> { @Autowired RepositoryEntityLinks repositoryEntityLinks; public PersonResourceAssembler() { super(PersonCustomSearchController.class, PersonResource.class); } @Override public PersonResource toResource(Person person) { Link personLink = repositoryEntityLinks.linkToSingleResource(Person.class, person.getId()); Link selfLink = new Link(personLink.getHref(), Link.REL_SELF); return new PersonResource(person, Arrays.asList(selfLink, personLink)); } }
Custom Spring MVC Controller
@BasePathAwareController @RequestMapping("person/search") public class PersonCustomSearchController implements ResourceProcessor<RepositorySearchesResource> { @Autowired PersonRepository personRepository; @Autowired PersonResourceAssembler personResourceAssembler; @Autowired private PagedResourcesAssembler<Person> pagedResourcesAssembler; @RequestMapping(value="customFind", method=RequestMethod.GET) public ResponseEntity<PagedResources> customFind(@RequestParam String param1, @RequestParam String param2, @PageableDefault Pageable pageable) { Page personPage = personRepository.customFind(param1, param2, pageable); PagedResources adminPagedResources = pagedResourcesAssembler.toResource(personPage, personResourceAssembler); if (personPage.getContent()==null || personPage.getContent().isEmpty()){ EmbeddedWrappers wrappers = new EmbeddedWrappers(false); EmbeddedWrapper wrapper = wrappers.emptyCollectionOf(Person.class); List<EmbeddedWrapper> embedded = Collections.singletonList(wrapper); adminPagedResources = new PagedResources(embedded, adminPagedResources.getMetadata(), adminPagedResources.getLinks()); } return new ResponseEntity<PagedResources>(adminPagedResources, HttpStatus.OK); } @Override public RepositorySearchesResource process(RepositorySearchesResource repositorySearchesResource) { final String search = repositorySearchesResource.getId().getHref(); final Link customLink = new Link(search + "/customFind{?param1,param2,page,size,sort}").withRel("customFind"); repositorySearchesResource.add(customLink); return repositorySearchesResource; } }