Groovy 語言快速入門

前言

因爲項目須要用到 Groovy 語言,這兩天對其進行了粗略的學習,本文是對學習作的一個簡單總結,主要內容參考於官方文檔(Groovy 的官方文檔仍是很是不錯的,強烈推薦閱讀),但願本文對準備學習使用或者對 Groovy 感興趣的同窗有所幫助,若有不對之處還望指出哈,對這門語言的理解仍是比較膚淺的。php

簡介

Groovy 是 Apache 旗下的一門基於 JVM 平臺的動態/敏捷編程語言,在語言的設計上它吸納了 Python、Ruby 和 Smalltalk 語言的優秀特性,語法很是簡練和優美,開發效率也很是高(編程語言的開發效率和性能是相互矛盾的,越高級的編程語言性能越差,由於意味着更多底層的封裝,不過開發效率會更高,需結合使用場景作取捨)。而且,Groovy 能夠與 Java 語言無縫對接,在寫 Groovy 的時候若是忘記了語法能夠直接按Java的語法繼續寫,也能夠在 Java 中調用 Groovy 腳本,均可以很好的工做,這有效的下降了 Java 開發者學習 Groovy 的成本。Groovy 也並不會替代 Java,而是相輔相成、互補的關係,具體使用哪門語言這取決於要解決的問題和使用的場景。html

快速開始

  1. 下載Groovy開發工具包(GDK)
    www.groovy-lang.org/download.ht…
  2. 建立Groovy項目
    使用IDEA的話須要安裝Groovy的支持插件,安裝完成後在新建項目中便會出現Groovy項目選項,選擇Groovy項目並關聯Groovy libray便可,固然也能夠直接建立.groovy文件用命令行直接運行。
  3. Hello World
    在Java中要輸出「hello world」須要像下面這樣,建立一個類,而後建立一個main方法。
    public class Hello {
     public static void main(String[] args) {
         System.out.println("hello world");
     }
    }複製代碼
    在Groovy中,這些均可以省略,下面這4種方式均可以輸出「hello world」。
    System.out.println("hello world");
    System.out.println "hello world";
    println("hello world")
    println 'hello world'複製代碼
    固然,也能夠像Java同樣運行在類的main方法中。
    class Hello {
     static void main(args) {
         println 'hello world'
     }
    }複製代碼
    若是 Groovy 腳本文件裏只有執行代碼,沒有類的定義,則 Groovy 編譯器會生成一個 Script 的子類,類名和腳本文件的文件名同樣,而腳本中的代碼會被包含在一個名爲run的方法中,同時還會生成一個main方法,做爲整個腳本的入口。因此,做爲 JVM 平臺語言,與 Java 本質上仍是同樣的。

與Java的一些區別

默認導入

Groovy 會默認導入下面這些包、類,不須要使用import語句顯式導入。java

java.io.*
java.lang.*
java.math.BigDecimal
java.math.BigInteger
java.net.*
java.util.*
groovy.lang.*
groovy.util.*複製代碼

多重方法

在 Groovy 中,調用的方法將在運行時被選擇。這種機制被稱爲運行時分派或多重方法(multi-methods),是根據運行時實參(argument)的類型來選擇方法。Java 採用的是相反的策略:編譯時根據聲明的類型來選擇方法。mysql

下面是一個例子,一樣的 Java 代碼在 Java 和 Groovy 環境中運行結果是不一樣的.web

int method(String arg) {
    return 1;
}
int method(Object arg) {
    return 2;
}
Object o = "Object";
int result = method(o);
// In Java
assertEquals(2, result);
// In Groovy
assertEquals(1, result);複製代碼

產生差別的緣由在於,Java 使用靜態數據類型,o 被聲明爲 Object 對象,而 Groovy 會在運行時實際調用方法時進行選擇。由於調用的是 String 類型的對象,因此天然調用 String 版本的方法。spring

數組初始化語法

在 Groovy 中,{...} 語句塊是留給閉包(Closure)使用的,因此不能像 Java 中同樣使用下面這種方式初始化數組sql

int[] array = { 1, 2, 3}複製代碼

而應該是下面這樣shell

int[] array = [1,2,3]複製代碼

