Spring - 如何在单个资源上应用投影?

时间:2017-04-22 06:20:09

标签: java spring spring-mvc spring-data-rest

我正在尝试对名为Institute的实体类应用投影。

我定义了以下投影类。

@Projection(name = "instituteProjection", types = { Institute.class })
public interface InstituteProjection {

    String getOrganizationName();

    Contact getContact();

    Address getRegisteredAddress();

    Address getMailingAddress();

}

我遵循了Oliver Gierke link的回答,并且能够在调用http://localhost:8080/institutes时返回带有投影的收集资源。我通过在服务层中实现以下方法然后使用REST控制器调用它来完成此操作。

@Autowired
private ProjectionFactory projectionFactory;

@Autowired
InstituteTypeRepository instituteTypeRepo;

@Override
public PagedResources<Institute> getAllInstitutes(Pageable page) {
    Page<?> instituteList = instituteRepo.findAll(page).
            map(institute -> projectionFactory.createProjection(InstituteListProjection.class, institute));
    PagedResources<Institute> instituteListPaged = pagedResourcesAssembler.toResource(instituteList);
    return instituteListPaged;

}

现在,当调用http://localhost:8080/institutes/1时,如何将相同的投影应用于项目资源?

更新1:

获取单一资源的控制器方法

@RequestMapping(value = "institutes/{instituteId}", method = RequestMethod.GET,
        produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> getInstitute(@PathVariable Long instituteId) {
    Institute institute = service.getInstitute(instituteId);
    return new ResponseEntity<>(institute, HttpStatus.OK);
}

更新2:

从存储库中获取单个资源的服务层方法

@Override
public Institute getInstitute(Long instituteId) {
    Institute institute = instituteRepo.findOne(instituteId);
    return institute;
}

3 个答案:

答案 0 :(得分:1)

你的问题有点不清楚。您可以自动将Spring Data存储库作为其他资源公开,即您不需要定义自己的Spring MVC控制器。

http://docs.spring.io/spring-data/rest/docs/current/reference/html/#install-chapter

使用SDR存储库,预测被定义为&#39;摘录预测&#39;可以自动应用于收集资源:

http://docs.spring.io/spring-data/rest/docs/current/reference/html/#projections-excerpts.excerpts

但不是单一资源。对于单个资源,客户端必须通过请求参数指定所需的投影。

如果您希望将投影自动应用于单个资源,那么这可能是实施您自己的控制器的原因(但是,您的问题是否与您正在进行的操作无关)。

对于自动将投影应用于单个资源的替代方法(即没有自定义控制器,请参见此处):

Spring Data REST: projection representation of single resource

如果要创建自定义控制器以自动应用投影,则可以简单地编写返回投影而不是完整实体的自定义查询方法,并从控制器/服务调用该方法:

https://spring.io/blog/2016/05/03/what-s-new-in-spring-data-hopper#projections-on-repository-query-methods

基本上,通过一些配置,您可以选择自动公开为REST资源的Spring Data存储库,而无需编写任何控制器代码。

答案 1 :(得分:0)

在你的控制器或@RestController中你应该声明一个 @PathVariable 。也许该线程将为您服务:Spring mvc @PathVariable 因此,您使用路径变量解析实现控制器,然后使用 PathVariable 作为争论来调用您的服务

答案 2 :(得分:0)

在最新的 Spring Data Rest 版本中可以轻松完成!

您需要做的就是:

  1. 将投影名称作为请求参数传递

    `/institutes/1?projection=instituteProjection`
    
  2. 从您的服务方法中返回 PersistentEntityResource 而不是 Institute

完成!

我假设您想从自定义控制器调用此服务方法,在这种情况下,您需要从控制器方法返回 ResponseEntity<PersistentEntityResource>

Spring Data Rest 负责在 api 请求上将 @Projection 应用到 PersistentEntityResource,就像您不断从 @RestResource 中暴露 @RepositoryRestResource 一样;相同的投影行为,保持相同的命名约定,基本相同的 URI(对于当前示例)。

带有一些业务逻辑的服务方法可能如下所示:

    @Override
    @Transactional(readOnly = true)
    public PersistentEntityResource getInstitute(Long instituteId, PersistentEntityResourceAssembler resourceAssembler) {
        Institute institute = instituteRepo.findOne(instituteId);
        return resourceAssembler.toModel(institute);
    }

您的控制器方法可能如下所示:

    @GetMapping(value = "institutes/{instituteId}")
    ResponseEntity<PersistentEntityResource> getInstitute(@PathVariable Long instituteId,
                                                                    PersistentEntityResourceAssembler resourceAssembler) {
        return ResponseEntity.status(HttpStatus.OK)
                .body(service.getInstitute(instituteId, resourceAssembler));
    }
}

spring-data-rest 3.3.4.RELEASE

还可以查看更简单的方法to return a collection resource with the projections