Spring Boot集成groovy快速入门Demo

1.什么是groovy?

Groovy 是构建在 JVM 上的一个轻量级却强大的动态语言,它结合了 Python、Ruby 和 Smalltalk 的许多强大的特性。 Groovy 就是用 Java 写的,Groovy 语法与 Java 语法类似,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码。相对于 Java,它在编写代码的灵活性上有非常明显的提升,Groovy 可以使用其他 Java 语言编写的库。 Groovy 是增强 Java 平台的唯一的脚本语言。它提供了类似于 Java 的语法,内置映射(Map)、列表(List)、方法、类、闭包(closure)以及生成器。脚本语言不会替代系统编程语言,两者是相互补充的。

系统编程语言的目的:

  • 开发复杂的算法或者数据结构
  • 实现计算密集型应用
  • 操作大型数据集
  • 实现定义良好的、变更缓慢的需求

脚本语言应用的目的:

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

集成groovy的好处:

  1. groovy跟java都是基于jvm的语言,可以在java项目中集成groovy并充分利用groovy的动态功能;
  2. groovy兼容几乎所有的java语法,开发者完全可以将groovy当做java来开发,甚至可以不使用groovy的特有语法,仅仅通过引入groovy并使用它的动态能力;
  3. groovy可以直接调用项目中现有的java类(通过import导入),通过构造函数构造对象并直接调用其方法并返回结果;
  4. groovy支持通过GroovyShell预设对象,在groovy动态脚本中直接调用预设对象的方法。因此我们可以通过将spring的bean预设到GroovyShell运行环境中,在groovy动态脚本中直接调用spring容器中bean来调用其方法,这点对于spring项目非常方便!

2.代码工程

实验目的

如何通过动态groovy脚本直接调用spring context中注册的bean的方法

pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>groovy</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-all -->
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.4.7</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
    </dependencies>
</project>

conotroller

将binding对象注入后,在初始化方法init()中用binding对象构造GroovyShell对象,在提供的execute接口实现中用GroovyShell对象生成Script脚本对象,并调用Script的run()方法运行动态脚本并返回结果。

kotlin 复制代码
package com.et.groovy.controller;

import com.et.groovy.component.TestScript;
import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;

@RestController
@RequestMapping("/groovy/script")
public class GroovyScriptController {

    @Autowired
    private Binding groovyBinding;

    private GroovyShell groovyShell;

    @PostConstruct
    public void init(){
        GroovyClassLoader groovyClassLoader = new GroovyClassLoader(this.getClass().getClassLoader());
        CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
        compilerConfiguration.setSourceEncoding("utf-8");
        compilerConfiguration.setScriptBaseClass(TestScript.class.getName());

        groovyShell = new GroovyShell(groovyClassLoader, groovyBinding, compilerConfiguration);
    }

    @RequestMapping(value = "/execute", method = RequestMethod.POST)
    public String execute(@RequestBody String scriptContent) {
        Script script = groovyShell.parse(scriptContent); 
        return String.valueOf(script.run());
    }
}

service

ini 复制代码
package com.et.groovy.service;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.springframework.stereotype.Service;

@Service
public class TestService {

    public String testQuery(long id){
        return "Test query success, id is " + id;
    }

    public static void main(String[] args) {
        Binding groovyBinding = new Binding();
        groovyBinding.setVariable("testService", new TestService());
        GroovyShell groovyShell = new GroovyShell(groovyBinding);

        String scriptContent = "import pers.doublebin.example.groovy.script.service.TestService\n" +
                "def query = new TestService().testQuery(1L);\n" +
                "query";

        /*String scriptContent = "def query = testService.testQuery(2L);\n" +
                "query";*/

        Script script = groovyShell.parse(scriptContent);
        System.out.println(script.run());
    }
}

config

首先配置类可以实现org.springframework.context.ApplicationContextAware接口用来获取应用上下文,然后再配置类中通过应用上下文获取所有的bean并注册到groovy的Binding中

typescript 复制代码
package com.et.groovy.config;

import groovy.lang.Binding;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

@Configuration
public class GroovyBindingConfig implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    //@Bean("groovyBinding")
    public Binding groovyBinding() {
        Binding groovyBinding = new Binding();

        Map<String, Object> beanMap = applicationContext.getBeansOfType(Object.class);
        for (String beanName : beanMap.keySet()) {
            groovyBinding.setVariable(beanName, beanMap.get(beanName));
        }
        return groovyBinding;
    }

    @Bean("groovyBinding1")
    public Binding groovyBinding1() {
        Map<String, Object> beanMap = applicationContext.getBeansOfType(Object.class);
        return new Binding(beanMap); 
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;

    }
}

components

groovy支持通过GroovyShell预设对象,在groovy动态脚本中直接调用预设对象的方法

scala 复制代码
package com.et.groovy.component;

import groovy.lang.Script;

public class TestScript extends Script {
    @Override
    public Object run() {
        return null;
    }

    public Integer add (Integer first, Integer second) {
        return first + second;
    }
}

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

3.测试

启动Spring Boot应用

测试执行groovy脚本

4.引用

相关推荐
Theodore_10223 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸4 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象5 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了5 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
小二·5 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic6 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
懒洋洋大魔王6 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq
武子康6 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
qq_17448285756 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
转世成为计算机大神6 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式