一、为什么要这样子做?
虽然知道业界已经有很多包,而且功能、性能方面很强大了!但是做这人包纯粹为了学习Java的映射和Jdom,顺便也磨一磨自己的设计思想!
二、需求分析
我希望这个包能够为我做以下二个事情:
1)将xml文件里面存储的数据取出来放到存入JavaBean的集合里面
2)将存有JavaBean的集合里面的数据写入xml文件
三、开始动工
1)接口设计:
package cn.huion.xml;

import java.util.Collection;


/**//**
* @author huion
*
*/


public interface XmlBuilder
{
public Collection buildBean();//从文件里面读取数据,返回集合
public void buildXml(Collection collection);//传入集合,并将数据存入xml文件
}

为了做到约束,我为所有的JavaBean做了一个统一的基类
package cn.huion.xml.bean;


/**//**
* @author huion
*
*/

public class XmlBean
{
}
不知道要约束好还是不要约束好?这个问题我没有答案,希望有人能够帮我解惑!
2)行为抽象,不管用什么方法进去buildBean 进行buildXml,之前所需要进行的相关运行,我抽象出来,在这一步上,如果抽象得好,那么扩展性就高了,如果抽象得不好,以后扩展的时候,要改动这个抽象类的话,就违反了原则,所以在这个类上我不敢放入太多的设计
package cn.huion.xml;

import java.util.Collection;
import java.lang.reflect.Method;

import cn.huion.xml.bean.XmlBean;


/**//**
* @author huion
*
*/

public abstract class AbstractXmlBuilder implements XmlBuilder
{
protected Method [] setMethods;
protected Method [] getMethods;
protected String [] property;
protected String xmlPath;
protected Class beanClass;


public AbstractXmlBuilder(Class clazz,String xmlPath)throws Exception
{
this.xmlPath = xmlPath;
beanClass = clazz;
}


protected void buildPrecondition()
{//实现前提条件

try
{
Method []ms = beanClass.getMethods();//取得XmlBean的所有方法
int allMethodSize = ms.length;//取得方法的个数
int objectMethodLength = Object.class.getMethods().length;//取得Object的方法的个数
property = new String[(allMethodSize-objectMethodLength)/2];//计算出XmlBean的属性数 property[]是用来读xml文件的时候用的
int propertylength = property.length;
getMethods = new Method[propertylength];//存放XmlBean的所有getter方法
setMethods = new Method[propertylength];//存放XmlBean的所有setter方法
int setCount = 0;
int getCount = 0;

for(int i=0;i<ms.length;i++)
{//迭代XmlBean的所有方法

if(ms[i].getDeclaringClass().equals(beanClass))
{//如果这个方法是XmlBean声明的
String methodName = ms[i].getName();//得到方法名

if(isGetMethod(methodName))
{//如果是getter方法
getMethods[setCount] = ms[i];//存到getter数组中去
setCount++;//计数器加1

}else
{
setMethods[getCount] = ms[i];//否则放到setter方法中去
getCount++;//计数器加1
}
}
}

for(int i=0;i<propertylength;i++)
{//填充属性名到property[]中去
property[i] = this.getPropertyName(getMethods[i].getName());
}

} catch (SecurityException e)
{
e.printStackTrace();
}
}
abstract public Collection buildBean();//子类扩展
abstract public void buildXml(Collection collection);//子类扩展

private String getPropertyName(String methodName)
{
StringBuffer sb=new StringBuffer();
sb.append(methodName.substring(3,4).toLowerCase());
sb.append(methodName.substring(4,methodName.length()));
return sb.toString();
}

private boolean isSetMethod(String methodName)
{

if(methodName.substring(0,3).equals("set"))
{
return true;
}
return false;
}

private boolean isGetMethod(String methodName)
{

if(methodName.substring(0,3).equals("get"))
{
return true;
}
return false;
}

}
或许我可以更大胆点,把xml 解析成Document的代码也放在这个抽象类中...
3)先做个简单的现实来尝试一下
先做个SimpleXmlBuilder尝试一下,如果涉及到无限类包含或者在取出存入的时候要按一定的规则排序的话,如果能够从AbstractXmlBuilder中扩展,那算是比较好的情况,当然要是不行,必需再进行分析,不断的重构
package cn.huion.xml;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.lang.reflect.Method;
import java.io.*;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
import org.jdom.Document;
import org.jdom.Element;

