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

时间:2015-01-23 22:33:11

标签: rest grails

我有grails运行REST API并在URL中使用版本号,如下所示:https://api.mycompany.com/v2/metadata。我需要更改其中一个端点的参数,因此我将版本提升到v3。只有一个控制器受到影响,因此我希望将剩余的调用委托给v2的控制器,而无需再次复制/粘贴所有内容。以下是我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

2 个答案:

答案 0 :(得分:1)

我会在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版本在另一个上分层时,它会变得非常卷曲。

答案 1 :(得分:0)

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

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资源之间的不同之处。