Grails配置-基本配置-如何覆盖默认配置,在哪里进行自定义配置

article/2025/9/13 18:28:42

文章目录

  • Grails配置
    • 基本配置
      • Grails4风格配置
      • Grails2风格的Groovy配置
      • 使用GrailsApplication对象访问配置信息
        •   在控制器中使用grailsApplication对象
        •   能获取到的配置信息有哪些
        •   在业务层中使用grailsApplication对象方式一
        •   在业务层中使用grailsApplication对象方式二
      • 使用Spring值注解注入配置信息
      • 在application.yml中访问命令行参数或者系统参数
      • 使用外部application.yml文件
      • 内置的一些设置,了解一下有好处
      • Logging配置
        •   Logging实例演示
        •   logback.groovy 默认的日志配置
        •   彩色日志
          •   1. IDEA控制台彩色日志输出方式一
          •   2. IDEA控制台彩色日志输出方式二
          •   3. 打包后的项目默认是彩色日志,不需其他配置
        •   程序报错时,指定敏感请求参数不写入日志
        •   完全关闭请求参数日志记录功能
        •   使用外部日志配置文件
          •   1.使用logging.config指定外部Logback配置文件
          •   2.使用JVM启动参数配置外部日志文件
          •   3. 系统环境变量添加`LOGGING_CONFIG`
      • GORM配置
        •   为所有领域类启用 failOnError
        •   按包名为领域类启用 failOnError
      • 小结

Grails配置

在上一讲中,我们使用Grails的默认约定配置,没有进行任何其他配置就完成了Grails入门学习。Grails是一个“约定优于配置”的框架,只使用默认配置是不够的,我们还需要了解在需要时在哪里以及如何覆盖约定配置。

基本配置

Grails4风格配置

Grails4 中有两种配置:构建配置和运行时配置。

  • 构建配置:通常通过 Gradle 和 build.gradle 文件完成。
  • 运行时配置:默认情况下,在 YAML 文件中指定,文件位于 grails-app/conf/application.yml。

Grails2风格的Groovy配置

如果喜欢以前的Grails2风格的Groovy配置,可以使用Groovy 的 ConfigSlurper 语法指定配置。有两个 Groovy 配置文件可用:grails-app/conf/application.groovy 和 grails-app/conf/runtime.groovy:

  • application.groovy:用于不依赖于应用程序类的配置,因为加载这个配置文件的时候还没有加载应用程序的类。
  • runtime.groovy: 用于依赖于应用程序类的配置。

在Groovy配置中可以使用以下内置变量。

变量描述
userHome运行 Grails 应用程序的帐户的主目录的位置。对于Linux系统就是/home下的账户目录,例如/home/test
grailsHome安装 Grails 的目录的位置。如果设置了 GRAILS_HOME 环境变量,则使用它。
appName出现在 build.gradle 中的应用程序名称。
appVersion出现在 build.gradle 中的应用程序版本。

这些变量不能在conf/application.yml和build.gradle中使用。

使用GrailsApplication对象访问配置信息

可以在控制器和标签库中使用内置的grailsApplication对象获取运行时配置(application.yml中)的信息。
现在添加一个运行时配置信息

book.title="《Grails教程》"
book.author.name="肖伞"

添加到conf/application.yml中的格式为:

book:title: "《Grails教程》"author:name: "肖伞"

  在控制器中使用grailsApplication对象

修改HelloController.groovy,添加hello动作,读取application.yml信息