POJO

Groovy 默認會隱式的建立getter、setter方法,而且會提供帶參的構造器,下面二者是等價的。apache

// In Java
public class Person {
    private String name;
    Person(String name) {
        this.name = name
    }
    public String getName() {
        return name
    }
    public void setName(String name) {
        this.name = name
    }
}

// In Groovy
class Person {
    String name
}

def person = new Person(name: '張三')
assert '張三' == person.name
person.name = '李四'
//person.setName('李四')
assert '李四' == person.getName()複製代碼

包訪問權限

在 Java 中若是沒有顯式的指定訪問修飾符(public、protected、private)那麼默認是包訪問權限,但在 Groovy 中默認是public的,因此須要使用@PackageScope註解。編程

class Person {
    @PackageScope String name
}複製代碼

ARM 語句塊

ARM(Automatic Resource Management,自動資源管理)語句塊(或者叫TWR語法)從 Java 7 開始引入,用於下降IO操做代碼的複雜度,但 Groovy 並不支持。相反,Groovy 提供多種基於閉包的方法,不但能夠達到一樣的效果而且會更加簡潔優美。

//In Groovy
Path file = Paths.get("/User/lihengming/test.txt");
Charset charset = Charset.forName("UTF-8");
try (BufferedReader reader = Files.newBufferedReader(file, charset)) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }

} catch (IOException e) {
    e.printStackTrace();
}

//In Groovy
new File('/User/lihengming/test.txt').eachLine('UTF-8') {
   println it
}
//或者這樣,更接近於Java的方式
new File('/User/lihengming/test.txt').withReader('UTF-8') { reader ->
   reader.eachLine {
       println it
   }
}
//若是隻是爲了讀取並打印出文本的內容的話,下面是最簡潔的方式
print new File('/User/lihengming/test.txt').text複製代碼

內部類

Groovy 一樣支持內部類而且實現跟 Java 是同樣的,但不該拿 Java 語言規範來考量它,應對差別狀況保持冷靜與寬容(keep shaking the head about things that are different)。在Groovy中內部類看起來有點相似 groovy.lang.Closure 類的實現。

//靜態內部類
class A {
    static class B {}
}
new A.B()

//匿名內部類
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

CountDownLatch called = new CountDownLatch(1)

Timer timer = new Timer()
timer.schedule(new TimerTask() {
    void run() {
        called.countDown()
    }
}, 0)

assert called.await(10, TimeUnit.SECONDS)複製代碼

Lambda 表達式

Java 8 支持 Lambda 表達式和方法引用

Runnable run = () -> System.out.println("Run");
list.forEach(System.out::println);複製代碼

Java 8 的 lambda 幾乎能夠認爲是匿名內部類。Groovy 並無採用這種語法,而採用閉包來實現。

Runnable run = { println 'run' }
list.each { println it } // or list.each(this.&println)複製代碼

GString

因爲雙引號所包括起來的字符串字面量會被解釋爲 GString 值(即 「Groovy 字符串」的簡稱),因此若是當某個類中的 String 字面量含有美圓字符($)時,那麼利用 Groovy 和 Java 編譯器進行編譯時,Groovy 極可能就會編譯失敗,或者產生與 Java 編譯所不一樣的結果。

一般,若是某個 API 聲明瞭形參的類型,Groovy 會自動轉換 GString 和 String。要當心那些形參爲 Object 的 Java API,須要檢查它們的實際類型。

字符串和字符字面量

在 Groovy 中,由單引號所建立的字面量屬於 String 類型對象,而雙引號建立的字面量則多是 String 或 GString 對象,具體分類由字面量中是否有插值來決定。

assert 'c'.getClass()==String
assert "c".getClass()==String
assert "c${1}".getClass() in GString複製代碼

基礎語法

  • Groovy 語句無需使用分號(;)結尾,固然加上也不會報錯,畢竟徹底兼容 Java 的語法。
  • Groovy 中==等價於 Java 中的equals方法。

註釋

