SpringBoot整合Groovy腳本實現(xiàn)動態(tài)編程詳解
Groovy簡介
Groovy 是增強 Java 平臺的唯一的腳本語言。它提供了類似于 Java 的語法,內(nèi)置映射(Map)、列表(List)、方法、類、閉包(closure)以及生成器。腳本語言不會替代系統(tǒng)編程語言,兩者是相互補充的。
大名鼎鼎的 Gradle,背后是 Groovy。Spring 的未來越來越多的使用 Groovy,甚至在用 Jira 跟蹤項目時,背后也有 Groovy。實際上,就應(yīng)用場景而言,Java 開發(fā)已經(jīng)有越來越多的 Groovy 出現(xiàn)在后臺了。而對于一般的應(yīng)用開發(fā),只要能用 Java 就都能用到 Groovy,唯一的難點只在于能不能招到足夠的人員。
應(yīng)用場景
- 連接已有的組件
- 處理經(jīng)常變化的多種類型的實體
- 具有圖形化用戶界面
- 擁有快速變化的功能
Groovy腳本的基礎(chǔ)概念請移步
集成與使用
那么接下來介紹SpringBoot如何集成Groovy腳本,并應(yīng)用到實際開發(fā)中。
第一步、與SpringBoot集成
1、pom.xml文件如下:
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
第二步、寫出Groovy版本的“Hello World”
1、HelloWorld.groovy腳本代碼
package groovy
def HelloWorld(){
println "hello world"
}
2、創(chuàng)建測試類GroovyTest.java
package com.example.springbootgroovy.service;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
/**
* 這個是Groovy的第一個小程序,腳本為:
*
package groovy
def helloworld(){
println "hello world"
}
*
*/
public class GroovyTest {
public static void main(String[] args) throws Exception {
//創(chuàng)建GroovyShell
GroovyShell groovyShell = new GroovyShell();
//裝載解析腳本代碼
Script script = groovyShell.parse("package groovy\n" +
"\n" +
"def HelloWorld(){\n" +
" println \"hello world\"\n" +
"}");
//執(zhí)行
script.invokeMethod("HelloWorld", null);
}
}
3、運行結(jié)果

第三步、傳入變量與獲取返回值
1、變量與返回值Groovy腳本代碼
package groovy
/**
* 簡易加法
* @param a 數(shù)字a
* @param b 數(shù)字b
* @return 和
*/
def add(int a, int b) {
return a + b
}
/**
* map轉(zhuǎn)化為String
* @param paramMap 參數(shù)map
* @return 字符串
*/
def mapToString(Map<String, String> paramMap) {
StringBuilder stringBuilder = new StringBuilder();
paramMap.forEach({ key, value ->
stringBuilder.append("key:" + key + ";value:" + value)
})
return stringBuilder.toString()
}
2、創(chuàng)建測試類GroovyTest2.java
package com.example.springbootgroovy.service;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import java.util.HashMap;
import java.util.Map;
/**
* 向Groovy腳本中傳入變量,以及獲取返回值
*/
public class GroovyTest2 {
public static void main(String[] args) {
//創(chuàng)建GroovyShell
GroovyShell groovyShell = new GroovyShell();
//裝載解析腳本代碼
Script script = groovyShell.parse("package groovy\n" +
"\n" +
"/**\n" +
" * 簡易加法\n" +
" * @param a 數(shù)字a\n" +
" * @param b 數(shù)字b\n" +
" * @return 和\n" +
" */\n" +
"def add(int a, int b) {\n" +
" return a + b\n" +
"}\n" +
"\n" +
"/**\n" +
" * map轉(zhuǎn)化為String\n" +
" * @param paramMap 參數(shù)map\n" +
" * @return 字符串\n" +
" */\n" +
"def mapToString(Map<String, String> paramMap) {\n" +
" StringBuilder stringBuilder = new StringBuilder();\n" +
" paramMap.forEach({ key, value ->\n" +
" stringBuilder.append(\"key:\" + key + \";value:\" + value)\n" +
" })\n" +
" return stringBuilder.toString()\n" +
"}");
//執(zhí)行加法腳本
Object[] params1 = new Object[]{1, 2};
int sum = (int) script.invokeMethod("add", params1);
System.out.println("a加b的和為:" + sum);
//執(zhí)行解析腳本
Map<String, String> paramMap = new HashMap<>();
paramMap.put("科目1", "語文");
paramMap.put("科目2", "數(shù)學(xué)");
Object[] params2 = new Object[]{paramMap};
String result = (String) script.invokeMethod("mapToString", params2);
System.out.println("mapToString:" + result);
}
}
3、運行結(jié)果

