java代码中使用Groovy的三种方式详解

java代码中使用Groovy

Groovy语言是一种运行在java虚拟机上的一种动态语言,它可以单独使用,也可以配合java语言一起使用,下面的部分,我们将用java项目结合Groovy做一些学习和使用。

​ 先建一个springboot项目,在项目中添加Groovy的依赖,本次演示使用的是groovy3.0.20版本:

       <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy</artifactId>
            <version>3.0.20</version>
        </dependency>

​ 在java中使用Groovy有三种方式:通过GroovyShell执行Groovy脚本;通过GroovyClassLoader动态加载Groovy Class文件;通过GroovyScriptEngine脚本引擎加载Groovy脚本。

1 GroovyShell执行Groovy脚本

​ 通过GroovyShellevaluate方法执行Groovy脚本,evaluate方法的入参比较多,可以是一个字符串,也可以是一个文件流或者文件,下图是该方法的入参。

在这里插入图片描述

​ 先通过一个简单的字符串脚本的执行来入门,下面代码就是在Groovy脚本中打印一行字,其中cmd代表需要执行的脚本,通过groovyShell.evaluate(cmd)执行:

package com.dream21th.groovy;

import groovy.lang.GroovyShell;

public class Groovy_study01 {

    public static void main(String[] args) {
        String cmd="def name=\"张三\";\n" +
                "println(\"my name is \"+ name)\n";
        GroovyShell groovyShell = new GroovyShell();
        Object evaluate = groovyShell.evaluate(cmd);
        System.out.println("执行指令返回结果:"+evaluate);
    }
}

​ 接着来学习一下加载Groovy脚本文件来执行脚本中的方法,脚本代码如下:

// 不带参数的groovy方法
def sayHello() {
    println 'Hello Groovy'

    // 如果不写return, groovy方法的默认最后一行为 方法的返回值
    //return "Groovy_02中的sayHello()方法的返回值"
    "Groovy_02.groovy中的sayHello()方法的返回值"
}

// 运行groovy方法
sayHello()

​ 编写java逻辑代码如下:

package com.dream21th.groovy;

import groovy.lang.GroovyShell;
import java.io.File;
import java.io.IOException;

public class Groovy_study02 {

    public static void main(String[] args) throws IOException {
        GroovyShell groovyShell = new GroovyShell();
        Object evaluate = groovyShell.evaluate(new File("D:\\code\\study\\java\\java_groovy\\src\\main\\resources\\Groovy_02.groovy"));
        System.out.println("代码执行结果:"+evaluate);
    }
}

​ 通过下面代码可以看出,在evaluate方法的入参是一个文件,通过该方式可以执行脚本文件并返回脚本执行结果。

​ 上面的例子介绍了如何执行脚本文件,这个例子介绍如何在脚本文件中添加参数,编写一个带有参数的方法的脚本,脚本的内容如下:

// 带参数的groovy方法
def sayHello(name, age) {
    printf("my name is %s,i am %s year old \n",name,age)
    // 如果不写return, groovy方法的默认最后一行为 方法的返回值
    //return "Groovy_03中的sayHello()方法的返回值"
    "Groovy_03.groovy中的sayHello(name, age)方法的返回值"
}

// 运行groovy方法
sayHello(name, age)

​ 该脚本包含两个入参,下面编写执行该脚本的java代码:

package com.dream21th.groovy;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import java.io.File;
import java.io.IOException;

public class Groovy_study03 {
    public static void main(String[] args) throws IOException {
        //调用带有入参的groovy脚本时,使用Binding进行参数传递
        Binding binding = new Binding();
        binding.setProperty("name","徐达");
        binding.setProperty("age",18);
        GroovyShell groovyShell = new GroovyShell(binding);
        Object evaluate = groovyShell.evaluate(new File("D:\\code\\study\\java\\java_groovy\\src\\main\\resources\\Groovy_03.groovy"));
        System.out.println("代码执行结果:"+evaluate);
    }
}

​ 在调用含有入参的脚本的时候,参数的传递是通过Binding来辅助完成的。

2 GroovyClassLoader动态加载Groovy Class文件

​ 除了执行Groovy的脚本文件,还可以通过GroovyClassLoader动态加载Groovy Class文件,编写一个Groovy_04.groovy的class文件:

在这里插入图片描述

class Groovy_04 {
    String sayHello(name,age){
        printf("my name is %s,i am %s year old \n",name,age)
        return "my name is "+name+",i am "+age+"year old"
    }
}

​ 该文件包含一个sayHello(name,age)方法,方法有两个入参,接着编写java测试代码:

