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>

posted on   黑暗伯爵  阅读(1485)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 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的设计模式综述

导航

< 2012年7月 >
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 1 2 3 4
5 6 7 8 9 10 11

统计

点击右上角即可分享
微信分享提示