package helloworldgrails4class HelloController {def index() {render "Hello World!"}def hello() {// 内置grailsApplication变量可以直接使用,使用getProperty(String name)方法获取application.yml中的配置信息def bookTitle = grailsApplication.config.getProperty('book.title')// 获取application.xml中配置的作者姓名def bookAuthorName = grailsApplication.config.getProperty('book.author.name')// 获取application.xml中配置的书籍价格,默认获取值的类型是String类型,通过第二个参数值的类型,值为空时返回第三个参数作为默认值def bookPrice = grailsApplication.config.getProperty('book.price', Integer, 50)// 注意这里没有配置 book.price, 应该返回默认值 50render "bookTitle = ${bookTitle}, bookAuthorName = ${bookAuthorName}, bookPrice = ${bookPrice}"}
}

启动项目访问http://localhost:8080/hello/helo
第一个hello是控制器的名字
第二个hello是动作的名字
grailsApplication获取application.yml配置信息
grailsApplication 对象的 config 属性是 Config 接口的一个实例,它提供了许多有用的方法来读取应用程序的配置。
特别是getProperty 方法,可以很方便的获取运行时配置属性信息,同时指定属性类型(默认类型为 String)和提供默认返回值。

注意:
Config 实例是基于 Spring 的 PropertySource 概念的合并配置。
即将开发环境、计算机操作系统属性和本地应用程序中的配置信息合并为一个对象了。

那么到底将哪些配置信息合并到一起了呢,我们将config对象里的配置信息输入一下。

  能获取到的配置信息有哪些

修改HelloController.groovy,添加allConfig方法输出所有配置信息。

    /*** 获取 grailsApplication.config 中所有配置信息* @return*/def allConfig() {grailsApplication.config?.sort{it.key}?.each {if(  it.value.getClass().toString() != "class org.grails.config.NavigableMap"){render it.key  + "=" + it.value + "<br/>"}}}

访问http://localhost:8080/hello/allConfig页面
所有配置信息
可以看到有很多的配置信息,例如:
GRAILS_HOME:本地配置的Grails4环境
JAVA_HOME:本地配置的Java8开发环境
book.author.name:应用程序中配置的信息
配置的信息,太多了截图不完整。
完整信息如下:

ANDROID_HOME=/Users/xiaosan/Library/Android/sdk
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.GGLczpfvow/Render
CLASS_PATH=.:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/lib
GOBIN=/Users/xiaosan/go/bin
GOPATH=/Users/xiaosan/go
GRAILS_FORK_OPTS=
GRAILS_HOME=/opt/grails-4.0.0
HOME=/Users/xiaosan
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home
JAVA_MAIN_CLASS_82071=org.grails.cli.GrailsCli
JAVA_MAIN_CLASS_82089=helloworldgrails4.Application
LANG=en_US.UTF-8
LC_CTYPE=en_US.UTF-8
LESS=-R
LOGNAME=xiaosan
LSCOLORS=Gxfxcxdxbxegedabagacad
M2_HOME=/opt/apache-maven-3.6.2/bin
MAVEN_HOME=/opt/apache-maven-3.6.2
OLDPWD=/
PAGER=less
PATH=/usr/local/opt/icu4c/sbin:/usr/local/opt/icu4c/bin:/usr/local/opt/curl/bin:/usr/local/bin:/usr/local/sbin:/opt/apache-maven-3.6.2/bin:.:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Applications/Wireshark.app/Contents/MacOS:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/bin:/usr/local/mysql/bin:/opt/grails-4.0.0/bin:/Users/xiaosan/Library/Android/sdk/platform-tools:/Users/xiaosan/Library/Android/sdk/tools:/Users/xiaosan/Library/Android/sdk/tools/bin:/Users/xiaosan/Library/Android/sdk/build-tools/26.0.0:/Users/xiaosan/go/bin:/Applications/OpenOffice.app/Contents/MacOS:/usr/local/nginx/sbin:/opt/gradle-6.4.1/bin
PID=82089
PWD=/Users/xiaosan/Documents/work/helloworldgrails4
SDKMAN_CANDIDATES_DIR=/Users/xiaosan/.sdkman/candidates
SDKMAN_CURRENT_API=https://api.sdkman.io/2
SDKMAN_DIR=/Users/xiaosan/.sdkman
SDKMAN_LEGACY_API=https://api.sdkman.io/1
SDKMAN_PLATFORM=Darwin
SDKMAN_VERSION=5.6.3+299
SHELL=/bin/zsh
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.tnmreq3K7O/Listeners
TMPDIR=/var/folders/5p/0lhw6dwj45nfn0zrchplk46m0000gn/T/
USER=xiaosan
VERSIONER_PYTHON_PREFER_32_BIT=no
VERSIONER_PYTHON_VERSION=2.7
XPC_FLAGS=0x0
XPC_SERVICE_NAME=com.jetbrains.intellij.39532
ZSH=/Users/xiaosan/.oh-my-zsh
__CF_USER_TEXT_ENCODING=0x1F5:0x19:0x34
awt.toolkit=sun.lwawt.macosx.LWCToolkit
book.author.name=肖伞
book.title=《Grails教程》
catalina.base=/private/var/folders/5p/0lhw6dwj45nfn0zrchplk46m0000gn/T/tomcat.4326420305887272758.8080
catalina.home=/private/var/folders/5p/0lhw6dwj45nfn0zrchplk46m0000gn/T/tomcat.144908067832705976.8080
catalina.useNaming=false
dataSource.dbCreate=create-drop
dataSource.driverClassName=org.h2.Driver
dataSource.jmxExport=true
dataSource.password=
dataSource.pooled=true
dataSource.url=jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
dataSource.username=sa
env=development
environments.development.dataSource.dbCreate=create-drop
environments.development.dataSource.url=jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
environments.production.dataSource.dbCreate=none
environments.production.dataSource.properties.defaultTransactionIsolation=2
environments.production.dataSource.properties.initialSize=5
environments.production.dataSource.properties.jdbcInterceptors=ConnectionState
environments.production.dataSource.properties.jmxEnabled=true
environments.production.dataSource.properties.maxActive=50
environments.production.dataSource.properties.maxAge=600000
environments.production.dataSource.properties.maxIdle=25
environments.production.dataSource.properties.maxWait=10000
environments.production.dataSource.properties.minEvictableIdleTimeMillis=60000
environments.production.dataSource.properties.minIdle=5
environments.production.dataSource.properties.testOnBorrow=true
environments.production.dataSource.properties.testOnReturn=false
environments.production.dataSource.properties.testWhileIdle=true
environments.production.dataSource.properties.timeBetweenEvictionRunsMillis=5000
environments.production.dataSource.properties.validationInterval=15000
environments.production.dataSource.properties.validationQuery=SELECT 1
environments.production.dataSource.properties.validationQueryTimeout=3
environments.production.dataSource.url=jdbc:h2:./prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
environments.test.dataSource.dbCreate=update
environments.test.dataSource.url=jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
file.encoding=UTF-8
file.encoding.pkg=sun.io
file.separator=/
ftp.nonProxyHosts=192.168.0.0/16|*.192.168.0.0/16|10.0.0.0/8|*.10.0.0.0/8|172.16.0.0/12|*.172.16.0.0/12|127.0.0.1|localhost|*.localhost|local|*.local|timestamp.apple.com|*.timestamp.apple.com
full.stacktrace=false
gopherProxySet=false
grails.codegen.defaultPackage=helloworldgrails4
grails.controllers.defaultScope=singleton
grails.converters.encoding=UTF-8
grails.env=development
grails.env.initializing=true
grails.env.standalone=true
grails.full.stacktrace=false
grails.gorm.reactor.events=false
grails.mime.disable.accept.header.userAgents=[Gecko, WebKit, Presto, Trident]
grails.mime.disable.accept.header.userAgents[0]=Gecko
grails.mime.disable.accept.header.userAgents[1]=WebKit
grails.mime.disable.accept.header.userAgents[2]=Presto
grails.mime.disable.accept.header.userAgents[3]=Trident
grails.mime.types.all=*/*
grails.mime.types.atom=application/atom+xml
grails.mime.types.css=text/css
grails.mime.types.csv=text/csv
grails.mime.types.form=application/x-www-form-urlencoded
grails.mime.types.hal=[application/hal+json, application/hal+xml]
grails.mime.types.hal[0]=application/hal+json
grails.mime.types.hal[1]=application/hal+xml
grails.mime.types.html=[text/html, application/xhtml+xml]
grails.mime.types.html[0]=text/html
grails.mime.types.html[1]=application/xhtml+xml
grails.mime.types.js=text/javascript
grails.mime.types.json=[application/json, text/json]
grails.mime.types.json[0]=application/json
grails.mime.types.json[1]=text/json
grails.mime.types.multipartForm=multipart/form-data
grails.mime.types.pdf=application/pdf
grails.mime.types.rss=application/rss+xml
grails.mime.types.text=text/plain
grails.mime.types.xml=[text/xml, application/xml]
grails.mime.types.xml[0]=text/xml
grails.mime.types.xml[1]=application/xml
grails.profile=web
grails.shutdown.hook.installed=true
grails.urlmapping.cache.maxsize=1000
grails.views.default.codec=html
grails.views.gsp.codecs.expression=html
grails.views.gsp.codecs.scriptlet=html
grails.views.gsp.codecs.staticparts=none
grails.views.gsp.codecs.taglib=none
grails.views.gsp.encoding=UTF-8
grails.views.gsp.htmlcodec=xml
hibernate.cache.queries=false
hibernate.cache.use_query_cache=false
hibernate.cache.use_second_level_cache=false
http.nonProxyHosts=192.168.0.0/16|*.192.168.0.0/16|10.0.0.0/8|*.10.0.0.0/8|172.16.0.0/12|*.172.16.0.0/12|127.0.0.1|localhost|*.localhost|local|*.local|timestamp.apple.com|*.timestamp.apple.com
http.proxyHost=127.0.0.1
http.proxyPort=1087
https.proxyHost=127.0.0.1
https.proxyPort=1087
info.app.grailsVersion=4.0.0
info.app.name=helloworldgrails4
info.app.version=0.1
java.awt.graphicsenv=sun.awt.CGraphicsEnvironment
java.awt.headless=true
java.awt.printerjob=sun.lwawt.macosx.CPrinterJob
java.class.path=/Users/xiaosan/Documents/work/helloworldgrails4/src/main/resources:/Users/xiaosan/Documents/work/helloworldgrails4/grails-app/views:/Users/xiaosan/Documents/work/helloworldgrails4/grails-app/i18n:/Users/xiaosan/Documents/work/helloworldgrails4/grails-app/conf:/Users/xiaosan/Documents/work/helloworldgrails4/build/classes/java/main:/Users/xiaosan/Documents/work/helloworldgrails4/build/classes/groovy/main:/Users/xiaosan/Documents/work/helloworldgrails4/gsp-classes:...后面太多省略
java.class.version=52.0
java.endorsed.dirs=/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/endorsed
java.ext.dirs=/Users/xiaosan/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre
java.io.tmpdir=/var/folders/5p/0lhw6dwj45nfn0zrchplk46m0000gn/T/
java.library.path=/Users/xiaosan/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
java.runtime.name=Java(TM) SE Runtime Environment
java.runtime.version=1.8.0_171-b11
java.specification.name=Java Platform API Specification
java.specification.vendor=Oracle Corporation
java.specification.version=1.8
java.vendor=Oracle Corporation
java.vendor.url=http://java.oracle.com/
java.vendor.url.bug=http://bugreport.sun.com/bugreport/
java.version=1.8.0_171
java.vm.info=mixed mode
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vm.specification.name=Java Virtual Machine Specification
java.vm.specification.vendor=Oracle Corporation
java.vm.specification.version=1.8
java.vm.vendor=Oracle Corporation
java.vm.version=25.171-b11
line.separator=
management.endpoints.enabled-by-default=false
management.endpoints.jmx.unique-names=true
management.endpoints.shutdown.enabled=true
micronaut.classloader.logging=true
org.grails.MAIN_CLASS_NAME=helloworldgrails4.Application
org.jboss.logging.provider=slf4j
os.arch=x86_64
os.name=Mac OS X
os.version=10.14.6
path.separator=:
run.active=true
server.error.include-stacktrace=ALWAYS
server.servlet.jsp.init-parameters.development=true
server.servlet.session.persistent=true
socksNonProxyHosts=192.168.0.0/16|*.192.168.0.0/16|10.0.0.0/8|*.10.0.0.0/8|172.16.0.0/12|*.172.16.0.0/12|127.0.0.1|localhost|*.localhost|local|*.local|timestamp.apple.com|*.timestamp.apple.com
socksProxyHost=127.0.0.1
socksProxyPort=1087
spring.beaninfo.ignore=true
spring.devtools.restart.additional-exclude=[*.gsp, **/*.gsp, *.gson, **/*.gson, logback.groovy, *.properties]
spring.devtools.restart.additional-exclude[0]=*.gsp
spring.devtools.restart.additional-exclude[1]=**/*.gsp
spring.devtools.restart.additional-exclude[2]=*.gson
spring.devtools.restart.additional-exclude[3]=**/*.gson
spring.devtools.restart.additional-exclude[4]=logback.groovy
spring.devtools.restart.additional-exclude[5]=*.properties
spring.freemarker.cache=false
spring.groovy.template.cache=false
spring.groovy.template.check-template-location=false
spring.h2.console.enabled=true
spring.jmx.unique-names=true
spring.main.banner-mode=off
spring.mustache.cache=false
spring.mvc.log-resolved-exception=true
spring.output.ansi.enabled=always
spring.profiles.active=
spring.reactor.stacktrace-mode.enabled=true
spring.resources.cache.period=0
spring.resources.chain.cache=false
spring.template.provider.cache=false
spring.thymeleaf.cache=false
sun.arch.data.model=64
sun.boot.class.path=/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/classes
sun.boot.library.path=/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib
sun.cpu.endian=little
sun.cpu.isalist=
sun.io.unicode.encoding=UnicodeBig
sun.java.command=helloworldgrails4.Application
sun.java.launcher=SUN_STANDARD
sun.jnu.encoding=UTF-8
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
sun.os.patch.level=unknown
user.country=CN
user.dir=/Users/xiaosan/Documents/work/helloworldgrails4
user.home=/Users/xiaosan
user.language=zh
user.name=xiaosan
user.timezone=Asia/Shanghai
user.variant=
verbose=false

  在业务层中使用grailsApplication对象方式一

创建HelloService.groovy
IDEA创建Service
输入Service的名字Hello或者HelloService都可以,会自动判断是否需要添加Service后缀,最后生成HelloService.groovy文件
输入Service的名字
创建好的HelloService文件
在这里插入图片描述
修改HelloService文件

package helloworldgrails4import grails.core.GrailsApplication
import grails.gorm.transactions.Transactional@Transactional
class HelloService {def serviceMethod() {}// grailsApplication 对象通过 Spring 注入进来GrailsApplication grailsApplicationdef useConfigInService() {def bookTitle = grailsApplication.config.getProperty("book.title")return bookTitle}
}

在HelloController中使用HelloService

package helloworldgrails4class HelloController {// 通过 Spring 将HelloService注入进来def helloServicedef index() {render "Hello World!"}def hello() {// 内置grailsApplication变量可以直接使用,使用getProperty(String name)方法获取application.yml中的配置信息def bookTitle = grailsApplication.config.getProperty('book.title')// 获取application.xml中配置的作者姓名def bookAuthorName = grailsApplication.config.getProperty('book.author.name')// 获取application.xml中配置的书籍价格,默认获取值的类型是String类型,通过第二个参数值的类型,值为空时返回第三个参数作为默认值def bookPrice = grailsApplication.config.getProperty('book.price', Integer, 50)// 注意这里没有配置 book.price, 应该返回默认值 50render "bookTitle = ${bookTitle}, bookAuthorName = ${bookAuthorName}, bookPrice = ${bookPrice}"}/*** 获取 grailsApplication.config 中所有配置信息* @return*/def allConfig() {grailsApplication.config?.sort{it.key}?.each {if(  it.value.getClass().toString() != "class org.grails.config.NavigableMap"){render it.key  + "=" + it.value + "<br/>"}}}/*** 从 Service中读取 grailsApplication.config 对象*/def getConfigFromService() {def result = helloService.useConfigInService()render "从Service中获取的book.title = ${result}"}}