import cn.huion.xml.bean.XmlBean;



/**//**
* @author huion
*
*/

public class SimpleXmlBuilder extends AbstractXmlBuilder
{
private static final String BEAN_MARK="xmlBean";
private static final String XML_ROOT_NAME="root";

protected List readBeans;


public SimpleXmlBuilder(Class clazz,String xmlPath)throws Exception
{
super(clazz,xmlPath);
readBeans=new ArrayList();
}

public Collection buildBean()
{
super.buildPrecondition();

try
{
SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(new File(xmlPath));
Element element=doc.getRootElement();
List beans = new ArrayList();
beans=element.getChildren(BEAN_MARK);
int beanSize=beans.size();
int propertySize=property.length;

for(int i=0;i<beanSize;i++)
{
element=(Element)beans.get(i);
Object o=beanClass.newInstance();
Element e;
Method m;

for(int j=0;j<propertySize;j++)
{
e=element.getChild(property[j]);
m=(Method)setMethods[j];

m.invoke(o,new String[]
{e.getTextTrim()});
}
readBeans.add(o);
}
return readBeans;

}catch(Exception e)
{
e.printStackTrace();
return null;
}
}

public void buildXml(Collection collection)
{
super.buildPrecondition();

try
{
XMLOutputter xo=new XMLOutputter();
Document doc=new Document();
Element root=new Element(XML_ROOT_NAME);
Iterator it = collection.iterator();

while(it.hasNext())
{
Element xmlBean=new Element(BEAN_MARK);
Object bean=it.next();

for(int j=0;j<property.length;j++)
{
System.out.println(getMethods[j].getName());
Element e=new Element(property[j]);
String str=(String)getMethods[j].invoke(bean,null);
e.setText(str);
xmlBean.addContent(e);
}
root.addContent(xmlBean);
}
doc.addContent(root);
xo.output(doc,new FileOutputStream(new File(xmlPath)));

}catch(Exception e)
{
e.printStackTrace();
}
}
}
四、相关测试
1)定义XmlBean
import cn.huion.xml.bean.XmlBean;


/**//**
* @author huion
*
*/

public class TestBean extends XmlBean
{
private String name;
private String sex;


/**//**
*
*/

public TestBean()
{
super();
}



/**//**
* @return 返回 name。
*/

public String getName()
{
return name;
}

/**//**
* @param name 要设置的 name。
*/

public void setName(String name)
{
this.name = name;
}

/**//**
* @return 返回 sex。
*/

public String getSex()
{
return sex;
}

/**//**
* @param sex 要设置的 sex。
*/

public void setSex(String sex)
{
this.sex = sex;
}
}
2)新建一个xml文件
<?xml version="1.0" encoding="UTF-8"?>
<root>
<xmlBean>
<name>
huion
</name>
<sex>
1
</sex>
</xmlBean>

<xmlBean>
<name>
dobedo
</name>
<sex>
2
</sex>
</xmlBean>
</root>
3) 功能测试用例
package cn.huion.xml;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;

import junit.framework.TestCase;


/**//**
* @author huion
*
*/

public class TestSimpleXmlBuilder extends TestCase
{

SimpleXmlBuilder sxb;

protected void setUp() throws Exception
{
super.setUp();
sxb = new SimpleXmlBuilder(TestBean.class,"C:/test.xml");
}


protected void tearDown() throws Exception
{
super.tearDown();
}


public void testBuildBean()
{
Collection coll = sxb.buildBean();
Iterator it = coll.iterator();

while(it.hasNext())
{
TestBean bean = (TestBean)it.next();
System.out.println("Name: "+bean.getName()+" Sex: "+bean.getSex());
}
}


public void testBuildXml()
{
List list = new ArrayList();
TestBean b = new TestBean();
b.setName("love");
b.setSex("1");
list.add(b);
TestBean bb = new TestBean();
bb.setName("dobedo");
bb.setSex("2");
list.add(bb);
sxb.buildXml(list);
}

}
五、总结
至此为止功能基本实现了,性能上的测试还没有做相关的工作!异常处理是好像有点麻烦!或者应该再制定一个XmlBuilderException出来!在模块处理中应该抛出来,而不应该返回null,这一点是有点不负责任!
呵呵!希望有人能够加入评论!
posted on 2005-07-08 02:29
一辉 阅读(431)
评论(1) 编辑 收藏 所属分类:
My Design