註釋和 Java 同樣,支持單行(//)、多行(/* */)和文檔註釋(/** */)

除此以外還支持 Shebang line(UNIX系統支持一種特殊的單行註釋叫做 Shebang line,用於指明腳本的運行環境,便於在終端中能夠直接運行)#號必須是文件的第一個字符。

#!/usr/bin/env groovy
println "Hello from the shebang line"複製代碼

變量

Groovy 中定義變量默認訪問修飾符是public,變量定義時遵循 Java 變量命名規範,變量名以字母、下劃線或美圓符號$開始,能夠包含字母、數字、下劃線和美圓符號$,但關鍵字除外。除了這些規則以外,Groovy 定義變量時若是是一行定義一個類型,末尾的分號能夠省略,可是若是多個變量佔一行,變量之間必須以分號分割。

Groovy 定義變量的方式和 Java 是相似的,區別在於 Groovy 提供了def關鍵字供使用,它能夠省略變量類型的定義,根據變量的值進行類型推導。

def a = 123
def b = 'b'
def c = true 
boolean d = false
int e = 123複製代碼

若是定義變量的字面量值爲數字時,類型會根據數字的大小自動調整

def a = 1
assert a instanceof Integer

// Integer.MAX_VALUE
def b = 2147483647
assert b instanceof Integer

// Integer.MAX_VALUE + 1
def c = 2147483648
assert c instanceof Long

// Long.MAX_VALUE
def d = 9223372036854775807
assert d instanceof Long

// Long.MAX_VALUE + 1
def e = 9223372036854775808
assert e instanceof BigInteger複製代碼

對於浮點型字面量爲了精度 Groovy 默認使用的類型爲 BigDecimal

def decimal = 123.456
println decimal.getClass() // class java.math.BigDecimal複製代碼

Groovy爲 數字類型提供一種更簡單的聲明類型的方式:類型後綴

- Integer 使用I或i
- Long 使用L或l
- BigInteger 使用G或g
- BigDecimal 使用G或g
- Double 使用D或d
- Float 使用F或f複製代碼

使用例子

def a = 123I
assert a instanceof Integer
def b= 123L
assert b instanceof Long複製代碼

字符串

在Groovy種有兩種字符串類型,普通字符串(java.lang.String)和插值字符串(groovy.lang.GString)。
普通字符串使用單引號

println 'hello'複製代碼

插值字符串使用雙引號

def name = '張三'
println "hello $name"複製代碼

除此以外,還支持三單引號的寫法,能夠保留文本的換行及縮進格式

def strippedFirstNewline = '''line one
        line two
            line three
'''
println strippedFirstNewline
// 能夠寫成下面這種形式,可讀性更好
def strippedFirstNewline2 = '''\
line one
    line two
line three
'''
println strippedFirstNewline2複製代碼

字符

在 Groovy 中並無明確的字符字面量表示形式,須要顯示的指定,有三種方式

char c1 = 'A' // 聲明類型
assert c1 instanceof Character

def c2 = 'B' as char // 用as關鍵字
assert c2 instanceof Character

def c3 = (char) 'C' // 強制類型轉換
assert c3 instanceof Character複製代碼

方法(函數)

Groovy 方法的默認訪問修飾符是public,方法的返回類型能夠不須要聲明,但需添加def關鍵字。有返回值的方法return能夠被省略,默認返回最後一行代碼的運行結果,若是使用了return關鍵字則返回指定的返回值。

String method1() {
    return 'hello'
}
assert method1() == 'hello';

def method2() {
    return 'hello'
}
assert method2() == 'hello';

def method3() {
    'hello'
}
assert method3() == 'hello';複製代碼

Groovy 方法的參數類型能夠被省略,默認爲Object類型。

def add(int a, int b) {
    return a + b
}
//與上面的等價
def add(a, b) {
    a + b
}複製代碼

Groovy 方法的其餘特性與Java同樣,好比支持重載、不定長參數(...)等。

閉包

Groovy 提供了閉包的支持,語法和 Lambda 表達式有些相似,簡單來講就是一段可執行的代碼塊或函數指針。閉包在 Groovy 中是groovy.lang.Closure類的實例,這使得閉包能夠賦值給變量,或者做爲參數傳遞。Groovy 定義閉包的語法很簡單,就像下面這樣。

//閉包的參數爲可選項
def closure = { [closureParameters -> ] statements }複製代碼

閉包能夠訪問外部變量,而方法(函數)則不能。

def str = 'hello'
def closure={
    println str
}
closure()//hello複製代碼

閉包調用的方式有兩種,閉包.call(參數)或者閉包(參數),在調用的時候能夠省略圓括號。

def closure = {
    param -> println param
}

closure('hello')
closure.call('hello')
closure 'hello'複製代碼

閉包的參數是可選的,若是沒有參數的話能夠省略->操做符。

def closure = {println 'hello'}
closure()複製代碼

多個參數以逗號分隔,參數類型和方法同樣能夠顯式聲明也可省略。

def closure = { String x, int y ->                                
    println "hey ${x} the value is ${y}"
}複製代碼

若是隻有一個參數的話,也可省略參數的定義,Groovy提供了一個隱式的參數it來替代它。

def closure = { it -> println it } 
//和上面是等價的
def closure = { println it }   
closure('hello')複製代碼

閉包能夠做爲參數傳入,閉包做爲方法的惟一參數或最後一個參數時可省略括號。

def eachLine(lines, closure) {
    for (String line : lines) {
        closure(line)
    }
}

eachLine('a'..'z',{ println it }) 
//可省略括號,與上面等價
eachLine('a'..'z') { println it }複製代碼

Lists

Groovy 定義 List 的方式很是簡潔,使用中括號([]),以逗號(,)分隔元素便可。Groovy中的 List 其實就是java.util.List,實現類默認使用的是java.util.ArrayList

def numbers = [1, 2, 3]         

assert numbers instanceof List  
assert numbers.class == java.util.ArrayList  
assert numbers.size() == 3複製代碼

Arrays

Groovy 定義數組的語法和 List 很是相似,區別在於數組的定義必須指定類型爲數組類型,能夠直接定義類型或者使用def定義而後經過as關鍵字來指定其類型。

String[] arrStr = ['Ananas', 'Banana', 'Kiwi'] //直接聲明類型爲數組類型 String[]

assert arrStr instanceof String[]    
assert !(arrStr instanceof List)

def numArr = [1, 2, 3] as int[]     //痛過as關鍵字指定類型爲數組類型 int[] 

assert numArr instanceof int[]       
assert numArr.size() == 3複製代碼

Maps

Groovy 定義 Map 的方式很是簡潔,經過中括號包含key、val的形式,key和value以冒號分隔([key:value])。Groovy中的Map其實就是java.util.Map,實現類默認使用的是java.util.LinkedHashMap

// key雖然沒有加引號,不過Groovy會默認將其轉換爲字符串
def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']

assert colors['red'] == '#FF0000' // 使用中括號訪問
assert colors.green == '#00FF00' // 使用點表達式訪問

colors['pink'] = '#FF00FF' // 使用中括號添加元素,至關於Java Map 的 put(key,value)方法
colors.yellow = '#FFFF00'// 使用點表達式添加元素
assert colors.pink == '#FF00FF'
assert colors['yellow'] == '#FFFF00'
assert colors instanceof java.util.LinkedHashMap // 默認使用LinkedHashMap類型

// Groovy Map的key默認語法不支持變量,這裏的key時間上是字符串'keyVal'而不是keyVal變量的值'name'
def keyVal = 'name'
def persons = [keyVal: 'Guillaume'] 
assert !persons.containsKey('name')
assert persons.containsKey('keyVal')

//要使用變量做爲key,須要使用括號
def keyVal = 'name'
def persons = [(keyVal): 'Guillaume'] 
assert persons.containsKey('name')
assert !persons.containsKey('keyVal')複製代碼

Range

在 Groovy 中可使用..操做符來定義一個區間對象,簡化範圍操做的代碼。

def range = 0..5
assert (0..5).collect() == [0, 1, 2, 3, 4, 5]
assert (0..<5).collect() == [0, 1, 2, 3, 4] // 至關於左閉右開區間
assert (0..5) instanceof List // Range其實是List接口的實現
assert (0..5).size() == 6
assert ('a'..'d').collect() == ['a','b','c','d']//也能夠是字符類型

//常見使用場景
for (x in 1..10) {
    println x
}

('a'..'z').each {
    println it
}

def age = 25;
switch (age) {
    case 0..17:
        println '未成年'
        break
    case 18..30:
        println '青年'
        break
    case 31..50:
        println '中年'
        break
    default:
        println '老年'
}複製代碼

常見使用場景

Grails

Grails 是一個基於 Groovy 語言,構建於 Spring/Spring Boot、Hibernate 之上的高生產力、一站式 Web 開發框架。特別適合小型團隊進行敏捷開發,效率很是高。因爲性能和學習成本的緣由,普及率比較低,大分部公司仍是更傾向於選擇 Spring Boot 做爲開發框架。

Gradle

Gradle 是一個基於 Apache Ant 和 Apache Maven 概念的項目自動化構建工具。它使用一種基於 Groovy 的特定領域語言(DSL)來進行構建配置,拋棄了基於XML的各類繁瑣配置,主要以面向Java應用爲主,支持從 Maven 倉庫下載依賴。如今愈來愈多的項目(Android項目居多)使用Gradle 來做爲項目的構建工具,相信將來 Gradle 也會逐漸代替 Maven,就像 Maven 代替 Ant 那樣。

使用Maven構建項目

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.vs</groupId>
    <artifactId>com.vs.maven.gradle</artifactId>
    <version>1.0</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.6.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa
            </artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.25</version>
        </dependency>
    </dependencies>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>複製代碼

使用Gradle構建項目

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.6.RELEASE")
    }
}
dependencies {
    compile("org.springframework.boot:spring-boot-starter-web") {
        exclude module: "spring-boot-starter-tomcat"
    }
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    testCompile("mysql:mysql-connector-java:5.1.25")
}複製代碼

