Grails的更新速度真的好慢,现在总算Grails 1.0RC1进入stable了,先来看看这个版本中有哪些亮点吧。
1.ORM 增强
1.1 DSL
新版本将支持Object Relation Mapping(ORM)Domain Specific Language(DSL),今后再也不需要使用传统Hibernate回调映射方式了。先看个例子:
class Person {
String firstName
static hasMany = [addresses:Address]
static mapping = {
table 'people'
version false
id column:'person_id'
columns {
firstName column:'First_Name'
addresses lazy:false
}
}
}
class Address {
String street
String postCode
}
对于DSL的支持主要在以下方面:
- 表和列名
- 继承策略
- 二级缓存配置
- Id生成策略
- 组合Id支持
- 前期/惰性加载
- 数据库索引
- 客户化Hibernate用户类型
1.2 悲观锁
缺省情况下GORM Domain Class被配置为使用乐观锁(Optimistic Locking),现在你可以使用悲观锁以得到“SELECT ... FOR UPDATE"功能:
def book = Book.get(1)
book.lock()
book.title = "The Stand"
book.save()
1.3 Session flusing控制
一般来讲,Grails会控制什么时候怎么样实现Session的flush操作,但现在你也可以自已控制flush。
def book = Book.get(1)
book.save(flush:true)
// or book.delete(flush:true)
2. 过滤器(Filters)
Grails通过在控制器中使用Filter来实现拦截机制,例如:
class SecurityFilters {
def filters = {
loginCheck(controller:'*', action:'*') {
before = {
if(!session.user && !actionName.equals('login')) {
redirect(action:'login')
return false
}
}
}
}
}
3. 标签库加强
3.1 支持命名空间
这也是一个期待已久的特性,有了她就不怕标签名冲突了。
// tag code
class FormatTagLib {
static namespace = 'fmt'
def dateFormat = { attrs ->
out << new java.text.SimpleDateFormat(attrs.format).format(attrs.value)
}
}
// gsp code
<fmt:dateFormat format="dd-MM-yyyy" value="${new Date()}" />
// or as a method
${fmt.dateFormat(format:'dd-MM-yyyy',value:new Date())}
3.2 Body变量
还是看个例子吧:
// tag code
def repeat = { attrs, body ->
def count = attrs.times.toInteger()
count.times {
body(num:it)
}
}
// gsp code
<g:repeat times="10">Number: ${num}</g:repeat>
3.3 加入了新的范围支持
新的pageScope变量可以被用在标签中,可以使用<g:set>来使用些变量。
<g:set var="foo" value="${new Date()}" scope="page" />
<g:set var="bar" value="${new Date()-7}" scope="session" />
4. 控制器(Controller)加强
4.1 多维参数
Grails params对象可以被多维定义了。也就是说如果你的表单提交使用以"."分隔的参数
<g:textField name="book.title" value="The Stand" />
<g:textField name="author.name" value="Stephen King" />
那么你可以通过使用以下方式来获得这个参数
params["book"]
这只要是被用来在处理域至象时实现数据绑定
def book = new Book(params["book"])
def author = new Author(params["author"])
或是
def book = new Book(title:params["book"]?.title)
4.2 数据绑定与类型转换错误
Grails完全兼顾Spring的数据绑定功能,保留类型转换时的错误信息以及原始值,例如:
def site = new Site(url:"bad_url")
assert site.hasErrors()
assert "bad_url" == site.errors.getFieldError("url")
5. 配置加强
5.1 JNDI Data Sources
这可不用多讲了吧,有了它,你就可以方便的使用很多商业应用服务器提供的数据库连接池了。
配置文件:grails-app/conf/DataSource.groovy
dataSource {
jndiName = "java:comp/env/myDataSource"
}
5.2 更灵活的配置位置
你可以定义多个内部或外部的配置位置
grails.config.locations = [ "classpath:${appName}-config.properties",
"classpath:${appName}-config.groovy",
"file:${userHome}/.grails/${appName}-config.properties",
"file:${userHome}/.grails/${appName}-config.groovy"]
Grails现在支持Spring的property place hodler功能,你可以通过在Config.groovy中指定属性值以覆盖原值通过使用beans scope。
beans {
myService.someProperty = "foo"
}
6. URL映射加强
6.1 响应代码与错误处理
你可以自定义出错代码对应的处理动作
class UrlMappings {
static mappings = {
"500"(controller:"errors", action:"serverError")
"404"(controller:"errors", action:"notFound")
"403"(controller:"errors", action:"forbidden")
}
}
6.2 映射URL到Views
static mappings = {
"/"(view:"/index") // map the root URL
"/help"(controller:"site",view:"help") // to a view for a controller
}
6.3 双通配符
tatic mappings = {
// will match /product/MacBook and /product/Apple/MacBook
"/products/**"(controller:"product")
}
如果你想获得路径的剩余部分,你可以使用一个变量
static mappings = {
"/products/$path**"(controller:"product", action:"show")
}
// then in the action
def show = {
def path = params.path
render path // prints "MacBook" or "Apple/MacBook"
}