Grails中的UrlMapping
>几乎每种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:
<g:link controller="blog" action="show" params="[blog:'fred', year:2007]">My Blog</g:link>
<g:link controller="blog" action="show" params="[blog:'fred', year:2007, month:10]">My Blog - October 2007 Posts</g:link>
产生结果:
<a href="/fred/2007" rel="noopener nofollow">My Blog</a>
<a href="/fred/2007/10" rel="noopener nofollow">My Blog - October 2007 Posts</a>
避免了直接使用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 <mapping name="">: <url pattern="">{...}
。例子如下:
static mappings = {
name personList: "/showPeople" {
controller = 'person'
action = 'list'
}
name accountDetails: "/details/$acctNumber" {
controller = 'product'
action = 'accountDetails'
}
}
使用时引用名字即可:
<g:link mapping="personList">List People</g:link>
<g:link mapping="accountDetails" params="[acctNumber:'8675309']">Show Account</g:link>
还可以使用<link:名字>
来使用,以上例子则变成:
<link:personlist>List People</link:personlist>
<link:accountdetails acctnumber="8675309">Show Account</link:accountdetails></link:名字></url></mapping>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述