《The Definitive Guide to Grails》 学习笔记四 (对应第6-7章)

阅读更多

1. 先补充一些第五章有关标签的:
GSP 模板:利用GSP template进行GSP的复用,并简化比较繁杂的页面处理。
g:render:在GSP中使用这个标签来引用GSP模板,相当于把GSP模板中的代码粘贴
到g:render标签的地方,对应的controller 需要提供GSP中使用的model数据。
测试定制的标签:扩展grails.test.TagLibUnitTestCase类,grails内置的tagLib
属性包含了所有的定制标签(如 tagLib.repeat() ) ,tagLib.out.toString()可
以得到模拟的页面输出。


2. 缺省的URLMapping:在UrlMappings类中,定义static mappings = {
"/$controller/$action?/id?",“500”(view:'/error') }


3. 增加静态文本:/myProject/$controller/$action?/id?


4. 去掉controller和action:上面的URL类似于这样:/artist/show/42,这很不
优雅,所以我们希望把controller和 action合并起来,变成一个更加直观易懂的
文字如:showArtist/42,grails为这种需求提供了用包含controller和 action赋
值的closure定制方法:
static mappings = {
    "/showArtist/$id" {
        controller='artist'
        action='show'
    }

}
或更简洁的方法调用方式:
static mappings = {
    "/showArtist/$id"(controller: 'artist', action: 'show')
}


5. 有人会觉得showArtist/42中的42很不优雅,其实id=42对应的是著名歌星刘德
华,于是他打算把这个URL换成更直观的 /showArtist?artistName=liudehua,在
UrlMappings类里改成:
static mappings = { "/showArtist"(controller:'artist', action:'show') ... }
这样看上去好多了!artistName=LiuDeHua作为request参数传递给controller的
action,不属于 UrlMapping。这是可行的,但是grails达人还是觉得这个url的样
子很丑,而且如果参数很多,url会变得很长,这样是非常不优雅的。哪 grails是
怎么做的呢?可以这样:
static mappings = { "/showArtist/$artistName" (controller:'artist', action:'show') ...}
这样简单一改,最后生成的url会是这样的:/showArtist/liudehua,完美了!
当然,这么改了之后,controller也得改,不然怎么利用$artistName筛选出刘德
华的记录呢?所以,在artistController 的show这个action里需要这么写:

def show = { def artist= Artist.findByName(params.artistName) ... }

这样就对应来自url的参数进行了数据的筛选。
还有一个细节问题需要考虑,url里不是什么字符都可以放的,比如空格就不行,
如果刘德华在Artist类里表达的是"liu de hua",用URL encode可以把这个url表
达成 /showArtist/liu%20de%20hua,但是grails达人怎么可以弄出这么难看的东
西?达人做出来的url应该是: /showArtist/liu_de_hua,这样就美观了。其实,
这个问题很容易解决,就是把上面的那个def artist后面加点替换语句就可以了:
def artist= Artist.findByName(params.artistName.replaceAll('_',' '))


6. 增加更多的参数:只要mappings里定义的内容和controller里的action配合
好,在UrlMappings里可以添加任意多的参数。


7. 直接mapping到view:有些url不需要经过controller的action处理,比如”500
“,”/“,可以直接对应到一个view,例如:
”/“(view:'/home'),也可以指定到某个controller所拥有的view,如:“/find"
(view:'query', controller:'search')


8. URL Mappings的约束:mappings里都有一个constraints方法调用,具体条件是
一个closure作为该方法的参数(这个与 domain类里的constraints不同,虽然名
字一样,domain类里的constraints本身是一个闭包),可以用来对request提交的
url进行合法性验证,避免所有的url都要到action里才能发现错误,例如:
static mappings = {
    "/showLog/$year/$month/$day/$module?" {
        controller ='log'
        action = 'display'
        constraints {
            year mathches: /[0-9]{4}/
            month matches: /[0-9]{2}/
            day matches: /[0-9]{2}/
        }
    }
}


9. 在mappings中使用通配符*:*可以在mappings中作为占位符替换任何动态内
容,例如:“/images/*.jpg" (controller:'image'),这样所有images目录下
的.jpg文件的请求都会被imageController处理,如果要处理所有子目录包含的内
容,则可以用两个*来表示。还可以在通配符之前放置一个变量来作为request参数
传递给controller,如“/images /$pathToFile**.jpg"(controller:'image'),会
把image下到相应.jpg文件的路径作为pathToFile 的值传递给imageController。


10. mapping到HTTP request方法:RESTful API需要把URL mapping根据request的
不同自动映射到不同的action,比如对同一个url,GET request对应show,DELETE
request对应delete,POST request对应save,等等,这在grails里也不是问题:
static mappings = {
    "/artist/$artistName" {
        controller = 'artist'
        action = [GET: 'show', PUT: 'update', POST: 'save', DELETE: 'delete']
    }
}


11. 反向URL Mapping:通过生成的链接也需要保持优雅,因此
            controller='artist'
            id="${artist.id}">${artist.name}

生成出来的链接liu de hua也是grails达人所无
法接受的。既然咱们已经有了很优雅的正向mappings定义
"/showArtist/$artistName"(controller:'artist', action:'show')

就应该好好利用,g:link标签应该写成这样:
            controller='artist'
            params="[artistName:${artist.name.replaceAll(' ','_')}" >

    ${artist.name}


12. 如果应用里的URLMapping很多,可以把它们拆分成多个class,各自有不同的
命名,只要都放在grails-app/conf下,名称最后都是 UrlMappings结尾就可以。


13. 测试URL Mappings:利用grails.test.GrailsUrlMappingsTestCase类,测试
正向的映射可以用 assertForwardUrlMapping()方法,反向的用
assertReverseUrlMapping(),或者用 assertUrlMapping()同时测试两个方向的映射。


14. 国际化:Java里的java.util.ResourceBundle类可以用于读取.properties中
的信息,grails也使用这个类进行国际化,并提供GSP标签message来根据不同条件
从messages.properties中提取相应的信息。URL Mappings也可以用于国际化,例
如"/store/$lang"(controller:'store'),其中的lang是一个request参数。
message里也可以使用占位符实现参数化的动态信息,在messages.proerties中的
{0},{1}就可以作为变量,在中再使用args="xxx"的方式对变量进
行赋值,在validate()中对错误信息的渲染就采用了这种方式。例如:


15. 使用messageSource:有时候message不是用于渲染GSP,而是用来发送邮件,
或者生成log,这时需要提取出message的内容进行处理,这时候message标签就用
不上了。该怎么办呢?当然还是要相信grails是无所不能的。grails提供了一个
bean叫 messageSource,它可以被注入到任何grails artifact,包括
controller,taglib,其他的bean等等。比如在一个controller里使用它,只需在
controller 里定义,就可以使用:
class StoreController {
    def messageSource

    def index = {
        def msg = messageSource.getMessage('gtunes.my.music', null , locale.ITALIAN)
    }
}


你可能感兴趣的:(Grails,Bean)