xsr*_*ity 7 spring-mvc spring-data spring-data-rest spring-hateoas
我使用 Spring Data JPA 来管理 JPA 实体,Spring Data Rest 将存储库导出到 REST API。
我还在构建一个自定义控制器,我想在其中获取实体的 URI(HAL 链接)并通过CrudRepository.
自定义控制器
@RequestMapping(path = MeLinks.ELEVATE, method = RequestMethod.PUT, consumes = RestMediaTypes.TEXT_URI_LIST_VALUE)
HttpEntity<?> elevate(@RequestBody @Valid CollectionModel<Contact> contact) {
...
}
Run Code Online (Sandbox Code Playgroud)
当尝试使用 Content-Type 之PUT类的联系链接时,我可以使用而不是 Contact 对象本身访问链接。http://localhost:8080/contacts/1text/uri-listcontact.getLinks()
Spring Data Rest 是否可以从 URI 自动推断实体?我知道一个内置的,UriToEntityConverter但我如何使用它?
编辑
这是一种有效但并没有真正优雅地解决问题的尝试。
下面的代码初始化 aUriToEntityConverter并将传入的 URI 转换为域对象。
@Autowired
private ApplicationContext applicationContext;
@Autowired
private MappingContext<?, ?> mappingContext;
@RequestMapping(path = MeLinks.ELEVATE, method = RequestMethod.PUT, consumes = RestMediaTypes.TEXT_URI_LIST_VALUE)
HttpEntity<?> elevate(@RequestBody @Valid CollectionModel<Contact> uris) {
URI uri = URI.create(uris.getLinks().get(0).getHref());
Repositories repositories = new Repositories(applicationContext);
PersistentEntity<?,?> contactPersistentEntity = repositories.getPersistentEntity(Contact.class);
UriToEntityConverter uriToEntityConverter = new UriToEntityConverter(
new PersistentEntities(Collections.singleton(mappingContext)),
new DefaultRepositoryInvokerFactory(repositories),
repositories);
Contact t = (Contact) uriToEntityConverter.convert(uri, TypeDescriptor.valueOf(URI.class), TypeDescriptor.valueOf(Contact.class));
}
Run Code Online (Sandbox Code Playgroud)
可以想象,从 中获取域对象Repository比上面的要容易得多。假设 URI 使用ID链接的唯一部分,这也有效。就我而言,我已将其自定义为使用 UUID。所以默认行为是UriToEntityConverter行不通的。
注意:HATEOAS 首次发布时已将Resources类重命名为CollectionModel。
如果您想继续使用,UriToEntityConverter我建议您查看Spring Data REST 文档的这一部分,以使用该类将资源 URI 自定义为不同的属性EntityLookupSupport<T>。然后应该UriToEntityConverter正确返回实体。
如果您希望按照您的说明直接使用存储库,请考虑以下事项:
看源码UriToEntityConverter,它使用URI的最后一部分作为对象的标识符。你也可以这样做。(在此代码片段中,我刚刚修改了上面的代码,假设您正确检索了对象URI)
private ContactRepository contactRepository;
// You should use constructor injection, as it is preferred over field injection.
@Autowired
public CustomController(ContactRepository contactRepository){
this.contactRepository = contactRepository;
}
@RequestMapping(path = MeLinks.ELEVATE, method = RequestMethod.PUT, consumes = RestMediaTypes.TEXT_URI_LIST_VALUE)
HttpEntity<?> elevate(@RequestBody @Valid CollectionModel<Contact> uris) {
URI uri = URI.create(uris.getLinks().get(0).getHref());
Optional<Contact> optionalContact = contactRepository.findByName(getLastUriPart(uri));
if (optionalContact.isPresent()){
return optionalContact.get();
} else {
// Error handling
}
}
private String getLastUriPart(URI uri) {
String[] uriParts = uri.getPath().split("/");
if (uriParts.length < 2) {
// Error handling
}
return uriParts[uriParts.length - 1];
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
927 次 |
| 最近记录: |