Spring boot SpringBoot/Kotlin和通过内容协商进行版本控制:正确的方法?

Spring boot SpringBoot/Kotlin和通过内容协商进行版本控制:正确的方法?,spring-boot,kotlin,api-versioning,Spring Boot,Kotlin,Api Versioning,我一直在尝试将内容协商作为SpringBoot/Kotlin应用程序的后端版本控制。我有以下资料: @GetMapping("/user", produces = [MediaType.APPLICATION_JSON_VALUE]) fun getUsers() { //some code here } 我发现合并了“接受”标题和“接受版本”自定义标题。我想知道这是否是实现内容协商方法的正确方法,如果不是,我如何修复它 @GetMapping("/u

我一直在尝试将内容协商作为SpringBoot/Kotlin应用程序的后端版本控制。我有以下资料:

 @GetMapping("/user", produces = [MediaType.APPLICATION_JSON_VALUE])
      fun getUsers() {
        //some code here
      }
我发现合并了“接受”标题和“接受版本”自定义标题。我想知道这是否是实现内容协商方法的正确方法,如果不是,我如何修复它

@GetMapping("/user", produces = [MediaType.APPLICATION_JSON_VALUE], headers = ["Accept-Version=$CUSTOM_ACCEPT_HEADER"])
          fun getUsers() {
            //some code here
          }

object VersioningUtility {
  const val CUSTOM_ACCEPT_HEADER = "vnd.sample.com-v1+json"
  //here more constants as each controller can be versioned independently
}

谢谢

是的,您可以通过使用指定的自定义标头和标头值,使用内容协商实现API版本控制。但是,由于这不是标准标头,因此您可能需要自己处理其他情况,例如:

  • 标题不存在时的默认表示形式
  • 作为标头的一部分传递无效媒体类型值时出现异常情况
如果您只处理json响应,内容协商的标准是发送值为
application/vnd.api+json
Accept
头。因为这是一个标准请求头,所以最好使用它。如果您需要处理其他类型的响应,您仍然可以使用自定义头。

您可以按如下方式实施内容协商:

@RestController
class UserController {

    @GetMapping("/users", headers = ["Accept=${VersioningUtility.VERSION_1_HEADER}"])
    fun getUser(): ResponseEntity<Any> {
        return ResponseEntity(listOf(User("Abraham Lincoln")), HttpStatus.OK)
    }

    @GetMapping("/users", headers = ["Accept=${VersioningUtility.VERSION_2_HEADER}"])
    fun getNewUser(): ResponseEntity<Any> {
        return ResponseEntity(listOf(NewUser(Name("Abraham", "Lincoln"))), HttpStatus.OK)
    }
}

data class User(val name: String)
data class NewUser(val name: Name)
data class Name(val firstName: String, val lastName: String)

object VersioningUtility {
    const val VERSION_1_HEADER = "application/vnd.v1+json"
    const val VERSION_2_HEADER = "application/vnd.v2+json"
}
当使用头值的v2发出curl请求时,响应将根据版本v2

curl -L -X GET 'http://localhost:8080/users' \
-H 'Accept: application/vnd.v2+json'

[
    {
        "name": {
            "firstName": "Abraham",
            "lastName": "Lincoln"
        }
    }
]
当发送无效的头值时,它将以406不可接受的

curl -L -X GET 'http://localhost:8080/users' \
-H 'Accept: application/vnd.abc+json'

{
    "timestamp": "2020-04-01T18:33:16.393+0000",
    "status": 406,
    "error": "Not Acceptable",
    "message": "Could not find acceptable representation",
    "path": "/users"
}
当没有
Accept
头被发送时,它将以默认版本响应,即v1

curl -L -X GET 'http://localhost:8080/users'

[
    {
        "name": "Abraham Lincoln"
    }
]
甚至GitHub也以类似的方式通过内容协商实现了版本控制,您可以在他们的网站中看到这一点

curl -L -X GET 'http://localhost:8080/users'

[
    {
        "name": "Abraham Lincoln"
    }
]