支持脚本调试

This commit is contained in:
2023-08-31 21:36:58 +08:00
parent ce7bf55d23
commit 440e49d78b
4 changed files with 115 additions and 0 deletions

View File

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

View File

@@ -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<String> logs;
}

View File

@@ -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<ScriptEntity, ScriptRepository> {
@@ -22,11 +35,14 @@ public class ScriptService extends BaseService<ScriptEntity, ScriptRepository> {
@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<ScriptEntity, ScriptRepository> {
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<ILoggingEvent> 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;
}
}