GPath是一种识别查询结构化数据的表达式。GPath 对 Groovy来说相对于XPath对XML的作用,它能帮助您遍历任何简单Java对象(POJO)或XML文件的结构。GPath的强大功能在于它使您使用最小的代码来完成复杂的类层次结构的查询。
举个简单例子,您可使用GPath打印String类的所有的方法,如:
"".class.methods.name.sort()
具体结果如下:
["charAt", "codePointAt", "codePointBefore", "codePointCount", "compareTo", "compareTo", "compareToIgnoreCase", "concat", "contains", "contentEquals", "contentEquals", "copyValueOf", "copyValueOf", "endsWith", "equals", "equalsIgnoreCase", "format", "format", "getBytes", "getBytes", "getBytes", "getBytes", "getChars", "getClass", "hashCode", "indexOf", "indexOf", "indexOf", "indexOf", "intern", "isEmpty", "lastIndexOf", "lastIndexOf", "lastIndexOf", "lastIndexOf", "length", "matches", "notify", "notifyAll", "offsetByCodePoints", "regionMatches", "regionMatches", "replace", "replace", "replaceAll", "replaceFirst", "split", "split", "startsWith", "startsWith", "subSequence", "substring", "substring", "toCharArray", "toLowerCase", "toLowerCase", "toString", "toUpperCase", "toUpperCase", "trim", "valueOf", "valueOf", "valueOf", "valueOf", "valueOf", "valueOf", "valueOf", "valueOf", "valueOf", "wait", "wait", "wait"]
接下来,将给出一个更广泛的例子。假设您有Book和BookSales类,两者之间是一对一的关系,如清单4.30。
清单 4.30 BookSales和Book类
class BookSales{
int numSold
Book book
int sales(){
return book.price * numSold
}
}
class Book{
int price
float authorRoyaltyFee
String title
}
同时,还有Author类,它与BookSales存在一对多的关系,如清单4.31所示。
例程4.31 Author类
class Author{
String name
List bookSales
int totalEarnings(){
def total = 0
bookSales.each{
total += it.sales() * it.book.authorRoyaltyFee
}
return total
}
}
紧接着创建一些Book和BookSales对象,并赋值于相应的Author对象:
def book1 = new Book(title:"Groovy Grails Recipes", price:44, authorRoyaltyFee:0.1)
def book2 = new Book(title:"Groovy and Grails Rock", price:35, authorRoyaltyFee:0.2)
def bookSales1 = new BookSales(numSold : 5000, book: book1)
def bookSales2 = new BookSales(numSold : 1000, book: book2)
def authors = [
new Author(name:"Bashar", bookSales: [bookSales1, bookSales2]),
new Author(name:"Sami", bookSales:[bookSales2])]
正是由于GPath的强大功能,查询对象图变得异常简单。如查询每个作者的总收入,您可使用以下代码:
assert authors*.totalEarnings() == [29000, 7000]
注意到该清单使用了展开操作符*.(spread operator)。该操作符用来在一个集合对象的所有元素上执行一个动作的,而不是集合本身。
查询销售额达到200,000美元的所有书名,如:
authors.bookSales.each{
println it.grep{it.sales() > 200000}.book.title
}
Groovy 代码就是如此简单!想象一下,如果使用 Java 遍历对象图,您则需编写多行 Java 代码才能实现。