【问题标题】:Spring Data REST: Multiple endpoints for one entitySpring Data REST:一个实体的多个端点
【发布时间】:2016-01-07 12:02:28
【问题描述】:

前提:
Web 服务通过 REST 公开其数据。每条记录都属于创建记录的用户(行级安全)。用户只能检索自己的记录。

@RepositoryRestResource(path = "talks")
public interface TalkRepository extends PagingAndSortingRepository<Talk, Long> {

    @Override
    @Query("select t from Talk t where t.owner.id= ?#{principal?.id}")
    Page<Talk> findAll(Pageable pageable);
}

该存储库现在在 /talks 端点下可用。

问题:
有没有办法 1) 在多个端点上公开相同的域实体和 2) 根据端点定义不同的 @Query 注释?

  • /talks
    我会让它成为我对管理员角色开放的默认实现
  • /me/talks
    这是针对主体应用行级安全性的端点,作为/me/** 端点的一部分,它作为公共 api 公开给实现客户端。

此问题与https://jira.spring.io/browse/DATAREST-555 部分相关,但仅在目前不支持附加路径段的情况下。

理由:
我喜欢不必在像is owner or has_some_role(一些例子here)这样的SPeL查询中加入太多条件逻辑的想法。此外,通过与默认 API 不同的策略来保护 /me/** 端点将变得容易(例如,只有 /me/** 可能受 OAuth2 约束)。

【问题讨论】:

  • 只写一个控制器,绑定一个URI,然后自己调用repository?

标签: spring-security spring-data spring-data-rest


【解决方案1】:

如果您知道更好/更简洁的解决方案,我很乐意接受其他答案。

根据@OliverGierke、official docs 和其他各种 SO 答案的建议(也几乎完全由 Oliver 提供,主要是 1、2 和 2 和 3),我实现了一个自定义控制器来服务端点.

这还可以在自定义端点上启用投影,并使用 Spring Data REST 的 HATEOS 汇编器来提供 HAL+JSON 输出。到目前为止我还没有研究的是如何重用 SDR 提供的开箱即用但在自定义控制器中丢失的配置文件和 alps 逻辑。

@BasePathAwareController
public class MyTalksController {

    private final TalkRepository repository;
    private final PagedResourcesAssembler pagedResourcesAssembler;

    @Autowired
    public MyTalksController(TalkRepository repo, PagedResourcesAssembler assembler) {
        repository = repo;
        pagedResourcesAssembler = assembler;
    }

    @RequestMapping(method = RequestMethod.GET, value = "/me/talks")
    @ResponseBody
    public PagedResources<?> getTalks(Pageable pageable, PersistentEntityResourceAssembler entityAssembler) {
        Page<Talk> talks = repository.meFindAll(pageable);
        return pagedResourcesAssembler.toResource(talks, entityAssembler);
    }
}

【讨论】:

  • 你知道不使用 PagedResourceAssembler 是否有可能吗?
【解决方案2】:

回答 1) — 是的,可能如下:

// skipping old requests for the sake of the backward compatibility with the clients
// just returning ok with HTTP status 200
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST, RequestMethod.OPTIONS, RequestMethod.DELETE},
                value = {"/lock", "/configure", "/cancel", "/initialize", "/register"})
public ApiResponse ok() {
    return ApiResponse.success();
}

回答 2) — 不同的查询逻辑自然会适合不同的端点,因此我假设需要为每个端点创建相应的方法。

【讨论】:

    猜你喜欢
    • 2016-07-06
    • 2017-12-02
    • 2019-01-07
    • 1970-01-01
    • 2016-07-11
    • 1970-01-01
    • 2017-05-10
    • 2019-09-30
    • 2012-10-04
    相关资源
    最近更新 更多