>几乎每种web服务都提供两种风格的路由:__CGI风格__与__REST__风格 >CGI: `http://example/user/张三` >REST:`http://example/user?name=张三` >一目了然,上面就列出了这两种风格的差异,当然也可以混用 Grails中也支持这些路由风格,虽然强调惯例优于配置,但在实际中总避免不了对uri路由地址进行精确控制,它的定义如下 class UrlMappings { static mappings = { //定义与此 } } __具体URL的映射语法例子如下__: * 全格式:`"/product" (controller:"product", action:"list")` * 使用缺省Action:`"/product" (controller:"product")` * 使用闭包: "/product" { controller = "product" action = "list" } * 将URI映射到另一个URI,常在与其他框架集成时用:`"/hello" (uri:"/hello.dispatch")` __在映射语法中我们还可以使用变量,它们以 *$* 开头,变量值会自动进入`params`,这样在对应的action中就可以通过`“params.变量名”`访问:__ * params.id:`"/product/$id" (...)`。如“/product/1”,其中1就是id的值,通过params.id即可访问。 * 多个变量:`"/$blog/$year/$month/$day/$id"`。如`“/graemerocher/2007/01/10/my_funky_blog_entry”`,其中blog的值是graemerocher,year的值是2007,month的值是01,依次类推。 __利用变量,我们还可以动态构造Controller和Action的名字:__ * `“/$controller/$action?/$id?” ()`,通过params中的变量名得到Controller和Action的名字。 * 同样,我们也可以通过闭包来实现: "/$controller" { action = { params.goHere } } __URL映射语法中同样还支持可选参数,规则很简单,在变量名后面加?即可。如上例的*“$id?”*。跟Java中的一样,可选参数必须位于最后,形如`“/…/$变量名?/$变量名/$变量名?”`是不行的,但是`“/…/$变量名/$变量名?/$变量名?”`是可以的。__ 定义变量也不一定非要在URL上进行,还可以在闭包中定义,如: //传递任意值 "/holiday/win" { id = "Marrakech" year = 2007 } //动态计算 "/holiday/win" { id = { params.id } isEligible = { session.user != null } } __上述例子都是演示的是如何把URL映射到Controller的Action,我们同样可以把它映射到View:__ * 将root url映射到grails-app/views/index.gsp:`"/" (view:"/index")` * 映射到某Controller的View:`"/help" (controller:"site",view:"help")` __对于Http响应码,我们也同样可以进行映射,这样我们就可以显示更友好的错误信息界面,而不是单调的应用服务器相关的错误页面了:__ * 把响应码映射到Controller:`"500" (controller:"errors", action:"serverError")` * 把响应码映射到View:`"500" (view:"/errors/serverError")` __URL映射还可以映射Http的方法,这在定义Restful Api的时候非常有用:__ static mappings = { "/product/$id" (controller:"product"){ action = [GET:"show", PUT:"update", DELETE:"delete", POST:"save"] } } __Grails还支持在映射中使用通配符:__ * `"/images/*.jpg"(controllers:"image")` * `"/images/$name.jpg"(controllers:"image")`,效果同上,不同的是使用了变量名。 * 同样还可以使用**来映射多级目录:`"/images/**.jpg"(controllers:"image")` * 更好的一种方式则是:`"/images/$name**.jpg"(controllers:"image")`,这样匹配的路径会放到params.name中。 __在映射中我们还可以指定哪些URL不参与映射,在UrlMappings.groovy中静态熟悉excludes中定义即可:__ class UrlMappings = { static excludes = ["/images/**", "/css/**"] //排除 static mappings = { ... } } Grails的URL映射还支持链接的自动重写。如对于映射:`"/$blog/$year?/$month?/$day?/$id?"(controller:"blog", action:"show")`,以下的Link: 产生结果: 避免了直接使用URL,使得链接的定义和使用更灵活。 __在前面的文章中我们已经领略到了contraints的好处,对于URL映射,你同样可以使用它,以验证URL的有效性(正则):__ "/$blog/$year?/$month?/$day?/$id?" { controller = "blog" action = "show" constraints { year(matches:/d{4}/) month(matches:/d{2}/) day(matches:/d{2}/) } } 结果: *有效*:/graemerocher/2007/01/10/my_funky_blog_entry *无效*:/graemerocher/2007/01/101/my_funky_blog_entry __对于映射,我们还可以给它起个名字,这就是命名映射的由来。语法:`name : {...}`。例子如下:__ static mappings = { name personList: "/showPeople" { controller = 'person' action = 'list' } name accountDetails: "/details/$acctNumber" { controller = 'product' action = 'accountDetails' } } 使用时引用名字即可: 还可以使用``来使用,以上例子则变成: List PeopleShow Account