>几乎每种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:
My Blog
My Blog - October 2007 Posts
产生结果:
My Blog
My Blog - October 2007 Posts
避免了直接使用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 People
Show Account
还可以使用``来使用,以上例子则变成:
List People
Show Account