??xml version="1.0" encoding="utf-8" standalone="yes"?> JDOM因其z易用易懂的API而被q泛的用。JDOM常用的核心类及它们间的关pd下图所C: Document代表了文对象,抽象cContent表示文中的内容元素Q各U内容组成了文对象。常用的内容元素有xml元素Element、xml注释Comment、文本Text。下面以如下片段来说明各cȝ含义?/font> <?xml version="1.0" encoding="UTF-8"?> <customers> <customer> <name>徐辛?lt;/name> <occupation>developer</occupation> <!-- comment:following is contact info --> <contact> <email>sinpo.xu@hotmail.com</email> <mobile>15029357227</mobile> <fix-phone>02985457683</fix-phone> </contact> </customer> </customers> 上述文用Document来抽象;customers为文档的根元素(root element Q,Element即一个封闭v来的元素Qelement元素可以有子元素Q如<mobile>15029357227</mobile>是一个元素,?lt;contact>...</contact>也是一个元素,甚至<customers>...</customers>也是一个大元素Q?lt;!-- ... -->代表了xml中注释,注释在JDOM中用CommentcL抽象QText代表了xml中的文本|如元素属性的倹{元素的倹{注释的内容{,父元素的Text为子元素和值组成的Ԍ使用Textcd以方便的表示一些特D字W?如: Element element = new Element("name"); Text text = new Text("AAA.<、BBB/>.<CCC>"); element.addContent(text); 值得一提的是Element的方法addContent(Content content),因参数是抽象父类ContentQ所以可以添加Text、Element和Comment{,如果d的是Text则自动作为element的文本|如果是Element则作为element的子元素Q如果是Comment则作为element的注释,使用十分方便。元素的值如<name>徐辛?lt;/name>中的“徐辛?#8221;也是一个和元素q的Content对象QText对象Q,当用Element的getDescendants()Ҏ时将q回一个该元素所有后代的q代器,q些后代包括Element、Comment、Text{,如元?lt;contact>的后代包括email、mobile、fix-phone三个元素以及q三个元素的Text?个后代,如果计算后代时有父子嵌套则应注意Q父元素作ؓ一个后代,其嵌套的子元素作为另一个后代?/font> 刚才提到核心c都包含在org.jdom包下Qjdomq包含了org.jdom.input和org.jdom.output两个包分别来处理xml内容的输入输出。当要读取xml资源时我们通常使用input包下的SAXBuildercM输入构建dom对象Q当资源加蝲后常用的做法是在内存中缓存,q样后箋的查找修改等操作非常快。文加载后内存的中各个元素是记录有各自的位|和关系的,即保持有上下文环境的。如果想要删除一D内容(Element Comment TextQ,只用调用该内容的detachҎ卛_Q这样元素即和文脱dpMQ再Ҏ档进行遍历或者持久化到磁盘上时游ȝ元素׃可见了。Jdom的输出类包括XMLOutputter、DOMOutputter、SAXOutputter。最常用的是XMLOutputterQ通过它可以将dom对象输出到指定的输出,q且可以指定所输出xml文g的格式,比如~进的样式等。DOMOutputter输出org.w3c.dom.Document对象Q用于JDOM对象同w3c dom对象转换QSAXOutputter可以注册回调函数来处理相应的sax事g?/font>
一下示例代码实C个常用的d配置文gq且允许更改后同步到盘的操作:
package sinpo.usagedemo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
/**
* d配置文gQƈ且修改后及时同步到磁?/font>
* @author 徐辛?sinpo.xu@hotmail.com)
* Oct 23, 2008
*/
public class Configuration {
private Element root = null;
private Document dom = null;
private static final String resourceName = "/config.xml";
private static Configuration _INSTANCE = null;
public static synchronized Configuration getInstance() {
if (_INSTANCE == null) {
_INSTANCE = new Configuration();
}
return _INSTANCE;
}
private Configuration() {
load();
}
public String getConfig(String configName) {
String configValue = null;
Element found = findRecursively(configName, root);
if (found != null) {
configValue = found.getText();
}
return configValue;
}
public void updateConfig(String configName, String newValue)
throws IOException {
Element found = findRecursively(configName, root);
if (found != null) {
found.setText(newValue);
} else {
Element configNode = new Element(configName);
configNode.addContent(newValue);
// also: configNode.setText(newValue);
root.addContent(configNode);
}
sync();
}
public void deleteConfig(String configName) throws IOException {
Element found = findRecursively(configName, root);
if (found != null) {
found.detach();
}
sync();
}
private void load() {
SAXBuilder builder = new SAXBuilder();
InputStream source = getClass().getResourceAsStream(resourceName);
try {
dom = builder.build(source);
root = dom.getRootElement();
} catch (Exception e) {
e.printStackTrace();
}
}
// 递归查找. 在指定的父节点下查找叶子元素
private Element findRecursively(String name, Element parent) {
Element found = null;
List<Element> children = parent.getChildren();
if (children != null) {
for (int i = 0; i < children.size(); i++) {
Element element = children.get(i);
String tmpName = element.getName();
if ((name.equals(tmpName)) && (!hasChild(element))) {
return element;
}
}
for (int i = 0; i < children.size(); i++) {
Element element = children.get(i);
if (hasChild(element)) {
found = findRecursively(name, element);
if (found != null) {
return found;
}
}
}
}
return found;
}
private boolean hasChild(Element element) {
boolean hasChild = false;
List children = element.getChildren();
if ((children != null) && (children.size() > 0)) {
hasChild = true;
}
return hasChild;
}
private void sync() throws IOException {
Format format = Format.getPrettyFormat();
XMLOutputter outputter = new XMLOutputter(format);
File file = null;
URL url = getClass().getResource(resourceName);
if (url == null) {
file = new File(resourceName);
} else {
file = new File(url.getPath());
OutputStream out = null;
try {
out = new FileOutputStream(file);
outputter.output(dom, out);
out.close();
out = null;
} catch (Exception e) {
e.printStackTrace();
if (out != null) {
out.close();
}
}
}
}
}
]]>
关于{待和休眠还有另一个区别就是当U程{待Ӟ该线E锁定的资源是释放掉的,q时其它U程是可以锁定这些资源的Q当U程被唤醒或者等待时限到时线E重新获取资源才能l运行;而当U程休眠时线E锁定的资源是不被释攄?/font>
q有一点就是要在对象lock上等待时是必d要获取lock的对象锁才能q行的,卛_要cM下面的逻辑
synchronizedQlock){ lock.wait()}
以下Z个简单的CZQ?/font>
package
sinpo.usagedemo;
|
q几天需要实C个底层基于UDP的协议,该协议底层用UDP传输但是h拥塞控制、超旉发、数据确认等功能又比TCP?QRUDPQReliable UDPQ。在实现协议底层的UDP服务时准备用Java的NIOQ在|上查资料都是以TCPZ讲的Q于是自qI了一下基于UDP的NIO?/font>
NIO的思\是基于多路选择的,即由原来的每个连接都׃个线E来{待消息Q改为每个连接都在选择器上注册Q由选择器来{待。当然NIO引入了很多新的概念,如ChannelQBuffer、Charset、Selector{,使得~程更简z、更面向对象化?/font>
下面贴出用NIO API攚w成UDPCZ代码Q注意其中用Charset来编码解码的q程Q当然Charsetq支持很多其他编码不仅局限于默认~码Q以及Buffer的用?/font>
package
sinpo.usagedemo;
|
package
sinpo.usagedemo;
|
package sinpo.usagedemo; |