groovy语法


过去半年都在写Groovy,基本都是在实战中学习,从java转过来,也还没什么问题,毕竟基础,架构都没变。

Groovy的强大特性中,Closure,MetaClass都尝试过,Closure基本上就是当方法或者回调接口使用,再高级的用法就没用过了,没有特别体会什么好处,当回调接口就是省的定义接口,简洁了一些;MetaClass就有专门为一个模块做了些MetaClass,和GORM差不多的,给一些类加了save,update,delete之类的方法,不同的是GORM是存到数据库,我做的那模块是调用Restful Service,还不错,如果有需求是不能改变类而要给类加方法,还是很适用的。但是在绝大部分情况下,这些优势都体现不出来,到目前位置,还是对Groovy的一些语法印象深刻些,总结一些常用的语法:

1.List,和Map的初始化

这个用的最多了,原来java的时候,非要新建一个List或者Map,然后把element一个一个加进去,特繁琐。用Groovy在语法上简洁了很多。

定义一个List: 

[java]  view plain copy
  1. List intList = [1,3,5,7,9]  
  2. List stringList = ['a''b','']  

定义一个Map:

[java]  view plain copy
  1. Map map = [a:4,b:'d']  
 

定义Map的时候,对于key,如果像上面的例子一样,没有特别指示,那所有key都是String类型的,key值就是‘a’,'b',上面的例子等价于

[java]  view plain copy
  1. Map map = ['a':4,'b':'d']  

某些时候,map的key可能是存在的一个变量,那这个时候,就要用括号把key抱起来,比如

[java]  view plain copy
  1. String a = 'I am Key'  
  2. Map map = [(a):'I am Value']  

也可以定义空的List或者Map

[java]  view plain copy
  1. List empty = []  
  2. Map empty = [:]  

需要知道的是,这种方式新建的List实例是ArrayList,Map实例是LinkedHashMap

2.二元运算符 ?:

java继承了C语言的问号表达式,二元运算符就是更加精简的问号表达式。形式:

[java]  view plain copy
  1. def result = a ?: b  

意为,如果条件为真,即a为true或者a有值,则result为a,否则result为b

3.安全占位符

这个很有用,可以避免很多NullPointerException,但是也不能滥用了

[java]  view plain copy
  1. def result = obj?.property  

代码里,obj是个对象,property是对象的一个熟悉,这行代码的意思,如果obj不为null,则会返回property属性的值,如果obj为null,这会直接返回null。语句可以一直串下去

[java]  view plain copy
  1. def result = a?.b?.c?.d...  

4.字段操作

按照Groovy Bean的标准,默认的时候类里面的所有字段,Groovy都会帮忙生成一个get方法。在类的外部,即便你直接用了属性名而不用get方法去取值,拿到的也是通过get方法拿到的值。如果想直接拿属性值怎么办呢? 通过字段运算符:

[java]  view plain copy
  1. class A {  
  2.    String b  
  3. }  
  4.   
  5. A a = new A()  
  6. a.b //通过get方法拿值  
  7. a.getB() //通过get方法拿值  
  8. a.@b //直接拿值  

5.GString

Java里有String,Groovy里新加了GString。Groovy的语法是,如果用单引号括起来的就是String,如果是双引号括起来的就是GString。所以Groovy不能直接定义原来Java里的char了。

String

[java]  view plain copy
  1. String s = 'This is a String'  

GString

[java]  view plain copy
  1. GString s = "This is a GString"  

两种方式定义出来的实例类型是不一样的。当然GString不是这么简单的,GString的强大之处在于它可以作为模板使用

[java]  view plain copy
  1. String name = 'count'  
  2. int value1 = 23  
  3. int value2 = 22  
  4. GString s = "The value of $name is ${value1+value2}"   
  5. println s  

最终的输出是: The value of count is 55

倒数第二行,里面有关键字符 $, $即代表去引用上下文中的变量值,而${}中间不仅可以引用变量值,还可以加上一些运算,作为一个表达式

