grails 使用需要知道和注意的tips:
1- gsp中的注释,如果是中文的话,在其后多加一个空格,可以避免gsp编译时的跟中文字节有关系的错误。
2- 服务类必须以Service结尾,它的运行时单件模式,默认开启事务,如果没有用到数据库事务,最好关闭事务,避免数据库连接占用过多。
3- 当域类很多时,可以在DataSource文件中进行修改,dbCreate=“none”。
4- grails同类工件的类名称不能重名,即使包名称不一样,类名称相同,这种情况也是不行,在grails内部会解析出现问题。
5- 服务类不要太多,比较耗内存,Grails启动时,初始化也慢
6- 修改BuildConfig.groovy,把相关的配置在打包war时就复制到指定的位置
grails.war.resources = { stagingDir, args -> copy(todir:"${stagingDir}/WEB-INF/classes/config/", overwrite:true){fileset(dir:"config")} copy(todir:"${stagingDir}/WEB-INF/classes/projectconfig/", overwrite:true){fileset(dir:"projectconfig")} }
7- layout应用与搜索顺序:
1)、gsp模板文件里指定的layout 比如:<meta name="layout" content="main" />
2)、在控制器里指定的layout 比如:static layout = 'main'
3)、layouts/{ControlerName}/{ActionName}.gsp
4)、layouts/{ControlerName}.gsp
5)、layouts/application.gsp
8- 获取所有的服务类:grailsApplication.getArtefacts('Service')
9- 在Groovy源包里的类,如果设计成需要被继承的,那边不能放在默认包下,必须有包名称
10- grails由于域类、服务类多、加载的类多等关系,比较占perm内存,经常会内存溢出,需要修改jvm的 perm内存配置。
tomcat操作如下:需要在bin/catalina.sh (catalina.bat windows平台) 调整一下jvm的内存设置,即在注释后面加上下面一句话,该配置内存量大小,根据实际来调整
catalina.bat:
set JAVA_OPTS=-Xms128m -Xmx1300m -XX:PermSize=128m -XX:MaxPermSize=500m
catalina.sh:
JAVA_OPTS='-Xms128m -Xmx1300m -XX:PermSize=128m -XX:MaxPermSize=500m'
11- 升级Grails版本时,可能出现一些插件升级不了,删除grails的项目缓存就可以,一般在用户目录的.grails/projects
12- 用GORM批量(大量)维护数据时,性能相对与grovy.sql.Sql, jdbc 等慢很多。
如果是主子表的话,用域类.addXXX(),GORM性能会急剧下降(不执行.save, )。
建议用grovy.sql.Sql, jdbc,直接数据库存储过程等高效方法。
13- 在Web服务器里部署多个Grails应用时,无法reload。 可以用 取消部署,再部署 操作来代替。
14- src/groovy使用服务类
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH def ctx = AH.application.mainContext def authService=ctx.authService
15- 获取网站根目录的绝对路径:org.codehaus.groovy.grails.web.context.ServletContextHolder.servletContext.getRealPath('/')
16- Groovy转化成接口几种方式:
a)、闭包方式:{} as 接口
b)、Map方式:[方法1名称:闭包, 方法2名称:闭包] as 接口
17- controller里的render使用经验:
1)、response.setStatus(304) 之后还需要 render '' //此处必须写render 否则网页会出错。建议使用 render status:304
2)、在action闭包里调用了response.outputStream,那么默认的contentType='text/html'的属性会被去掉,需要再设置,但不能仍然为'text/html',
如果需要一定要设置contentType='text/html',建议不要使用response.outputStream,可以直接用 render text:content 或 render content。
3)、在render 内容字符串变量。在内容字符串变量里如果还有存在 <meta name="layout" content="main_crs"/> 的布局,依然有效。
4)、render 二进制类型的文件
def getbin = { response.contentType = 'application/octet-stream' File file = new File('./Discipline.pdf') file.withInputStream { response.outputStream << it } //render(contentType:'text/xml', text: file.text) }
18- DataSource.groovy 经验:
1)、pooled=true //Grails用户手册记载默认值为true,通过测试证明实际的默认值为false,用户手册此处有描述错误
2)、在dataSource闭包里使用dbcp优化配置如下:
//以下是 dbcp 重要配置 properties { //针对数据库,不能数据库可能需要做一下调整(默认:空)。经过测试好像没有影响,都会检测数据库链接是否有效 //validationQuery = 'select 1' initialSize = 5 //初始化连接(默认:0) maxIdle=20 //最大空闲连接(默认:8) minIdle=5 //最小空闲连接(默认:0) maxActive=20 //最大连接数量 (默认:8) logAbandoned=true //是否在自动回收超时连接的时候,打印连接的超时错误(默认:false) removeAbandoned=true //是否自动回收超时连接(默认:false) //超时时间(以秒数为单位) //设置超时时间有一个要注意的地方,超时时间=现在的时间-程序中创建Connection的时间,如果maxActive比较大,比如超过100,那么removeAbandonedTimeout可以设置长一点比如180,也就是三分钟无响应的连接进行回收,当然应用的不同设置长度也不同。 removeAbandonedTimeout=180 //(默认:300) maxWait=5000 //超时等待时间以毫秒为单位,maxWait代表当Connection用尽了,多久之后进行回收丢失连接(默认:空) }
3)、在pool=true的情况下才能配置上面 dbcp优化配置properties,否则启动Grails程序就会报错。即使用properties必须启用了数据库连接池pool=true,从此处也证明了第1)点。
4)、在配置了DataSource.groovy后,在服务类里可能会切入数据库事务,未证实。
5)、bean名称为dataSource的,是已经切入了事务,如果需要原始的,使用bean名称 dataSourceUnproxied。
6)、最好将数据源配置放在外部文件中,这样可以避免因为数据源的改变而重新打包的问题。
19- XML使用经验:
1)、XmlSlurper实例的parse(路径),而路径在windows上类似D:\\test/route.xml 会报错误:
java.net.MalformedURLException: unknown protocol: d
建议可以写成parse(new File('D:\\test/route.xml'))
2)、GPathResult类型实际存在attributes()方法,但在api doc里没有,不影响使用
20- Grails使用JSON经验
1)、List、Map可以用as JSON 转成 json格式
2)、下面多种方法输出JSON格式
def json = { def data2 = "[[id:1,name:'yang'],[id:2,name:'gang']]" def data = [[id:1,name:'yang',date:new Date()],[id:2,name:'gang',date:new Date()]] println data //方法1 // render (contentType:'text/json'){ // //[[id:1,name:'yang'],[id:2,name:'gang']] // data // } def jsonFile = new File(baseDir, 'states.json') //states.json为utf-8无BOM格式,内容里有中文,下面各种方法测试都没有乱码 println jsonFile.text def j = JSON.parse(jsonFile.text) //render (contentType:'text/json',text:jsonFile.text)//方法2 //render (contentType:'text/json',text:data2) //方法3 //render (contentType:'text/json',text:data as JSON) //方法4 //render (contentType:'text/json',text:getMap() as JSON) //方法5 //render data as JSON //方法5 //render JSON.parse(data2) //方法6 //render j //方法7 ontentType:'text/html' render contentType:'text/json',text:j //方法8 } def getMap={ [ identifier:"abbreviation", label: "name", items: [ [name:"Alabama测试2", label:"<img width='97px' height='127px' src='images/Alabama.jpg'/>Alabama",abbreviation:"AL"], [name:"Alaska", label:"Alaska",abbreviation:"AK"], ] ] }