Spring 支持

從 Spring 2.0 版本開始對動態腳本語言進行了支持(Spring 官方文檔該部分地址),其中便包括 Groovy ,Spring 提供了<lang:groovy/>標籤來定義 Groovy Bean 。Groovy Bean 能夠經過script-source屬性加載腳本文件,腳本源文件能夠來自本地或者網絡,而且能夠經過refresh-check-delay屬性監聽腳本內代碼變動從新裝載 Bean 實現動態 Bean 。

// from the file '/java/Calculator.java'
public interface Calculator {
    int add(int x, int y);
}

// from the file '/resources/CalculatorGroovyImpl.groovy'
class CalculatorGroovyImpl implements Calculator {
    int add(int x, int y) {
        x + y
    }
}複製代碼
<-- from the file 'beans.xml' 省略 xmlns -->
<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <lang:groovy id="calculator" script-source="classpath:CalculatorGroovyImpl.groovy" refresh-check-delay="1000"/>
</beans>複製代碼
public class Tester {
    public static void main(String[] args) throws InterruptedException {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Calculator calculator = (Calculator)context.getBean("calculator");
        //嘗試修改CalculatorGroovyImpl.groovy,將 x + y,修改成x * y。
        while (true){
            System.out.println(calculator.add(1, 1));
            TimeUnit.SECONDS.sleep(1);
        }
    }
}複製代碼

