在Grails上搜索RESTful接口的实现

时间:2012-12-10 20:23:18

标签: rest grails

我正在Grails 2.1.1应用程序上构建一个RESTful接口。我该如何实施搜索操作?我不想重复大量的代码,这是我目前的想法所需要的。

服务器结构很正常Grails-MVC:域类表示数据,控制器提供接口,服务具有业务逻辑。我使用命令对象在控制器中进行数据绑定,但不使用服务方法。客户端是Web UI。我的目标是拥有这样的搜索网址:

/cars/?q=generic+query+from+all+fields
/cars/?color=red&year=2011

(我知道有关使用查询字符串的这种URL的RESTfulness的辩论:RESTful URL design for search。虽然我认为这是我的目的的最佳模型,但如果他们制作的话,我会接受其他选择。 API和实现更好。)

从下面的代码示例中可以看出,我的问题是第二种URL,即特定于字段的搜索。为了对包含大量字段的几个域类实现这种搜索操作,我的方法签名会爆炸。

可能有一种“Groovy方式”可以做到这一点,但我仍然是一个更精简的Groovy技巧n00b:)

域:

class Car {
    String color
    int year
}

控制器:

class CarsController {
    def carService
    def list(ListCommand cmd) {
        def result
        if (cmd.q) {
            result = carService.search(cmd.q, cmd.max, cmd.offset, cmd.order, cmd.sort)
        }
        else {
            result = carService.search(cmd.color, cmd.year, cmd.max, cmd.offset, cmd.order, cmd.sort)
        }
        render result as JSON
    }

    class ListCommand {
        Integer max
        Integer offset
        String order
        String sort
        String q
        String color // I don't want this field in command
        int year // I don't want this field in command

        static constraints = {
            // all nullable
        }
    }
    // show(), save(), update(), delete() and their commands clipped
}

服务:

class CarService {
    List<Car> search(q, max=10, offset=0, order="asc", sort="id") {
        // ...
    }

    List<Car> search(color, year, max=10, offset=0, order="asc", sort="id") {
        // ...
    }
}

UrlMappings:

class UrlMappings {
    static mappings = {
        name restEntityList: "/$controller"(parseRequest: true) {
            action = [GET: "list", POST: "save"]
        }
        name restEntity: "/$controller/$id"(parseRequest: true) {
            action = [GET: "show", PUT: "update", POST: "update", DELETE: "delete"]
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您可以从params获取所有这些参数,例如:

result = carService.search(params.color, params.year as Integer, cmd.max, cmd.offset, cmd.order, cmd.sort)

params map的所有值都是字符串,因此您应该将其转换为控制器中的相应数据结构(最好检查params.year是否为实际数字)


更新

如果您不想编写字段名称,可以将其作为Map传递:

resutl = carService.search(params)

其中

List<Car> search(Map params)