精通 Grails:用定制URI和codec优化Grails中的URI
按作者显示条目
我们的最终目的就是支持像 http://localhost:9090/blogito/entry/list/jdoe 这样的 URI。注意到,User.login 出现在此 URI 内,而不是主键。在这个过程中,还需要对分页(pagination)做稍许调整。
EntryController.list 的搭建(scaffolded)行为不允许按 User 过滤。清单 5 显示了 list 闭包的默认实现:
清单 5. 默认的 list 实现
if(!params.max) params.max = 10
[ entryInstanceList: Entry.list( params ) ]
}
若要支持在路径的末尾允许出现一个可选的用户名,还需要对之进行扩展。编辑 grails-app/controllers/EntryController.groovy 并添加一个新的 list 闭包,如清单 6 所示:
清单 6. 按作者限制此列表
def scaffold = Entry
def list = {
if(!params.max) params.max = 10
flash.id = params.id
if(!params.id) params.id = "No User Supplied"
def entryList
def entryCount
def author = User.findByLogin(params.id)
if(author){
def query = { eq('author', author) }
entryList = Entry.createCriteria().list(params, query)
entryCount = Entry.createCriteria().count(query)
}else{
entryList = Entry.list( params )
entryCount = Entry.count()
}
[ entryInstanceList:entryList, entryCount:entryCount ]
}
}
您应该注意到的第一件事情是,若终端用户没有提供 params.max 和 params.id 二者的值,就用默认值填充。现在,先不要担心 flash.id — 我稍后在探讨有关分页问题的时候还会对之进行详细讨论。
params.id 值通常是一个整型 — 确切的说是主键。我们一般习惯于 /entry/show/1 和 entry/edit/2 这样的 URI。我本可以在 grails-app/conf/UrlMappings.groovy 内设置一个映射以便返回一个描述性更好的名称,比如 params.name 或 params.login,但现有的映射已经获取了操作名称后的路径元素并将其存储在 params.id 内。我只是充分利用了现有的行为。在 URLMapper.groovy 内,如清单 7 所示,可以看到返回 params.id 的默认映射:
清单 7. UrlMappings.groovy 内的默认映射
static mappings = {
"/$controller/$action?/$id?"{
constraints {}
}
//snip
}
}
由于这不是 User 的主键,所以不能像往常那样使用 User.get(params.id)。相反,必须使用 User.findByLogin(params.id)。
如果找到了一个匹配的 User,就需要创建一个查询块。这就需要用到 Hibernate Criteria Builder(参见 参考资料)。在本例中,我们限制了列表只包含匹配某特定作者的那些条目。同样地,我们注意到 GORM 也允许您从对象而不是主键或外键的角度来思考。
如果没有匹配 params.id 的作者,就会返回全部条目的完整列表: entryList = Entry.list( params )。
注意,entryCount 值是被显式计算出来的。Scaffolded GroovyServer Pages (GSP) 代码通常会在
在 flash.id 内存储 params.id 值将允许应用程序将此查询条件传递回
清单 8. 针对定制分页调整 list.gsp 页面
<g:paginate total="${entryCount}" params="${flash}"/>
</div>
重启 Grails 并在 Web 浏览器内访问 http://localhost:9090/blogito/entry/list/jsmith。屏幕应该类似图 2:
图 2. 按作者列出条目

为了确保分页仍能工作,键入 http://localhost:9090/blogito/entry/list/jsmith?max=1。单击 Previous 和 Next 按钮以确保只有 Jane 的 blog 条目才会出现,如图 3 所示:
图 3. 测试定制分页

按作者过滤的功能就绪后,就可以更进一步,创建一个更为友好的定制 URI。