有没有办法使用@Projection接口作为SDR中资源的默认表示?通过SDR存储库还是通过自定义控制器?
以前可以通过注入ProjectionFactory
并使用createProjection
方法在自定义控制器中执行此操作,但最近的Spring Data Rest更新已经破坏了这一点。
我想在实体上强制执行特定视图,并且SDR投影看起来像是一种理想的方法,特别是在HAL API的上下文中,而不是为自定义控制器和映射编写硬DTO类他们之间的摘录预测不是我所追求的,因为这些仅适用于查看相关资源时。
答案 0 :(得分:12)
要回答我自己的问题,现在有几种简单的方法可以做到这一点。
默认情况下,您可以让SDR存储库查找器返回投影:
public interface PersonRepository extends PagingAndSortingRepository<Person,Long> {
Set<PersonProjection> findByLastName(String lastName);
}
通过使用@BasePathAwareController创建自定义Spring MVC控制器,您还可以选择性地覆盖SDR默认为您处理的响应。如果您计划提供分页响应,则需要注入ProjectionFactory和可能的PagedResourcesAssembler。
@BasePathAwareController
public class CustomPersonController {
@Autowired
private ProjectionFactory factory;
@Autowired
private PersonRepository personRepository;
@Autowired
private PagedResourcesAssembler<PersonProjection> assembler;
@RequestMapping(value="/persons", method = RequestMethod.GET, produces = "application/hal+json")
public ResponseEntity<?> getPeople(Pageable pageable) {
Page<Person> people = personRepository.findAll(pageable);
Page<PersonProjection> projected = people.map(l -> factory.createProjection(PersonProjection.class, l));
PagedResources<Resource<PersonProjection>> resources = assembler.toResource(projected);
return ResponseEntity.ok(resources);
}
答案 1 :(得分:2)
不可以开箱即用。如果嵌入了资源,则始终使用摘录投影。在单个资源上,您可以提供所需的投影作为查询参数。
你可以做的是使用Jackson Mixins改变json表示。
你可以在这里找到一些很好的例子: https://github.com/olivergierke/spring-restbucks/blob/master/src/main/java/org/springsource/restbucks/JacksonCustomizations.java
答案 2 :(得分:2)
我想建议另一个解决方案。
我使用自定义控制器作为@adam
建议,直到我不得不PATCH
一个资源并获得新的表示。默认情况下,无法覆盖存储库的save
方法以使用投影。始终实现自定义控制器为项目带来了一些样板。
由于我已经使用过ResourceProcessor
,我决定在这些处理器中应用默认投影。
@Component
public class ProductResourceProcessor implements ResourceProcessor<Resource<Product>> {
@Autowired
private ProjectionFactory projectionFactory;
@Override
@SuppressWarnings("unchecked")
public Resource<Product> process(Resource<Product> resource) {
Product content = resource.getContent();
ProductInline projection = projectionFactory.createProjection(ProductInline.class, content);
Resource<ProductInline> result = new Resource<>(projection);
//copying and adding links
return (Resource) result;
}
}
处理器重新打包处理资源的内容。无论哪个处理程序将资源作为响应返回(GET
,POST
,PATCH
任何内容),都会应用投影。
这种方法的缺点是假设spring-data-rest
并不要求处理后内容的类型相同。这可能会在将来的版本中随时改变。