启动项目访问http://localhost:8080/hello/getConfigFromService
从Service中获取grailsApplication对象
成功在Service中通过grailsApplication获取application.yml中的配置信息。

  在业务层中使用grailsApplication对象方式二

Service实现 GrailsConfigurationAware 接口,它提供了一个 setConfiguration 方法,该方法在类初始化时接受应用程序配置作为参数。然后通过这个参数获取相关的配置属性,赋值给service实例属性。这种方式比较麻烦,要为service定义属性来接收配置信息。了解一下就好。
实例代码:

import grails.core.support.GrailsConfigurationAwareclass MyService implements GrailsConfigurationAware {// 定义属性变量用于接收获取到的配置信息String recipientString greeting() {//在 service 方法中使用获取到的配置信息return "Hello ${recipient}"}// 该方法接收应用程序配置作为参数void setConfiguration(Config config) {// 通过配置参数获取配置信息recipient = config.getProperty('foo.bar.hello')}}

使用Spring值注解注入配置信息

修改HelloController,在下面添加:

    @Value('${book.author.name}')String bookAuthorName/*** 通过 Spring 的 Value 注解来注入配置* @return*/def getAuthorBookBySpringAno() {render "bookAuthorName = ${bookAuthorName}"}

启动项目访问http://localhost:8080/hello/getAuthorBookBySpringAno
Spring注入配置信息
注意:
在 Groovy 代码中,Value 注释的值必须使用单引号括起来,否则它会被解释为 GString 而不是 Spring 表达式。
@Value('${book.author.name}')

在application.yml中访问命令行参数或者系统参数

修改conf/application.yml,添加age属性配置

book:title: "《Grails教程》"author:name: "肖伞"# age 属性值通过 ${AUTHOR_AGE} 从外部获取age: ${AUTHOR_AGE}

进入外部属性信息配置界面
进入配置界面
进入命令行环境变量配置界面
进入环境配置界面
添加配置名称为AUTHOR_AGE,值为18
配置名称和值
保存配置
保存配置
修改HelloController,添加accessExternalVarFromYml动作获取age

    /*** 在YML文件中访问命令行参数或者外部系统信息*/def accessExternalVarFromYml() {render "age = " + grailsApplication.config.getProperty("book.author.age")}

启动项目
启动项目
访问http://localhost:8080/hello/accessExternalVarFromYml
在这里插入图片描述
applicationi.yml成功获取到外部配置的AUTHOR_AGE属性。

使用外部application.yml文件

默认情况下,Grails 将从 ./config 或当前目录读取 application.(properties|yml) .
由于 Grails4 是基于 Spring Boot 2.1.18 ,所以完全能参考Spring Boot的相关配置
这里简单测试一下使用外部application.yml文件更新服务启动端口号。
先进入项目所在目录,打包项目
grails war

➜ /Users/xiaosan/Documents/work/helloworldgrails4 >grails warBUILD SUCCESSFUL in 8s
7 actionable tasks: 4 executed, 3 up-to-date
| Built application to build/libs using environment: production

启动项目,默认运行在8080端口上

➜ /Users/xiaosan/Documents/work/helloworldgrails4 >java -jar build/libs/helloworldgrails4-0.1.war
Grails application running at http://localhost:8080 in environment: production

在build/libs目录创建一个application.yml文件,设置端口号8088

server:port: 8088

停止项目,重新使用一下命令启动项目
java -jar build/libs/helloworldgrails4-0.1.war --spring.config.additional-location=./build/libs/application.yml

➜ /Users/xiaosan/Documents/work/helloworldgrails4 >java -jar build/libs/helloworldgrails4-0.1.war --spring.config.additional-location=./build/libs/application.yml
Grails application running at http://localhost:8088 in environment: production

可以看到在没有改变已打包war文件的前提下,使用外部application.yml文件改变了默认的8080端口。
使用--spring.config.additional-location添加了外部配置文件的位置,优先级高于默认的配置文件位置。

内置的一些设置,了解一下有好处

Grails 有一组比较重要的核心设置。它们的默认值适用于大多数项目,但我们可能需要修改其中的一个或多个设置。这些设置都在application.yml中配置。

配置默认值描述
grails.enable.native2asciitrue如果不需要 Grails i18n 属性文件的 native2ascii 转换,则将此设置为 false
grails.views.default.codecnone设置 GSP 的默认编码机制 - 可以是“none”、“html”或“base64”之一。为了降低 XSS 攻击的风险,请将其设置为 ‘html’。
grails.views.gsp.encodingutf-8用于 GSP 源文件的文件编码
grails.mime.file.extensionstrue是否使用文件扩展名来指定内容协商中的 mime 类型
grails.mime.typesall: */*用于内容协商的受支持 mime 类型的映射。
grails.serverURL指定绝对链接的服务器 URL 部分的字符串,包括服务器名称,例如grails.serverURL=“http://my.yourportal.com”。请参阅创建链接。也被重定向使用。
grails.views.gsp.sitemesh.preprocess确定是否发生 SiteMesh 预处理。禁用它会减慢页面渲染的速度,但如果您需要 SiteMesh 从 GSP 视图解析生成的 HTML,那么禁用它是正确的选择。如果您不了解此高级属性,请不要担心:将其设置为 true。
grails.reload.excludes 和 grails.reload.includes配置这些指令决定了项目特定源文件的重新加载行为。每个指令都采用一个字符串列表,这些字符串是项目源文件的类名,在使用 run-app 命令运行开发中的应用程序时,这些字符串应从重新加载行为中排除或相应地包含在内。如果配置了 grails.reload.includes 指令,则只会重新加载该列表中的类。

Logging配置

从 Grails 3.0 开始,日志记录由 Logback 日志记录框架处理,并且可以使用 grails-app/conf/logback.groovy 文件进行配置。

在Grails中不需要我们自己去创建日志对象,Grails会自动把log对象注入到控制器、服务中。

在 Grails 3.3.0 之前,Grails 日志记录器的名称遵循约定
grails.app.<type>.<className>,其中 type 是控制器或者服务, className 是控制器或者服务的完全限定名称。
例如:
grails.app.controllers.com.company.BookController
这里的type是controllers,className是com.company.BookController
grails.app.services.com.company.BookService
这里的type是services,className是com.company.BookService

Grails 3.3.x 简化了记录器名称。下面的例子说明了这些变化:

控制器BookController.groovy 位于 grails-app/controllers/com/company

记录器名称(Grails 3.3.x 或更高版本)记录器名称(Grails 3.2.x 或更低版本)
未用 @Slf4j 注解com.company.BookControllergrails.app.controllers.com.company.BookController
启用 @Slf4j 注解com.company.BookControllercom.company.BookController

BookService.groovy 位于 grails-app/services/com/company

记录器名称(Grails 3.3.x 或更高版本)记录器名称(Grails 3.2.x 或更低版本)
未用 @Slf4j 注解com.company.BookServicegrails.app.services.com.company.BookService
启用 @Slf4j 注解com.company.BookServicecom.company.BookService

BookDetail.groovy 位于 src/main/groovy/com/company

记录器名称(Grails 3.3.x 或更高版本)记录器名称(Grails 3.2.x 或更低版本)
启用 @Slf4j 注解com.company.BookDetailcom.company.BookDetail

可见在Grails3.3版本之后就算不使用@Slf4j注解,日志记录器的名称也会比较精简,不会太过复杂,现在已经是Grails4版本了,我们在编写代码的时候可以不写@Slf4j注解。如果项目是Grails3.3之前的版本还是老老实实的加上。

  Logging实例演示

修改 helloworldgrails4/HelloController.groovy的index方法,添加日志记录

    def index() {// 这里的 log 对象是 grails 内置的对象,可以直接使用log.error("这是一个 error 级别的日志")log.warn("这是一个 warn 级别的日志")log.info("这是一个 info 级别的日志")log.debug("这是一个 debug 级别的日志")render "Hello World!"}

启动项目
启动项目
访问http://localhost:8080/hello,查看控制台输出
error日志输出
可以看到只输出了一条 error 级别的日志。
因为grails-app/conf/logback.groovy配置的是ERROR及以上的级别才会显示。
日志级别:DEBUG < INFO < WARN < ERROR < FATAL

  logback.groovy 默认的日志配置

查看 grails-app/conf/logback.groovy 默认的日志配置

import grails.util.BuildSettings
import grails.util.Environment
import org.springframework.boot.logging.logback.ColorConverter
import org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverterimport java.nio.charset.StandardCharsets// 彩色日志依赖的渲染类
conversionRule 'clr', ColorConverter
conversionRule 'wex', WhitespaceThrowableProxyConverter// See http://logback.qos.ch/manual/groovy.html for details on configuration
// 配置一个日志输出目的地:控制台(ConsoleAppender),给这个目的地起别名为:STDOUT
appender('STDOUT', ConsoleAppender) {// 配置日志显示方式:自定义规则模式(PatternLayout)encoder(PatternLayoutEncoder) {// 显示日志的编码格式为UTF-8charset = StandardCharsets.UTF_8// 定义日志输出格式pattern =// %d{ } 格式化时间显示,%clr(%d{ }){faint} 将时间显示为淡灰色'%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} ' +// %p 显示日志级别,%5p表示字符串长度不足5个,用空格填充左边位置。%clr() 没有设置颜色默认红色'%clr(%5p) ' +// %t输出产出日志的线程名,%15.15t表示不足15左边填空格,超过15截去后面的。%clr(---){faint} 三个短横线淡灰色'%clr(---){faint} %clr([%15.15t]){faint} ' +// %logger 显示记录器的名称, %-40.40logger{39},名字长度小于40右边空格填充,超过40后面截断,{cyan}青色显示'%clr(%-40.40logger{39}){cyan} %clr(:){faint} ' + // Logger// %m显示输出信息,%n当前平台下的换行符,%wex在堆栈跟踪周围添加一些额外的空白'%m%n%wex' // Message}
}// targetDir 默认为当前项目目录下面的build目录
def targetDir = BuildSettings.TARGET_DIR
// 如果是开发环境,并且存在targetDir目录
if (Environment.isDevelopmentMode() && targetDir != null) {// 配置一个日志输出目的地:文件(FileAppender),给这个目的地起个别名叫:FULL_STACKTRACEappender("FULL_STACKTRACE", FileAppender) {// 配置日志输出到哪个文件file = "${targetDir}/stacktrace.log"// 是否覆盖:true持续添加日志,不覆盖之前添加的。false:覆盖之前添加的。append = true// 配置日志输出格式为:自定义规则模式(PatternLayoutEncoder)encoder(PatternLayoutEncoder) {// 配置日志编码为UTF-8charset = StandardCharsets.UTF_8// 自定义的日志输出格式pattern = "%level %logger - %msg%n"}}// 配置一个日志记录器名字叫StackTrace,记录ERROR及以上的信息,日志输出到别名为 FULL_STACKTRACE 的目的地,additivity:false信息不显示在父日志记录器中。logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false)
}
// 配置根日志记录器,不用配置名字,记录ERROR及以上的日志信息,日志输出到别名为 STDOUT 的目的地
root(ERROR, ['STDOUT'])

  彩色日志

logback.groovy 中使用了彩色日志配置,但是在IDEA的控制台中并没有输出彩色的日志。
要显示彩色日志,需要打开一个开关
-Dspring.output.ansi.enabled=always

  1. IDEA控制台彩色日志输出方式一

在启动grails项目时,加上这个JVM配置就可以了,而grails4采用gradle来构建项目的,在build.gradle中已经配置好了彩色日志的启动任务,我们直接使用这个任务启动项目就可以了。
grails彩色日志启动任务
启动好之后,再次访问http://localhost:8080/hello查看控制台输出
彩色日志输出内容
可以看到现在已经是彩色日志了。

  2. IDEA控制台彩色日志输出方式二

使用helloworldgrails4/Application.groovy启动项目
配置启动项
配置启动参数
配置启动参数
启动项目
启动项目
访问项目http://localhost:8080/hello 查看控制台输出
彩色日志输出

  3. 打包后的项目默认是彩色日志,不需其他配置

终端彩色日志终端彩色日志2
可以看到在终端中启动项目,日志颜色更加的明显。

  程序报错时,指定敏感请求参数不写入日志

当 Grails遇到错误, 记录堆栈跟踪时,日志消息可能包含当前请求的所有请求参数的名称和值。
可以在grails-app/conf/application.yml文件中的grails.exceptionresolver.params.exclude 配置属性中指定要屏蔽参数名称:

grails:exceptionresolver:params:exclude:- password- creditCard

  完全关闭请求参数日志记录功能

可以通过将 grails.exceptionresolver.logRequestParameters 配置属性设置为 false 来完全关闭请求参数日志记录。
当应用程序在 DEVELOPMENT 模式下运行时,默认值为 true,对于所有其他环境,默认值为 false。

grails:exceptionresolver:logRequestParameters: false

  使用外部日志配置文件

  1.使用logging.config指定外部Logback配置文件

修改grails-app/conf/application.yml文件,添加外部日志配置

logging:config: /opt/logback.groovy

复制conf/logback.groovy文件到/opt/logback.groovy
修改/opt/logback.groovy最后一行,将根日志级别为WARN

// 配置根日志记录器,不用配置名字,记录WARN及以上的日志信息,日志输出到别名为 STDOUT 的目的地
root(WARN, ['STDOUT'])

重启启动项目,访问localhost:8080/hello/index查看控制台输出
配置外部logback日志文件
输出了ERROR和WARN的日志记录,说明使用了我们刚刚修改的外部日志配置文件。

  2.使用JVM启动参数配置外部日志文件

删除grails-app/conf/application.yml文件中的logging.config配置。
在JVM配置中添加-Dlogging.config=/opt/logback.groovy
JVM配置外部日志文件
启动项目后查看控制台,同样使用的外部配置文件。

  3. 系统环境变量添加LOGGING_CONFIG

删除grails-app/conf/application.yml文件中的logging.config配置。
删除JVM中的-Dlogging.config=/opt/logback.groovy配置
在环境变量中配置LOGGING_CONFIG=/opt/logback.groovy
环境变量配置外部日志文件
启动项目后查看控制台,同样使用的外部配置文件。

GORM配置

  为所有领域类启用 failOnError

grails-app/conf/application.yml文件中将
grails.gorm.failOnError 设置为 true,所有领域类在调用save()方法保存时,如果校验失败就会抛出grails.validation.ValidationException异常。

grails:gorm:failOnError: true

  按包名为领域类启用 failOnError

可以指定哪些包下面的领域类启用failOnError,该值是一个表示包名称的字符串列表。如果该值为字符串列表,则 failOnError 行为将仅限于这些包(包括子包)中的领域类。

grails:gorm:failOnError:- com.companyname.somepackage- com.companyname.someotherpackage

小结

本章主要讲了Grails的基本配置:

  • 如何配置,在哪里配置,在代码中如何访问这些配置。
  • 如何将配置信息注入到程序中。
  • 如何使用外部application.yml配置文件。
  • 如何在程序中使用log日志,如何配置,在哪里配置。
  • 如何配置保存领域类校验出错的行为。

下一章会讲如何配置外部数据源,数据持久化到数据库中。


http://chatgpt.dhexx.cn/article/WHIZ67LE.shtml

相关文章

Grails 的插件开发

警告&#xff1a;本文还未整理&#xff0c;可读性差&#xff0c;还只是草稿 文档 Grails Plugin Develop Document grails-spring-security-core 插件文档 grails-spring-security-rest插件 文档 创建插件 执行命令行 grails create-plugin <<PLUGIN NAME>>即…

Grails配置-启动类配置,数据源配置,连接Mysql数据库

文章目录 Grails配置1. 启动类配置Application.groovy启动类中可以做哪些事情1. 启动Grails应用程序2. 自定义包扫描路径3. 注册bean4. 应用程序生命周期管理 2. 环境配置2.1 默认的多环境配置2.2 预设的环境2.3 打包和运行使用不同的环境2.4 在代码启动过程中判断当前环境2.5 …

java grails mave_Grails 与 Maven 集成

Grails 与 Maven 集成 杨 健 2013 年 9 月 09 日发布 概述 Grails 简介&#xff1a;Grails 是一个开源的 Web 开发框架&#xff0c;它采用动态语言 Groovy 进行开发&#xff0c;并且可以和用 Java 开发的项目进行集成。Grails 充分体现了约定优于配置的原则&#xff0c;将项目的…

Grails4.0.11入门

文章目录 Grails4.0.11介绍相关依赖入门⎮Java环境搭建⎮Grails环境搭建⎮如何创建grails应用⎮如何选择开发工具IDEA如何导入Grails项目 ⎮目录结构&#xff0c;约定优于配置⎮如何部署Grails项目1. 使用默认内嵌的Tomcat8部署2. 使用外部Tomtcat8部署3. 使用外部Tomcat7部署 …

grails java_Grails

十二、Grails 如今的Java Web开发对于需求来说已经变得过于复杂。当今众多Java领域的Web开发框架不仅使用复杂&#xff0c;而且并没有很好的遵循Don’t Repeat Yourself(DRY)原则。像Rails&#xff0c;Django和TurboGears这样的动态框架在Web开发领域开辟了一条新的道路&#x…

JAVA AIO编程

Asynchronous IO&#xff1a; 异步非阻塞的编程方式 与NIO不同&#xff0c;当进行读写操作时&#xff0c;只须直接调用API的read或write方法即可。这两种方法均为异步的&#xff0c;对于读操作而言&#xff0c;当有流可读取时&#xff0c;操作系统会将可读的流传入read方法的缓…

java aio_Java AIO详解

JDK1.7升级了NIO类库&#xff0c;升级后的NIO类库被称为NIO 2.0。 Java正式提供了异步文件I/O操作&#xff0c;同时提供了与UNIX网络编程事件驱动I/O对应的AIO。 AIO编程 NIO 2.0引入了新的异步通道的概念&#xff0c;并提供了异步文件通道和异步套接字通道的实现。 异步通道获…

Java I/O 模型之 AIO

❤️ 个人主页&#xff1a;水滴技术 &#x1f680; 支持水滴&#xff1a;点赞&#x1f44d; 收藏⭐ 留言&#x1f4ac; &#x1f338; 订阅专栏&#xff1a;Java 教程&#xff1a;从入门到精通 大家好&#xff0c;我是水滴~~ 文章目录 服务端API创建服务端套接字的异步通道接…

如何用AIO技术提高程序性能

写在前面 这是一篇关于 AIO 的文章。本篇文章详细对比了几个常见的I/O模型&#xff0c;并且介绍了AIO相关的一些API。 我把英文原文翻译过来整理成这篇文章。目的一个是自己学习&#xff0c;一个是方便不习惯看英文资料的同学进行学习。 英文原文地址&#xff1a; https://…

08【AIO编程】

八、AIO编程 8.1 AIO编程简介 8.1.1 AIO编程概述 AIO也叫异步非阻塞&#xff0c;JDK1.7之后的新特性&#xff0c;AIO引入异步通道的概念&#xff0c;采用了 Proactor 模式&#xff0c;简化了程序编写&#xff0c;有效的请求才启动线程&#xff0c;它的特点是先由操作系统完成…

linux aio进程简介,Linux AIO机制

Linux的I/O机制经历了一下几个阶段的演进&#xff1a; 1. 同步阻塞I/O: 用户进程进行I/O操作&#xff0c;一直阻塞到I/O操作完成为止。 2. 同步非阻塞I/O: 用户程序可以通过设置文件描述符的属性O_NONBLOCK&#xff0c;I/O操作可以立即返回&#xff0c;但是并不保证I/O操作成功…

关于aio

AIO 是异步非阻塞 同步意味着&#xff0c;在进行读写操作时&#xff0c;线程需要等待结果&#xff0c;还是相当于闲置 异步意味着&#xff0c;在进行读写操作时&#xff0c;线程不必等待结果&#xff0c;而是将来由操作系统来通过回调方式由另外的线程来获得结果 AIO的read方…

linux AIO

AIO 是 Linux 下的异步读写模型&#xff0c;它是 2.6 内核提供的一个标准增强特性。对于文件的读写&#xff0c;即使以 O_NONBLOCK 方式来打开一个文件&#xff0c;也会处于 “阻塞” 状态&#xff0c;因为文件时时刻刻处于可读状态&#xff0c;而从磁盘到内存所等待的时间是惊…

AIO模型

目录 AIO模型介绍 AsynchronousServerSocketChannel&#xff1a;AIO中网络通信服务端的socket 1、future方法 2、callback回调方式 AIO 的回调方式编程 BIO、NIO、AIO的比较 1、释义 BIO&#xff1a;同步阻塞IO模型 NIO&#xff1a;同步非阻塞IO模型 AIO&#xff1a;…

java中IO模型-AIO模型

AIO模型介绍 AIO&#xff08;Asynchronous I/O&#xff09; 异步非阻塞模型&#xff0c; 在javajdk.17版本开始支持AIO&#xff0c;AIO模型需要操作系统的支持。 AIO最大的特性是异步能力&#xff0c;对socket和I/O起作用。 异步IO模型类似的 与NIO模型不同&#xff0c;读写操…

架构解密从分布式到微服务:深入理解网络,AIO

AIO AIO是I/O模型里一个很高的层次&#xff0c;体现了大道至简的软件美学理念。与NIO相比&#xff0c;AIO的框架和使用方法相对简单很多。 AIO包括两大部分:AIO Files解决了文件的异步处理问题&#xff0c;AIO Sockets解决了Socket的异步处理问题。AIO的核心概念为应用发起非…

BIO,NIO,AIO区别

BIO,NIO,AIO 总结 Java 中的 BIO、NIO和 AIO 理解为是 Java 语言对操作系统的各种 IO 模型的封装。程序员在使用这些 API 的时候&#xff0c;不需要关心操作系统层面的知识&#xff0c;也不需要根据不同操作系统编写不同的代码。只需要使用Java的API就可以了。 在讲 BIO,NIO,…

Apache CXF - 快速指南

Apache CXF - 简介 在当今的环境中&#xff0c;您可以使用多个选项来创建 Web 服务应用程序。您可以使用多种标准和广泛接受的协议中的一种或多种进行通信。例如SOAP、XML/HTTP、RESTful HTTP和CORBA&#xff08;通用对象请求代理架构&#xff0c;在过去非常流行&#xff0c;但…

java cxf 安全_CXF client在并发下的线程安全问题

这个是发生在上周周末的真实案例&#xff0c;因为cxf client 端线程安全导致的错误&#xff0c;总结出来希望其他使用cxf的兄弟注意。 首先描述一下背景&#xff0c;简单的说就是使用cxf作为web service的客户端&#xff0c;运行在weblogic上&#xff0c;连接外部的服务器。为了…

linux cxf服务端,Apache CXF 框架应用实战

一、概述 Apache CXF提供了用于方便地构建和开发WebService的可靠基础架构。它允许创建高性能和可扩展的服务&#xff0c;可以部署在Tomcat和基于Spring的轻量级容器中&#xff0c;也可以部署在更高级的服务器上&#xff0c;例如Jboss、WebSphere或WebLogic。 CXF提供了以下功能…