⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/weixin_33005117/article/details/126712394 「sum墨」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

Groovy简介

Groovy 是增强 Java 平台的唯一的脚本语言。它提供了类似于 Java 的语法,内置映射(Map)、列表(List)、方法、类、闭包(closure)以及生成器。脚本语言不会替代系统编程语言,两者是相互补充的。

大名鼎鼎的 Gradle,背后是 Groovy。Spring 的未来越来越多的使用 Groovy,甚至在用 Jira 跟踪项目时,背后也有 Groovy。实际上,就应用场景而言,Java 开发已经有越来越多的 Groovy 出现在后台了。而对于一般的应用开发,只要能用 Java 就都能用到 Groovy,唯一的难点只在于能不能招到足够的人员。

应用场景

  • 连接已有的组件
  • 处理经常变化的多种类型的实体
  • 具有图形化用户界面
  • 拥有快速变化的功能

Groovy脚本的基础概念请移步

  • http://mvnbook.com/groovy-introduction.html

集成与使用

那么接下来介绍SpringBoot如何集成Groovy脚本,并应用到实际开发中。

第一步、与SpringBoot集成

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、创建测试类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 {
//创建GroovyShell
GroovyShell groovyShell = new GroovyShell();
//装载解析脚本代码
Script script = groovyShell.parse("package groovy\n" +
"\n" +
"def HelloWorld(){\n" +
" println \"hello world\"\n" +
"}");
//执行
script.invokeMethod("HelloWorld", null);
}
}

3、运行结果

图片

第三步、传入变量与获取返回值

1、变量与返回值Groovy脚本代码

package groovy

/**
* 简易加法
* @param a 数字a
* @param b 数字b
* @return
*/
def add(int a, int b) {
return a + b
}

/**
* map转化为String
* @param paramMap 参数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、创建测试类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) {
//创建GroovyShell
GroovyShell groovyShell = new GroovyShell();
//装载解析脚本代码
Script script = groovyShell.parse("package groovy\n" +
"\n" +
"/**\n" +
" * 简易加法\n" +
" * @param a 数字a\n" +
" * @param b 数字b\n" +
" * @return 和\n" +
" */\n" +
"def add(int a, int b) {\n" +
" return a + b\n" +
"}\n" +
"\n" +
"/**\n" +
" * map转化为String\n" +
" * @param paramMap 参数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" +
"}");
//执行加法脚本
Object[] params1 = new Object[]{1, 2};
int sum = (int) script.invokeMethod("add", params1);
System.out.println("a加b的和为:" + sum);
//执行解析脚本
Map<String, String> paramMap = new HashMap<>();
paramMap.put("科目1", "语文");
paramMap.put("科目2", "数学");
Object[] params2 = new Object[]{paramMap};
String result = (String) script.invokeMethod("mapToString", params2);
System.out.println("mapToString:" + result);
}
}

3、运行结果

图片

第四步、启动SpringBoot,在Groovy脚本中通过SpringContextUtil获取SpringBoot容器中的Bean

1、创建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、创建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脚本调用");
}

}

3、Groovy脚本如下

package groovy

import com.example.springbootgroovy.service.GroovyTestService
import com.example.springbootgroovy.util.SpringContextUtil

/**
* 静态变量
*/
class Globals {
static String PARAM1 = "静态变量"
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() {
//创建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" +
" * 静态变量\n" +
" */\n" +
"class Globals {\n" +
" static String PARAM1 = \"静态变量\"\n" +
" static int[] arrayList = [1, 2]\n" +
"}\n" +
"\n" +
"def getBean() {\n" +
" GroovyTestService groovyTestService = SpringContextUtil.getBean(GroovyTestService.class);\n" +
" groovyTestService.test()\n" +
"}");
//执行
script.invokeMethod("getBean", null);
return "ok";
}
}

5、启动后调用接口:http://localhost:8080/groovy/test,运行结果如下

注意!!!

通过第四步中我们可以看到,在Groovy中是可以获取到SpringBoot容器对象的。虽然很方便,但是很危险。如果没有做好权限控制,Groovy脚本将会成为攻击你系统最有力的武器!!!

文章目录
  1. 1. Groovy简介
  2. 2. 应用场景
  3. 3. 集成与使用
    1. 3.1. 第一步、与SpringBoot集成
    2. 3.2. 第二步、写出Groovy版本的“Hello World”
    3. 3.3. 第三步、传入变量与获取返回值
    4. 3.4. 第四步、启动SpringBoot,在Groovy脚本中通过SpringContextUtil获取SpringBoot容器中的Bean
  4. 4. 注意!!!