通过长堆栈转储,Grails可能有点像熊一样调试.找到问题的根源可能很棘手.我在BootStrap.groovy中做过几次烧伤,例如"def foo = new Foo(a:a,b:b).save()".您最喜欢调试Grails应用程序的技巧是什么?
Chr*_*ing 33
一些一般提示:
less stacktrace.loglinux)...一旦在你的查看器中,搜索.groovy和.gsp ...这通常会带你到你的东西实在在意.?showSource中使用查询字符串打开该视图,即http://localhost:8080/myProject/myController/myAction?showSource...这显示已编译的GSP源,并且堆栈跟踪中的所有GSP行号引用已编译的GSP,而不是实际的GSP来源例:
try {
if(!someDomainObject.save()) {
throw new Exception ("Save failed")
}
} catch(Exception e) {
println e.toString()
// This will at least tell you what is wrong with
// the instance you are trying to save
someDomainObject.errors.allErrors.each {error ->
println error.toString()
}
}
Run Code Online (Sandbox Code Playgroud)
除此之外,很多东西只是归结为识别堆栈跟踪和错误消息......很多时候,Grails在它给你的错误消息中非常无益,但你可以学会识别模式,如下所示:
grails clean或grails upgrade...为了避免这些问题,我总是在命令行上使用以下命令来运行grails:grails clean; yes | grails upgrade; grails run-applib/确保您DataSource.groovy的用户名,密码和主机的数据库内和数据库中的权限都是正确的,并确保你知道你的连接器版本的来龙去脉(即mysql连接器版本5.1.X有一个奇怪的问题,别名,可能需要你useOldAliasMetadataBehavior=true在网址上设置DataSource.groovy)等等.有许多模式需要学会识别.
Jea*_*ash 16
为了增加Chris King关于save的建议,我写了一个可重用的闭包:
Closure saveClosure = { domainObj ->
if(domainObj.save())
println "Domain Object $domainObj Saved"
else
{
println "Errors Found During Save of $domainObj!"
println domainObj.errors.allErrors.each {
println it.defaultMessage
}
}
}
Run Code Online (Sandbox Code Playgroud)然后你可以在任何地方使用它,它将负责错误报告:
def book = new Book(authorName:"Mark Twain")
saveClosure(book)
Run Code Online (Sandbox Code Playgroud)
另外,我使用调试插件 - 它允许额外的日志记录,我将标签添加到我的主要底部 - 这使我可以查看会话/请求中的所有变量.
运行时日志插件允许在运行时启用日志记录.
在编写这个答案时,P6SPY插件似乎也很有用 - 它通过充当代理来记录您的应用程序对数据库所做的所有语句.
Grails Console也很有用.我用它来交互式地浏览并试验一些代码,这些代码在调试时也很方便.
当然,能够通过调试器是很好的.我切换到IntelliJ IDEA,因为它具有最好的Grails/Groovy支持.
小智 14
我曾经问过一位经验丰富的常规开发人员,他是如何有效地调试他的应用程序的.他的回答是:
我写测试!
他有一个非常好的观点:如果你的代码有足够的单元和集成测试,你几乎不需要调试任何东西.另外,你可以向你的开发人员说出类似的东西......
对于Grails:
使用GrailsUtil记录异常.
try{
...
}catch (Exception e){
log.error("some message", GrailsUtil.sanitize(e))
...
}
Run Code Online (Sandbox Code Playgroud)
我不确定这是否可以开箱即用,但在 webapps 中,我发现“我是谁?”很有用。工具在各种视图文件中。
这个想法是在呈现的 HTML 中发出一条消息,以识别片段。当我第一次遇到应用程序时尤其如此。
在 Grails 中,我使用自定义标记来完成此操作。例如,考虑一个学生的 list.gsp:
<g:debug msg="student list" />
Run Code Online (Sandbox Code Playgroud)
这是代码:
class MiscTagLib {
def debug = { map ->
if (grailsApplication.config.grails.views.debug.mode == true) {
def msg = map['msg']
out << "<h2>${msg}</h2><br/>"
}
}
}
Run Code Online (Sandbox Code Playgroud)
关键是,如果需要,您可以将这些标签留在那里,因为它们仅在 Config.groovy 中启用该模式时才会出现:
grails.views.debug.mode=true
Run Code Online (Sandbox Code Playgroud)
将此代码添加到Bootsrap.groovy:init将覆盖save方法并执行其他一些代码,在这种情况下打印出错误消息.
class BootStrap {
def grailsApplication
def init = {servletContext ->
grailsApplication.domainClasses.each { clazz ->
clazz.clazz.get(-1)
def gormSave = clazz.metaClass.getMetaMethod('save')
clazz.metaClass.save = {->
def savedInstance = gormSave.invoke(delegate)
if (!savedInstance) {
delegate.errors.each {
println it
}
}
savedInstance
}
def gormSaveMap = clazz.metaClass.getMetaMethod('save', Map)
clazz.metaClass.save = { Map m ->
def savedInstance = gormSaveMap.invoke(delegate, m)
if (!savedInstance) {
delegate.errors.each {
println it
}
}
savedInstance
}
def gormSaveBoolean = clazz.metaClass.getMetaMethod('save', Boolean)
clazz.metaClass.save = { Boolean b ->
def savedInstance = gormSaveBoolean.invoke(delegate, b)
if (!savedInstance) {
delegate.errors.each {
println it
}
}
savedInstance
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
希望有人帮助:)
(我知道它不是真的干)
参考:http://grails.1312388.n4.nabble.com/How-to-override-save-method-on-domain-class-td3021424.html
| 归档时间: |
|
| 查看次数: |
16808 次 |
| 最近记录: |