【问题标题】:Can i offer an endpoint in parallel to a spring-data-rest GET?我可以提供与 spring-data-rest GET 并行的端点吗?
【发布时间】:2017-08-22 21:44:24
【问题描述】:

我的项目正在从自定义 json 格式转移到 json-hal 和 spring-data-rest。为了继续支持“旧”json,我想将现有的 Resource-Controller 与提供的新 Spring-Data-Rest 并行运行。

每当我将 spring-data-rest 配置为使用与我们现有控制器相同的 url 时,只使用旧控制器并且如果接受标头不匹配,我会收到错误响应。当我使用不同的网址时,一切正常

是否可以与 spring-data-rest 并行运行控制器并根据 Accept-Header 响应?

旧控制器:

@RepositoryRestController
@RequestMapping(value = "/api/accounts", produces = {"application/custom.account+json"})
public class AccountResource {

    @RequestMapping(method = RequestMethod.GET)
    @PreAuthorize("#oauth2.hasScope('read') and hasRole('ROLE_ADMIN')")
    public ResponseEntity<List<Account>> getAll(
        @RequestParam(value = "page", required = false) Integer offset,
        @RequestParam(value = "per_page", required = false) Integer limit,
        @RequestParam(value = "email", required = false) String email
    ) throws URISyntaxException {
        ...
    }
}

【问题讨论】:

  • 您是否尝试在您的@RequestMapping 中指定headers

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


【解决方案1】:

@RepositoryRestControllertype level 上与@RequestMapping 不能很好地配合使用。 第一步,通过从 RequestMapping 中删除 produces 参数,确保您确实设法捕获了请求(我在这里使用 GetMapping 快捷方式)。我还删除了 @PreAuthorize 注释,因为它现在不相关,并引入了一个参数来捕获 Accept 标头值(用于调试):

@RepositoryRestController
public class AccountResource {

    @GetMapping(value = "/api/accounts")
    public ResponseEntity<List<Account>> getAll(
        @RequestParam(value = "page", required = false) Integer offset,
        @RequestParam(value = "per_page", required = false) Integer limit,
        @RequestParam(value = "email", required = false) String email,
    ) throws URISyntaxException {
        ...
    }

}

有了这个,您应该能够随意自定义 GET /api/accounts 并且仍然可以从 POST/PUT/PATCH.../api/accounts 中受益由 Spring Data Rest 自动提供,并且还断言 content-type

如果它按预期工作,您可以:

  • 尝试在 GetMapping 注释中使用 produces = "application/custom.account+json"(单个值不需要大括号)来缩小方法范围,并查看您的端点和 Spring 生成的端点方法都可用
  • 恢复您的 @PreAuthorize 注释
  • 去掉@RequestHeader参数

这给了你:

@RepositoryRestController  // NO MAPPING AT THE TYPE LEVEL
public class AccountResource {

    @GetMapping(value = "/api/accounts", // Mapping AT THE METHOD LEVEL
                produces = "application/custom.account+json") // the content-type this method answers to
    @PreAuthorize("#oauth2.hasScope('read') and hasRole('ADMIN')")  // ROLE is 'ADMIN' not 'ROLE_ADMIN'
    public ResponseEntity<List<Account>> getAll(
        @RequestHeader("Content-Type") String contentType,
        @RequestParam(value = "page", required = false) Integer offset,
        @RequestParam(value = "per_page", required = false) Integer limit,
        @RequestParam(value = "email", required = false) String email,
    ) throws URISyntaxException {
        ...
    }

}

现在:

  • curl host:port/api/accounts 将命中 Spring 控制器端点
  • curl host:port/api/accounts -H "Accept: application/custom.account+json" 将命中您的自定义控制器端点。

【讨论】:

  • 我知道您所描述的是可能的,但我想保留自动 spring-data-rest GET-endpoint 并为我自己的内容类型提供我的自定义。到目前为止,我自己实现的任何 GET 都将取代自动的。
  • 我为你提供了一个工作一步一步来获得你想要的结果。我只是自己尝试过,它可以工作,您可以获得自动和自定义端点...我将使用最终版本和 curl 示例编辑我的答案...
  • 顺便说一句,您应该考虑用 Pageable 替换您的偏移量和限制参数。
  • 如果我在现有项目中复制您的示例,我的自定义资源将被忽​​略,所有请求都会转到 spring-data-rest。两个请求之间的唯一区别是,对于自定义 Accept-Header,jackson 序列化程序无法识别 hal。我将在一个空项目中尝试您的解决方案,因为我现在无法更新到最新的启动/数据休息版本。
  • 可能有其他一些配置妨碍了。跟踪具有大量自定义配置的大型项目并不总是那么容易。您使用的是哪个版本的 Spring Boot?自 1.4.x 版以来,我一直在使用类似于我所描述的解决方案。您的日志应该显示一堆带有RepositoryRestHandlerMapping : Mapped "{" 的行。应明确提及您的控制器,应将 Spring 控制器提及为RepositoryRestHandlerMapping : Mapped "{[/{repository}],methods=[GET],produces=[application/hal+json || application/json]}"
猜你喜欢
  • 2020-02-17
  • 1970-01-01
  • 2016-07-11
  • 2019-12-27
  • 2016-10-26
  • 2014-10-02
  • 2019-06-19
  • 2018-03-02
  • 2016-10-01
相关资源
最近更新 更多