gpt4 book ai didi

spring - 使用与 Spring MVC 的内容协商进行 REST API 版本控制

转载 作者:行者123 更新时间:2023-12-01 12:31:03 25 4
gpt4 key购买 nike

我正在尝试使用内容协商来实现 API 版本控制,因为将版本放入 URI 不是 RESTful。 Spring MVC 似乎不可能,因为在解析 Controller 方法时不考虑 @RequestMapping 的消耗/生产属性,只考虑路径。为了便于讨论,假设我有这个 Controller

@RestController
@RequestMapping(path = "/foo")
public class FooController {
@RequestMapping(path = "{id}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
@ResponseBody
public Foo getFoo(@PathVariable Long id) {
return repository.findOne(id);
}

@RequestMapping(path = "{id}", method = RequestMethod.GET, produces = { "application/vnd.com.me.model.v1+json" })
@ResponseBody
public FooV1 getFooV1(@PathVariable Long id) {
return repositoryV1.findOne(id);
}
...
}

REST API 是“GET/foo/1”或“GET/foo/2”等,但我希望能够发送任何一个

Accept: application/json

Accept: application/vnd.com.me.model.v1+json

并让它转到正确的 Controller 方法。忽略如何最好地表示模型的问题。这只是让 Spring MVC 让我有一个单一的 REST URI 来处理不同的内容类型。这显然也适用于其他 HTTP 方法,PUT、POST 等。鉴于上面的 Controller 定义,当 Spring 尝试解析映射时,您会收到一个错误,“抱歉,已经有 '/foo/{id}' 的映射。”

我是否错过了可以让我实现这一目标的东西?

最佳答案

这绝对应该像您描述的那样工作。我这里有一个工作示例:

@RestController
@RequestMapping(path = "/persons")
public class PersonController {

private final PersonV1Repository personV1Repository;
private final PersonV2Repository personV2Repository;

@Autowired
public PersonController(PersonV1Repository personV1Repository, PersonV2Repository personV2Repository) {
this.personV1Repository = personV1Repository;
this.personV2Repository = personV2Repository;
}

@RequestMapping(produces = "application/vnd.com.me.model.v1+json")
public ResponseEntity<List<PersonV1>> getPersonsV1() {
return ResponseEntity.ok(personV1Repository.findAll());
}

@RequestMapping(path = "/{id}", produces = "application/vnd.com.me.model.v1+json")
public ResponseEntity<PersonV1> getPersonV1(@PathVariable Long id) {
return ResponseEntity.ok(personV1Repository.findOne(id));
}

@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<PersonV2>> getPersonsV2() {
return ResponseEntity.ok(personV2Repository.findAll());
}

@RequestMapping(path = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<PersonV2> getPersonV2(@PathVariable Long id) {
return ResponseEntity.ok(personV2Repository.findOne(id));
}
}

我使用 Accept header 获取我选择的版本 - 以下是示例请求和响应:

http :8080/persons/2 Accept:application/vnd.com.me.model.v1+json -v
GET /persons/2 HTTP/1.1
Accept: application/vnd.com.me.model.v1+json
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/0.9.2



HTTP/1.1 200 OK
Content-Type: application/vnd.com.me.model.v1+json;charset=UTF-8
Date: Mon, 07 Dec 2015 20:14:26 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
X-Application-Context: application

{
"firstname": "some",
"id": 2,
"lastname": "other"
}

并获取默认版本:

http :8080/persons/2 Accept:application/json -v
GET /persons/2 HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/0.9.2



HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Date: Mon, 07 Dec 2015 20:16:20 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
X-Application-Context: application

{
"id": 2,
"name": "some"
}

您的 Controller 中必须有一些其他重复映射 - 您可以添加完整的 Controller 代码以进行进一步调查。

关于spring - 使用与 Spring MVC 的内容协商进行 REST API 版本控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34140857/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com