0

0

springboot怎么集成groovy脚本使用

WBOY

WBOY

发布时间:2023-05-18 23:25:04

|

2009人浏览过

|

来源于亿速云

转载

在我们的应用中引入脚本能力,可以很好的提升灵活性,我们的核心开发工作可以集中在核心平台能力的开发上,具体场景的功能可以通过脚本来实现,例如jenkins就可以通过groovy脚本来编写pipeline,可以很灵活的定制构建过程。 spring本身提供了groovy集成的机制,分为两种方式,一种是用groovy开发程序,跟用java开发类似,需要经过编译。一种是将groovy作为脚本来执行,不需要编译。在此我们介绍的是第二种方式,将groovy作为脚本来使用。 

一、概述

在spring中集成groovy脚本,主要有2种思路,一种是在groovy脚本中定义bean,这样groovy脚本就融入了整个spring的体系,跟使用普通的bean没有区别。一种是在程序中调用groovy脚本,让groovy脚本成为一个可执行的部件。下面我们分别介绍这2种方式。 在spring中声明groovy脚本中定义的bean有两种方式,一种是传统的xml,一种是spring-framework-4中引入的groovy声明方式。

二、在groovy中定义bean

首先我们定义一个interface:

public interface MyService {
    String fun(MyDomain myDomain);
}

这儿提供了一种思路,我们可以用java代码编写默认的interface实现,如果默认实现不满足特定场景的要求时,配合策略模式,用groovy脚本实现特定场景,程序会变的很灵活,配合脚本的热加载机制,当处理逻辑需要变化时,在程序运行的过程中,我们可以随时调整脚本内容且能够及时生效。

在groovy脚本MyServiceImpl.groovy中实现这个interface:

class MyServiceImpl implements MyService {
    @Autowired
    FunBean useBean;

    String myProp;

    String fun(MyDomain myDomain) {
        return myDomain.toString() + useBean.getFunName() + myProp;
    }
}

下面分别介绍通过xml和groovy两种配置方式来声明bean。

2.1、通过xml配置的方式声明groovy中实现的bean

通过xml配置声明bean是spring传统的方法,这种方法近来已经被通过java代码声明的方式取代,但是对于声明groovy脚本中定义的bean来说还是最简单的方法。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/lang https://www.springframework.org/schema/lang/spring-lang.xsd">
    <lang:groovy id="myServiceXml" script-source="classpath:MyServiceImpl.groovy" refresh-check-delay="10000" >
        <lang:property name="myProp" value=" this is xml init prop" />
    </lang:groovy>
</beans>

以上xml代码声明了myServiceXml这个bean,script-source指定了这个bean的来源是classpath:MyServiceImpl.groovy这个脚本文件。将classpath替换为file,可以指定任一位置的脚本文件。
refresh-check-delay定义了脚本的刷新间隔,当脚本内容发生变化后,可以自动刷新脚本的内容。
lang:property这个标签可以对bean的属性进行初始化赋值。

我们分别用xml和groovy两种声明bean的方式给myProp这个属性赋值不同的初始值,在后续的演示代码中可以看到。

2.2、通过groovy配置的方式声明groovy中实现的bean

spring-framework-4中引入了groovy声明bean的方式,我们用groovy来声明myServiceGroovy这个bean,相比于xml的方式,groovy的声明方式可读性更强一些。

codingM
codingM

AI智能体协作软件开发平台

下载

详细介绍见spring的官方博文: Groovy Bean Configuration in Spring Framework 4

import org.springframework.scripting.groovy.GroovyScriptFactory
import org.springframework.scripting.support.ScriptFactoryPostProcessor

beans {
    scriptFactoryPostProcessor(ScriptFactoryPostProcessor) {
        defaultRefreshCheckDelay = 10000
    }
    myServiceGroovy(GroovyScriptFactory, 'classpath:MyServiceImpl.groovy') {
        bean ->
            bean.scope = "prototype"
            myProp = ' this is Bean Builder init prop'
            bean.beanDefinition.setAttribute(ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE, 6000)
    }
}