從 Spring 4.0 版本開始 Spring 支持使用 Groovy DSL 來定義 Bean 的配置,詳見 Spring 官方文檔該部分

beans {
    //beanName(type) 
    dataSource(BasicDataSource) {
        //注入屬性
        driverClassName = "org.hsqldb.jdbcDriver"
        url = "jdbc:hsqldb:mem:grailsDB"
        username = "sa"
        password = ""
        settings = [mynew:"setting"]
    }
    sessionFactory(SessionFactory) {
       //注入屬性,引用其餘Bean
        dataSource = dataSource
    }
    myService(MyService) {
       //使用閉包定義嵌套的Bean
        nestedBean = { AnotherBean bean ->
            dataSource = dataSource
        }
    }
}複製代碼
ApplicationContext context = new GenericGroovyApplicationContext("beans.groovy");
MyService myService = context.getBean(MyService.class);複製代碼

與Java集成

Groovy很是容易集成在Java環境中,利用其動態性來作規則引擎、流程引擎、動態腳本環境,很是適合那些不不須要常常發佈但又常常變動的場景下使用。在Java中集成(調用)Groovy 代碼有下面幾種方式。

Eval

groovy.util.Eval 類是最簡單的用來在運行時動態執行 Groovy 代碼的類,提供了幾個靜態工廠方法供使用,內部其實就是對GroovyShell的封裝。