package com.dream21th.groovy;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import org.codehaus.groovy.control.CompilerConfiguration;
import java.io.File;

public class Groovy_study04 {

    public static void main(String[] args) {
        initGroovyClassLoader();
        String result = invokeSayHello("李武", 18,"D:\\code\\study\\java\\java_groovy\\src\\main\\resources\\Groovy_04.groovy");
        System.out.println("执行结果:"+result);
    }

    private static GroovyClassLoader groovyClassLoader = null;

    //初始化GroovyClassLoader
    public static void initGroovyClassLoader() {
        CompilerConfiguration config = new CompilerConfiguration();
        config.setSourceEncoding("UTF-8");
        // 设置该GroovyClassLoader的父ClassLoader为当前线程的加载器(默认)
        groovyClassLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config);
    }

    /**
     * 通过GroovyClassLoader加载Groovy_04.groovy,并反射调用其sayHello(name, age)方法
     */
    public static String invokeSayHello(String name, int age,String filePath) {
        String result = "";

        File groovyFile = new File(filePath);
        if (!groovyFile.exists()) {
            return result;
        }

        try {
            // 获得Groovy_04.groovy加载后的class
            Class<?> groovyClass = groovyClassLoader.parseClass(groovyFile);
            // 获得Groovy_04.groovy的实例
            GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
            // 反射调用sayHello方法得到返回值
            Object methodResult = groovyObject.invokeMethod("sayHello", new Object[] {name,age});
            if (methodResult != null) {
                result = methodResult.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }
}

​ 通过反射调用Groovy_04.groovy中的sayHello方法,并传入参数,最终得到结果。

​ 除了这个例子中使用的java中的自带数据类型,还可以使用自定义的数据类型,接着看下面的例子,先定义一个Student类,类的代码信息如下(包含两个属性):

package com.dream21th.groovy.dto;

public class Student {

    private String name;

    private Integer age;

    public Student() {
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

​ 我们编写Groovy_05.groovyclass文件,文件的内容如下:

import com.dream21th.groovy.dto.Student

class Groovy_05 {
    String sayHello(Student student){
        printf("my name is %s,i am %s year old \n",student.name,student.age)
        return "my name is "+student.name+",i am "+student.age+"year old"
    }
}

​ 该类中的方法sayHello包含自定义的Student类,接下来编写测试代码:

package com.dream21th.groovy;

import com.dream21th.groovy.dto.Student;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import org.codehaus.groovy.control.CompilerConfiguration;

import java.io.File;

public class Groovy_study05 {

    public static void main(String[] args) {
        initGroovyClassLoader();
        String result = invokeSayHello("D:\\code\\study\\java\\java_groovy\\src\\main\\resources\\Groovy_05.groovy","sayHello",new Object[]{new Student("张三",18)});
        System.out.println("执行结果:"+result);
    }

    private static GroovyClassLoader groovyClassLoader = null;

    //初始化GroovyClassLoader
    public static void initGroovyClassLoader() {
        CompilerConfiguration config = new CompilerConfiguration();
        config.setSourceEncoding("UTF-8");
        // 设置该GroovyClassLoader的父ClassLoader为当前线程的加载器(默认)
        groovyClassLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config);
    }

    /**
     * 通过GroovyClassLoader加载Groovy_05.groovy,并反射调用其sayHello(student)方法
     */
    public static String invokeSayHello(String filePath,String methodName,Object[] params) {
        String result = "";

        File groovyFile = new File(filePath);
        if (!groovyFile.exists()) {
            return result;
        }

        try {
            // 获得Groovy_05.groovy加载后的class
            Class<?> groovyClass = groovyClassLoader.parseClass(groovyFile);
            // 获得Groovy_05.groovy的实例
            GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
            // 反射调用sayHello方法得到返回值
            Object methodResult = groovyObject.invokeMethod(methodName, params);
            if (methodResult != null) {
                result = methodResult.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }
}

​ 通过反射调用sayHello方法,并传入Student类的实例,运行得到正确的结果。

3 GroovyScriptEngine脚本引擎加载Groovy脚本

​ 除了上面的两种方式,还可以采用GroovyScriptEngine脚本引擎加载Groovy脚本的方式。编写Groovy_06.groovyGroovy_07.groovy两个脚本,代码信息如下:

// 带参数的groovy方法
def sayHello(name, age) {
    printf("my name is %s,i am %s year old \n",name,age)
    // 如果不写return, groovy方法的默认最后一行为 方法的返回值
    //return "Groovy_06中的sayHello()方法的返回值"
    "Groovy_06.groovy中的sayHello(name, age)方法的返回值"
}

// 运行groovy方法
sayHello(name, age)

import com.dream21th.groovy.dto.Student

def sayHello(Student student){
    printf("my name is %s,i am %s year old \n",student.name,student.age)
    return "my name is "+student.name+",i am "+student.age+"year old"
}

sayHello(student)

​ 两个脚本的主要差异在方法的入参上面,编写测试用的java代码:

package com.dream21th.groovy;

import com.dream21th.groovy.dto.Student;
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;


public class Groovy_study06 {

    public static void main(String[] args) throws Exception {
        // GroovyScriptEngine的根路径(目录),如果参数是字符串数组,说明有多个根路径
        GroovyScriptEngine engine = new GroovyScriptEngine("D:\\code\\study\\java\\java_groovy\\src\\main\\resources");
        Binding binding = new Binding();
        binding.setVariable("name", "王三");
        binding.setVariable("age",19);
        binding.setVariable("student",new Student("无名",39));

        Object result1 = engine.run("Groovy_06.groovy", binding);
        System.out.println(result1);

        Object result2 = engine.run("Groovy_07.groovy", binding);
        System.out.println(result2);
    }
}

​ 需要注意的是,使用GroovyScriptEngine加载脚本,指定的是文件夹,所以该文件夹下的所有脚本都可以执行,看上面的代码实例,Groovy_06.groovyGroovy_07.groovy两个脚本都可以正常的执行。
整个项目的代码结构如下:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习|5.2 偏差和方差

偏差和方差 Bias&#xff08;偏差&#xff09;&#xff1a;偏差是指对样本点的估计值和实际值的偏离程度。偏差越大&#xff0c;样本点越不符合实际值。偏差衡量单个数据点的偏离程度&#xff0c;如下图的第二行。 Variance&#xff08;方差&#xff09;&#xff1a;方差能代表…

resetlogs失败故障恢复-ORA-01555---惜分飞

客户数据库resetlogs报错 Tue Dec 19 15:21:23 2023 ALTER DATABASE MOUNT Successful mount of redo thread 1, with mount id 1683789043 Database mounted in Exclusive Mode Lost write protection disabled Completed: ALTER DATABASE MOUNT Tue Dec 19 15:22:01 2023…

pytorch04:网络模型创建

目录 一、模型创建过程1.1 以LeNet网络为例1.2 LeNet结构1.3 nn.Module 二、网络层容器(Containers)2.1 nn.Sequential2.1.1 常规方法实现2.1.2 OrderedDict方法实现 2.2 nn.ModuleList2.3 nn.ModuleDict2.4 三种容器构建总结 三、AlexNet网络构建 一、模型创建过程 1.1 以LeNe…

短剧分销系统搭建,打造新的蓝海项目

近一年来&#xff0c;短剧占据了当下大众的碎片化时间&#xff0c;各大影视公司也纷纷加入到了短剧行业中。2023年一整年短剧的规模已经达到了三百多亿元&#xff0c;发展非常快。目前&#xff0c;短剧作为一种新的商业模式&#xff0c;已经受到了广泛认可&#xff0c;也为创业…

Python在金融大数据分析中的AI应用实战

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 随着人工智能时代的到来&#xff0c;Python作为…

app store里面的构建版本在线上传

开发苹果ios应用&#xff0c;无论是用原生开发、用hbuilderx开发还是用其他h5框架开发的app&#xff0c;都需要将打包好的ipa文件上传到app store。 在上架app store的过程中&#xff0c;我们会遇到下图的这样一个问题&#xff1a; 就是它要求我们上传一个构建版本&#xff0c…

基于SSM(非maven)的教室预约管理系统——有报告(Javaweb)

项目简介 本项目为基于SSM&#xff08;非maven&#xff09;的教室预约管理系统&#xff0c;本项目主要分为二种角色&#xff1a;用户&#xff0c;管理员 管理员拥有功能&#xff1a;教室信息管理、预约审核管理、预约记录查询、用户注册管理、修改个人信息、退出登录等 用户…

为团队进行文档赋能

大家好&#xff0c;才是真的好。 说来也巧&#xff0c;最近看一个论坛&#xff0c;有人问他们在公司内网管理接收到的外部发文&#xff0c;请问有什么办法工具能够快速的进行管理&#xff0c;在需要的时候供给大家搜索和查看。很多人提了不同的办法&#xff0c;比如说用文件共…

JavaBean

学习目的与要求 熟练掌握<jsp:useBean>、<jsp:setProperty>、<jsp:getProperty>等JSP的操作指令。 本章主要内容 编写JavaBean在JSP中使用JavaBean 一个JSP页面通过使用HTML标记为用户显示数据&#xff08;静态部分&#xff09;&#xff0c;页面中变量的…

【每日一题】2487. 从链表中移除节点-2024.1.3

题目&#xff1a; 2487. 从链表中移除节点 给你一个链表的头节点 head 。 移除每个右侧有一个更大数值的节点。 返回修改后链表的头节点 head 。 示例 1&#xff1a; 输入&#xff1a;head [5,2,13,3,8] 输出&#xff1a;[13,8] 解释&#xff1a;需要移除的节点是 5 &…

LeetCode做题总结 15. 三数之和(未完)

不会做&#xff0c;参考了代码随想录和力扣官方题解&#xff0c;对此题进行整理。 代码思路 思想&#xff1a;利用双指针法&#xff0c;对数组从小到大排序。先固定一个数&#xff0c;找到其他两个。 &#xff08;1&#xff09;首先对数组从小到大排序。 &#xff08;2&…

【vue/uniapp】使用 uni.chooseImage 和 uni.uploadFile 实现图片上传(包含样式,可以解决手机上无法上传的问题)

引入&#xff1a; 之前写过一篇关于 uview 1.x 版本上传照片 的文章&#xff0c;但是发现如果是在微信小程序的项目中嵌入 h5 的模块&#xff0c;这个 h5 的项目使用 u-upload 的话&#xff0c;图片上传功能在电脑上正常&#xff0c;但是在手机的小程序上测试就不会生效&#x…

声明式管理方(yaml)文件

声明式管理方(yaml)文件: 1、适合对资源的修改操作 2、声明式管理依赖于yaml文件&#xff0c;所有的内容都在yaml文件当中。 3、编辑好的yaml文件需要依靠陈述是还是要依靠陈述式的命令发布到k8s集群当中 create只能创建&#xff0c;不能更新。从指定yaml文件中读取配置&#…

【华为机试】2023年真题B卷(python)-考古问题

一、题目 题目描述&#xff1a; 考古问题&#xff0c;假设以前的石碑被打碎成了很多块&#xff0c;每块上面都有一个或若干个字符&#xff0c;请你写个程序来把之前石碑上文字可能的组合全部写出来&#xff0c;按升序进行排列。 二、输入输出 三、示例 示例1: 输入输出示例仅供…

java练习题之常用类Object类,包装类

常用类 应用知识点&#xff1a; Object类 包装类 习题&#xff1a; 1&#xff1a;(Object 类)仔细阅读以下代码&#xff0c;写出程序运行的结果&#xff1b;并简述 和 equals 的区别。 true false 是判断两个变量或实例是不是指向同一个内存空间。 比较两个引用类型的地址&…

声明式管理方法

声明式管理方法&#xff08;yaml&#xff09;文件&#xff1a; 1&#xff0c;适合对资源的修改操作 2&#xff0c;声明式管理依赖于yaml文件&#xff0c;所有的内容都在yamI文件当中 3&#xff0c;编辑好的yaml文件&#xff0c;还是要依靠陈述式命令发布到k8s集群当中 发布的…

Spring见解 1

1.Spring概述 1.1.Spring介绍 ​ Spring是轻量级Java EE应用开源框架&#xff08;官网&#xff1a; http://spring.io/ &#xff09;&#xff0c;它由Rod Johnson创为了解决企业级编程开发的复杂性而创建 1.2.简化应用开发体现在哪些方面&#xff1f; IOC 解决传统Web开发中…

SpringBoot—支付—微信

一、支付流程 1.1、支付准备 1.获取商户号 微信商户平台 申请成为商户 > 提交资料 > 签署协议 > 获取商户号 2.获取 AppID 微信公众平台 注册服务号 > 服务号认证 > 获取APPID > 绑定商户号 3.申请商户证书 登录商户平台 > 选择 账户中心 > 安全…

Kali Linux实现UEFI和传统BIOS(Legacy)引导启动

默认Kali linux安装会根据当前启动的引导模式进行安装 例:以UEFI引导启动安装程序,安装后仅能在UEFI引导模式下进入系统 安装Kali系统 这边基于VirtualBox虚拟机镜像实战操作 首先创建一个Kali虚拟机 这里需要注意,把启动 EFI (只针对某些操作系统)选项勾选上,内存、处理器…

I.MX6ULL_Linux_驱动篇(52)linux CAN驱动

CAN 是目前应用非常广泛的现场总线之一&#xff0c;主要应用于汽车电子和工业领域&#xff0c;尤其是汽车领域&#xff0c;汽车上大量的传感器与模块都是通过 CAN 总线连接起来的。 CAN 总线目前是自动化领域发展的热点技术之一&#xff0c;由于其高可靠性&#xff0c; CAN 总线…
最新文章