本文是"
使XML作为持久存储介质的解决方案 "的续文.
上文中对成员的CRUD都采用同步进行资源保护,这种方案实际上是保护过度,带来的消极影响是降低了程序的效率,在下面的例子中,我们应该使用读写锁对资源进行保护.关于读写锁的分析请见"
读写锁的OO分析(http://www.blogjava.net/sitinspring/archive/2007/10/21/154652.html)".
下面是代码:
MemberService类:
package com.sitinspring.model.service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import com.sitinspring.exception.PersistFileReadException;
import com.sitinspring.exception.PersistFileWriteException;
import com.sitinspring.model.domain.Member;
import com.sitinspring.model.domain.MemberFilter;
import com.sitinspring.model.persistence.Db4OPersistence;
import com.sitinspring.model.persistence.HibernatePersistence;
import com.sitinspring.model.persistence.Persistence;
import com.sitinspring.model.persistence.SqlPersistence;
import com.sitinspring.model.persistence.XmlPersistence;
import com.sitinspring.util.ReadWriteLock;
public class MemberService {
private static Logger logger = Logger.getLogger(MemberService.class);
private Persistence persistence;
private Persistence xmlPersistence;
private Persistence sqlPersistence;
private Persistence db4OPersistence;
private Persistence hibernatePersistence;
private Hashtable<String, Member> members;
private ReadWriteLock lock;
public MemberService() {
members = new Hashtable<String, Member>();
lock = new ReadWriteLock();
}
public void setPersistenceType(String type){
logger.info("指定持久层为"+type);
if(type.equals("Xml")){
if(xmlPersistence==null){
try{
xmlPersistence=new XmlPersistence();
}
catch(Exception ex){
logger.error("不能初始化XmlPersistence,原因:"+ex.getMessage());
}
}
persistence=xmlPersistence;
}
else if(type.equals("Sql")){
if(sqlPersistence==null){
try{
sqlPersistence=new SqlPersistence();
}
catch(Exception ex){
logger.error("不能初始化XmlPersistence,原因:"+ex.getMessage());
}
}
persistence=sqlPersistence;
}
else if(type.equals("Hibernate")){
if(hibernatePersistence==null){
try{
hibernatePersistence=new HibernatePersistence();
}
catch(Exception ex){
logger.error("不能初始化XmlPersistence,原因:"+ex.getMessage());
}
}
persistence=hibernatePersistence;
}
else{
if(db4OPersistence==null){
try{
db4OPersistence=new Db4OPersistence();
}
catch(Exception ex){
logger.error("不能初始化XmlPersistence,原因:"+ex.getMessage());
}
}
persistence=db4OPersistence;
}
try{
members.clear();
members=persistence.loadMemberFromPersistence();
}
catch(PersistFileReadException ex){
logger.error("从"+persistence+"中读取失败");
}
}
public boolean hasMember(String name) {
return members.containsKey(name);
}
public boolean hasMember(Member member) {
return hasMember(member.getName());
}
public boolean add(Member member) throws PersistFileWriteException {
if (hasMember(member)) {
System.out.println("Member:" + member.getName()
+ " has been exist!");
return false;
} else {
try {
lock.writeLock();
persistence.add(member);
members.put(member.getName(), member);
return true;
} finally {
lock.writeUnlock();
}
}
}
public boolean update(Member member) throws PersistFileWriteException {
if (hasMember(member)) {
try {
lock.writeLock();
persistence.update(member);
Member oldMember = members.get(member.getName());
oldMember.setTitle(member.getTitle());
oldMember.setAge(member.getAge());
return true;
} finally {
lock.writeUnlock();
}
} else {
System.out.println("Member:" + member.getName()
+ " can't been found!");
return false;
}
}
public boolean saveOrUpdate(Member member) throws PersistFileWriteException {
if (hasMember(member)) {
return update(member);
} else {
return add(member);
}
}
public boolean delete(Member member) throws PersistFileWriteException {
return delete(member.getName());
}
public boolean delete(String memberName) throws PersistFileWriteException {
if (hasMember(memberName)) {
try {
lock.writeLock();
persistence.delete(memberName);
members.remove(memberName);
return true;
} finally {
lock.writeUnlock();
}
} else {
System.out.println("Member:" + memberName
+ " can't been found!");
return false;
}
}
@SuppressWarnings("unchecked")
public List<Member> search(MemberFilter memberFilter) {
List<Member> retval = new ArrayList<Member>();
try {
lock.readLock();
for (Iterator it = members.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
Member member = members.get(key);
if (memberFilter.match(member)) {
retval.add(member);
}
}
} finally {
lock.readUnlock();
}
Collections.sort(retval);
return retval;
}
public List<Member> getAll() {
MemberFilter filter = new MemberFilter() {
public boolean match(Member member) {
return true;
}
};
return search(filter);
}
public Member getMemberByName(String name) {
try {
lock.readLock();
for (Iterator it = members.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
Member member = members.get(key);
if (member.getName().equals(name)) {
return member;
}
}
} finally {
lock.readUnlock();
}
return null;
}
}
XmlPersistence类代码:
package com.sitinspring.model.persistence;
import java.io.File;
import java.io.FileWriter;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import com.sitinspring.exception.PersistFileReadException;
import com.sitinspring.exception.PersistFileWriteException;
import com.sitinspring.model.domain.Member;
import com.sitinspring.util.FileDirUtil;
public class XmlPersistence extends Persistence {
private Document document;
public XmlPersistence() throws PersistFileReadException,
PersistFileWriteException {
filePos = "member.xml";
if (FileDirUtil.isFileExist(filePos) == false) {
// Create document when file not exist
createDocument();
return;
} else {
// Get Docunent when file exist
SAXReader reader = new SAXReader();
try {
document = reader.read(new File(filePos));
} catch (Exception ex) {
throw new PersistFileReadException(ex.getMessage());
}
}
}
public String toString(){
return "XML存储介质,文件为:"+filePos;
}
private void createDocument() throws PersistFileWriteException {
String text = "<members></members>";
try {
document = DocumentHelper.parseText(text);
writeDocumentToFile();
} catch (PersistFileWriteException ex) {
throw ex;
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void writeDocumentToFile() throws PersistFileWriteException {
try {
XMLWriter writer = new XMLWriter(new FileWriter(filePos));
writer.write(document);
writer.close();
} catch (Exception ex) {
throw new PersistFileWriteException(ex.getMessage());
}
}
public Hashtable<String, Member> loadMemberFromPersistence()
throws PersistFileReadException {
try {
Hashtable<String, Member> retval = new Hashtable<String, Member>();
List nodes = document.getRootElement().elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
Member member = new Member(elm.attributeValue("name"), elm
.elementText("age"), elm.elementText("title"));
retval.put(member.getName(), member);
}
return retval;
} catch (Exception ex) {
throw new PersistFileReadException(ex.getMessage());
}
}
public boolean add(Member member) throws PersistFileWriteException {
try {
Element rootElm = document.getRootElement();
Element newMemberElm = rootElm.addElement("member");
newMemberElm.addAttribute("name", member.getName());
Element ageElm = newMemberElm.addElement("age");
ageElm.setText(member.getAge());
Element titleElm = newMemberElm.addElement("title");
titleElm.setText(member.getTitle());
writeDocumentToFile();
return true;
} catch (PersistFileWriteException ex) {
throw ex;
}
}
public boolean update(Member member) throws PersistFileWriteException {
try {
Element rootElm = document.getRootElement();
List nodes = rootElm.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
if (elm.attributeValue("name").equals(member.getName())) {
elm.element("age").setText(member.getAge());
elm.element("title").setText(member.getTitle());
break;
}
}
writeDocumentToFile();
return false;
} catch (PersistFileWriteException ex) {
throw ex;
}
}
public boolean delete(String name) throws PersistFileWriteException {
try {
Element rootElm = document.getRootElement();
List nodes = rootElm.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
Member member = new Member(elm.attributeValue("name"), elm
.elementText("age"), elm.elementText("title"));
if (member.getName().equals(name)) {
rootElm.remove(elm);
break;
}
}
writeDocumentToFile();
return false;
} catch (PersistFileWriteException ex) {
throw ex;
}
}
public boolean delete(Member member) throws PersistFileWriteException {
return delete(member.getName());
}
}