最后一行这是把GString转换成String,再输出。

String是常量,但是GString是变量,准确的说,在GString中的$仅仅是作为一个模板的占位符存在,GString会保存对那个对象的引用,如果引用的对象值发生改变,GString的值也就跟着改变。

需要注意的是,Map里面String和GString就算最终生成的String值一样,但是还是当作两个key存在的。很容易理解,但是很容易犯的错误,比如手误把单引号写成了双引号等等都会引起这个错误。

6.构造函数

[java]  view plain copy
  1. class ClassA {  
  2.     String s1  
  3.     int i1  
  4.     ClassB cb  
  5. }  
  6. class ClassB {  
  7.     String s2  
  8. }  
  9. new ClassA(s1:'pro in A', i1:5, cb:[s2:'pro in B'])  

以上代码是可以工作的,Groovy会创建一个ClassA的实例,并把‘pro in A’ 和 5 分别设到属性s1和i1里。即便有一个复杂类型的熟悉cb,也能正常工作,ClassB的对象会被创建出来,并设到属性cb上。ClassB里的s2熟悉当然就是'pro in B'了。

可以看到构造函数里的参数很像Map的定义,确实,其实传入Map也是可以的

[java]  view plain copy
  1. new ClassA([s1:'pro in A', i1:5, cb:[s2:'pro in B']])  

这个功能,在一些数据模型转换的时候,比较方便。打个比方,前台来的JSON数据,直接全转成Map,再用构造函数new一下,就全部出来了。注意的是,如果Map存在某个类里没有的属性值,会出错误的。

7.asType

用Groovy的是,可能经常看到这样的代码

[java]  view plain copy
  1. String a = '78'  
  2. int b = a as int  
  3. print b  

第二行,有个关键字 as ,可以看出来作用就是把String类型的a转成int类型的b。它是怎么工作的呢,很简单,就是把这个操作代理给了String的asType方法,比如String有如下的方法(仅仅是例子,代码中不是这样)

[java]  view plain copy
  1. class String {  
  2.     Object asType(Class clz) {  
  3.          if(clz == Integer) {  
  4.                 return Integer.parseInt(this)  
  5.          } else if(clz == GString) {  
  6.                  return "$this"  
  7.          } else {  
  8.                  return super.asType(clz)  
  9.          }  
  10.     }  
  11. }  

那么,String就可以用as运算符转换成int或者GString类型

[java]  view plain copy
  1. String a = '45'  
  2. int b = a as int  
  3. GString c = a as GString  

上面的 clz == GString 是合法的,在Groovy里等价于 clz == GString.class

8. inspect和eval

eval就和javascript里的eval一样,就是直接执行一段Groovy脚本,可以用Eval.me(...script here...)直接调用。

