Groovy Process Xml(创建XML)
参考资料:
http://groovy.codehaus.org/Creating+XML+using+Groovy%27s+MarkupBuilder
NOTE: 这是笔者的备忘录BLog,如果代码有运行不成功的, 请访问上面给出的链接. 感谢Groovy社区的所有Groovy Monkey 谢谢!
Groovy处理XML之创建XML:
一 简单的创建实例:
def stringWriter = new StringWriter(); def xml = new MarkupBuilder(stringWriter); //红色表示元素, 绿色表示属性, 黄色表示元素的text值 xml.cars() { car(name:"car1",no:"1") { country('china') city('kunming') } car(name:"car2",no:"2") { country('china') city('kunming') } car(name:"car3",no:"3") { country('china') city('kunming') } } println stringWriter //打印结果如下: <cars> <car name='car1' no='1'> <country>china</country> <city>kunming</city> </car> <car name='car2' no='2'> <country>china</country> <city>kunming</city> </car> <car name='car3' no='3'> <country>china</country> <city>kunming</city> </car> </cars> 对比示例程序和输出的结果看出: 1 一个方法表示一个Element; 2 方法中的参数代表此ELement的Attributes[propertyName:propertyValue] 3 方法中如果propertyName 和propertyValue不是成对出现,只是出现了propertyValue,那么将会被设置为ELement的text值. 二 使用DomToGroovy类,将一个现有的XML转化Groovy MakeUpBuilder的相关代码: class XmlExamples { static def CAR_RECORDS = ''' <records> <car name='HSV Maloo' make='Holden' year='2006'> <country>Australia</country> <record type='speed'>Production Pickup Truck with speed of 271kph</record> </car> <car name='P50' make='Peel' year='1962'> <country>Isle of Man</country> <record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg in weight</record> </car> <car name='Royale' make='Bugatti' year='1931'> <country>France</country> <record type='price'>Most Valuable Car at $15 million</record> </car> </records> ''' } //使用DomToGroovy进行反向的转化: import javax.xml.parsers.DocumentBuilderFactory import org.codehaus.groovy.tools.xml.DomToGroovy def builder = DocumentBuilderFactory.newInstance().newDocumentBuilder() def inputStream = new ByteArrayInputStream(XmlExamples.CAR_RECORDS.bytes) def document = builder.parse(inputStream) def output = new StringWriter() def converter = new DomToGroovy(new PrintWriter(output)) converter.print(document) println output.toString() 打印出的结果如下: //红色表示元素, 绿色表示属性, 黄色表示元素的text值 records() { car(make:'Holden', name:'HSV Maloo', year:'2006') { country('Australia') record(type:'speed', 'Production Pickup Truck with speed of 271kph') } car(make:'Peel', name:'P50', year:'1962') { country('Isle of Man') record(type:'size', 'Smallest Street-Legal Car at 99cm wide and 59 kg in weight') } car(make:'Bugatti', name:'Royale', year:'1931') { country('France') record(type:'price', 'Most Valuable Car at $15 million') } } 三 为创建的XML添加NameSpace 实例代码: def xml = new MarkupBuilder(writer) xml.'rec:records'('xmlns:rec': 'http://groovy.codehaus.org') { car(name:'HSV Maloo', make:'Holden', year:2006) { country('Australia') record(type:'speed', ' Truck with speed of 271kph') } } result <rec:records xmlns:rec='http://groovy.codehaus.org'> <car name='HSV Maloo' make='Holden' year='2006'> <country>Australia</country> <record type='speed'> Truck with speed of 271kph</record> </car> </rec:records> ================================= xml.records(xmlns: 'http://groovy.codehaus.org') { car(name:'HSV Maloo', make:'Holden', year:2006) { country('Australia') record(type:'speed', ' Truck with speed of 271kph') } } result <records xmlns='http://groovy.codehaus.org'> <car name='HSV Maloo' make='Holden' year='2006'> <country>Australia</country> <record type='speed'> Truck with speed of 271kph</record> </car> </records> 四 使用Groovy的StreamingMarkupBuilder创建XML: 示例代码: import groovy.xml.StreamingMarkupBuilder def xml = new StreamingMarkupBuilder().bind { root { a( a1:'one' ) { b { mkp.yield( '3 < 5' ) } //注意点 c( a2:'two', 'blah' ) } } } println xml.toString(); 程序运行结果: <root> <a a1='one'> <b>3 < 5</b> <c a2='two'>blah</c> </a> </root> 五 使用Groovyapi结合Dom创建XML 参考链接:http://groovy.codehaus.org/Creating+XML+with+Groovy+and+DOM
Groovy 集合类常用api之List篇
参考资料:
<<Programming Groovy>>
DefaultGroovyMethods源代码
Groovy collection 常用api之List篇:
1 each
each 源代码<私有方法>:
private static <T> Iterator<T> each(Iterator<T> iter, Closure closure) {
while (iter.hasNext()) {
closure.call(iter.next()); // 在闭包中改变it这个默认参数是达不到更改集合的效果的.
}
return iter;
}
each 将集合中的每一个元素传递到闭包中执行,也就是闭包直接修改元素,并且是执行一个iterator,注意多线程同时修改引发的异常. 最终将处理完毕的List
返回,注意,在闭包中使用 it = "changedValue"是不会有效的! 例如:
def list = ["1",2,3,54]
list.each{
if(it.equals("1")){
//try to change the value,but it is noe affect the list!!
it = "changed"
}
}
assert list == ["1",2,3,54]
如果想要得到闭包修改以后的集合,使用方法: collect
2 collect: 使得每一个集合元素都参与闭包的运算,并最终返回一个新的集合,此集合的每一个元素都是闭包执行后的结果.
源代码:<私有方法>
public static Collection collect(Collection self, Collection collection, Closure closure) {
for (Iterator iter = self.iterator(); iter.hasNext();) {
collection.add(closure.call(iter.next()));
if (closure.getDirective() == Closure.DONE) {
break;
}
}
return collection;
}
测试:
def list = [1,2,3,4]
assert list.collect {
it * 2;
} == [2,4,6,8]
//原来的集合不变
assert list == [1,2,3,4]
3 find方法以及findAll方法: 注意,find方法只查找第一个
源代码: public static Object find(Object self, Closure closure) { for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) { Object value = iter.next(); if (DefaultTypeTransformation.castToBoolean(closure.call(value))) { //如果满足条件 return value; //只是返回第一个 } } return null; //不满足闭包调价就返回null } 测试代码: def list = [1,2,3,4] assert 1 == list.find { it < 5 //表明闭包会返回一个boolean } //原来的集合不变 assert list == [1,2,3,4] ====================findAll <源代码> private static <T> Collection<T> findAll(Closure closure, Collection<T> answer, Iterator<T> iter) { while (iter.hasNext()) { T value = iter.next(); if (DefaultTypeTransformation.castToBoolean(closure.call(value))) { answer.add(value); //把符合闭包条件的元素添加到新的集合answer中. } } return answer; }
4 inject 方法: 每次都会传入value和每一个集合元素给闭包,并返回闭包的执行结果,注意,闭包对应的参数是一个object[2],要有两个参数
public static Object inject(Iterator self, Object value, Closure closure) { Object[] params = new Object[2]; while (self.hasNext()) { Object item = self.next(); params[0] = value; params[1] = item; value = closure.call(params); } return value; } 测试代码: def list = [1,2,3,4] assert list.inject(1) { param1, param2 -> param1 + param2; } == 11 //(1+1,2+2,4+3,7+4),最终为11
5 一些辅助的集合方法:
5.1 sum()方法:
def list = [1,2,3,4]
assert list.sum() == 10
//代闭包的sum方法;
assert list.sum{
it * 2
} == 20
5.2 join()方法: 将集合合并
def list = [1,2,3,4]
assert list.join().class == String
assert list.join() == "1234"
//带上分隔符
assert list.join('|') == "1|2|3|4"
5.3 flatten方法:
先将测试代码贴出;
def list1 = [["Be" , "Productive" ], "In" , "Groovy" ];
assert list1.flatten() == ["Be" , "Productive" , "In" , "Groovy" ]
源代码贴出:
DefaultGroovyMethods类中的代码:
private static Collection flatten(Collection elements, Collection addTo) {
for (Object element : elements) {
if (element instanceof Collection) {
flatten((Collection) element, addTo);
} else if (element != null && element.getClass().isArray()) {
flatten(DefaultTypeTransformation.arrayAsCollection(element), addTo);
} else {
// found a leaf
addTo.add(element);
}
}
return addTo;
}
DefaultGroovyMethodsSuport中的代码贴出:[这里只是贴出有关List的,map,set的请参考相关源代码]
protected static <T> List<T> createSimilarList(List<T> orig, int newCapacity) {
if (orig instanceof LinkedList)
return new LinkedList<T>();
if (orig instanceof Stack)
return new Stack<T>();
if (orig instanceof Vector)
return new Vector<T>();
return new ArrayList<T>(newCapacity);
}
5.4 groupBy方法: public static <T> Map<Object, List<T>> groupBy(Collection<T> self, Closure closure) 方法根据传入的闭包执行以后, 闭包执行的结果被
封装为一个Map Entry的key,集合元素被封装为对应key的value. 源代码如下:
public static <T> Map<Object, List<T>> groupBy(Collection<T> self, Closure closure) { Map<Object, List<T>> answer = new LinkedHashMap<Object, List<T>>(); //创建相关的MAP for (T element : self) { Object value = closure.call(element);//执行闭包,并保存闭包的执行结果到value groupAnswer(answer, element, value); } return answer; } //下面是groupAnser的源代码: protected static <T> void groupAnswer(final Map<Object, List<T>> answer, T element, Object value) { if (answer.containsKey(value)) { answer.get(value).add(element); } else { List<T> groupedElements = new ArrayList<T>(); //如果闭包的执行结果value不存在Map的keySet中, 建立一个新的ArrayList存放对应集合元素 groupedElements.add(element); answer.put(value, groupedElements);//加入Map中. } }
5.5 count函数: 计算传入参数值匹配的个数,相当于在一个集合中统计出现元素的次数. 示例代码:
assert [2,4,2,1,3,5,2,4,3].count(4) == 2
Grails (一)
参考资料:
InfoQ ----- Grails 入门指南:
http://www.cjsdn.net/doc/jvm/grails/docs/1.1/guide/2.%20Getting%20Started.html#2.5%20Getting%20Set-up%20in%20an%20IDE Grails Getting Started
Grails 安装配置:
1 下载grails : http://grails.org/Download 获取grails
2 解压, 类似JDK一样配置:GRAILS_HOME=%groovy_install_root%;
并将%groovy_install_root%bin 追加到PATH环境变量中[注: %groovy_install_root%是grails解压后的目录];
3 cmd 运行 grails 以检查配置的正确性;
创建Grails项目
到达你指定的一个grails work space, 在cmd中cd 到此目录,运行命令: grails create-app <your_app_name>;
从命令的执行信息看出grails会去下载一些jar包,包括了spring,Hibernate ,commons-*,ejb3,servlet,以及日志jar包等等; 其实,在你解压
的grails目录下面的lib目录中就有相关的jar包,之所以create-app命令执行比较快是因为其不用网络下载. 就向maven引用本地jar包一样. 此
目录的输出是: 建立C:\Documents and Settings\User\.grails 目录;
建立C:\Documents and Settings\User\.ivy2 目录[包含jar包]
建立相关的工程目录如下截图:
可以看到.classpath文件和.project文件. 可以带入到eclipse当中; 导入的时候, 可能会报错: 无法找到groovy.lang.GroovyObjectjar包,
此时可以到C:\Documents and Settings\User\.ivy2中找到groovy-all的依赖包. 工程加入jar包以后就没问题了.
创建相关的领域模型:
上一个步骤创建了相关的目录结构,在grails中,是使用"惯例大于配置"的方式. 使用这样的方式可以省去很多繁琐的配置文件信息. 具体每个目录代表什么意思,
请参考: http://www.cjsdn.net/doc/jvm/grails/docs/1.1/guide/2.%20Getting%20Started.html#2.5%20Getting%20Set-up%20in%20an%20IDE
下面创建一个User 类的domain model:
cd <刚刚创建的app目录>
grails create-domain-class com.hcl.domain.Student
上面的命令告诉grails,在<your-app-root-dir>\grails-app\domain 下面创建一个包:com.hcl.domain 再创建一个类:Student.groovy 由于Grails是敏捷开发的工具,
避免不了TDD的思想,于是,grails还会在工程<your-app-root-dir>\test\unit 下面添加单元测试文件com.hcl.domain.StudentTests.Groovy.如下截图:
注意,当你将工程导入Eclipse的时候,加入依赖的jar包[截止此步骤至少含有的jar包]:
开始编写你的Student类吧,如果使用过Hibernate, 就应该很快了. 首先看看grails生成的Student.groovy文件:
class Student { static constraints = { } } static constrants是grails自动生成的, 至于作用是什么,等等再介绍. 下面考试添加一些属性: class Student { String studentName; long studentNumber; Integer studentAge; Date studentBirthDay; String studentPhone; static constraints = { } } 使用哪个同样的方式[grails create-domain-class com.hcl.domain.Teacher],或者直接在Eclipse上创建相关的脚本文件Tearch: class Teacher { String teacherName; String teacherNumber; Integer teacherAge; String teacherPoneNumber; static constraints = { } } NOTE: [下面给出一些比较犀利的使用方法, 只是作为提醒, 如果使用到,就到官方文档库里面搜搜吧.] 1 Grails允许你定义一些特殊地位字段,所谓特殊就是grails会对这些字段进行"特殊关照". 例如: Date dateCreated 和 Date lastUpdated 等等. 详细说明请参考相关给出的文档; 2 Grails允许你使用Groovy闭包来定义相关的一些类似"触发器"的程序; 3 在static mapping ={..}闭包中,可以使用"sort "Property" " 之类的结果映射附加操作. 请参考:http://grails.org/GORM+-+Mapping+DSL 这篇文档;
创建Controller:
使用 grails create-controller com.hcl.controllers.Student 来创建一个关于Student的控制器. grails会自动在Student后面加上
Controller: StudentController
class StudentController { def index = { } } 命令同样会生成相关的测试类: import grails.test.* class StudentControllerTests extends ControllerUnitTestCase { protected void setUp() { super.setUp() } protected void tearDown() { super.tearDown() } void testSomething() { } } 当然,同样需要将相关的依赖jar包导入, jar包路径和在生成domain的时候一样的方式寻找. 在StudentController中添加代码如下: def index = { render("Hello ,Grails World!"); } def helloStudent = { render("Hello Student!"); } 现在可以启动项目了, 可以首先使用:grails help 命令查看grails的相关命令,发现:grails run-app 然后敲此命令: 打开浏览器: http://localhost:8080/<your_app_name>/student[注意,student是我们创建的controller],这个时候浏览器显示: "Hello,Grils World!" 敲入: http://localhost:8080/<your_app_name>/student/helloStudent [helloStudent是在StudentController中添加的一个闭包] 验证一下是否打印出"Hello Student!" 通过上面的运行结果看出: Grails 首先去找你的conreoller,找到以后再找你url后面跟着的groovy闭包名称, 然后执行. 最后使用render("")方法渲染页面. 整个过程没有任何配置文件的干预, 可见上面叫"约定大于配置"原则. 再看看一个相当神奇的controller属性: <添加一个属性到StudentController.groovy文件>如下: def scaffold = Student; 添加完毕以后注意引入包:import com.hcl.domain.* 并且把相关的闭包都去掉!!!; 代码如下: class StudentController { def scaffold = Student; //注意把下面的闭包注释掉: // def index = { // render("Hello ,Grails World!"); // } // // def helloStudent = { // render("Hello Student!"); // } } 进入:http://localhost:8080/racetrack/student/ 截图如下[现在暂时没有数据,如果有数据,会是一个关于Student的列表!!!]:
点击右边的"New Student" ,截图如下: 看到了么? 神奇的地方时只用了一个def scaffold = Student;属性.
Groovy Process Xml(解析XML)
参考资料:
http://groovy.codehaus.org/Processing+XML 官方Groovy xml 操作
测试的xml文件内容:
<?xml version="1.0" encoding="UTF-8"?>
<books location="theLocation">
<book bookid="1" mark="4">Java in action</book>
<book bookid="2" mark="3">Groovy in action</book>
<book bookid="3" mark="2">JavaScript in action</book>
<book bookid="4">
<position url="http://">
<property name="propertiName1">Hello</property>
<property name="propertiName2">World</property>
</position>
</book>
</books>
解析XML示例1:
def books = new XmlParser().parse("testXml.xml"); //参见groovy.util.XmlParser类的api
println langs.attributes().get("location");
//下面的语句更加具有"魅力",因为book是xml中的一个Element,Groovy能够很清楚的知道它是一个Node.
books.book.each {
def bookid = it.attributes().get("bookid");
println bookid;
}
解析XML示例二: 使用数组的下标直接定位;
def books = new XmlParser().parse("testXml.xml");
def bookCollection = books.book;
def book = bookCollection[0];
assert book.text() == "Java in action";
assert book.'@bookid' == "1";
解析XML示例三: 解析示例xml中Position
def file = new XmlParser().parse("testXml.xml");
def books = file.book;
def specialBook = books[3];
assert specialBook.'@bookid' == "4";
def properties = specialBook.position[0].property; //获取position的值;
properties.each {
println "-------------------"
println it.'@name';
println it.text();
println "-------------------"
}
解析XML示例四: 挑选合适的集合并使用排序的方式:
xmlFile.book.findAll { it.attributes().keySet().contains("mark"); //先找到含有"mark"的标签, 因为有一个book是没有这个属性的, //为了避免有些操作会抛出NullPointException. }.sort{ it.'@mark'.toInteger(); //排序的依据 }.each { println it.'@bookid'; }
结束语: 在groovy的文档中,还有很多的方便的解析方式, 这里只是使用了XmlParser这个类来解析.其他的方式可参考Groovy文档,很齐全!
Groovy IO
参考资料:
http://groovy.codehaus.org/groovy-jdk/java/io/File.html Groovy JDK File 文档;
http://groovy.codehaus.org/JN2025-Streams Groovy 官方文档之IO操作
前言: 文章内容收集自互联网以作备忘, 感谢各位作者的支持.
Groovy IO 操作:
1 将文本放置到一个String 对象中.
def textFileContent;
try{
textFileContent = new File("testFile.txt").getText();
}catch(IOException e){
println "系统找不到文件";
}
2 使用闭包操作:
try{
def fileContent = new File("testFile.txt").eachLine {
println it.getClass();
}
}catch(Exception e){
e.printStackTrace();
}
3 将文件内容用List收集:
try{
def fileContentAsList = new File("testFile.txt").readLines();
assert fileContentAsList.getClass() == java.util.ArrayList.class;
}catch(Exception e){
e.printStackTrace();
}
4 用特殊的字符分割每一行<ArrayList>,使用内敛函数操作:
try{
text = new File("testFile.txt").splitEachLine(',') {
//do you code
}
}catch(Exception e){
e.printStackTrace();
}
5 处理二进制文件:
new File("foo.bin").eachByte { ... }
6 文件的写操作:
new File("testFile.txt").write("...");
----文件的追加
new File("foo.txt").append("...");