1.项目结构

spring 动态编译方法 springboot动态编译java_Java动态编译

各模块介绍

compile-dao:dao层,数据库持久化层,本文暂时用不到

compile-pojo:实体类

compile-service:业务逻辑模块

compile-shell:Java动态编译的一些java文件

compile-web:SpringBoot的入口

springboot-java-compile父工程pom.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">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>compile-shell</module>
        <module>compile-service</module>
        <module>compile-web</module>
        <module>compile-dao</module>
        <module>compile-pojo</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wjx</groupId>
    <artifactId>springboot-java-compile</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-java-compile</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!--指定使用maven打包-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <configuration>
                    <skipTests>true</skipTests>  <!--默认关掉单元测试 -->
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

 

compile-shell 模块

spring 动态编译方法 springboot动态编译java_Java动态编译_02

pom.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-java-compile</artifactId>
        <groupId>com.wjx</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>compile-shell</artifactId>


    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.54</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

JavaShellExecutor.java

package com.compile.executor;

import com.compile.shell.*;
import lombok.Data;

import java.lang.reflect.Method;

/**
 * @Description: 获取编译后的结果
 * @Auther: wjx
 * @Date: 2019/1/29 15:45
 */
@Data
public class JavaShellExecutor {

    /**
     * 获取类名,className等于ruleName
     *
     * @param ruleName
     * @return
     */
    public String getClassName(String ruleName) {
        String className = ruleName.replaceAll("[^a-z^A-Z]", "");
        return className.substring(0, 1).toUpperCase() + className.substring(1);
    }

    /**
     * 获取编译的结果
     *
     * @param className
     * @param classObject
     * @param ruleName
     * @return
     */
    public Class<?> getCompileResult(String className, JavaClassObject classObject, String ruleName) {
        //使用新的自定义Classloader,记得每个规则使用一个新的classloader,
        //当规则更新时,老的classloader可被释放
        try {
            return getLoadClass(className, classObject, ruleName);
        } catch (Throwable e) {
            throw new RuntimeException("load class error!" + ",className=" + className + "\r\n" + e.getMessage(), e);
        }
    }

    /**
     * 获取加载的Class
     *
     * @param className
     * @param classObject
     * @param ruleName
     * @return
     */
    public Class<?> getLoadClass(String className, JavaClassObject classObject, String ruleName) {
        if (DataEventFactory.eventClassLoaders.get(ruleName) == null) {
            DynamicEngine.getInstance().createNewClassLoader(ruleName);
        }
        DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(DataEventFactory.eventClassLoaders.get(ruleName));
        Class aClass = dynamicClassLoader.loadClass(JavaSourceObject.packageName + ruleName, classObject);
        return aClass;
    }

    /**
     * 执行方法并返回结果
     *
     * @param aClass
     * @param methodName
     * @return
     */
    public Object getMethodResult(Class aClass, String methodName, Object... params) {
        Object result = null;
        try {
            Object instance = aClass.newInstance();
            Method method = aClass.getMethod(methodName, String.class);
            result = method.invoke(instance, params);
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

}

ClassFileManager.java

package com.compile.shell;

import javax.tools.*;
import java.io.IOException;

/**
 * @Description: 类文件管理器
 * @Auther: wjx
 * @Date: 2019/1/18 14:22
 */
public class ClassFileManager extends ForwardingJavaFileManager<JavaFileManager> {


    private JavaClassObject javaClassObject;

    protected ClassFileManager(StandardJavaFileManager standardJavaFileManager) {
        super(standardJavaFileManager);
    }

    public JavaClassObject getJavaClassObject() {
        return javaClassObject;
    }

    /**
     * 源文件被编译成 .class 文件
     *
     * @param location
     * @param className
     * @param kind
     * @param sibling
     * @return
     * @throws IOException
     */
    @Override
    public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
        javaClassObject = new JavaClassObject(className, kind);
        return javaClassObject;
    }
}

DataEventFactory.java

package com.compile.shell;

import java.net.URLClassLoader;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: 创建一个存放ClassLoad的类
 * @Auther: wjx
 * @Date: 2019/1/18 15:47
 */
public class DataEventFactory {
    /**
     * 存放当前的ClassLoader
     */
    public static Map<String, URLClassLoader> eventClassLoaders = new ConcurrentHashMap<>();
}

DynamicClassLoader.java

package com.compile.shell;


import java.net.URL;
import java.net.URLClassLoader;

/**
 * @Description: 读取java文件编译结果
 * @Auther: wjx
 * @Date: 2019/1/18 15:41
 */
public class DynamicClassLoader extends URLClassLoader {

