美文网首页java高级开发springboot
SpringBoot整合Groovy实现动态编程

SpringBoot整合Groovy实现动态编程

作者: 老鼠AI大米_Java全栈 | 来源:发表于2023-03-21 22:37 被阅读0次

    Groovy简介

    Groovy 是增强 Java 平台的唯一的脚本语言。它提供了类似于 Java 的语法,内置映射(Map)、列表(List)、方法、类、闭包(closure)以及生成器。脚本语言不会替代系统编程语言,两者是相互补充的。
    大名鼎鼎的 Gradle,背后是 Groovy。Spring 的未来越来越多的使用 Groovy,甚至在用 Jira 跟踪项目时,背后也有 Groovy。实际上,就应用场景而言,Java 开发已经有越来越多的 Groovy 出现在后台了。而对于一般的应用开发,只要能用 Java 就都能用到 Groovy,唯一的难点只在于能不能招到足够的人员。

    应用场景

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

    集成与使用

    那么接下来介绍SpringBoot如何集成Groovy脚本,并应用到实际开发中。

    第一步、与SpringBoot集成

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

    第三步、传入变量与获取返回值
    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);
        }
    }
    

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

    相关文章

      网友评论

        本文标题:SpringBoot整合Groovy实现动态编程

        本文链接:https://www.haomeiwen.com/subject/zycvrdtx.html