Java的虚拟机JVM上可以支持多种语言,除了原住民Java之外,还有Kotlin,Closure,Scala等等。Groovy也是其中一员。参考List of JVM languages。
groovy官方对其解释是
Apache Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax. It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.
以我稍微粗浅的理解,Groovy之于JVM,就像PowerShell之于.Net。Groovy和Java的区别,在Differences with Java有所说明。
安装Groovy
官方的安装指导是Install Groovy。在macOS上和IntelliJ IDEA结合的话,好像需要在homebrew上安装groovysdk而不是groovy。
IDEA有免费的Community版可以使用,可以到Download IntelliJ IDEA下载。对比不同的版本的话,参照IntelliJ IDEA Ultimate vs IntelliJ IDEA Community Edition。另外这篇文章How do I tell IntelliJ about groovy installed with brew on OSX也可以参考一下。从IDE integration可以看IDE集成相关的信息。
需要在IDEA里面创建Groovy的SDK,点击Create之后在文件浏览对话框中按cmd+shift+g,然后浏览到/usr/local/Cellar/groovysdk/3.0.7/libexec(这里假设Groovy的版本是3.0.7)。
安装好groovy之后,有几个可执行文件:
- groovy用于执行脚本
- groovyc用于编译脚本
- groovysh控制台REPL
- groovyConsole图形化的REPL
- grape包管理器 The Grape dependency manager
groovysh - the Groovy repl-like shell
- 历史记录功能来自jline2。
- 当次执行结果保存在
_
。 def foo = "bar"
声明的是局部变量,不会保存在shell的执行环境中。可以通过:= interpreterMode
关闭。- 可以使用
:help
来输出帮助,查看所有命令,除了:=
外,可以使用set
来设置偏好。 - 删除环境中的变量是通过
:purge
命令达成的,通过:edit
可以调用外部编辑器,通过:doc java.util.List
可以查看文档。 - 偏好包括verbosity,show-last-result,sanitize-stack-trace,editor等等。
- 启动配置在
$HOME/.groovy/groovysh.profile
,交互配置在$HOME/.groovy/groovysh.rc
,历史保存在$HOME/.groovy/groovysh.history
。 - 可以编制自定义命令,并使用
:register
注册。
一些问题:
- 改变工作目录似乎有些困难,参考How to change the current working directory in Groovy。
如何给Groovy指定classpath或者使用jar包
- How do I include jars in a groovy script? [duplicate]
- How do I auto load a database jar in Groovy without using the -cp switch?
groovy -cp ojdbc5.jar RunScript.groovy
this.class.classLoader.rootLoader.addURL(new URL("file:///path to file"))
@GrabConfig(systemClassLoader=true)
@Grab('com.oracle:ojdbc6:12.1.0.2.0')
Class.forName("oracle.jdbc.OracleDriver").newInstance()
或者直接把jar包放在
.groovy/lib
。
新手入门
def x = "hello"
==> hello
def x = "world
==> world
x
Unknown property: x // 为啥打印出这个饿?
// closure的例子
0.upto(4) {println "$it"}
在groovysh中,貌似#
会把计算输出的显示给屏蔽掉。
- Groovy Script Tutorial for Beginners
- Groovy Tutorial - TutorialsPoint
- https://groovy-lang.org/learn.html 上有不少资源
出现异常的时候要用:clear来清楚之。
getProperteis
How to get all property names of a Groovy class? [duplicate]
println demoClass.getProperties().toString()
f2.properties.each { prop, val ->
if(prop in ["metaClass","class"]) return
if(f.hasProperty(prop)) f[prop] = val
}
Groovy数据相关模块指导
官方文档Working with a relational database
下面是在groovysh之下通过jdbc连接filemaker数据库:
注意要把filemaker的jdbc驱动放在
.groove/lib
下面。
driver = 'com.filemaker.jdbc.Driver'
url = 'jdbc:filemaker://127.0.0.1/demodb/'
password = ''
user = 'dbuser'
sql = Sql.newInstance(url, user, password, driver)
===> groovy.sql.Sql@7219ac49
可以创建独立的DataSource:
def ds = new BasicDataSource(driverClassName: "org.hsqldb.jdbcDriver",
url: 'jdbc:hsqldb:mem:yourDB', username: 'sa', password: '')
def sql = new Sql(ds)
sql.close()用来关闭链接。
// 限定连接对象的作用域
Sql.withInstance(url, user, password, driver) { sql ->
// use 'sql' instance ...
}
执行sql:
sql.execute '''
CREATE TABLE Author (
id INTEGER GENERATED BY DEFAULT AS IDENTITY,
firstname VARCHAR(64),
lastname VARCHAR(64)
);
'''
sql.execute "INSERT INTO Author (firstname, lastname) VALUES ('Dierk', 'Koenig')"
执行带参数的sql:
def insertSql = 'INSERT INTO Author (firstname, lastname) VALUES (?,?)'
def params = ['Jon', 'Skeet']
def keys = sql.executeInsert insertSql, params
assert keys[0] == [1]
另一个示例:
def first = 'Guillaume'
def last = 'Laforge'
def myKeyNames = ['ID']
def myKeys = sql.executeInsert """
INSERT INTO Author (firstname, lastname)
VALUES (${first}, ${last})
""", myKeyNames
assert myKeys[0] == [ID: 2]
Better JDBC With Groovy Sql
// iterate over query's result set and "process" each row by printing two names
sql.eachRow("SELECT employee_id, last_name, first_name FROM employees")
{
println "Employee ${it.first_name} ${it.last_name} has ID of ${it.employee_id}."
}
// when you know there's only one match, firstRow can be particularly useful
def employee140 = sql.firstRow("SELECT employee_id, last_name, first_name FROM employees where employee_id = ?", [140])
println "Employee 140 is ${employee140.first_name} ${employee140.last_name}"
// update the previously added employee
def updateStr =
"""update employees set email='dustin@marxblog.com'
where employees.first_name='Dustin' and employees.last_name='Marx'"""
def numberRowsUpdated = sql.executeUpdate(updateStr)
println "${numberRowsUpdated} row(s) was/were updated."
JDBC with Groovy
Map dbConnParams = [
url: 'jdbc:hsqldb:mem:testDB',
user: 'sa',
password: '',
driver: 'org.hsqldb.jdbc.JDBCDriver']
def sql = Sql.newInstance(dbConnParams)
sql.withTransaction {
sql.execute """
INSERT INTO PROJECT (NAME, URL)
VALUES ('tutorials', 'github.com/eugenp/tutorials')
"""
sql.execute """
INSERT INTO PROJECT (NAME, URL)
VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')
"""
}
sql.cacheConnection {
sql.execute """
INSERT INTO PROJECT (NAME, URL)
VALUES ('tutorials', 'github.com/eugenp/tutorials')
"""
throw new Exception('This does not roll back')
}
blobs in groovy sql
import groovy.sql.*
def jdbcUrl = 'jdbc:derby:E:/Christof/Labor/GroovyJPA/db;create=true'
def sql = Sql.newInstance(jdbcUrl, '', '',
'org.apache.derby.jdbc.EmbeddedDriver')
sql.execute('CREATE TABLE testBlob (bits BLOB)')
def is = new ByteArrayInputStream('Alles in Butter'.getBytes())
def ps = sql.connection.prepareStatement(
'INSERT INTO testBlob (bits) VALUES (?)')
ps.setBinaryStream(1, is)
ps.executeUpdate()
sql.eachRow('SELECT bits FROM testBlob') {
println 'bits.class: ' + it.bits.class
byte[] readBits = it.bits.getBytes(1L, it.bits.length()as int)
println 'bits: ' + new String(readBits)
}
madan712/SimpleBlobExample.java How to insert Binary data into a table using JDBC?
sqlite with jdbc
sql = Sql.newInstance("jdbc:sqlite:sample.db", "org.sqlite.JDBC")
sql.execute "insert into t1 values(0)"
t1 = sql.dataSet("t1")
t1.add(i:10)
sql.eachRow("select * from t1") { println "${it.i}" }
metadata = sql.connection.getMetaData()
t1_meta = metadata.getTables(null, null, "t1", null)
import java.nio.charset.StandardCharsets
sql.execute 'create table t2(b blob)'
sql.eachRow('select b from t2') {
n = input.available()
bytes = new byte[n]
input.read(bytes)
println new String(bytes, StandardCharsets.UTF_8)
println n
}
- Use Groovy language JDBC with SQLite database
- sqlite-jdbc/Usage.md
- Convert Contents Of A ByteArrayInputStream To String
文件IO
基于Java.io的File,InputStream,OutputStream,Reader,Writer。以及java.nio.file.path。
遍历一个目录:
dir = new File('C:\Windows`)
dir.eachFile{ file -> println file.name }
读入一个文件的内容:
file = new File('a.txt')
bytes[] content = file.bytes
正则表达式
用在FileMaker之上
- 表格必须在Relationships里面出现,否则执行sql的时候会视为不存在
插入PDF
sql = Sql.newInstance(connPars)
stmt = sql.connection.prepareStatement("""
insert into t (pdf) values(PutAs(?, 'PDF '))
""")
stmt.setBytes(1, new File("doc.pdf").bytes)
stmt.executeUpdate()
其他参考
(本篇完)