3.1 基本配置 - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith
Version: null
3.1 基本配置
For general configuration Grails provides a file called Then later in your application you can access these settings in one of two ways. The most common is from the GrailsApplication object, which is available as a variable in controllers and tag libraries:The other way involves getting a reference to the ConfigurationHolder class that holds a reference to the configuration object:
Grails提供了一个 grails-app/conf/Config.groovy. This file uses Groovy's ConfigSlurper which is very similar to Java properties files except it is pure Groovy hence you can reuse variables and use proper Java types!You can add your own configuration in here, for example:foo.bar.hello = "world"assert "world" == grailsApplication.config.foo.bar.helloimport org.codehaus.groovy.grails.commons.* … def config = ConfigurationHolder.config assert "world" == config.foo.bar.hello
ConfigurationHolder and ApplicationHolder are deprecated and will be removed in a future version of Grails, so it is highly preferable to access theGrailsApplicationand config from thegrailsApplicationvariable.
grails-app/conf/Config.groovy 配置文件,用来完成通用的配置。此文件除了是Groovy的ConfigSlurper 之外,其他非常类似于Java属性文件,这样就既可以重用变量又可以使用合适的Java类!你可以添加属于你自己的配置信息,例如:foo.bar.hello = "world"assert "world" == grailsApplication.config.foo.bar.helloimport org.codehaus.groovy.grails.commons.* … def config = ConfigurationHolder.config assert "world" == config.foo.bar.hello
ConfigurationHolder和ApplicationHolder现在已经被废弃,并且将在Grails的未来版本中移除,因此强烈推荐采用GrailsApplication的实例变量grailsApplication方式来访问配置对象。
3.1.1 内置选项
Grails also provides the following configuration options:
Grails同样提供了如下配置选项:
grails.config.locations- The location of properties files or addition Grails Config files that should be merged with main configurationgrails.enable.native2ascii- Set this to false if you do not require native2ascii conversion of Grails i18n properties filesgrails.views.default.codec- Sets the default encoding regime for GSPs - can be one of 'none', 'html', or 'base64' (default: 'none'). To reduce risk of XSS attacks, set this to 'html'.grails.views.gsp.encoding- The file encoding used for GSP source files (default is 'utf-8')grails.mime.file.extensions- Whether to use the file extension to dictate the mime type in Content Negotiationgrails.mime.types- A map of supported mime types used for Content Negotiationgrails.serverURL- A string specifying the server URL portion of absolute links, including server name e.g. grails.serverURL="http://my.yourportal.com". See createLink.
grails.config.locations- 配置文件的位置,包括属性文件或者其他需要合并到主配置的Grails配置文件grails.enable.native2ascii- 如果不需要native2ascii来转化Grails i18n属性文件的话,将该选项设为falsegrails.views.default.codec- 设置GSP的默认编码制式,可以是:'none', 'html', 或者 'base64' (缺省为'none'). 为了减少XSS攻击的风险,建议设置成'html'.grails.views.gsp.encoding- GSP源文件的字符编码(缺省是'utf-8')grails.mime.file.extensions- 是否使用文件的扩展名表示内容协商中的媒体类型(mime type)grails.mime.types- 内容协商所支持的媒体类型grails.serverURL- 一个指向服务器URL的绝对地址,包括服务器名称,比如grails.serverURL="http://my.yourportal.com". 详细请看createLink。
War generation
grails.project.war.file- Sets the name and location of the WAR file generated by the war commandgrails.war.dependencies- A closure containing Ant builder syntax or a list of JAR filenames. Lets you customise what libaries are included in the WAR file.grails.war.copyToWebApp- A closure containing Ant builder syntax that is legal inside an Ant copy, for example "fileset()". Lets you control what gets included in the WAR file from the "web-app" directory.grails.war.resources- A closure containing Ant builder syntax. Allows the application to do any other other work before building the final WAR file
War生成选项
grails.project.war.file- 设置 war 命令生成WAR文件的名称和位置grails.war.dependencies- 符合Ant生成器语法的闭包或者JAR文件的列表,让你可以定制WAR文件所需要的依赖库。grails.war.copyToWebApp- 完成Ant拷贝且满足其生成器语法的闭包,比如"fileset()"。让你控制"web-app"目录下那些资源可以被打包到WAR文件中。grails.war.resources- 符合Ant生成器语法的闭包,运行应用在构建最终的WAR文件前做任何其他的预处理
3.1.2 日志
The Basics
Grails uses its common configuration mechanism to provide the settings for the underlying Log4j log system, so all you have to do is add alog4j setting to the file grails-app/conf/Config.groovy.So what does this log4j setting look like? Here's a basic example:log4j = {
error 'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages' // GSP warn 'org.apache.catalina'
}基础
Grails利用其自身的配置机制来提供对 Log4j 日志系统的配置,因此你所需要做的只是将log4j配置添加到grails-app/conf/Config.groovy配置文件中。那么log4j该配置什么样子呢?下边是一个基础的示例:log4j = {
error 'org.codehaus.groovy.grails.web.servlet', // controllers
'org.codehaus.groovy.grails.web.pages' // GSP warn 'org.apache.catalina'
}Logging levels
The are several standard logging levels, which are listed here in order of descending priority:- off
- fatal
- error
- warn
- info
- debug
- trace
- all
log.error(msg) will log a message at the 'error' level. Likewise, log.debug(msg) will log it at 'debug'. Each of the above levels apart from 'off' and 'all' have a corresponding log method of the same name.The logging system uses that message level combined with the configuration for the logger (see next section) to determine whether the message gets written out. For example, if you have an 'org.example.domain' logger configured like so:warn 'org.example.domain'
日志级别
以下是按照优先级降序(由高到低)排列的标准日志级别:- off
- fatal
- error
- warn
- info
- debug
- trace
- all
log.error(msg)方法,就是使用其'error'级别,同理log.debug(msg)指定的是'debug'。上述从'off'到'all'的级别都有一个同名对应的日志方法。日志系统使用记录器(介绍见下一节)配置的 message 级别来判断此消息是否应该输出,比如你有一个'org.example.domain'记录器,其配置如下:warn 'org.example.domain'
Loggers
Loggers are fundamental to the logging system, but they are a source of some confusion. For a start, what are they? Are they shared? How do you configure them?A logger is the object you log messages to, so in the calllog.debug(msg), log is a logger instance (of type Log). These loggers are cached and uniquely identified by name, so if two separate classes use loggers with the same name, those loggers are actually the same instance.There are two main ways to get hold of a logger:
- use the
loginstance injected into artifacts such as domain classes, controllers and services; - use the Commons Logging API directly.
log property, then the name of the logger is 'grails.app.<type>.<className>', where type is the type of the artifact, for example 'controller' or 'service, and className is the fully qualified name of the artifact. For example, if you have this service:package org.exampleclass MyService {
…
}package org.otherimport org.apache.commons.logging.LogFactoryclass MyClass { private static final log = LogFactory.getLog(this) … }
getLog() method, such as "myLogger", but this is less common because the logging system treats names with dots ('.') in a special way.
记录器(Loggers)
记录器是日志系统的基础,但是依然有一些根源上的困惑,比如它们是什么?可否共享?以及如何配置它们?一个记录器就是你要将信息记录进去的对象,因此log.debug(msg)中的log就是一个记录器实例(其类型是Log). 这些记录器通过唯一的名字标识被缓存起来,因此如果两个不同的类使用同一个名字的记录器,那么这些记录器是同一个运行实例。主要有两种方法来获取一个记录器:
- 使用注入到工件(比如领域类、控制器以及服务)中的
log实例 - 直接使用Commons Logging API。
log属性,那么记录器的名字是'grails.app.<type>.<className>',此处的type是工件的类型,比如'controller'或者'service',而className则是此工件的全名,假设你有如下的一个服务:package org.exampleclass MyService {
…
}package org.otherimport org.apache.commons.logging.LogFactoryclass MyClass { private static final log = LogFactory.getLog(this) … }
getLog()方法,但是这种用法并不常见,因为在日志系统中,名字中的点('.')是被特殊处理的。Configuring loggers
You have already seen how to configure loggers in Grails:log4j = {
error 'org.codehaus.groovy.grails.web.servlet'
}org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet class and the org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest one.In other words, loggers are hierarchical. This makes configuring them by package much simpler than it would otherwise be.The most common things that you will want to capture log output from are your controllers, services, and other artifacts. Use the convention mentioned earlier to do that: grails.app.<artifactType>.<className> . In particular the class name must be fully qualifed, i.e. with the package if there is one:log4j = {
// Set level for all application artifacts
info "grails.app" // Set for a specific controller in the default package
debug "grails.app.controllers.YourController" // Set for a specific domain class
debug "grails.app.domain.org.example.Book" // Set for all taglibs
info "grails.app.taglib"
}conf- For anything undergrails-app/confsuch asBootStrap.groovy(but excluding filters)filters- For filterstaglib- For tag librariesservices- For service classescontrollers- For controllersdomain- For domain entities
org.codehaus.groovy.grails.commons- Core artifact information such as class loading etc.org.codehaus.groovy.grails.web- Grails web request processingorg.codehaus.groovy.grails.web.mapping- URL mapping debuggingorg.codehaus.groovy.grails.plugins- Log plugin activitygrails.spring- See what Spring beans Grails and plugins are definingorg.springframework- See what Spring is doingorg.hibernate- See what Hibernate is doing
配置记录器
你已在Grails中看到如何配置记录器了,比如:log4j = {
error 'org.codehaus.groovy.grails.web.servlet'
}org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet和org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest。换句话说,记录器是分层级的,这使得用包名来配置比其他方式容易很多。在应用中,你最常记录的是控制器、服务以及其他工件的输出日志,这可以通过以前提到过的_grails.app.<artifactType>.<className>_来实现。需要注意的是类名必须是全名(包括包名),如下所示:log4j = {
// Set level for all application artifacts
info "grails.app" // Set for a specific controller in the default package
debug "grails.app.controllers.YourController" // Set for a specific domain class
debug "grails.app.domain.org.example.Book" // Set for all taglibs
info "grails.app.taglib"
}conf-grails-app/conf下的任何类(过滤器除外),比如:BootStrap.groovyfilters- 过滤器taglib- 标签库services- 服务类controllers- 控制器domain- 领域类
org.codehaus.groovy.grails.commons- 核心工件信息,比如类加载等org.codehaus.groovy.grails.web- Grails的web请求处理org.codehaus.groovy.grails.web.mapping- 调试URL映射信息org.codehaus.groovy.grails.plugins- 记录插件的活动情况grails.spring- 在Grails和插件中定义的Spring的beansorg.springframework- Spring的活动情况org.hibernate- Hibernate的活动情况
The Root Logger
All logger objects inherit their configuration from the root logger, so if no explicit configuration is provided for a given logger, then any messages that go to that logger are subject to the rules defined for the root logger. In other words, the root logger provides the default configuration for the logging system.Grails automatically configures the root logger to only handle messages at 'error' level and above, and all the messages are directed to the console (stdout for those with a C background). You can customise this behaviour by specifying a 'root' section in your logging configuration like so:log4j = {
root {
info()
}
…
}log4j = {
appenders {
file name:'file', file:'/var/logs/mylog.log'
}
root {
debug 'stdout', 'file'
}
}org.apache.log4j.Logger instance is passed as an argument to the log4j closure. This lets you work with the logger directly:log4j = { root ->
root.level = org.apache.log4j.Level.DEBUG
…
}Logger instance, refer to the Log4j API documentation.Those are the basics of logging pretty well covered and they are sufficient if you're happy to only send log messages to the console. But what if you want to send them to a file? How do you make sure that messages from a particular logger go to a file but not the console? These questions and more will be answered as we look into appenders.
根记录器
所有的记录器对象配置都是从其根记录器继承而来的,因此一个记录器如果没有明确地配置,那么此记录器的任何消息规则都使用其根记录器的定义。或者说,根记录器提供日志系统的缺省配置。Grails自动地将根记录器配置成只处理'error'级别地消息,并且将这些消息显示在命令行终端(stdout是从C语言中借鉴而来)中。你可以通过'root'来重新定义其行为,比如:log4j = {
root {
info()
}
…
}log4j = {
appenders {
file name:'file', file:'/var/logs/mylog.log'
}
root {
debug 'stdout', 'file'
}
}org.apache.log4j.Logger实例,这让你可以直接操作logger:log4j = { root ->
root.level = org.apache.log4j.Level.DEBUG
…
}Logger实例的信息,请参考Log4j API文档。如果你仅仅满足于将日志信息输出到字符终端,那么目前所涉及到的基本信息已经足够用的了。但是如果你还想输出到一个文件呢?以及想将特定记录器的信息输出到一个特定文件,而不是字符终端,又该如何做呢?这些疑问将在下一节的输出器中得到解答。Appenders
Loggers are a useful mechanism for filtering messages, but they don't physically write the messages anywhere. That's the job of the appender, of which there are various types. For example, there is the default one that writes messages to the console, another that writes them to a file, and several others. You can even create your own appender implementations!This diagram shows how they fit into the logging pipeline:
As you can see, a single logger may have several appenders attached to it. In a standard Grails configuration, the console appender named 'stdout' is attached to all loggers through the default root logger configuration. But that's the only one. Adding more appenders can be done within an 'appenders' block:log4j = {
appenders {
rollingFile name: "myAppender",
maxFileSize: 1024,
file: "/tmp/logs/myApp.log"
}
}| Name | Class | Description |
|---|---|---|
| jdbc | JDBCAppender | Logs to a JDBC connection. |
| console | ConsoleAppender | Logs to the console. |
| file | FileAppender | Logs to a single file. |
| rollingFile | RollingFileAppender | Logs to rolling files, for example a new file each day. |
name, maxFileSize and file properties of the RollingFileAppender instance.You can have as many appenders as you like - just make sure that they all have unique names. You can even have multiple instances of the same appender type, for example several file appenders that log to different files.If you prefer to create the appender programmatically or if you want to use an appender implementation that's not available in the above syntax, simply declare an appender entry with an instance of the appender you want:import org.apache.log4j.*log4j = { appenders { appender new RollingFileAppender( name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log") } }
JMSAppender, SocketAppender, SMTPAppender, and more.Once you have declared your extra appenders, you can attach them to specific loggers by passing the name as a key to one of the log level methods from the previous section:error myAppender: "grails.app.controllers.BookController"error myAppender: "grails.app.controllers.BookController", myFileAppender: ["grails.app.controllers.BookController", "grails.app.services.BookService"], rollingFile: "grails.app.controllers.BookController"
myFileAppender) by using a list.Be aware that you can only configure a single level for a logger, so if you tried this code:error myAppender: "grails.app.controllers.BookController" debug myFileAppender: "grails.app.controllers.BookController" fatal rollingFile: "grails.app.controllers.BookController"
log4j = {
appenders {
console name: "stdout", threshold: org.apache.log4j.Level.INFO
}
}threshold argument which determines the cut-off for log messages. This argument is available for all appenders, but do note that you currently have to specify a Level instance - a string such as "info" will not work.
输出器(Appenders)
记录器是很好的信息过滤机制,但是它们并不将信息进行任何物理的写操作,这些都是不同类型的输出器所做的事。比如缺省的一个就是将信息输出到字符终端,另外一个输出到一个文件等等,更有甚者,你还可以创建你自己的输出器!下图展示了输出器在日志管道系统中的位置:
如你所见,一个记录器可以挂载多个输出器。 在一个标准的Grails配置中,所有从根记录器而来的记录器都有一个名为'stdout'并唯一的字符终端输出器。你可以通过'appenders'代码块来增加更多的输出器,比如:log4j = {
appenders {
rollingFile name: "myAppender",
maxFileSize: 1024,
file: "/tmp/logs/myApp.log"
}
}| 名称 | 类名 | 描述 |
|---|---|---|
| jdbc | JDBCAppender | 记录到JDBC连接。 |
| console | ConsoleAppender | 记录到字符终端。 |
| file | FileAppender | 记录到一个文件。 |
| rollingFile | RollingFileAppender | 记录到滚动文件,比如一天一个新文件。 |
RollingFileAppender的实例中,name、maxFileSize和file都是其属性而已。你可以添加任意你需要的输出器,只要确保它们的名字不重复就可以了。同一类型的输出器,你甚至还可以有多个实例,比如将日志内容输出到不同的文件中。你如果倾向于手工创建输出器或者你需要的输出器不在上述的列表中,那么你只需简单的声明一个appender代码即可,比如:import org.apache.log4j.*log4j = { appenders { appender new RollingFileAppender( name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log") } }
JMSAppender、SocketAppender和SMTPAppender等输出器。一旦你声明了这些额外的输出器,那么你还需要将它们跟特定的记录器进行关联,这可以通过记录器的名称和记录级别来完成,比如:error myAppender: "grails.app.controllers.BookController"error myAppender: "grails.app.controllers.BookController", myFileAppender: ["grails.app.controllers.BookController", "grails.app.services.BookService"], rollingFile: "grails.app.controllers.BookController"
myFileAppender)中如何通过列表来配置多个记录器。需要注意的是:一个记录器只能配置一个级别,如果你配置了如下的内容:error myAppender: "grails.app.controllers.BookController" debug myFileAppender: "grails.app.controllers.BookController" fatal rollingFile: "grails.app.controllers.BookController"
log4j = {
appenders {
console name: "stdout", threshold: org.apache.log4j.Level.INFO
}
}threshold参数用以判断那些消息需要截去。此参数对所有的输出器有效,但需要注意的是你必须使用Level实例-"info"字符串的便利用法不能工作。Custom Layouts
By default the Log4j DSL assumes that you want to use a PatternLayout. However, there are other layouts available including:xml- Create an XML log filehtml- Creates an HTML log filesimple- A simple textual logpattern- A Pattern layout
layout setting:log4j = {
appenders {
console name: "customAppender",
layout: pattern(conversionPattern: "%c{2} %m%n")
}
}log4j = {
appenders {
console name: "stdout",
layout: pattern(conversionPattern: "%c{2} %m%n")
}
}自定义布局
多数情况下,Log4j DSL使用缺省的PatternLayout,除此之外,还有以下布局可以选择:xml- 创建一个XML日志文件html- 创建一个HTML日志文件simple- 简单的文本文件pattern- Pattern布局的文件
layout来给一个输出器自定义布局:log4j = {
appenders {
console name: "customAppender",
layout: pattern(conversionPattern: "%c{2} %m%n")
}
}log4j = {
appenders {
console name: "stdout",
layout: pattern(conversionPattern: "%c{2} %m%n")
}
}Environment-specific configuration
Since the logging configuration is insideConfig.groovy, you can put it inside an environment-specific block. However, there is a problem with this approach: you have to provide the full logging configuration each time you define the log4j setting. In other words, you cannot selectively override parts of the configuration - it's all or nothing.To get around this, the logging DSL provides its own environment blocks that you can put anywhere in the configuration:log4j = {
appenders {
console name: "stdout",
layout: pattern(conversionPattern: "%c{2} %m%n") environments {
production {
rollingFile name: "myAppender", maxFileSize: 1024,
file: "/tmp/logs/myApp.log"
}
}
} root {
//…
} // other shared config
info "grails.app.controllers" environments {
production {
// Override previous setting for 'grails.app.controllers'
error "grails.app.controllers"
}
}
}root definition, but you can put the root definition inside an environment block.
特定环境的配置
既然日志是配置在Config.groovy中,你自然也就可以将其配置在环境相关的代码块中。不过这种方式有一个小问题:每次你配置log4j的时候,你必须提供完整的日志配置。或者换句话说,你不能选择性的覆盖部分配置-要么全覆盖要么一点也不覆盖。为了避免此问题,日志DSL提供了自己的environment代码块配置,这样你就可以自由的配置了。log4j = {
appenders {
console name: "stdout",
layout: pattern(conversionPattern: "%c{2} %m%n") environments {
production {
rollingFile name: "myAppender", maxFileSize: 1024,
file: "/tmp/logs/myApp.log"
}
}
} root {
//…
} // other shared config
info "grails.app.controllers" environments {
production {
// Override previous setting for 'grails.app.controllers'
error "grails.app.controllers"
}
}
}root定义的_内部_,但是你可以将其放在environment代码块中。Full stacktraces
When exceptions occur, there can be an awful lot of noise in the stacktrace from Java and Groovy internals. Grails filters these typically irrelevant details and restricts traces to non-core Grails/Groovy class packages.When this happens, the full trace is always logged to theStackTrace logger, which by default writes its output to a file called stacktrace.log. As with other loggers though, you can change its behaviour in the configuration. For example if you prefer full stack traces to go to the console, add this entry:error stdout: "StackTrace"log4j = {
appenders {
rollingFile name: "stacktrace", maxFileSize: 1024,
file: "/var/tmp/logs/myApp-stacktrace.log"
}
}log4j = {
appenders {
'null' name: "stacktrace"
}
}grails.full.stacktrace VM property to true:grails -Dgrails.full.stacktrace=true run-app完整的栈跟踪
当一个异常发生时,可能有大量的来自Java和Groovy内部栈跟踪信息,这其实是很恼人的。Grails的过滤器将这些不相干的细节屏蔽了,并且将栈的跟踪信息限制非Grails/Groovy的类包范围。当异常发生时,完整的跟踪信息总是被记录到StackTrace记录器中,此记录器缺省将内容输出到一个名为stacktrace.log的文件中。跟其他的记录器配合,你还可以改变其在配置中的行为,比如你可以将栈跟踪信息输出到字符终端:error stdout: "StackTrace"log4j = {
appenders {
rollingFile name: "stacktrace", maxFileSize: 1024,
file: "/var/tmp/logs/myApp-stacktrace.log"
}
}log4j = {
appenders {
'null' name: "stacktrace"
}
}grails.full.stacktrace为true来实现,比如:grails -Dgrails.full.stacktrace=true run-appMasking Request Parameters From Stacktrace Logs
When Grails logs a stacktrace, the log message may include the names and values of all of the request parameters for the current request. To mask out the values of secure request parameters, specify the parameter names in thegrails.exceptionresolver.params.exclude config property:grails.exceptionresolver.params.exclude = ['password', 'creditCard']
grails.exceptionresolver.logRequestParameters config property to false. The default value is true when the application is running in DEVELOPMENT mode and false for all other modes.grails.exceptionresolver.logRequestParameters=false屏蔽栈跟踪日志中的请求参数
当Grails记录栈跟踪信息的时候,有可能将当前请求参数的名称和值一并包含了。为了避免隐私信息被记录,可以通过设置grails.exceptionresolver.params.exclude来屏蔽那些有关隐私字段的名称,比如:grails.exceptionresolver.params.exclude = ['password', 'creditCard']
grails.exceptionresolver.logRequestParameters为false的方式来禁止掉。其运行于“开发”模式下,缺省值是true,除此之外的其他模式为false。grails.exceptionresolver.logRequestParameters=falseLogger inheritance
Earlier, we mentioned that all loggers inherit from the root logger and that loggers are hierarchical based on '.'-separated terms. What this means is that unless you override a parent setting, a logger retains the level and the appenders configured for that parent. So with this configuration:log4j = {
appenders {
file name:'file', file:'/var/logs/mylog.log'
}
root {
debug 'stdout', 'file'
}
}log4j = {
appenders {
…
}
root {
…
} info additivity: false
stdout: ["grails.app.controllers.BookController",
"grails.app.services.BookService"]
}info additivity: false, ["grails.app.controllers.BookController", "grails.app.services.BookService"]
记录器的继承
早期,我们提到过所有的记录器都是从跟记录器继承而来的,其继承的层次是通过'.'来分割的。这意味着一个记录器将一直使用其上一级的级别和输出器配置,当然了你覆盖除外。以如下配置为例:log4j = {
appenders {
file name:'file', file:'/var/logs/mylog.log'
}
root {
debug 'stdout', 'file'
}
}log4j = {
appenders {
…
}
root {
…
} info additivity: false
stdout: ["grails.app.controllers.BookController",
"grails.app.services.BookService"]
}info additivity: false, ["grails.app.controllers.BookController", "grails.app.services.BookService"]
Customizing stack trace printing and filtering
Stacktraces in general and those generated when using Groovy in particular are quite verbose and contain many stack frames that aren't interesting when diagnosing problems. So Grails uses a implementation of theorg.codehaus.groovy.grails.exceptions.StackTraceFilterer interface to filter out irrelevant stack frames. To customize the approach used for filtering, implement that interface in a class in src/groovy or src/java and register it in Config.groovy:grails.logging.stackTraceFiltererClass =
'com.yourcompany.yourapp.MyStackTraceFilterer'org.codehaus.groovy.grails.exceptions.StackTracePrinter interface in a class in src/groovy or src/java and register it in Config.groovy:grails.logging.stackTracePrinterClass =
'com.yourcompany.yourapp.MyStackTracePrinter'org.codehaus.groovy.grails.web.errors.ErrorsViewStackTracePrinter and it's registered as a Spring bean. To use your own implementation, either implement the org.codehaus.groovy.grails.exceptions.StackTraceFilterer directly or subclass ErrorsViewStackTracePrinter and register it in grails-app/conf/spring/resources.groovy as:import com.yourcompany.yourapp.MyErrorsViewStackTracePrinterbeans = { errorsViewStackTracePrinter(MyErrorsViewStackTracePrinter,
ref('grailsResourceLocator'))
}自定义栈跟踪的输出和过滤
总的来说,Groovy生成的那些特定栈跟踪信息是比较冗余的,并且对于诊断问题也造成不少的干扰。因此Grails使用org.codehaus.groovy.grails.exceptions.StackTraceFilterer接口来完成对不相关信息的过滤。要完成对特定信息的过滤,只需要再src/groovy或者src/java中实现上述接口,并且在Config.groovy注册一下即可:grails.logging.stackTraceFiltererClass =
'com.yourcompany.yourapp.MyStackTraceFilterer'org.codehaus.groovy.grails.exceptions.StackTracePrinter接口,并且在Config.groovy中注册即可:grails.logging.stackTracePrinterClass =
'com.yourcompany.yourapp.MyStackTracePrinter'org.codehaus.groovy.grails.web.errors.ErrorsViewStackTracePrinter,并且被注册为一个Spring服务。你也可以通过实现org.codehaus.groovy.grails.exceptions.StackTraceFilterer接口或者定义ErrorsViewStackTracePrinter的子类来实现属于自己的渲染器,并且将其在grails-app/conf/spring/resources.groovy中注册,如下:import com.yourcompany.yourapp.MyErrorsViewStackTracePrinterbeans = { errorsViewStackTracePrinter(MyErrorsViewStackTracePrinter,
ref('grailsResourceLocator'))
}Alternative logging libraries
By default, Grails uses Log4J to do its logging. For most people this is absolutely fine, and many users don't even care what logging library is used. But if you're not one of those and want to use an alternative, such as the JDK logging package or logback, you can do so by simply excluding a couple of dependencies from the global set and adding your own:grails.project.dependency.resolution = {
inherits("global") {
excludes "grails-plugin-logging", "log4j"
}
…
dependencies {
runtime "ch.qos.logback:logback-core:0.9.29"
…
}
…
}替换日志框架
缺省情况下,Grails使用Log4J来完成日志操作。对大多数的人来说,这绝对绰绰有余,而且很多的用户也根本就不关心使用那个日志框架。但是,如果你不是那些大多数,并且确实很想使用另外一个替代品,比如JDK自带的日志包或者logback。这时候,你只需要简单地全局设置中排除一些依赖,并且添加你自己地依赖即可,比如:grails.project.dependency.resolution = {
inherits("global") {
excludes "grails-plugin-logging", "log4j"
}
…
dependencies {
runtime "ch.qos.logback:logback-core:0.9.29"
…
}
…
}3.1.3 配置GORM
Grails provides the following GORM configuration options:
and to enable failOnError for domain classes by package:
Grails提供了如下的GORM配置选项:
grails.gorm.failOnError- If set totrue, causes thesave()method on domain classes to throw agrails.validation.ValidationExceptionif validation fails during a save. This option may also be assigned a list of Strings representing package names. If the value is a list of Strings then the failOnError behavior will only be applied to domain classes in those packages (including sub-packages). See the save method docs for more information.
grails.gorm.failOnError=truegrails.gorm.failOnError = ['com.companyname.somepackage',
'com.companyname.someotherpackage']grails.gorm.failOnError- 如果此选项值为true并且在保存的时候 校验 失败,那么此领域类的save()方法将抛出一个grails.validation.ValidationException异常。此选项的值还可以是代表包名的字符串列表。如果是字符串列表的话,那么failOnError仅仅作用于属于这些包名(包括子包名)的领域类。更多详细信息请参考 save 方法
grails.gorm.failOnError=truegrails.gorm.failOnError = ['com.companyname.somepackage',
'com.companyname.someotherpackage']
