grails学习笔记

关于groovy中的def定义

java有两个正式的语法规则:

1 变量只允许在定义它的块内以该块内嵌的块内及访问

2 一个变量不能被定义两次以上

java有classwide variable和localwide variable,而classwide variable根据其可见性(如public)是违反规则1的。但java遵循着规则二。

def 很简单,在java中定义一个对象一般需要制定具体对象类型,比如String/List等,而def就是dynamic变量,定义的对象类型是可变的。

 

grails的日志配置

grails使用了log4j作为plus来记录日志

grails在代码中怎么记录日志?

对于约定的controller、service、domain,grails会将一个log instance object注入(injection)到其中

package com.yuhe.controller class com.yuhe.controller.UserController{ def login = { log.error "people enter UserController action login" } }

 

对于非约定的类,就必须实例化一个log

package org.otherimport org.apache.commons.logging.LogFactoryclass MyClass { private static final log = LogFactory.getLog(this) … }

 

grails日志是怎么配置的?
grails中的日志配置是在grails-app/conf/Config.groovys

1 log level:

There are serveral stardard loging levels, which are listed here in order of descending priority:

  1. off
  2. fatal
  3. error
  4. warn
  5. info
  6. debug
  7. trace
  8. all

当你记录日志时,log实例有相应于以上level的方法,比如log.debug(msg)

 

2 配置 logger

在代码中已经通过log对象记录不同级别的日志,

配置logger,让日志输出到一个地方,文件、数据库、控制台等,以及按照级别来输出。

