如何在 Grails 中正确映射版本化资源?

How do I correctly map versioned resources in Grails?

我有 grails 运行 REST API 并在 URL 中使用版本号,如下所示:https://api.mycompany.com/v2/metadata。我需要更改其中一个端点的参数,因此我将版本提高到 v3。只有一个控制器受到影响,所以我想将剩余的调用委托给 v2 的控制器,而不必再次 copy/paste 一切。这是我的相关部分 UrlMappings.groovy:

class UrlMappings {

    static mappings = {

        "/v3/widget"(controller: "v3widget")
        "/v3/$otherResource" {
            // does not work, but illustrates what I want to happen
            uri = { "/v2/" + params.otherResource }
        }


        // rest of my file...
        "/v2/metadata"(controller: 'metadata')
...

正确的做法是什么?我正在使用 grails 2.2.5

我发现有效的解决方案依赖于通配符映射也可以接受其他正则表达式这一事实:

class UrlMappings {

    static mappings = {

        // v3 specific
        "/v3/widget"(controller: "v3widget")
        // v3/v2 common
        "/v[23]/$otherResource" {
            // normal mappings go here
        }
        // v2 specific
        "/v2/metadata"(controller: 'v2metadata')
...

此解决方案效果很好,因为我不必重复任何映射,而且很清楚 v2 和 v3 资源之间的区别。

我会在 uri 路径中使用一个变量,而不是你的例子,你会有以下映射:

class UrlMappings {

    static mappings = {

        "/$apiVersion/widget"(controller: "v3widget")
        "/$apiVersion/otherResource"(controller: "otherResource")
        // rest of my file...
        "/$apiVersion/metadata"(controller: 'metadata')
...

然后您可以检查控制器中的值:

class OtherResourceController {

    def index(){
        if(params.apiVersion == 'v2') {
          ...
        } else {
          ...
        }
    }

}

此处的示例是检查字符串值,但您可以更深入一点,将字符串值实际转换为内部 api 版本枚举表示形式,这可能更易于管理。您也可以在过滤器中执行此操作。

这样您可以增加逻辑更改,api 将有一个很好的回退,将委托给默认版本。

但是当你有几个 api 版本一个层叠在一起时,它会变得非常卷曲。