您的位置:首页 > 编程语言 > Java开发

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: