SpringBoot 整合 Groovy 脚本,实现动态编程

news2025/1/18 19:00:50

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脚本将会成为攻击你系统最有力的武器!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/81350.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在idea中离线安装scala

由于网络受限&#xff0c;需要离线安装和使用scala&#xff0c;安装步骤如下。 1 安装idea scala插件 首先在idea的Help-Aboout选项中&#xff0c;查看idea的版本。 这里可以看到我的版本是2022.3&#xff0c;因此我需要下载对应版本的scala插件&#xff08;Scala插件地址&a…

git使用说明

在Windows上使用Git&#xff0c;可以从Git官网直接下载安装程序&#xff0c;然后按默认选项安装即可。 安装完成后&#xff0c;在开始菜单里找到“Git”->“Git Bash”&#xff0c;蹦出一个类似命令行窗口的东西&#xff0c;就说明Git安装成功&#xff01; 安装完成后&…

MySQL重大Bug!自增主键竟然不是连续递增

InnoDB 自增值保存在内存&#xff0c;MySQL 8.0后&#xff0c;才有了“自增值持久化”能力&#xff0c;即才实现了“若重启&#xff0c;表的自增值可以恢复为MySQL重启前的值”&#xff0c;具体情况是&#xff1a; ≤5.7&#xff0c;自增值保存在内存&#xff0c;无持久化。每…

基于免疫算法的认知无线电资源分配优化算法的matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 认知无线电&#xff08;CR&#xff09;的概念来自Joseph Mitolo博士1999年的开创性工作。它自适应地调整内部通信机制&#xff0c;通过学习&#xff0c;了解等实时变化特定的无线电操作参数&…

数据库实验四:触发器实验

实验四 触发器实验 1.实验目的 ​ 掌握数据库触发器的设计和使用方法。 2.实验内容和要求 ​ 定义BEFORE触发器和AFTER触发器&#xff0c;能够理解不同类型触发器的作用和执行原理&#xff0c;验证触发器的有效性。 3.实验重点和难点 ​ 实验重点&#xff1a;触发器的定义…

大二Web课程设计——张家界旅游网站设计与实现(HTML+CSS+JavaScript)

&#x1f468;‍&#x1f393;学生HTML静态网页基础水平制作&#x1f469;‍&#x1f393;&#xff0c;页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码&#xff0c;这是一个不错的旅游网页制作&#xff0c;画面精明&#xff0c;排版整洁&#xff0c;内容…

【应用】Modbus 通讯协议

Modbus 通讯协议Modbus 协议基础Modbus 存储区Modbus-RTU 协议Modbus-TCP 协议Java 实现 Modbus 通讯Modbus ReadModbus Write模拟数据进行代码测试Modbus-RTU 代码验证Modbus-TCP 代码验证SerialPortWrapper 实现类代码Modbus 协议基础 Modbus 是一种总线通讯协议&#xff0c;…

[附源码]计算机毕业设计贵港高铁站志愿者服务平台Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis MavenVue等等组成&#xff0c;B/S模式…

Spring Bean的生命周期

一、首先我们要知道什么是Spring Bean&#xff1a;Spring Bean是Spring框架在运行管理时的对象。 二、Spring Bean的生命周期&#xff1a; 简单来说bean会经历四个阶段&#xff1a; 实例化 -》 属性赋值 -》初始化 -》销毁 下面我们来具体看一下&#xff1a; 1.实例化 Bea…

软件质量评估模型

软件质量是指软件产品满足用户要求的程度。可以从多个方面来理解此处所指的用户要求,包括用户期望的软件系统的功能、性能、可维护性、可操作性、可重用性等等。在软件项目实施过程中,经常会听到用户关于软件系统的以下一组质量评价。 软件系统没有某些方面的功能软件系统运行…

【5G MAC】NR Timing Advance(RAR TA 和 MAC-CE TA)

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

[Linux]基础命令(1)

Linux基本命令&#xff08;1&#xff09; 文章目录Linux基本命令&#xff08;1&#xff09;1.操作系统&#xff1a;&#xff08;1&#xff09;什么是操作系统&#xff1a;&#xff08;2&#xff09;为什么要有操作系统&#xff1a;2. ls命令:3. pwd指令&#xff1a;4. cd命令:5…

2022-12-11

文章目录前言PWMPwmChannelPwmAssignedHwUnitPwmChannelIdPwmCoherentUpdatePwmDutycycleDefaultPwmIdleStatePwmNotificationPwmChannelClassPwmPeriodDefaultPwmPolarityPwmReferenceChannelPwmSafetySignalPwmShiftValuePWM输出偏移的使用PwmConfigurationOfOptApiServicesP…

windows 基于 MediaPipe 实现 Holistic

主页: https://google.github.io/mediapipe/solutions/holistic.html MediaPipe Holistic pipelines 集成了姿势、面部和手部组件的独立模型&#xff0c;每个组件都针对其特定领域进行了优化&#xff0c;每个组件的推断输入图不同。 MediaPipe Holistic 首先通过 BlazePose 的姿…

基于极限学习机进行股市预测(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

MySQL-InnoDB的事务隔离级别

MySQL 是一个服务器&#xff0f;客户端架构的软件&#xff0c;对于同一个服务器来说&#xff0c;可以有若干个客户端与之连接&#xff0c;每个客户端与服务器连接上之后&#xff0c;就可以称之为一个会话&#xff08; Session &#xff09;。我们可以同时在不同的会话里输入各种…

【图像处理】opencv | 图像的载入,显示,保存 | 视频流的载入,显示,保存

文章目录前言一、cv2读取图片并展示1.1、cv2.imread读取图片1.2、cv2.imshow展示图片1.3、完整代码1.4、封装函数调用1.5、cv2读取为灰度图像1.6、cv2.imwrite保存图像二、cv2读取视频并且展示2.1 展示彩色视频2.2 展示灰度视频2.3 保存视频前言 本文参考视频&#xff1a;唐宇…

二进制搭建k8s——部署etcd集群和单master

二进制搭建k8s——部署etcd集群和单master二进制搭建k8s——部署etcd集群和单master环境1、操作系统初始化配置&#xff08;全部节点&#xff09;2、部署 docker 引擎&#xff08;所有节点&#xff09;3、部署 etcd 集群准备签发证书环境在 master01 节点上操作在 node01 和 no…

端口隔离实现同一vlan下,二层和三层的互不通

如图&#xff1a;我们要实现下图中&#xff0c;PC1和PC2不通&#xff0c;但都和PC3互通&#xff1a; 配置如下&#xff1a; vlan batch 10 port-isolate mode all # interface GigabitEthernet0/0/1 port link-type access port default vlan 10 port-isolate enable grou…

【golang】 demo 之王realworld,使用golang+gin做后端技术,使用vue做前端项目的开源博客项目

目录前言1&#xff0c;关于realworld项目2&#xff0c;前端项目使用vue3开发的3&#xff0c;后端使用golanggin进行接口开发4&#xff0c;总结前言 本文的原文连接是: https://blog.csdn.net/freewebsys/article/details/108971807 未经博主允许不得转载。 博主CSDN地址是&…