创建模板java文件
使用freemaker创建一个java代码运行的模板,整体设计类似于模板方法设计模式,在模板内规定了程序运行的主体步骤,细节实现放在模板中的key中
前端配置模块
每个模块的背后都是一段提前写好的代码,这段代码是可以嵌入到之前准备好的模板的
用户通过拖拽模块来实现自己的逻辑
用户拖拽好模块并保存,后端基于模板及用户的配置信息,生成java文件
编译java文件
编辑java文件,加载相关的类,加入到spring容器中
后端提前准备好一个通用接口
这个接口的核心逻辑就是根据不同的java类名来调用spring容器中的类来完成逻辑。
已经写的demo类
@RestController
public class TestController {
@Autowired
private UserService userService;
@GetMapping("/test")
public String test01() throws Exception {
String hello = userService.sayHello("hello");
return hello;
}
}
@Service
public class UserService {
public String sayHello(String name) throws Exception {
ReflectObj reflectObj = LoadClassUtil.map.get(name);
return reflectObj.invoke();
}
}
public class LoadClassUtil {
public static Map<String, ReflectObj> map = new HashMap<>();
static {
try {
loadClass("com.example.javasou.Hello");
} catch (Exception exception) {
exception.printStackTrace();
}
}
//加载class对象
public static void loadClass(String className) throws Exception {
javac("E:\learn\java\Hello.java");
Thread.sleep(2000);
MyClassLoader myClassLoader = new MyClassLoader();
myClassLoader.setClassPath("E:\learn\java\Hello.class");
Class clazz = myClassLoader.loadClass(className);
DynamicLoadUtils.addBean(clazz,"hello111",SpringContextUtil.getApplicationContext());
Object obj = clazz.newInstance();
map.put("hello",new ReflectObj(clazz, obj));
}
public static void javac(String packageAndClass) throws IOException {
Runtime.getRuntime().exec("javac " + packageAndClass);
}
}
public class MyClassLoader extends ClassLoader {
//需要加载类的路径
private String classPath;
public MyClassLoader() {
}
public MyClassLoader(String classPath) {
super();
this.classPath = classPath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> clazz = null;
// 获取class文件字节码数组
byte[] clazzByteArr = getData();
if (clazzByteArr != null) {
// 将class的字节码数组转换成class类的实例
clazz = defineClass(name, clazzByteArr, 0, clazzByteArr.length);
}
return clazz;
}
private byte[] getData() {
File file = new File(this.classPath);
if (file.exists()) {
FileInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(file);
out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int size = 0;
while ((size = in.read(buffer)) != -1) {
out.write(buffer, 0, size);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return out.toByteArray();
} else {
return null;
}
}
public String getClassPath() {
return classPath;
}
public void setClassPath(String classPath) {
this.classPath = classPath;
}
}
public class ReflectObj {
public ReflectObj(Class aClass, Object object) {
this.aClass = aClass;
this.object = object;
}
private Class aClass;
private Object object;
public String invoke() throws Exception {
Method method = aClass.getMethod("sayHello", String.class);
return (String) method.invoke(object, "123");
}
}
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
public class DynamicLoadUtils {
public static void registerController(String controllerBeanName) throws Exception {
final RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
SpringContextUtil.getBean("requestMappingHandlerMapping");
if (requestMappingHandlerMapping != null) {
String handler = controllerBeanName;
Object controller = SpringContextUtil.getBean(handler);
if (controller == null) {
return;
}
unregisterController(controllerBeanName);
//注册Controller
Method method = requestMappingHandlerMapping.getClass().getSuperclass().getSuperclass().
getDeclaredMethod("detectHandlerMethods", Object.class);
method.setAccessible(true);
method.invoke(requestMappingHandlerMapping, handler);
}
}
public static void unregisterController(String controllerBeanName) {
final RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
SpringContextUtil.getBean("requestMappingHandlerMapping");
if (requestMappingHandlerMapping != null) {
String handler = controllerBeanName;
Object controller = SpringContextUtil.getBean(handler);
if (controller == null) {
return;
}
final Class<?> targetClass = controller.getClass();
ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) {
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
try {
Method createMappingMethod = RequestMappingHandlerMapping.class.
getDeclaredMethod("getMappingForMethod", Method.class, Class.class);
createMappingMethod.setAccessible(true);
RequestMappingInfo requestMappingInfo = (RequestMappingInfo)
createMappingMethod.invoke(requestMappingHandlerMapping, specificMethod, targetClass);
if (requestMappingInfo != null) {
requestMappingHandlerMapping.unregisterMapping(requestMappingInfo);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, ReflectionUtils.USER_DECLARED_METHODS);
}
}
public static void addBean(String className, String serviceName, ApplicationContext app) {
try {
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
registerBean(serviceName, beanDefinitionBuilder.getRawBeanDefinition(), app);
} catch (ClassNotFoundException e) {
System.out.println(className + ",主动注册失败.");
}
}
public static void addBean(Class clazz, String serviceName, ApplicationContext app) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
registerBean(serviceName, beanDefinitionBuilder.getRawBeanDefinition(), app);
}
private static void registerBean(String beanName, BeanDefinition beanDefinition, ApplicationContext context) {
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) context;
BeanDefinitionRegistry beanDefinitonRegistry = (BeanDefinitionRegistry) configurableApplicationContext
.getBeanFactory();
beanDefinitonRegistry.registerBeanDefinition(beanName, beanDefinition);
}
}