//執行Groovy代碼
Eval.me("println 'hello world'");
//綁定自定義參數
Object result = Eval.me("age", 22, "if(age < 18){'未成年'}else{'成年'}");
assertEquals(result, "成年");
//綁定一個名爲 x 的參數的簡單計算
assertEquals(Eval.x(4, "2*x"), 8);
//帶有兩個名爲 x 與 y 的綁定參數的簡單計算
assertEquals(Eval.xy(4, 5, "x*y"), 20);
//帶有三個綁定參數(x、y 和 z)的簡單計算
assertEquals(Eval.xyz(4, 5, 6, "x*y+z"), 26);複製代碼
GroovyShell

groovy.lang.GroovyShell除了能夠執行 Groovy 代碼外,提供了更豐富的功能,好比能夠綁定更多的變量,從文件系統、網絡加載代碼等。

GroovyShell shell = new GroovyShell();
//能夠綁定更多變量
shell.setVariable("age",22);
//直接求值
shell.evaluate("if(age < 18){'未成年'}else{'成年'}");
//解析爲腳本,延遲執行或者緩存起來
Script script = shell.parse("if(age < 18){'未成年'}else{'成年'}");
assertEquals(script.run(), "成年");
//能夠從更多位置加載/執行腳本
//shell.evaluate(new File("script.groovy"));
//shell.evaluate(new URI("http://wwww.a.com/script.groovy"));複製代碼
GroovyClassLoader

groovy.lang.GroovyClassLoader是一個定製的類加載器,能夠在運行時加載 Groovy 代碼,生成 Class 對象。

GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
 String scriptText = "class Hello { void hello() { println 'hello' } }";
 //將Groovy腳本解析爲Class對象
 Class clazz = groovyClassLoader.parseClass(scriptText);
 //Class clazz = groovyClassLoader.parseClass(new File("script.groovy"));
 assertEquals(clazz.getName(),"Hello");
 clazz.getMethod("hello").invoke(clazz.newInstance());複製代碼
GroovyScriptEngine

groovy.util.GroovyScriptEngine可以處理任何 Groovy 代碼的動態編譯與加載,能夠從統一的位置加載腳本,而且可以監聽腳本的變化,當腳本發生變化時會從新加載。

//script/groovy/hello.groovy
println "hello $name"複製代碼
GroovyScriptEngine scriptEngine = new GroovyScriptEngine("script/groovy");
Binding binding = new Binding();
binding.setVariable("name", "groovy");
while (true){
    scriptEngine.run("hello.groovy", binding);
    TimeUnit.SECONDS.sleep(1);
}複製代碼
//輸出
hello groovy
hello groovy
....
//將hello.groovy內代碼修改成println "hi $name", GroovyScriptEngine會從新進行加載
hi groovy
hi groovy複製代碼
JSR 223 javax.script API

JSR-223 是 Java 中調用腳本語言的標準 API。從 Java 6 開始引入進來,主要目的是用來提供一種統一的框架,以便在 Java 中調用多種腳本語言。JSR-223 支持大部分流行的腳本語言,好比JavaScript、Scala、JRuby、Jython和Groovy等。

ScriptEngine engine = new ScriptEngineManager().getEngineByName("groovy");
Bindings bindings = new SimpleBindings();
bindings.put("age", 22);
Object value = engine.eval("if(age < 18){'未成年'}else{'成年'}",bindings);
assertEquals(value,"成年");

//script/groovy/hello.groovy
//println "hello world"
engine.eval(new FileReader("script/groovy/hello.groovy"));
//hello world複製代碼

因爲 Groovy 自身已經提供了更豐富的集成機制,若是在 Java 應用中只是使用 Groovy 一種腳本語言的話,使用 Groovy 提供的集成機制可能會更合適一點。

與Java集成大體就以上幾種方式,在使用前推薦閱讀:Groovy與Java集成常見的坑

參考

相關文章
相關標籤/搜索