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

<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-demoartifactId>        <groupId>com.etgroupId>        <version>1.0-SNAPSHOTversion>    parent>    <modelVersion>4.0.0modelVersion>
<artifactId>groovyartifactId>
<properties> <maven.compiler.source>8maven.compiler.source> <maven.compiler.target>8maven.compiler.target> properties> <dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency>
<dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-autoconfigureartifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-testartifactId> <scope>testscope> dependency> <dependency> <groupId>org.codehaus.groovygroupId> <artifactId>groovy-allartifactId> <version>2.4.7version> dependency>
<dependency> <groupId>org.projectlombokgroupId> <artifactId>lombokartifactId> <version>1.16.10version> dependency> dependencies>project>

conotroller

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

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

package com.et.groovy.service;
import groovy.lang.Binding;import groovy.lang.GroovyShell;import groovy.lang.Script;import org.springframework.stereotype.Service;
@Servicepublic 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中

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;
@Configurationpublic 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动态脚本中直接调用预设对象的方法

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; }}

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

代码仓库

  • https://github.com/Harries/springboot-demo

3.测试

启动Spring Boot应用

测试执行groovy脚本

4.引用

  • https://github.com/double-bin/groovy-script-example


请使用浏览器的分享功能分享到微信等