inspect就是eval的反相操作了,就是把一个对象转成一个合法的可执行的脚本(我的理解,没仔细看过文档)。没试过其他对象,但是像Map,List之类的都可以转出来。这就够了,Map,List转出来的数据之于Groovy就相当于JSON之于JavaScript。在系统内部的时候就可以直接当作数据传输,虽然大家都不推荐这么用,但是我还是坚持,如果数据只包含Map,List,Number,String等简单类型,为什么不用呢?(如果Number里值是NaN或者Infinite的时候有问题,但是很容易解决,看Eval类里的其他两个方法就知道了)。呵呵,我也就这么用着,直到发现了一个Bug(http://stackoverflow.com/questions/7410252/groovy-inspect-handle-dollar-sign),没法解决,我才换掉了实现。

但是我对这个东西还是有很大期待,如果都是内部集成,不存在安全问题,且没有很好JSON支持的时候,这种方式还是很好的方式。

9.is方法

按照Groovy的定义,== 操作等于调用equals方法。这样,我们就失去了直接判断两个对象是不是同一对象的运算符。要判断是不是同一个对象,要调用is方法,比如thisObject.is(anotherObject)。这点非常重要,特别是在overwrite对象的equals方法的时候,eclipse自动生成的代码里面有些地方不能直接用==了,而要用is方法
此文为转载地址是:

过去半年都在写Groovy,基本都是在实战中学习,从java转过来,也还没什么问题,毕竟基础,架构都没变。

Groovy的强大特性中,Closure,MetaClass都尝试过,Closure基本上就是当方法或者回调接口使用,再高级的用法就没用过了,没有特别体会什么好处,当回调接口就是省的定义接口,简洁了一些;MetaClass就有专门为一个模块做了些MetaClass,和GORM差不多的,给一些类加了save,update,delete之类的方法,不同的是GORM是存到数据库,我做的那模块是调用Restful Service,还不错,如果有需求是不能改变类而要给类加方法,还是很适用的。但是在绝大部分情况下,这些优势都体现不出来,到目前位置,还是对Groovy的一些语法印象深刻些,总结一些常用的语法:

本文为转载:地址是:http://blog.csdn.net/yanical/article/details/7163138
-------------------------------------------------- Groovy 数据库操作 ---------------------------------------------------------------------------------------

迭代器在 Groovy 对 JDBC 的增强中扮演着重要角色。所以,我将从 Groovy 中迭代器的概述开始。

清单 1. 普通 Java 代码中的迭代器

import java.util.ArrayList;

import java.util.Collection;

import java.util.Iterator;

public class JavaIteratorExample {

  public static void main(String[] args) {

     Collection coll = new ArrayList();

     coll.add("JMS");

     coll.add("EJB");

     coll.add("JMX");

     for(Iterator iter = coll.iterator(); iter.hasNext();){

        System.out.println(iter.next());

     }

  }

}

 

在清单 2 中,您可以看到 Groovy 如何简化了我的工作。在这里,我跳过了 Iterator 接口,直接在集合上使用类似迭代器的方法。而且, Groovy 的迭代器方法接受闭包,每个迭代中都会调用闭包。清单 2 显示了前面基于 Java 语言的示例用 Groovy 转换后的样子。


清单 2. Groovy 中的迭代器

class IteratorExample1{

   static void main(args) {

     coll = ["JMS", "EJB", "JMX"]

     coll.each{ item | println item }

   }

}

进入迭代器

迭代是各种编程环境中最常见、最有用的技术。 迭代器 是某种代码助手,可以让您迅速地访问任何集合或容器中的数据,每次一个数据。Groovy 把迭代器变成隐含的,使用起来更简单,从而改善了 Java 语言的迭代器概念。在清单 1 中,您可以看到使用 Java 语言打印 String 集合的每个元素需要做的工作。


您可以看到,与典型的 Java 代码不同,Groovy 在允许我传递进我需要的行为的同时,控制了特定于迭代的代码。使用这个控制,Groovy 干净漂亮地把资源管理的责任从我手上转移到它自己身上。让 Groovy 负责资源管理是极为强大的。它还使编程工作更加容易,从而也就更迅速。


GroovySql 简介

Groovy 的 SQL 魔力在于一个叫做 GroovySql 的精致的 API。使用闭包和迭代器,GroovySql 干净漂亮地把 JDBC 的资源管理职责从开发人员转移到 Groovy 框架。这么做之后,就消除了 JDBC 编程的繁琐,从而使您可以把注意力放在查询和查询结果上。

如果您忘记了普通的 Java JDBC 编程有多麻烦,我会很高兴提醒您!在清单 3 中,您可以看到用 Java 语言进行的一个简单的 JDBC 编程示例。


清单 3. 普通 Java 的 JDBC 编程

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

public class JDBCExample1 {

  public static void main(String[] args) {

    Connection con = null;

    Statement stmt = null;

    ResultSet rs = null;

    try{

      Class.forName("org.gjt.mm.mysql.Driver");

      con = DriverManager.getConnection("jdbc:mysql://localhost:3306/words",

           "words", "words");

      stmt = con.createStatement();

      rs = stmt.executeQuery("select * from word");

      while (rs.next()) {

        System.out.println("word id: " + rs.getLong(1) +

            " spelling: " + rs.getString(2) +

            " part of speech: " + rs.getString(3));

      }

    }catch(SQLException e){

      e.printStackTrace();

    }catch(ClassNotFoundException e){

      e.printStackTrace();

    }finally{

      try{rs.close();}catch(Exception e){}

      try{stmt.close();}catch(Exception e){}

      try{con.close();}catch(Exception e){}

   }

  }

}

 

哇。清单 3 包含近 40 行代码,就是为了查看表中的内容!如果用 GroovySql,您猜要用多少行?如果您猜超过 10 行,那么您就错了。请看清单 4 中,Groovy 替我处理底层资源,从而非常漂亮地让我把注意力集中在手边的任务 —— 执行一个简单的查询。





清单 4. 欢迎使用 GroovySql!

import groovy.sql.Sql

class GroovySqlExample1{

  static void main(args) {

    sql = Sql.newInstance("jdbc:mysql://localhost:3306/words", "words",

           "words", "org.gjt.mm.mysql.Driver")

    sql.eachRow("select * from word"){ row |

       println row.word_id + " " + row.spelling + " " + row.part_of_speech

    }

  }

}

 

真不错。只用了几行,我就编码出与清单 3 相同的行为,不用关闭 Connection ,也不用关闭 ResultSet ,或者在 JDBC 编程中可以找到的任何其他熟悉的重要特性。这是多么激动人心的事情啊,并且还是如此容易。现在让我来仔细介绍我是如何做到的。






 

 

执行简单的查询

在 清单 4 的第一行中,我创建了 Groovy 的 Sql 类的实例,用它来连接指定的数据库。在这个例子中,我创建了Sql 实例,指向在我机器上运行的 MySQL 数据库。到现在为止都非常基本,对么?真正重要的是一下部分,迭代器和闭包一两下就显示出了它们的威力。

请把 eachRow 方法当成传进来的查询生成的结果上的迭代器。在底层,您可以看到返回了 JDBC ResultSet 对象,它的内容被传递进 for 循环。所以,每个迭代都要执行我传递进去的闭包。如果在数据库中找到的 word 表只有三行,那么闭包就会执行三次 —— 打印出 word_id 、 spelling 和 part_of_speech 的值。

如果将等式中我指定的变量 row 去掉,而使用 Groovy 的一个隐含变量 it (它恰好就是迭代器的实例),代码可以进一步简化。如果我这样做,那么前面的代码就可以写成清单 5 所示的这样:


清单 5. GroovySql 中的 it 变量

import groovy.sql.Sql

class GroovySqlExample1{

  static void main(args) {

    sql = Sql.newInstance("jdbc:mysql://localhost:3306/words", "words",

           "words", "org.gjt.mm.mysql.Driver")

    sql.eachRow("select * from word"){ println it.spelling +  " ${it.part_of_speech}"}

  }

}

 

在这个代码中,我可以删除 row 变量,用 it 代替。而且,我还能在 String 语句中引用 it 变量,就像我在${it.part_of_speech} 中所做的那样。

 



 


执行更复杂的查询

前面的例子相当简单,但是 GroovySql 在处理更复杂的数据操纵查询(例如 insert 、 update 和 delete 查询)时,也是非常可靠的。 对于这些查询,您没有必要用迭代器,所以 Groovy 的 Sql 对象另外提供了 execute 和executeUpdate 方法。这些方法让人想起普通的 JDBC statement 类,它也有 execute 和 executeUpdate 方法。

在清单 6 中,您看到一个简单的 insert ,它再次以 ${} 语法使用变量替换。这个代码只是向 word 表插入一个新行。


清单 6. 用 GroovySql 进行插入

 wid = 999

 spelling = "Nefarious"

 pospeech = "Adjective"

 sql.execute("insert into word (word_id, spelling, part_of_speech) 

   values (${wid}, ${spelling}, ${pospeech})")

 

Groovy 还提供 execute 方法的一个重载版本,它接收一列值,这些值与查询中发现的 ? 元素对应。在清单 7 中,我简单地查询了 word 表中的某个行。在底层,GroovySql 创建了普通 Java 语言 java.sql.PreparedStatement 的一个实例。


清单 7. 用 GroovySql 创建 PreparedStatement 的实例

val = sql.execute("select * from word where word_id = ?", [5])

 

更新的方式基本相同,也使用 executeUpdate 方法。还请注意,在清单 8 中 executeUpdate 方法接收一列值,与查询中的 ? 元素对应。


清单 8. 用 GroovySql 进行更新

 nid = 5

 spelling = "Nefarious"

 sql.executeUpdate("update word set word_id = ? where spelling = ?", [nid, spelling])

 

删除实际上与插入相同,当然,语法不同,如清单 9 所示。


清单 9. 用 GroovySql 进行删除

 sql.execute("delete from word where word_id = ?" , [5])




 

 

简化数据操纵

任何想简化 JDBC 编程的 API 或工具最好有一些好的数据操纵特性,在这一节中,我要向您再介绍三个。

数据集(DataSet)

构建于 GroovySql 简单性的基础之上,GroovySql 支持 DataSet 类型的概念,这基本上是数据库表的对象表示。使用 DataSet ,您可以在行中遍历,也可以添加新行。实际上,用数据集是方便地表示表格的公共数据集合的方式。

但是,目前 GroovySql DataSet 类型的不足之处是它们没有代表关系;它们只是与数据库表的一对一映射。在清单 10 中,我创建了一个来自 word 表的 DataSet 。


清单 10. 用 GroovySql 创建数据集

import groovy.sql.Sql

class GroovyDatasetsExample1{

  static void main(args) {

    sql = Sql.newInstance("jdbc:mysql://localhost:3306/words", "words",

          "words", "org.gjt.mm.mysql.Driver")

    words = sql.dataSet("word")

    words.each{ word |

     println word.word_id + " " + word.spelling

    }

    words.add(word_id:"9999", spelling:"clerisy", part_of_speech:"Noun")

  }

}

 

您可以看到,GroovySql 的 DataSet 类型可以容易地用 each 方法对表的内容进行遍历,容易地用 add 方法添加新行, add 方法接受一个 map 表示需要的数据。

使用存储过程和负索引

存储过程调用和负索引(negative indexing)可能是数据操纵的重要方面。GroovySql 使存储过程调用简单得就像在 Sql 类上使用 call 方法一样。对于负索引, GroovySql 提供了自己增强的 ResultSet 类型,它工作起来非常像 Groovy 中的 collections 。例如,如果您想获取结果集中的最后一个项目,您可以像清单 11 所示的那样做:


清单 11. 用 GroovySql 进行负索引

 sql.eachRow("select * from word"){ grs |

   println "-1  = " + grs.getAt(-1) //prints spelling

   println "2  = " + grs.getAt(2) //prints spelling

 }

 

您在清单 11 中可以看到,提取结果集的最后一个元素非常容易,只要用 -1 作索引就可以。如果想试试,我也可以用索引 2 访问同一元素。

这些例子非常简单,但是它们能够让您很好地感觉到 GroovySql 的威力。我现在要用一个演示目前讨论的所有特性的实际例子来结束本月的课程。

 



 


编写一个简单的报告应用程序

报告应用程序通常要从数据库拖出信息。在典型的业务环境中,可能会要求您编写一个报告应用程序,通知销售团队当前的 Web 销售情况,或者让开发团队对系统某些方面(例如系统的数据库)的性能进行日常检测。

为 了继续这个简单的例子,假设您刚刚部署了一个企业范围的 Web 应用程序。当然,因为您在编写代码时还(用 Groovy)编写了充足的单元测试,所以它运行得毫无问题;但是您还是需要生成有关数据库状态的报告,以便调优。您想知道客户是如何使用应用程序的,这 样才能发现性能问题并解决问题。

通常,时间约束限制了您在这类应用程序中能够使用的提示信息的数量。但是您新得到的 GroovySql 知识可以让您轻而易举地完成这个应用程序,从而有时间添加更多您想要的特性。

细节

在这个例子中,您的目标数据库是 MySQL,它恰好支持用查询发现状态信息这一概念。以下是您有兴趣的状态信息:

  • 运行时间。
  • 处理的全部查询数量。
  • 特定查询的比例,例如 insert 、 update 和 select 。

用 GroovySql 从 MySQL 数据库得到这个信息太容易了。由于您正在为开发团队构建状态信息,所以您可能只是从一个简单的命令行报告开始,但是您可以在后面的迭代中把报告放在 Web 上。这个报告例子的用例看起来可能像这样:

1.连接到我们的应用程序的活动数据库。
2.发布 show status 查询并捕获:
 a. 运行时间
 b. 全部查询数
 c. 全部 insert 数
 d. 全部 update 数
 e. 全部 select 数
3.使用这些数据点,计算:
 a. 每分钟查询数
 b. 全部 insert 查询百分比
 c. 全部 update 查询百分比
 d. 全部 select 查询百分比

在清单 12 中,您可以看到最终结果:一个将会报告所需数据库统计信息的应用程序。代码开始的几行获得到生产数据库的连接,接着是一系列 show status 查询,让您计算每分钟的查询数,并按类型把它们分开。请注意像uptime 这样的变量如何在定义的时候就创建。


清单 12. 用 GroovySql 进行数据库状态报告

import groovy.sql.Sql

class DBStatusReport{

  static void main(args) {

     sql = Sql.newInstance("jdbc:mysql://yourserver.anywhere/tiger", "scott",

        "tiger", "org.gjt.mm.mysql.Driver")

     sql.eachRow("show status"){ status |

        if(status.variable_name == "Uptime"){

           uptime =  status[1]

        }else if (status.variable_name == "Questions"){

           questions =  status[1]

        }

     }

     println "Uptime for Database: " + uptime

     println "Number of Queries: " + questions

     println "Queries per Minute = " + Integer.valueOf(questions) / Integer.valueOf(uptime)

     sql.eachRow("show status like 'Com_%'"){ status |

        if(status.variable_name == "Com_insert"){

           insertnum =  Integer.valueOf(status[1])

        }else if (status.variable_name == "Com_select"){

           selectnum =  Integer.valueOf(status[1])

        }else if (status.variable_name == "Com_update"){

           updatenum =  Integer.valueOf(status[1])

       }

    }

    println "% Queries Inserts = " + 100 * (insertnum / Integer.valueOf(uptime))

    println "% Queries Selects = " + 100 * (selectnum / Integer.valueOf(uptime))

    println "% Queries Updates = " + 100 * (updatenum / Integer.valueOf(uptime))

    }

}

================================   有关firstRow===========================

 /*根据基站信息 从基站-经纬信息表中查道对应的经纬度*/
    def findLngAndLatByCellInfo(mcc,mnc,lac,ci) {
        String signPOSMoveByLogStr = """
            select  LNG,LAT
            from CELL_LNG_LAT cell2LngLat
            where   cell2LngLat.mcc = '${mcc}'  and
                    cell2LngLat.mnc = '${mnc}'  and
                    cell2LngLat.lac = '${lac}'  and
                    cell2LngLat.ci  = '${ci}'
         """
        db.firstRow(signPOSMoveByLogStr);
    }

 def list = Commons.getDao().findLngAndLatByCellInfo(mcc,mnc,lac,ci);  //数据库缓存表中去查是否存在
        if(list!=null){//如果存在则从缓存表中去取
            lng = list.LNG;
            lat = list.LAT;
        }

主要注意这里的写法:

判断有没有值用null来比较

直接返回对象,点出来列就可以了,



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值