java 自定义动态脚本
2015-08-03 17:50
387 查看
java 语言自身具有动态性,通过字节码,类加载实现动态性,我们可以实现自己的字节码动态修改,再让jvm 加载。但是源码进行动态加载呢?就像php,python 这种及时编译,及时运行。(很方便,省去编译)下面说说我自己用java实现的一套支持java原生态的动态脚本实现过程1、源码编译2、实现类加载load源码,获取class3、通过反射,执行返回的class实现源码如下,有简略的注释,希望大家能看懂。。ScriptHelper //脚本引擎类ScriptClassLoader //自定义类加载器Script //脚本源码类ScriptHelper
package com.usefullc.crawler.common.script; import com.usefullc.platform.common.utils.MD5Utils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.ClassUtils; import org.apache.commons.lang.SystemUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * Created by shengshan.tang on 8/3/2015 at 2:10 PM * 脚本 */ public class ScriptHelper { private final static Logger log = LoggerFactory.getLogger(ScriptHelper.class); public static Map<String,Object> execute(String scriptContent,Map<String,Object> paramMap){ Map<String,Object> resultMap = new HashMap<String, Object>(); try { // String folder = System.getProperty("java.io.tmpdir"); // String fileId = UUID.randomUUID().toString(); String basePath = folder + "crawler"; String sourceFilePath = basePath + File.separator + "source"; if(new File(sourceFilePath).mkdir()){ log.info("init create base source folder"); } String fileId = "Script_"+MD5Utils.toMD5(scriptContent); String filePath = sourceFilePath + File.separator + fileId+".java"; log.info("filePath="+filePath); //operate source java //获取package int startIndex = scriptContent.indexOf("package"); int endIndex = scriptContent.indexOf(";",startIndex); String packageStr = scriptContent.substring(startIndex+7,endIndex).trim(); log.info("packageStr="+packageStr); scriptContent = scriptContent.replaceAll("Script",fileId); //class name replace FileUtils.write(new File(filePath),scriptContent,"utf-8"); //compiler String classFilePath = basePath+File.separator+"classs"; if(new File(classFilePath).mkdir()){ log.info("init create class folder"); } String libPath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); log.info("libPath="+libPath); libPath = libPath.replace("classes", "lib"); // libPath = libPath.substring(1); String classPath = "$CLASS_PATH"; if(SystemUtils.OS_NAME.startsWith("Windows")){ classPath = "%CLASS_PATH%"; } String cmd = "javac -g -Djava.ext.dirs="+libPath+" -cp "+classPath+" -sourcepath "+sourceFilePath+" -d "+classFilePath+" "+filePath; log.info("cmd="+cmd); //exeuce compiler Process process = Runtime.getRuntime().exec(cmd); int exitValue = process.waitFor(); log.info("exitValue="+exitValue); //class loader ScriptClassLoader classLoader = new ScriptClassLoader(classFilePath); Class scriptClass = classLoader.findClass(packageStr+"."+fileId); Object instance = scriptClass.newInstance(); Method method = scriptClass.getDeclaredMethod("execute", Map.class); method.invoke(instance,paramMap); }catch(Exception e){ e.printStackTrace(); } return resultMap; } public static void main(String[] args) { String sourceStr = "package com.usefullc.crawler.common.script;\n" + "\n" + "import java.util.Map;\n" + "import java.util.Set;\n" + "\n" + "/**\n" + " * Created by shengshan.tang on 8/3/2015 at 3:19 PM\n" + " */\n" + "public class Script {\n" + "\n" + " public void execute(Map<String,Object> paramMap){\n" + " System.out.println(\"test ok!\");\n" + " if(paramMap != null && !paramMap.isEmpty()){\n" + " Set<Map.Entry<String,Object>> entrySet = paramMap.entrySet();\n" + " for(Map.Entry<String,Object> entry : entrySet){\n" + " System.out.println(entry.getKey()+\"=\"+entry.getValue());\n" + " }\n" + " }\n" + " }\n" + "}\n"; Map<String,Object> paramMap = new HashMap<String, Object>(); paramMap.put("name","tangshengshan"); paramMap.put("sex","男"); execute(sourceStr,paramMap); } }//
ScriptClassLoader
package com.usefullc.crawler.common.script; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; /** * 脚本加载类 * Created by shengshan.tang on 8/3/2015 at 3:52 PM */ public class ScriptClassLoader extends ClassLoader { String classTargetPath; public ScriptClassLoader(String classTargetPath) { this.classTargetPath = classTargetPath; } @Override protected Class findClass(String name) throws ClassNotFoundException { try { byte bytes[] = getClassBytes(name); Class thisClass = defineClass(name,bytes,0,bytes.length); return thisClass; } catch (IOException e) { e.printStackTrace(); } return null; } private byte [] getClassBytes(String className) throws IOException { //builder class file path className = className.replace('.', File.separatorChar) + ".class"; String classFilePath = classTargetPath +File.separator+className; byte [] bytes = FileUtils.readFileToByteArray(new File(classFilePath)); return bytes; } }//
Script
package com.usefullc.crawler.common.script; import java.util.Map; import java.util.Set; /** * Created by shengshan.tang on 8/3/2015 at 3:19 PM */ public class Script { public void execute(Map<String,Object> paramMap){ System.out.println("test ok!"); if(paramMap != null && !paramMap.isEmpty()){ Set<Map.Entry<String,Object>> entrySet = paramMap.entrySet(); for(Map.Entry<String,Object> entry : entrySet){ System.out.println(entry.getKey()+"="+entry.getValue()); } } } }
//最后当前是看效果哈!!
[03 22:34:30,211 INFO ] [main] script.ScriptHelper - filePath=C:\Users\shan\AppData\Local\Temp\crawler\source\Script_f51a59e3ccffad6b28619ceb9bfd54ba.java[03 22:34:30,299 INFO ] [main] script.ScriptHelper - packageStr=com.usefullc.crawler.common.script[03 22:34:30,337 INFO ] [main] script.ScriptHelper - libPath=/D:/workspace/crawler/target/classes/[03 22:34:30,344 INFO ] [main] script.ScriptHelper - cmd=javac -g -Djava.ext.dirs=D:/workspace/crawler/target/lib/ -cp %CLASS_PATH% -sourcepath C:\Users\shan\AppData\Local\Temp\crawler\source -d C:\Users\shan\AppData\Local\Temp\crawler\classs C:\Users\shan\AppData\Local\Temp\crawler\source\Script_f51a59e3ccffad6b28619ceb9bfd54ba.java[03 22:34:34,264 INFO ] [main] script.ScriptHelper - exitValue=0test ok!sex=男name=tangshengshanProcess finished with exit code 0
相关文章推荐
- Java 学习笔记--------------做背景图片
- java发送邮件(1)
- 我的第一个Java程序 helloword
- Java内存泄露的理解与解决
- JAVA学习第十三天
- 自定义 Spring Security 4 的UserDetailsService和UserDetails
- java.lang.UnsatisfiedLinkError:Could not load bd_wsp_v1_0 loader dalvik.system
- Java实现“年-月-日 上午/下午时:分:秒”的简单代码
- Eclipse注解模板设置
- java 学习笔记------画图函数的认识
- spring入门基础(一)
- 修改myeclipse的jsp模板
- Eclipse 导入 cas-server-core3.5.1报错 CDI xxx El xxx
- Java成员变量的访问权限
- 理解Java对象序列化
- 学习笔记——Java内部类练习题
- Spring 之八 整合Mybatis
- 我为什么把think in java 读了10遍
- java中四种引用类型
- 给电脑插入安卓手机那么在eclipse的DDMS视图里的Devices没设备信息