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)最有力的武器?。?!
以上就是SpringBoot整合Groovy腳本實現(xiàn)動態(tài)編程詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot整合Groovy動態(tài)編程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaSwing實現(xiàn)小型學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了JavaSwing實現(xiàn)小型學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02解決Maven中關(guān)于依賴導(dǎo)入不進的問題
這篇文章主要介紹了解決Maven中關(guān)于依賴導(dǎo)入不進的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11Spring Cloud Gateway替代zuul作為API網(wǎng)關(guān)的方法
本文簡要介紹如何使用Spring Cloud Gateway 作為API 網(wǎng)關(guān)(不是使用zuul作為網(wǎng)關(guān)),結(jié)合實例代碼給大家詳細(xì)講解,感興趣的朋友跟隨小編一起看看吧2023-02-02