使用 Spring Data Rest @Projection 作为自定义控制器中资源的表示
Using a Spring Data Rest @Projection as a representation for a resource in a custom controller
有没有什么方法可以使用@Projection 接口作为 SDR 中资源的默认表示?是通过 SDR 存储库还是通过自定义控制器?
过去可以在自定义控制器中通过注入 ProjectionFactory
并使用 createProjection
方法来执行此操作,但这已被最近的 Spring Data Rest 打破更新。
我想对实体强制执行特定视图,SDR 投影似乎是执行此操作的理想方法,尤其是在 HAL API 的上下文中,而不是编写硬 DTO 类 用于自定义控制器和它们之间的映射等。摘录投影不是我所追求的,因为这些仅在查看相关资源时适用。
不,开箱即用是不可能的。如果嵌入资源,则始终使用摘录投影。在单个资源上,您可以提供所需的投影作为查询参数。
您可以使用 Jackson Mixins 来更改 json 表示。
您可以在这里找到一些很好的例子:
https://github.com/olivergierke/spring-restbucks/blob/master/src/main/java/org/springsource/restbucks/JacksonCustomizations.java
为了回答我自己的问题,现在有几种简单的方法可以做到这一点。
默认情况下,您可以进行 SDR 存储库查找器 return 投影:
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);
}
我想提出另一种解决方案。
我按照 @adam
的建议使用自定义控制器,直到我不得不 PATCH
一个资源并取回新的表示。默认情况下,无法覆盖存储库的 save
方法以使用投影。一直实施自定义控制器会给项目带来一些样板文件。
因为我已经使用了 ResourceProcessor
s 我决定在这些处理器中应用默认投影。
@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
不要求处理后内容的类型相同。这可能会在未来的版本中随时更改。
有没有什么方法可以使用@Projection 接口作为 SDR 中资源的默认表示?是通过 SDR 存储库还是通过自定义控制器?
过去可以在自定义控制器中通过注入 ProjectionFactory
并使用 createProjection
方法来执行此操作,但这已被最近的 Spring Data Rest 打破更新。
我想对实体强制执行特定视图,SDR 投影似乎是执行此操作的理想方法,尤其是在 HAL API 的上下文中,而不是编写硬 DTO 类 用于自定义控制器和它们之间的映射等。摘录投影不是我所追求的,因为这些仅在查看相关资源时适用。
不,开箱即用是不可能的。如果嵌入资源,则始终使用摘录投影。在单个资源上,您可以提供所需的投影作为查询参数。
您可以使用 Jackson Mixins 来更改 json 表示。
您可以在这里找到一些很好的例子: https://github.com/olivergierke/spring-restbucks/blob/master/src/main/java/org/springsource/restbucks/JacksonCustomizations.java
为了回答我自己的问题,现在有几种简单的方法可以做到这一点。
默认情况下,您可以进行 SDR 存储库查找器 return 投影:
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);
}
我想提出另一种解决方案。
我按照 @adam
的建议使用自定义控制器,直到我不得不 PATCH
一个资源并取回新的表示。默认情况下,无法覆盖存储库的 save
方法以使用投影。一直实施自定义控制器会给项目带来一些样板文件。
因为我已经使用了 ResourceProcessor
s 我决定在这些处理器中应用默认投影。
@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
不要求处理后内容的类型相同。这可能会在未来的版本中随时更改。