diff --git a/pom.xml b/pom.xml index 54afce51..d9b3eaf9 100644 --- a/pom.xml +++ b/pom.xml @@ -107,6 +107,13 @@ + + + org.apache.groovy + groovy + 4.0.14 + + org.springframework.boot spring-boot-starter-actuator diff --git a/src/main/java/cn/lihongjie/coal/controller/ScriptController.java b/src/main/java/cn/lihongjie/coal/controller/ScriptController.java index a2ab761a..56237d70 100644 --- a/src/main/java/cn/lihongjie/coal/controller/ScriptController.java +++ b/src/main/java/cn/lihongjie/coal/controller/ScriptController.java @@ -3,6 +3,7 @@ package cn.lihongjie.coal.controller; import cn.lihongjie.coal.annotation.SysLog; import cn.lihongjie.coal.dto.*; import cn.lihongjie.coal.service.ScriptService; +import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.PostMapping; @@ -49,4 +50,13 @@ public class ScriptController extends BaseController{ public ScriptDto getById(@RequestBody IdRequest dto) { return this.service.getById(dto.getId()); } + + + + + @SneakyThrows + @PostMapping("/exec") + public ScriptExecResultDto exec(@RequestBody ScriptExecResultDto json) { + return this.service.exec(json); + } } diff --git a/src/main/java/cn/lihongjie/coal/dto/ScriptExecResultDto.java b/src/main/java/cn/lihongjie/coal/dto/ScriptExecResultDto.java new file mode 100644 index 00000000..adfdab59 --- /dev/null +++ b/src/main/java/cn/lihongjie/coal/dto/ScriptExecResultDto.java @@ -0,0 +1,26 @@ +package cn.lihongjie.coal.dto; + + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.Data; + +import java.util.List; + + +@Data +public class ScriptExecResultDto { + + private String id; + + private JsonNode params; + + private Object response; + + + private String stackTrace; + + private long time; + + + private List logs; +} diff --git a/src/main/java/cn/lihongjie/coal/service/ScriptService.java b/src/main/java/cn/lihongjie/coal/service/ScriptService.java index d42b12cb..67128766 100644 --- a/src/main/java/cn/lihongjie/coal/service/ScriptService.java +++ b/src/main/java/cn/lihongjie/coal/service/ScriptService.java @@ -1,18 +1,31 @@ package cn.lihongjie.coal.service; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; import cn.lihongjie.coal.dao.ScriptRepository; import cn.lihongjie.coal.dto.*; import cn.lihongjie.coal.entity.ScriptEntity; import cn.lihongjie.coal.mapper.ScriptMapper; +import groovy.lang.GroovyClassLoader; +import groovy.lang.Script; import jakarta.annotation.PostConstruct; +import lombok.Cleanup; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.core.convert.ConversionService; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; +import javax.script.ScriptException; + @Service @Slf4j public class ScriptService extends BaseService { @@ -22,11 +35,14 @@ public class ScriptService extends BaseService { @Autowired ScriptMapper mapper; + private GroovyClassLoader groovyClassLoader; @PostConstruct public void init() { + CompilerConfiguration config = new CompilerConfiguration(); + groovyClassLoader = new GroovyClassLoader(this.getClass().getClassLoader(), config); } @@ -80,4 +96,60 @@ public class ScriptService extends BaseService { return page.map(this.mapper::toDto); } + + @Autowired + ApplicationContext applicationContext; + + + @SneakyThrows + public ScriptExecResultDto exec(ScriptExecResultDto json) throws ScriptException { + + // 执行groovy脚本 + // 1. 从数据库中获取脚本 + ScriptEntity scriptEntity = this.get(json.getId()); + + // 2. 执行脚本 + + + Class parsedClass = groovyClassLoader.parseClass(scriptEntity.getContent(), scriptEntity.getId()); + + Script script = (Script) parsedClass.newInstance(); + + Logger scriptLogger = LoggerFactory.getLogger("scriptLogger"); + ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) scriptLogger; + + @Cleanup("stop") ListAppender appender = new ListAppender<>(); + appender.start(); + logger.addAppender(appender); + script.setProperty("out", new Object() { + public void println(Object o) { + logger.info("{}", o); + } + + public void printf(String format, Object... args) { + logger.info(format, args); + } + }); + + + script.setProperty("params", json.getParams()); + script.setProperty("ioc", applicationContext); + + + long start = System.currentTimeMillis(); + try { + + json.setResponse(script.run()); + } catch (Exception e) { + json.setStackTrace(ExceptionUtils.getStackTrace(e)); + } + long end = System.currentTimeMillis(); + + // 3. 返回结果 + json.setLogs(appender.list.stream().map(x -> x.getFormattedMessage()).toList()); + json.setTime(end - start); + + return json; + + } }