第四步、啟動SpringBoot
在Groovy腳本中通過SpringContextUtil獲取SpringBoot容器中的Bean
1、創(chuàng)建SpringContextUtil.java
package com.example.springbootgroovy.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring上下文獲取
*/
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通過name獲取 Bean.
*
* @param name
* @return
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通過class獲取Bean.
*
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通過name,以及Clazz返回指定的Bean
*
* @param name
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
2、創(chuàng)建GroovyTestService.java,并加上@Service注解加入到SpringBoot容器中
package com.example.springbootgroovy.service;
import org.springframework.stereotype.Service;
@Service
public class GroovyTestService {
public void test(){
System.out.println("我是SpringBoot框架的成員類,但該方法由Groovy腳本調(diào)用");
}
}
3、Groovy腳本如下
package groovy
import com.example.springbootgroovy.service.GroovyTestService
import com.example.springbootgroovy.util.SpringContextUtil
/**
* 靜態(tài)變量
*/
class Globals {
static String PARAM1 = "靜態(tài)變量"
static int[] arrayList = [1, 2]
}
def getBean() {
GroovyTestService groovyTestService = SpringContextUtil.getBean(GroovyTestService.class);
groovyTestService.test()
}
4、啟動類代碼如下
package com.example.springbootgroovy;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/groovy")
@SpringBootApplication
public class SpringBootGroovyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootGroovyApplication.class, args);
}
@RequestMapping("/test")
public String test() {
//創(chuàng)建GroovyShell
GroovyShell groovyShell = new GroovyShell();
//裝載解析腳本代碼
Script script = groovyShell.parse("package groovy\n" +
"\n" +
"import com.example.springbootgroovy.service.GroovyTestService\n" +
"import com.example.springbootgroovy.util.SpringContextUtil\n" +
"\n" +
"/**\n" +
" * 靜態(tài)變量\n" +
" */\n" +
"class Globals {\n" +
" static String PARAM1 = \"靜態(tài)變量\"\n" +
" static int[] arrayList = [1, 2]\n" +
"}\n" +
"\n" +
"def getBean() {\n" +
" GroovyTestService groovyTestService = SpringContextUtil.getBean(GroovyTestService.class);\n" +
" groovyTestService.test()\n" +
"}");
//執(zhí)行
script.invokeMethod("getBean", null);
return "ok";
}
}
5、啟動后調(diào)用接口:http://localhost:8080/groovy/test
運行結(jié)果如下

注意?。?!
通過第四步中我們可以看到,在Groovy中是可以獲取到SpringBoot容器對象的。雖然很方便,但是很危險。如果沒有做好權(quán)限控制,Groovy腳本將會成為攻擊你系統(tǒng)最有力的武器?。。?/p>
以上就是SpringBoot整合Groovy腳本實現(xiàn)動態(tài)編程詳解的詳細內(nèi)容,更多關(guān)于SpringBoot整合Groovy動態(tài)編程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaSwing實現(xiàn)小型學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細介紹了JavaSwing實現(xiàn)小型學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02
解決Maven中關(guān)于依賴導(dǎo)入不進的問題
這篇文章主要介紹了解決Maven中關(guān)于依賴導(dǎo)入不進的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
Spring Cloud Gateway替代zuul作為API網(wǎng)關(guān)的方法
本文簡要介紹如何使用Spring Cloud Gateway 作為API 網(wǎng)關(guān)(不是使用zuul作為網(wǎng)關(guān)),結(jié)合實例代碼給大家詳細講解,感興趣的朋友跟隨小編一起看看吧2023-02-02