appender是日志输出控制对象


 log4j = { appenders { rollingFile name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log" } }

grails 的appender有:

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.

 

建立了一个appender,接下来要做的是把这个appender分配给一个日志级别

error myAppender

 

以上代码告知把所有error以及之上的log输出到myAppender定义的地方。

 

不同的类可以有不同的输出级别以及appender,也就是三个概念的自由组合,日志级别(level)、日志输出控制(appender)、以上两个组合作用的具体类(effected class)。

error myAppender:"grails.app.controller.BookController"

以上实例代码指在BookController的日志级别定为error,并输出到myAppender.

作用于一个effected class,在grals中尤其具体约定。grails.app..

log4j = { // Set level for all application artifacts info "grails.app" // Set for a specific controller debug "grails.app.controller.YourController" // Set for a specific domain class debug "grails.app.domain.org.example.Book" // Set for all taglibs info "grails.app.tagLib" }   

grails.app前缀是固定的,包括:

  • bootstrap - For bootstrap classes
  • dataSource - For data sources
  • tagLib - For tag libraries
  • service - For service classes
  • controller - For controllers
  • domain - For domain entities

是你定义的类全路径。effected class可以之给出前面的一段,例如grails.app,log4j会作用于以它开头的所有类。

 

完整log示例:

log4j = { // Example of changing the log pattern for the default console // appender: // appenders { rollingFile name: "myAppender", maxFileSize: 10240, file: "F:/workplace/goals/log/goals.log" //console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n') } error 'org.codehaus.groovy.grails.web.servlet', // controllers 'org.codehaus.groovy.grails.web.pages', // GSP 'org.codehaus.groovy.grails.web.sitemesh', // layouts 'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping 'org.codehaus.groovy.grails.web.mapping', // URL mapping 'org.codehaus.groovy.grails.commons', // core / classloading 'org.codehaus.groovy.grails.plugins', // plugins 'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration 'org.springframework', 'org.hibernate', 'net.sf.ehcache.hibernate' warn 'org.mortbay.log' debug myAppender:'grails.app' }

 

debug   myAppender:'grails.app'

将debug级别以上的所有应用日志输出:F:/workplace/goals/log/goals.log

 

grials的异常处理

    异常,在程序的一个方法无法按照正常的指令轨迹执行时,它抛出(throw)一个信息给调用者,调用者可以根据这个信息作相应处理,或者直接将信息返回给虚拟机。

    java异常的层次结构的顶端是Error和Exception,Error是虚拟机内部异常(虚拟机本身也是一个程序,如同一个os),Exception则是我们要关注的应用程序异常。

    Exception的继承结构下面又分为RuntimeException和其他Exception。RuntimeException被称为未检查异常(unchecked),其它则称为已检查异常(checked)。

    从Exception的继承类看异常结构,未检查异常(RuntimeException)指可以通过程序员对代码检查、控制而避免的异常,最通俗的例子就是数组下标越界,或者数据没有有效验证,无法插入到数据库中。未检查异常是可以通过检查下标和对无效数据进行隔离而避免的。在程序编码上来看,程序方法(method)抛出了这个异常,调用者是无需捕获(try catch finally)或者再次向上层方法抛出(throw)的。程序可以继续执行。当然,程序员也可以对这种异常进行捕获和再次抛出,但编译器不会作强制要求。

    已检查异常(checked)指程序执行轨迹是正确的,但遇到了一些外部情况,程序无法正常执行。比如磁盘满了、网络断了等。这种异常抛出后必须由调用者捕获或者再次向上层抛出,否则程序会中断。

    贴出checked和unchecked异常对照

import java.io.IOException; public class test3 { static void checkedException() throws IOException{ throw new IOException(); } static void uncheckedException() { throw new RuntimeException(); } static public void main(String args[]) throws IOException{ System.out.println("test exception"); checkedException(); uncheckedException(); } }

   

    现在回过头来看看grails中的异常,或者说我们应用程序中的异常。根据应用程序不同的程序层次结构我们应该使用不同的异常类型。简而概之,在低层次(domain、service)捕获已检查异常,如果无法正常运行的话则向高层次(controller)抛出未检查异常。比如domain对象在访问数据库时出现异常,这是一个已检查异常,我们必须捕获,不能放任其到高层次controller,如果无法处理则向高层次抛出一个未检查异常,例如UserUpdateException。

    在controller上如果可以处理,则捕获这个异常,如果不能,框架有一个默认程序捕获已检查异常。我们经常看到的500页面就是服务器自己捕获已检查异常,将其转到一个固定的页面。我们可以自定义如何处理500内部服务器报错,将其定位到一个自定义的页面,再以一种友好的方式打印exception stack(spring是这样做的)。

   

最后摘录<代码大全>的8.4章节,关于异常的处理原则

1 用异常通知程序的其他部分,发生了不可忽略的错误。

既然不可忽略,必须提供处理函数,所以使用已检查异常,并放在低层次结构中。

2 只在真正的例外情况下才跑出异常。3 不能用异常推卸责任

steve mcconnell的意思是做一个负责的程序员,尽可以的熟悉业务,用代码来规避向上层次跑出异常

4 避免在构造函数和析构函数中抛出异常

主要是针对c++而言

5 在恰当的抽象层次抛出异常

如我前文所说,不要把已检查异常放到controller。再具体点,不要在controller抛出一个IOException,而是UserUpdateException

6 考虑一个集中的异常报告机制

在捕获异常后,一般是catch{}代码中,我们要放一个异常报告机制,比如写到数据库、写到文件,通常我们使用log4j的error方法输出

7 避免使用空的catch语句

如果一定要如此的话,在try中写好注释

8 了解所有函数库可能抛出的异常

eclipse已经帮助我们查找已检查异常

9 把项目中对异常的使用标准化,10 考虑异常的替代方案。

   

 

 

 

grails的debug方法

 使用FireFox,安装firebug插件即可很方便的调试js

 

grails连mysql数据库

 1.先下载MySql的驱动, http://www.mysql.com/products/connector/j/
2.将MySql的Jar包放到项目的lib文件夹下
(1 ,2步骤我们没有做,可能高版本的grails自带了驱动)
3.修改grails-app/conf文件夹下的DataSource.groovy文件的DataSource:
dataSource {
    pooled = false
    driverClassName = "com.mysql.jdbc.Driver"
    username = "puras"  //MySql的用户名
    password = "123456"  //相应的密码
}

4.修改DataSource.groovy文件:

development {
        dataSource {
            dbCreate = "update" // one of 'create', 'create-drop','update'
            url = "jdbc:mysql://localhost/ibmhp?useUnicode=true&characterEncoding=UTF8

" //将URL改成MySql的,与Java的一样

        }
    }

5、MySQL GUI Tools(http://dev.mysql.com/downloads/gui-tools/)
用来管理mysql的gui工具

 

6 避免在mysql中出现乱码问题

6.1 连接mysql的url: jdbc:mysql://localhost:3306/mgrab?useUnicode=true&characterEncoding=utf-8

6.2 ALTER DATABASE db_name CHARACTER SET gbk

grails的单元测试、集成测试

你可能感兴趣的:(编程语言)