    public DynamicClassLoader(ClassLoader parent) {
        super(new URL[0], parent);
    }

    public Class findClassByName(String className) throws ClassNotFoundException {
        return this.findClass(className);
    }

    /**
     * 加载读取返回的类
     * @param fullName   fullName = packageName + className
     * @param classObject
     * @return
     */
    public Class loadClass(String fullName, JavaClassObject classObject) {
        byte[] bytes = classObject.getBytes();
        return this.defineClass(fullName, bytes, 0, bytes.length);
    }
}

DynamicEngine.java核心类

package com.compile.shell;

import com.compile.executor.JavaShellExecutor;

import javax.tools.*;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

/**
 * Compile动态执行java的String代码到内存中并执行
 * 1.创建 URLClassLoader 类加载器
 * 2.获取当前执行的classpath的所有jar包的路径
 * 3.通过java的ToolProvider创建JavaCompile,用来执行class源文件
 * 4.创建DiagnosticCollector用来执行获取执行失败的错误结果
 * 5.添加动态执行的编译环境 options 是个集合,添加内容,字符集,classpath等
 * 6.传入JavaFileObject的java文件,是个集合,创建JavaSourceObject实现这个接口,Kind.SOURCE.extension = '.java'
 * 7.创建任务并执行
 * 8.获取执行完成后的返回JavaClassObject类
 * 9.创建DynamicClassLoader来加载类 ,defineClass这个方法
 *
 * @Description:
 * @Auther: wjx
 * @Date: 2019/1/18 14:55
 */
public class DynamicEngine extends JavaShellExecutor {

    private static DynamicEngine dynamicEngine;

    /**
     * 单例模式
     *
     * @return
     */
    public static DynamicEngine getInstance() {
        if (dynamicEngine == null) {
            synchronized (DynamicEngine.class) {
                if (dynamicEngine == null) {
                    dynamicEngine = new DynamicEngine();
                }
            }
        }
        return dynamicEngine;
    }

    //创建动态加载jar包
    private URLClassLoader classLoader;
    //当前的classpath环境
    private String classpath;

    private DynamicEngine() {
        //获取类加载器
        this.classLoader = (URLClassLoader) this.getClass().getClassLoader();

        this.buildClasspath();
    }

    private void buildClasspath() {
        //初始化classpath为null
        this.classpath = null;
        StringBuilder sb = new StringBuilder();
        for (URL url : this.classLoader.getURLs()) {
            String f = url.getFile();
            sb.append(f).append(File.pathSeparator);
        }
        this.classpath = sb.toString();
    }


    /**
     * 编译
     *
     * @param className
     * @param javaCode
     * @return
     */
    public Object javaCodeToObject(String className, String javaCode) {
        //记录编译起始时间
        long startTime = System.currentTimeMillis();

        //通过java工具获取编译的compile
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        //创建DiagnosticCollector对象
        DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();

        //建立一个用于保存java文件管理器ClassFileManage
        //每一个文件被保存在JavaClassObject的类里面
        ClassFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(diagnosticCollector, null, null));

        //使用编译选项可以默认编译行为,编译选项是一个String的Iterable集合
        List<String> options = new ArrayList<>();
        options.add("-encoding");
        options.add("UTF-8");
        options.add("-classpath");
        options.add(this.classpath);

        //传递源文件,是一个JavaFileObject的集合
        List<JavaFileObject> fileObjectList = new ArrayList<>();
        fileObjectList.add(new JavaSourceObject(className, javaCode));