通过GroovyScriptFactory可以指定定义bean的groovy脚本位置。 通过bean的lambda表达式,可以对bean的属性进行赋值,除了我们定义的myProp这个属性外,还可以定义scope和脚本刷新时间。

2.3、调用groovy中实现的bean

前面我们通过xml和groovy两种方式分别声明了2个bean: myServiceXmlmyServiceGroovy,下面我们在程序中调用这2个bean。

@SpringBootApplication
@ImportResource({"classpath:xml-bean-config.xml", "classpath:BeanBuilder.groovy"})
public class Application implements CommandLineRunner {

    @Autowired
    private MyService myServiceXml;
    @Autowired
    private MyService myServiceGroovy;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws ScriptException, ResourceException, IllegalAccessException, InstantiationException {
        MyDomain myDomain = new MyDomain();
        myDomain.setName("test");
        System.out.println(myServiceXml.fun(myDomain));
        myDomain.setName("test2");
        System.out.println(myServiceGroovy.fun(myDomain));
    }
}

首先我们通过@ImportResource来引入bean的声明文件,然后就是普通的bean的依赖注入和方法调用,可以看到在bean的使用上,脚本定义的bean和用程序编写的bean没有任何区别。 在run方法中,我们分别调用了myServiceXml和myServiceGroovy的这2个bean的fun方法。 执行run方法可以看到输出到结果:

MyDomain(name=test)FunBean this is xml init prop
MyDomain(name=test2)FunBean this is Bean Builder init prop

三、执行groovy脚本

除了前面提到的在groovy中实现bean以外,我们还可以通过groovy提供的GroovyScriptEngine来执行groovy脚本,这种方式不依赖于springframework,普通的java程序中也可以使用。

@Component
public class MyEngine {
    private final GroovyScriptEngine engine;

    @Autowired
    private FunBean funBean;

    public MyEngine() throws IOException {

        engine = new GroovyScriptEngine(ResourceUtils.getFile("classpath:scripts/").getAbsolutePath()
                , this.getClass().getClassLoader());
    }

    public void runScript(int x, int y) throws IllegalAccessException,
            InstantiationException, ResourceException, ScriptException {
        Class<GroovyObject> calcClass = engine.loadScriptByName("CalcScript.groovy");
        GroovyObject calc = calcClass.newInstance();

        Object result = calc.invokeMethod("calcSum", new Object[]{x, y});
        System.out.println("Result of CalcScript.calcSum() method is " + result);

        Binding binding = new Binding();
        binding.setVariable("arg", "test");
        binding.setVariable("funBean", funBean);
        Object result1 = engine.run("CalcScript.groovy", binding);
        System.out.println("Result of CalcScript.groovy is " + result1);
    }
}

首先我们初始化GroovyScriptEngine,在构造方法中传入脚本文件的路径。

执行脚本的方法有2种,一种是获取到GroovyObject,通过invokeMethod来执行脚本中的某个方法,方法的参数通过Object数组传入。

Class<GroovyObject> calcClass = engine.loadScriptByName("CalcScript.groovy");
GroovyObject calc = calcClass.newInstance();

Object result = calc.invokeMethod("calcSum", new Object[]{x, y});

第二种是直接运行groovy脚本,可以通过Binding将变量传递到groovy脚本中。

Binding binding = new Binding();
binding.setVariable("arg", "test");
binding.setVariable("funBean", funBean);
Object result1 = engine.run("CalcScript.groovy", binding);

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

155

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

88

2026.01.26

pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1945

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

2119

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

1167

2024.11.28

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

215

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

192

2025.11.08

Python lambda详解
Python lambda详解

本专题整合了Python lambda函数相关教程,阅读下面的文章了解更多详细内容。

61

2026.01.05

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

4

2026.03.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Redis6入门到精通超详细教程
Redis6入门到精通超详细教程

共47课时 | 5.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号