spring-boot - Spring Boot/Kotlin 和通过内容协商进行版本控制 : correct approach?

标签 spring-boot kotlin api-versioning

我一直在尝试使用 Content Negotiation 作为 SpringBoot/Kotlin 应用程序的后端版本控制。我有以下几点:

 @GetMapping("/user", produces = [MediaType.APPLICATION_JSON_VALUE])
      fun getUsers() {
        //some code here
      }

我找到了 this project结合接受” header 和“接受版本”自定义 header 。我想知道这是否是实现内容协商方法的正确方法,如果不是,我该如何解决?
@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
}

谢谢

最佳答案

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

  • 标题不存在时的默认表示
  • 无效媒体类型值作为 header 的一部分传递时的异常情况。

  • 如果您只处理 json 响应,JSON API内容协商的标准是发送Accept带有值 application/vnd.api+json 的 header .自 Accept是一个标准的请求头,使用它是首选。如果您需要处理其他类型的响应,您仍然可以继续使用自定义 header 。

    您可以按如下方式实现内容协商:
    @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"
    }
    

    以上使您可以拥有 GET /users 的 2 个版本端点与 Accept标题。

    当使用 发出 curl 请求时v1 header 值,响应将根据 版本 v1
    curl -L -X GET 'http://localhost:8080/users' \
    -H 'Accept: application/vnd.v1+json'
    
    [
        {
            "name": "Abraham Lincoln"
        }
    ]
    

    当使用 发出 curl 请求时v2 header 值,响应将根据 版本 v2
    curl -L -X GET 'http://localhost:8080/users' \
    -H 'Accept: application/vnd.v2+json'
    
    [
        {
            "name": {
                "firstName": "Abraham",
                "lastName": "Lincoln"
            }
        }
    ]
    

    当发送无效的 header 值时,它将以 响应。 406 Not Acceptable
    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发送 header ,它将以默认版本响应,即 v1 这里
    curl -L -X GET 'http://localhost:8080/users'
    
    [
        {
            "name": "Abraham Lincoln"
        }
    ]
    

    GitHub 已经以类似的方式通过内容协商实现了版本控制,您可以在他们的 documentation 中查看。 .

    关于spring-boot - Spring Boot/Kotlin 和通过内容协商进行版本控制 : correct approach?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60916881/

    相关文章:

    spring-boot - Spring Boot 版本控制 - 版本控制是否应该应用于所有端点,即使只有一个端点发生了变化

    java - junit 测试用例通过,但仍在控制台 java 中打印异常

    java - 带选择的 CriteriaBuilder 不允许没有构造函数

    android - 如何将 EditText 的文本设置为 Int?

    php - 为每个版本的 API 使用单独的目录

    amazon-web-services - 使用 AWS API Gateway 进行 API 版本控制

    java - 如何设置 swagger 文档以使用 dd/MM/yyyy 格式?

    java - 尽管抛出相同的异常,但预期异常的 JUnit 测试仍失败

    java - 从逗号分隔整数的字符串数组映射的连续天数

    java - Kotlin 如何与 Java 和 JavaScript 互操作?