創建模板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);
}
}