        //创建任务
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticCollector, options, null, fileObjectList);
        //执行编译
        Boolean call = task.call();
        if (call) {
            //编译成功
            System.out.println("编译成功");
        } else {
            //编译失败
            System.out.println("编译失败");
            String error = null;
            for (Diagnostic diagnostic : diagnosticCollector.getDiagnostics()) {
                error += compilePrint(diagnostic);
            }
            throw new RuntimeException(error);
        }
        return fileManager.getJavaClassObject();
    }

    /**
     * @param diagnostic
     * @return
     * @MethodName : compilePrint
     * @Description : 输出编译错误信息
     */
    private String compilePrint(Diagnostic diagnostic) {

        System.out.println("Code:" + diagnostic.getCode());
        System.out.println("Kind:" + diagnostic.getKind());
        System.out.println("Position:" + diagnostic.getPosition());
        System.out.println("Start Position:" + diagnostic.getStartPosition());
        System.out.println("End Position:" + diagnostic.getEndPosition());
        System.out.println("Source:" + diagnostic.getSource());
        System.out.println("Message:" + diagnostic.getMessage(null));
        System.out.println("LineNumber:" + diagnostic.getLineNumber());
        System.out.println("ColumnNumber:" + diagnostic.getColumnNumber());
        StringBuffer res = new StringBuffer();
        res.append("Code:[" + diagnostic.getCode() + "]\n");
        res.append("Kind:[" + diagnostic.getKind() + "]\n");
        res.append("Position:[" + diagnostic.getPosition() + "]\n");
        res.append("Start Position:[" + diagnostic.getStartPosition() + "]\n");
        res.append("End Position:[" + diagnostic.getEndPosition() + "]\n");
        res.append("Source:[" + diagnostic.getSource() + "]\n");
        res.append("Message:[" + diagnostic.getMessage(null) + "]\n");
        res.append("LineNumber:[" + diagnostic.getLineNumber() + "]\n");
        res.append("ColumnNumber:[" + diagnostic.getColumnNumber() + "]\n");

        return res.toString();
    }

    /**
     * 创建一个新的ClassLoader
     *
     * @param ruleName
     */
    public void createNewClassLoader(String ruleName) {
        try {
            DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(this.classLoader);
            DataEventFactory.eventClassLoaders.put(ruleName, dynamicClassLoader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

JavaClassObject.java

package com.compile.shell;

import javax.tools.SimpleJavaFileObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;

/**
 * @Description: 获取编译后的class文件
 * @Auther: wjx
 * @Date: 2019/1/18 14:25
 */
public class JavaClassObject extends SimpleJavaFileObject {

    protected final ByteArrayOutputStream bos = new ByteArrayOutputStream();

    /**
     * @param name
     * @param kind
     */
    protected JavaClassObject(String name, Kind kind) {
        super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind);
    }


    public byte[] getBytes() {
        return bos.toByteArray();
    }


    @Override
    public OutputStream openOutputStream() throws IOException {
        return bos;
    }
}

JavaSourceObject.java

package com.compile.shell;

import javax.tools.SimpleJavaFileObject;
import java.io.IOException;
import java.net.URI;

/**
 * @Description: 传递java源文件
 * @Auther: wjx
 * @Date: 2019/1/18 14:45
 */
public class JavaSourceObject extends SimpleJavaFileObject {

    public static String packageName = "com.compile.";

    private String javaCode;

    /**
     * 传入.java文件
     */
    protected JavaSourceObject(String className, String javaCode) {
        super(URI.create("string:///" + className.replace(",", "/") +
                Kind.SOURCE.extension), Kind.SOURCE);
        this.javaCode = javaCode;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
        return javaCode;
    }
}

compile-pojo模块

spring 动态编译方法 springboot动态编译java_idea调试jar_03

 

pom.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-java-compile</artifactId>
        <groupId>com.wjx</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>compile-pojo</artifactId>


    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

CompilePojo.java

package com.compile.pojo;

import lombok.Data;

/**
 * @Description: 编译实体类
 * @Auther: wjx
 * @Date: 2019/1/29 14:52
 */
@Data
public class CompilePojo {
    /**
     * 规则名称
     */
    private String ruleName;

    /**
     * 包名称
     */
    private String packageName;

    /**
     * 类名称
     */
    private String className;

    /**
     * java代码片段
     */
    private String javaCode;

    /**
     * 方法名
     */
    private String methodName;
    /**
     * 参数值
     */
    public String params;
}

compile-dao模块

<?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-java-compile</artifactId>
        <groupId>com.wjx</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>compile-dao</artifactId>


    <dependencies>

        <dependency>
            <groupId>com.wjx</groupId>
            <artifactId>compile-shell</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.wjx</groupId>
            <artifactId>compile-pojo</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

    </dependencies>
</project>

compile-service模块

spring 动态编译方法 springboot动态编译java_idea调试jar_04

pom.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-java-compile</artifactId>
        <groupId>com.wjx</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>compile-service</artifactId>


    <dependencies>
        <dependency>
            <groupId>com.wjx</groupId>
            <artifactId>compile-dao</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

CompileService.java

package com.compile.service;

/**
 * @Description:
 * @Auther: wjx
 * @Date: 2019/1/30 10:58
 */

public interface CompileService {

    /**
     * 执行
     *
     * @param ruleName
     * @param javaCode
     * @return
     */
    Object execute(String ruleName, String javaCode);

    /**
     * 执行方法
     *
     * @param ruleName
     * @param javaCode
     * @param methodName
     * @param parameter
     * @return
     */
    Object executeMethod(String ruleName, String javaCode, String methodName, Object... parameter);
}

CompileServiceImpl.java

package com.compile.service.impl;

import com.compile.executor.JavaShellExecutor;
import com.compile.service.CompileService;
import com.compile.shell.DynamicEngine;
import com.compile.shell.JavaClassObject;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description:
 * @Auther: wjx
 * @Date: 2019/1/30 10:59
 */
@Service
public class CompileServiceImpl extends JavaShellExecutor implements CompileService {

    private Map<String, Class<?>> executorMap = new ConcurrentHashMap<>();

    /**
     * 执行
     *
     * @param ruleName
     * @param javaCode
     * @return
     */
    @Override
    public Object execute(String ruleName, String javaCode) {
        Class<?> aClass = compileGetClass(ruleName, javaCode);
        Object o = null;
        try {
            o = aClass.newInstance();
            System.out.println(o);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return o;
    }

    /**
     * 执行方法
     *
     * @param ruleName
     * @param javaCode
     * @param methodName
     * @param parameter
     * @return
     */
    @Override
    public Object executeMethod(String ruleName, String javaCode, String methodName, Object... parameter) {
        if (executorMap.get(ruleName) == null) {
            execute(ruleName, javaCode);
        }
        Class<?> aClass = executorMap.get(ruleName);
        try {
            return getMethodResult(aClass, methodName, parameter);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 编译Java文件
     *
     * @param ruleName
     * @param javaCode
     * @return
     */
    private Class<?> compileGetClass(String ruleName, String javaCode) {
        //先清空当前的ruleName的值
        executorMap.remove(ruleName);
        JavaClassObject classObject = (JavaClassObject) DynamicEngine.getInstance().javaCodeToObject(getClassName(ruleName), javaCode);
        //获取编译的结果
        Class<?> compileResult = getCompileResult(getClassName(ruleName), classObject, ruleName);
        executorMap.put(ruleName, compileResult);
        return compileResult;
    }

}

compile-web 模块

spring 动态编译方法 springboot动态编译java_Java动态编译_05

pom.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-java-compile</artifactId>
        <groupId>com.wjx</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>compile-web</artifactId>


    <dependencies>
        <dependency>
            <groupId>com.wjx</groupId>
            <artifactId>compile-service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>


    <!--打包-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!-- 指定该Main Class为全局的唯一入口 -->
                    <mainClass>com.Application</mainClass>
                    <!--<layout>ZIP</layout>-->
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

CompileController.java

package com.compile.controller;

import com.alibaba.fastjson.JSONObject;
import com.compile.pojo.CompilePojo;
import com.compile.service.CompileService;
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;

/**
 * @Description:
 * @Auther: wjx
 * @Date: 2019/1/30 11:13
 */
@RestController
public class CompileController {

    @Autowired
    private CompileService compileService;

    /**
     * 编译
     *
     * @param compilePojo
     * @return
     */
    @RequestMapping(value = "execute", method = RequestMethod.POST)
    public Object execute(@RequestBody CompilePojo compilePojo) {
        JSONObject result = new JSONObject();
        try {
            Object returnData = compileService.execute(compilePojo.getRuleName(), compilePojo.getJavaCode());
            result.put("code", "编译成功,内容是:" + returnData);
        } catch (Exception e) {
            result.put("code", e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 执行编译获取方法的返回值
     *
     * @param compilePojo
     * @return
     */
    @RequestMapping(value = "executeMethod", method = RequestMethod.POST)
    public Object executeMethod(@RequestBody CompilePojo compilePojo) {
        JSONObject result = new JSONObject();
        try {
            Object returnData = compileService.executeMethod(compilePojo.getRuleName(), compilePojo.getJavaCode(),
                    compilePojo.getMethodName(), compilePojo.getParams());
            result.put("code", "编译成功,内容是:" + returnData);
        } catch (Exception e) {
            result.put("code", e.getMessage());
            e.printStackTrace();
        }
        return result;
    }
}

 

测试项目

没有获取方法名

{
	"ruleName":"TestScripts",
	"javaCode":"package com.compile;public class TestScripts {  public String hi(String name) {        return \" hi, \" + name;    }   }"
}

返回结果

spring 动态编译方法 springboot动态编译java_maven_06

获取方法名

{
	"ruleName":"TestScripts",
	"javaCode":"package com.compile;public class TestScripts {  public String hi(String name) {        return \" hi, \" + name;    }   }",
	"methodName":"hi",
	"params":"wjx"
}

返回结果

spring 动态编译方法 springboot动态编译java_idea调试jar_07

 

 

打包部署测试

 

idea右侧

spring 动态编译方法 springboot动态编译java_spring 动态编译方法_08

springboot-java-compile 下面的 Lifecycle ,点击 package打包

spring 动态编译方法 springboot动态编译java_idea调试jar_09

运行jar  

java -jar compile-web-0.0.1-SNAPSHOT.jar

spring 动态编译方法 springboot动态编译java_idea调试jar_10

继续测试,

spring 动态编译方法 springboot动态编译java_spring 动态编译方法_11

发现报错了,好吧,只能调试程序了,

下面讲述一下idea如何调试jar包

java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 [jar文件名]

spring 动态编译方法 springboot动态编译java_maven_12

会发现我们的项目在5005被监听

下面在idea添加远程调试Remote

spring 动态编译方法 springboot动态编译java_Java动态编译_13

点击 Edit Configurations 

spring 动态编译方法 springboot动态编译java_java_14

以此点击左侧 + ,和下面Remote默认就ok了

spring 动态编译方法 springboot动态编译java_spring 动态编译方法_15

项目里面打上断点,启动项目

spring 动态编译方法 springboot动态编译java_idea调试jar_16

控制台出现

spring 动态编译方法 springboot动态编译java_maven_17

继续测试,

spring 动态编译方法 springboot动态编译java_idea调试jar_18

发现 

ToolProvider.getSystemJavaCompiler()获取的结果是null,查阅资料发现

上网搜了下,直接说就是找不到jdk lib目录下tools.jar文件,没法编译

查看JAVA_HOME

spring 动态编译方法 springboot动态编译java_java_19

解决方法就是 这个目录下面的lib文件夹的 tool.jar拷贝到  jre1.8.0_191 下面就可以运行了

spring 动态编译方法 springboot动态编译java_maven_20

再次测试

spring 动态编译方法 springboot动态编译java_maven_21

到此已经完成了。