最近有個朋友在做一個爬蟲項(xiàng)目寝衫,問我是否可以考慮用Java代碼動態(tài)生成一個Java文件!在我寫完了之后拐邪,然后問他用這個來干啥慰毅,朋友很直接的說,存數(shù)據(jù)庫扎阶,我當(dāng)時(shí)的表情就是抚垃,日狗茉兰,你忙吧,我吃檸檬。坟募。。好吧粹湃,下面我說一下思路:
其實(shí)說難不難蕴侧,就這樣用最蠢的方式寫了一個代碼!
原理就是自己生成代碼谤逼,其實(shí)java里面自動生成代碼的框架很多贵扰,例如JAVAssist,而我流部,為了簡單思路戚绕,就直接用StringBuffer寫!
- 使用Gson分析枝冀,Gson會生成一個解析對象LinkedTreeMap舞丛,而里面的Entity內(nèi)部類保存著Gson的key-value鍵值對,其中value可能是LinkedTreeMap對象果漾,也可能是其它數(shù)據(jù)類型球切,我們姑且用Object來代替
- 怎么去寫這個類,首先肯定是寫類名绒障,然后寫變量名
如果是基本數(shù)據(jù)類型和String吨凑,那么直接打印出來,變量名就是key值
如果是List類型户辱,那么則需要導(dǎo)入ArrayList類型鸵钝,然后取第一個數(shù)據(jù),開始遞歸操作
如果是數(shù)組類型(在Gson的解析里面是LinkedTreeMap)庐镐,那么就應(yīng)該重新聲明一個類恩商,開始進(jìn)行內(nèi)部類的遞歸操作,并添加變量和變量名必逆!
如此一步一步下去怠堪,直到判斷所有變量都是基本數(shù)據(jù)類型|String|自定義類 - 使用java i/o操作揽乱,將StringBuffer對象寫進(jìn)文件。那么要把文件寫到哪個地方去粟矿,idea編譯器只認(rèn)識自己識別的文件路徑凰棉,所以file = getClass().getResource().getFile()+""+filename + ".java"
- 編譯java文件,并使用urlClassLoader加載Class文件就可以了
代碼如下:
<pre>
package com.marco.test;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/**
-
Created by KdMobiB on 2017/7/11.
*/
public class Utils {
File file;//java文件的生成目錄
String rootName;/**
- 開始解析Json數(shù)據(jù)
- @param jsonStr
- @return
*/
@SuppressWarnings("unchecked")
public HashMap<String, Object> getRootFromJson(String rootClass, String jsonStr) {
LinkedTreeMap a = new Gson().fromJson(jsonStr, LinkedTreeMap.class);
return getKidFromJson(rootClass, a, true);
}
public HashMap<String, Object> getListRootFromJson(String rootClass, String jsonStr) {
LinkedTreeMap a = new Gson().fromJson(jsonStr, LinkedTreeMap.class);
startChildArrayClass(rootClass);
return getKidFromJson(rootClass, a, false);
}/**
WRITE THE KIDCLASS
@param a
-
@return
*/
public HashMap<String, Object> getKidFromJson(String childClass, LinkedTreeMap a, boolean disable) {
if ((!rootName.equals(childClass)) && disable) {
startChildClass(childClass);
}HashMap<String, Object> maps = new HashMap<String, Object>();
Set<LinkedTreeMap.Entry<String, Object>> entry = a.entrySet();
Iterator<LinkedTreeMap.Entry<String, Object>> iterator = entry.iterator();
while (iterator.hasNext()) {
LinkedTreeMap.Entry<String, Object> stringObjectEntry = iterator.next();
String sk = stringObjectEntry.getKey();
Object sv = stringObjectEntry.getValue();
if (sv instanceof LinkedTreeMap) {
//如果TreeMap類型嚷炉,代表數(shù)據(jù)還有分支渊啰,繼續(xù)遍歷下去
getKidFromJson(sk, (LinkedTreeMap) sv, true);
stopChildClass();
} else if (sv instanceof ArrayList) {
//如果是List類型,列表內(nèi)的數(shù)據(jù)需要重新創(chuàng)建一個類
getListRootFromJson(sk, new Gson().toJson(((ArrayList) sv).get(0)));
stopChildClass();
} else {
//當(dāng)判斷不是數(shù)組類型或者列表類型申屹,直接將key寫入當(dāng)前的類
sb.append("\t" + sv.getClass().getSimpleName() + " " + sk + ";\t\n");
addGetAndSet(sb, sk, sv.getClass().getSimpleName());
}
maps.put(sk, sv);
}
return maps;
}
StringBuilder sb = new StringBuilder("\r\n");
/**
- 開始
- @param root
*/
public void startFileWrite(String root) {
rootName = root;
file = new File(getClass().getResource("").getFile() + "/" + root + ".java");
sb.append(getClass().getPackage() + ";" + "\r\n");
sb.append("public class " + root + "{" + "\r\n");
}
/**
- 結(jié)束
*/
public void finishFileWrite() {
try {
FileWriter fw = new FileWriter(file);
sb.append("\r\n");
sb.append("}");
fw.write(sb.toString());
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void startChildClass(String childName) {
String childClass = childName + "Class";
sb.append("public " + childClass + " " + childName + ";\r\n");
sb.append("class " + childClass);
sb.append("{" + "\r\n");
}public void startChildArrayClass(String childName) {
addLibsImport("import java.util.ArrayList;");
String childClass = childName + "Class";
sb.append("public ArrayList<" + childClass + "> " + childName + ";\r\n");
sb.append("class " + childClass);
sb.append("{" + "\r\n");
}public void stopChildClass() {
sb.append("\r\n");
sb.append("}");
}/**
- 編寫Java文件
- @param maps
*/
public void writeInJava(HashMap<String, Object> maps) {
Iterator<LinkedTreeMap.Entry<String, Object>> iterator = maps.entrySet().iterator();
while (iterator.hasNext()) {
LinkedTreeMap.Entry<String, Object> entry = iterator.next();
if (entry.getValue() instanceof LinkedTreeMap) return;
String key = entry.getKey();
String FieldType = entry.getValue().getClass().getSimpleName();
sb.append("\r\n\t");
sb.append("public " + FieldType + " " + key + ";");
sb.append("\r\n\t");
addGetAndSet(sb, key, FieldType);
}
}
public void addGetAndSet(StringBuilder sb, String name, String type) {
sb.append("\r\n\t");
sb.append("public void " + "set" + name);
sb.append("(" + type + " " + name + "1" + ")");
sb.append("{");
sb.append("\r\n\t\t");
sb.append("this." + name + "=" + name + "1" + ";");
sb.append("\r\n\t");
sb.append("}");sb.append("\r\n\t"); sb.append("public " + type + " " + "get" + name); sb.append("(" + ")"); sb.append("{"); sb.append("\r\n\t\t"); sb.append("return " + name + ";"); sb.append("\r\n\t"); sb.append("}"); sb.append("\r\n");
}
/**
- 編譯生成的Java文件
*/
public void complie2Class() {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
Iterable units = fileMgr.getJavaFileObjects(file);
JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
t.call();
try {
fileMgr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
- 通過Url加載生成Class文件
- @param className
*/
public void loadClass(String className) {
String fileUrl = "file:/" + file.getParent();
System.out.println(fileUrl);
try {
URL[] urls = new URL[]{new URL(fileUrl)};
URLClassLoader ul = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
Class c = ul.loadClass(getClass().getPackage().getName() + "." + className);
System.out.println(c.newInstance().getClass().getName());
Object o = c.newInstance();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
- 添加第三方導(dǎo)包
*/
public void addLibsImport(String lib) {
String regex = getClass().getPackage() + ";" + "\r\n";
if (!sb.toString().contains(lib)) {
sb.insert(sb.indexOf(regex) + regex.length(), "\r\n" + lib + "\r\n");
}
}
}
</pre>
使用方式:
<pre>
package com.marco.test;
import com.google.gson.Gson;
import java.util.HashMap;
//1. 判斷當(dāng)前是否存在rootName相同類
//2.先寫rootClass類
//3.判斷是否需要創(chuàng)建新的類
/**
- Created by KdMobiB on 2017/7/11.
*/
public class Json2JavaObjcet {
static String jsonStr = "{" +
"animals:{" +
"dog:[" +
"{name:Rufus,breed:labrador,count:1,twoFeet:false}," +
"{name:Marty,breed:whippet,count:1,twoFeet:false}" +
"]," +
"cat:{name:Matilda}" +
"}" +
"}";
// static String jsonStr = "{cat:{name:Matilda}," +
// "dog:{name:Matilda}," +
// "elephant:{name:Matilda}}";
// static String jsonStr = "{" +
// "Id:[{name:myname},{name:myname}]," +
// "Name:Matilda," +
// "Age:52," +
// "Time:6" +
// "}";
public static void main(String args[]) {
Utils utils = new Utils();
String className = "RootName";
utils.startFileWrite(className);//開始啟動
utils.getRootFromJson(className,jsonStr);
utils.finishFileWrite();
utils.complie2Class();//編譯Java文件
utils.loadClass(className);//加載Class文件
System.out.println(utils.getClass().getPackage().getName());
}
}
</pre>