groovy的琐碎记录(错误提示,编译,语言细节及应用)

这里存放着关于书写groovy脚本中遇到的问题(主要)使用到的技术

 

文档结构

  1. 其他提示和问题
  2. groovy代码编译相关的问题
  3. 有用的语言细节/groovy语法糖
  4. 实现某些功能时需要用到的包和参考文档地址

 

我使用这个IDE:springsourcetool,基于eclipse的整合产品,提供groovy和grails的插件。在ide环境下,如果不能run as groovy或者java,很可能是因为源文件有问题(但IDE没有提示),无法成功编译。

莫名其妙的错误提示:

 

  • 提示No signature of method:xxx is applicable for argument types: SomeType,但是在下面的Possible solution里,同样签名的方法又被给出了。这可能是那个方法是非静态方法,而你直接通过类而非去调用它了。这个提示本身十二分的莫名其妙。

 

编译:

 

1. 命令行编译代码:
  1. groovyc file.groovy
  2. java -cp "$GROOVY_HOME/lib/*":.  file

2. 编译和引用:
把groovy源文件根据“有没有独立的执行语句”分为两种: 脚本文件和类文件
  1. 脚本会被编译成同名类,继承自script类, 脚本内的类也被分别编译成同名groovy类,因此,脚本名如果和类名相同,就不能在class{}体外有执行语句
  2. 引用类的方式:若该类与所属文件同名的,和java一样,或者通过groovyshell.evaluate获得返回的class对象,否则需要确保已经被编译成class;引用脚本的方式,groovyshell.evaluate返回脚本对象,或者使用scriptEngine.run
// 1
import classCompiled

// 2
def groovyScriptEngine = new GroovyScriptEngine(".")  
groovyScriptEngine .run("file.groovy", new Binding())

// 3
GroovyShell shell = new GroovyShell(new Binding());
shell.evaluate(new File("file.groovy")) 
 

3. import的类导致无法解析的错误: cannot resovle class:

 

  • 该类不在加载的路径上,groovy在启动时会加载groovy目录下的lib中的类,和用户定义的类目录
  • 如果该类是groovy自带的类,那么也可能是groovy的版本较旧
简单直接的增加路径的方式:
  1. 在conf/groovy-starter.conf中增加load配置
  2. 在已配置的路径中加入lib
  3. 在代码中对classLoader增加URL;在命令行中增加classpath参数
语言细节:
1. use的使用能够以可控的方式进行dsl,方法的增加仅限于use块内部,示例代码如下:
class ShellDSL {
    // non-thread safe
    def static ThreadLocal parentHolder = new ThreadLocal()
    def static mv (String src, String dest) {
	    def srcFile = src.file()
	    if (dest =~ "/\$")
		dest = "$dest${srcFile.name}"
	    srcFile.renameTo(dest.file())
    }
    
    def static file (String file) {
	if (parentHolder.get()) {
	    new File(parentHolder.get(), file)
	} else {
	    new File(file)
	}
    }
    
    def static dir(String dir, ensure) {
	//TODO should replace with seperator
	if (!dir =~ "/\$") {dir = "$dir/"}
	def d = dir.file()
	if (ensure)
	    d.mkdirs()
	d
    }

    def static ensure(File f) {
	f.mkdir()
	f
    }

    def static  inDir(String dir ,closure) {
	def d = dir.dir()
	parentHolder.set(d)
	closure.call()
	parentHolder.set(null)
    }
}
 
  1. 用static定义方法
  2. 方法的第一个参数的类型就是该方法注入的目标类
  3. 方法使用该类中的其他方法时不需要use块
2.  特殊运算符用法:
  1.  类型转换使用as, 源类型中需要定义asType(Class klass)的方法
  2. << 符号对应的是leftShift方法, >>对应rightShift
  3. 运算符 *. 的意思是依次调用数组中元素的方法,操作返回一个对应结果的数组,效果和collect相同
  4. &method,方法指针。在对象定义级别使用,和ruby的alias作用相同;在执行流程中使用可以提升代码可读性
as:    
def asType(Class r) {
	if (r == Registered)
	    new Registered()
            // alternative way
	    //return {it -> new Registered(name:it.name)}(this)
    }

new User() as Registered


<<:
def leftShift(v) {array.add v}

new Queue() << 'mock'

*. :
['cut', 'paste']*.size().each{println it}
 
&:
class Alias {
def method = {println "method"}
def alias = this.&method // 需要通过对象去引用.因此this不可省略
}
def alias = new Alias()
alias.method()
alias.alias()
def aliasMethod = alias.&alias
aliasMethod()
 

应用:
1. groovy file 调用接口文档: 点此 :
  • 可以进行eachFile, eachDir的操作
  • eachXXX有对应的Match版本, 传入一个nameFilter, 根据文件的名字进行filter操作
  • eachXXX还对应一个Recurse版本

2. Http请求可以使用 httpBuilder包,优点:
  • 像js中处理ajax请求那样来写代码,虽然其实底层就是基于apache的那个包
    client.request(GET, JSON){response, json -> 
    success: {
        .....
        .....
        }
    
    }
     
  • 如上面所示,格式已经自动转换好了,而且性能不错,至少xml比groovy自带的快
  • 适合复杂的场景使用,比较清晰
3. XML构建可以使用MarkupBuiler, 解析可以使用XMLSlurper:
  • 最大的好处是dsl风格,代码量少
  • 构建如<s.name ...></s.name>的元素,没找到直接简单的方式,我的解决办法是用下划线代替点,然后在实际调用时动态替换回点
4. 并行计算可以考虑 gpars,目前还在不断发展完善中, 将会正式加入下个版本的groovy中
  • 支持actor方式(传数据)和agent方式(传运算), 支持fork/join
  • 支持数据流的方式,用户可以不需关注消息和过程,只关注需要的结果数据,数据得不到时block,有点像future.get(),但是支持的数据种类更多
  • 据说性能不错,我没深入测试过
  • 应用参考链接点击

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值