JDOM操作xml以及Java中的动态类加载
这是最近的一个需求:
有一个算法库,里边的每一个算法是一个类,并且都有公共的入口函数,需要根据一个定义好的xml文档,依次执行指定的算法。
这里用到了两个以前不会的知识,一个是xml文档的处理,另一个是类的动态加载。
通过搜索,最后采用JDOM对xml进行操作,通过Java的reflect机制进行动态类加载,现记录如下:
xml的文档定义如下:
<?xml version="1.0" encoding="gb2312"?> <jobs> <algorithm name = "pdm.filters.PDAttributeExchange"> <setting> <set name="jobPriorityType"></set> <set name="numOfMapTasks"></set> <set name="numOfReduceTasks"></set> </setting> <input> <header>/home/maxd/data/3d.header.arff</header> <data>maxd/input</data> </input> <output> <header>maxd/xmloutputheader/3d.header.arff</header> <data>maxd/xmloutput</data> </output> <arguments> <arg name="attributeField1">A1</arg> <arg name="attributeField2">A3</arg> </arguments> </algorithm> </jobs>
处理代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | package pdm.xml; import org.jdom.*; import org.jdom.input.*; import java.io.*; import java.util.List; import java.util.ArrayList; import java.lang.reflect.Method; public class XmlStart { private static String[] constructArgs(Element algNode) { List<string> args = new ArrayList<string>(); String value; Element setting = algNode.getChild("setting"); List setList = setting.getChildren(); for(int i = 0; i < setList.size(); i++){ Element setNode = (Element)setList.get(i); value = setNode.getText(); if(!value.equals("")){ args.add(setNode.getAttributeValue("name")); args.add(value); } } Element inputNode = algNode.getChild("input"); value = inputNode.getChildText("header"); if (!value.equals("")) { args.add("inputHeader"); args.add(value); } value = inputNode.getChildText("data"); if (!value.equals("")) { args.add("inputData"); args.add(value); } Element outputNode = algNode.getChild("output"); value = outputNode.getChildText("header"); if(!value.equals("")){ args.add("outputHeader"); args.add(value); } value = outputNode.getChildText("data"); if(!value.equals("")){ args.add("outputData"); args.add(value); } List argsList = algNode.getChild("arguments").getChildren(); for(int i = 0; i < argsList.size(); i++){ Element argNode = (Element)argsList.get(i); value = argNode.getText(); if(!value.equals("")){ args.add(argNode.getAttributeValue("name")); args.add(value); } } return (String[]) args.toArray(new String[args.size()]); } public static void main(String[] args) { // TODO Auto-generated method stub String xmlFile = "/root/maxd/test.xml"; if (args.length > 0) xmlFile = args[0]; try { SAXBuilder sb = new SAXBuilder(); Document doc = sb.build(new FileInputStream(xmlFile)); Element root = doc.getRootElement(); List algList = root.getChildren(); for (int i = 0; i < algList.size(); i++) { Element algNode = (Element) algList.get(i); String[] arguments = constructArgs(algNode); String algName = algNode.getAttributeValue("name"); Class alg = Class.forName(algName); Method webRun = alg.getMethod("WebRun", new Class[]{String[].class}); webRun.invoke(alg.newInstance(), new Object[]{arguments}); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } |
遇到的问题:
1.运行的时候提示NoClassDefFoundError 是SAXBuilder类找不到,估计是jdom.jar包的问题,但是不管将其加入classpath,还是运行时指定-classpath都没有用,折腾了半天,才知道需要将jdom.jar拷到jre的库里,即/…/jdk1.5.0_14/jre/lib/ext目录下。
2.想通过Class.getMethod()函数获取入口函数时,不明白数组类型如何表示,搜索后才知道在java里数组也是对象(汗一下自己的java水平)……
3.List和数组的转换(还是java水平太烂)……