-
Java中配置文件的三种配置位置及读取方式XML的作用
-
配置 *.properties 键值对文件 *.xml *.ini .yaml/.yml
-
数据交换
-
xml webservice
-
json
-
object { }
-
array [ ]
-
-
-
1.2 存放位置及读取方式 1.2.1 src根目录下或resources资源文件夹 Xxx.class.getResourceAsStream("/config.properties"); 1.2.2 与读取配置文件的类在同一包 Xxx.class.getResourceAsStream("config2.properties"); 1.2.3 WebContent(webroot)(或其子目录下)
request :HttpServletRequest
session: HttpSession
ServletContext application = this.getServletContext(); InputStream is = application.getResourceAsStream("/WEB-INF/config3.properties");
InputStream is = application.getResourceAsStream("/upload/config3.properties");
-
解析properties文件
public static void main(String[] args) throws Exception{
InputStream is = PropertiesTest.class.getResourceAsStream("/db.properties");
Properties properties = new Properties();
properties.load(is);
String user = properties.getProperty("user");
String password = properties.getProperty("password");
System.out.println(user+":"+password);
}
xml解析方式(了解)
-
XML解析方式分为两种:DOM方式和SAX方式
-
DOM:Document Object Model,文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口的机制也被称作随机访问机制。
优点:
1、形成了树结构,有助于更好的理解、掌握,且代码容易编写。
2、解析过程中,树结构保存在内存中,方便修改。
缺点:
1、由于文件是一次性读取,所以对内存的耗费比较大。
2、如果XML文件比较大,容易影响解析性能且可能会造成内存溢出。
books.xml文件
冰与火之歌 乔治马丁2014 89 安徒生童话 2004 77 English
DOMTest文件
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class DOMTest {
public static void main(String[] args) throws Exception {
// 创建一个DocumentBuilderFactory的对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 创建DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
// 通过DocumentBuilder对象的parser方法加载books.xml文件到当前项目下
InputStream is = DOMTest.class.getResourceAsStream("/books.xml");
Document document = db.parse(is);
// 获取所有book节点的集合
NodeList bookList = document.getElementsByTagName("book");
// 通过nodelist的getLength()方法可以获取bookList的长度
System.out.println("一共有" + bookList.getLength() + "本书");
// 遍历每一个book节点
for (int i = 0; i < bookList.getLength(); i++) {
System.out.println("=========下面开始遍历第" + (i + 1) + "本书的内容=========");
// 通过 item(i)方法 获取一个book节点,nodelist的索引值从0开始
Node book = bookList.item(i);
// 获取book节点的所有属性集合
NamedNodeMap attrs = book.getAttributes();
System.out.println("第 " + (i + 1) + "本书共有" + attrs.getLength() + "个属性");
// 遍历book的属性
for (int j = 0; j < attrs.getLength(); j++) {
// 通过item(index)方法获取book节点的某一个属性
Node attr = attrs.item(j);
// 获取属性名
System.out.print("属性名:" + attr.getNodeName());
// 获取属性值
System.out.println("--属性值" + attr.getNodeValue());
}
// 解析book节点的子节点
NodeList childNodes = book.getChildNodes();
// 遍历childNodes获取每个节点的节点名和节点值
System.out.println("第" + (i + 1) + "本书共有" + childNodes.getLength() + "个子节点");
for (int k = 0; k < childNodes.getLength(); k++) {
// 区分出text类型的node以及element类型的node
if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
// 获取了element类型节点的节点名
System.out.print("第" + (k + 1) + "个节点的节点名:" + childNodes.item(k).getNodeName());
// 获取了element类型节点的节点值
System.out.println("--节点值是:" + childNodes.item(k).getFirstChild().getNodeValue());
// System.out.println("--节点值是:" + childNodes.item(k).getTextContent());
}
}
System.out.println("=========结束遍历第" + (i + 1) + "本书的内容=========");
}
}
}
SAX方式
-
SAX:Simple API for XML。XML简单应用程序接口。SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口。
优点:
1、采用事件驱动模式,对内存耗费比较小。
2、适用于只处理XML文件中的数据时。
缺点:
1、编码比较麻烦。
2、很难同时访问XML文件中的多处不同数据。
Book.java文件
public class Book {
private String id;
private String name;
private String author;
private String year;
private String price;
private String language;
//省略get/set
}
SAXParserHandler.java文件
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXParserHandler extends DefaultHandler {
String value = null;
Book book = null;
private ArrayList bookList = new ArrayList();
public ArrayList getBookList() {
return bookList;
}
int bookIndex = 0;
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("SAX解析开始");
}
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("SAX解析结束");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
//调用DefaultHandler类的startElement方法
super.startElement(uri, localName, qName, attributes);
if (qName.equals("book")) {
bookIndex++;
//创建一个book对象
book = new Book();
//开始解析book元素的属性
System.out.println("=========开始遍历某一本书的内容=========");
//不知道book元素下属性的名称以及个数,如何获取属性名以及属性值
int num = attributes.getLength();
for(int i = 0; i < num; i++){
System.out.print("book元素的第" + (i + 1) + "个属性名是:"
+ attributes.getQName(i));
System.out.println("---属性值是:" + attributes.getValue(i));
if (attributes.getQName(i).equals("id")) {
book.setId(attributes.getValue(i));
}
}
}
else if (!qName.equals("name") && !qName.equals("bookstore")) {
System.out.print("节点名是:" + qName + "---");
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//调用DefaultHandler类的endElement方法
super.endElement(uri, localName, qName);
//判断是否针对一本书已经遍历结束
if (qName.equals("book")) {
bookList.add(book);
book = null;
System.out.println("=========结束遍历某一本书的内容=========");
}
else if (qName.equals("name")) {
book.setName(value);
}
else if (qName.equals("author")) {
book.setAuthor(value);
}
else if (qName.equals("year")) {
book.setYear(value);
}
else if (qName.equals("price")) {
book.setPrice(value);
}
else if (qName.equals("language")) {
book.setLanguage(value);
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
super.characters(ch, start, length);
value = new String(ch, start, length);
if (!value.trim().equals("")) {
System.out.println("节点值是:" + value);
}
}
}
SAXTest测试类
import java.io.InputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class SAXTest {
public static void main(String[] args) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
SAXParserHandler handler = new SAXParserHandler();
InputStream is = SAXTest.class.getResourceAsStream("/books.xml");
//解析
parser.parse(is, handler);
System.out.println("~!~!~!共有" + handler.getBookList().size() + "本书");
for (Book book : handler.getBookList()) {
System.out.println(book.getId());
System.out.println(book.getName());
System.out.println(book.getAuthor());
System.out.println(book.getYear());
System.out.println(book.getPrice());
System.out.println(book.getLanguage());
System.out.println("----finish----");
}
}
}
XML解析开发包
-
JAXP(Java API for XMLProcessing,意为XML处理的Java API):是SUN公司推出的解析标准实现。
-
Dom4j:是开源组织推出的解析开发包。(牛,大家都在用,包括SUN公司的一些技术的实现都在用)
-
JDom:是开源组织推出的解析开发包。
-
下载地址及官网
下载地址 https://dom4j.github.io/
-
dom4j-1.6.1.jar
-
jaxen-1.1-beta-6
-
Jaxen是一个Java编写的开源的XPath库,它适用于许多不同的对象模型,包括 DOM、XOM、dom4j 和 JDOM
-
XPath 使用路径表达式在 XML 文档中进行导航,是一个 W3C 标准
-
参考文档:XPath 教程 | 菜鸟教程
节点-
在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。
Harry Potter J K. Rowling2005 29.99
选取节点
(文档节点,根元素) J K. Rowling (元素节点)
lang="en" (属性节点)
基本值(文本)
J K. Rowling "en"* 项目 * 项目是基本值或者节点。 * 节点关系 * 父(Parent) * 子(Children) * 同胞(Sibling) * 先辈(Ancestor) * 后代(Descendant)
| 表达式 | 描述 |
|---|---|
| nodename | 选取此节点的所有子节点。 |
| / | 从根节点选取。 |
| // | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
| . | 选取当前节点。 |
| .. | 选取当前节点的父节点。 |
| @ | 选取属性。 |
| 路径表达式 | 结果 |
|---|---|
| /bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
| /bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
| /bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
| /bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
| //title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
| //title[@lang='en'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
| /bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
| /bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
有DOMReader和SAXReader两种方式。因为利用了相同的接口,它们的调用方式是一样的。
SAXReaderSAXReader saxReader = new SAXReader(); Document document = saxReader.read(参数);Node
| 方法 | 描述 |
|---|---|
| public String getName() | 取得节点名称 |
| public void setName(String name) | 设置节点名称 |
| public Element getParent() | 取得父元素 |
| public String getText() | 取得节点文本 |
| public void setText(String text) | 设置节点内容 |
| public void setParent(Element parent) | 设置父元素 |
| public void write(Writer writer) throws IOException | 输出 |
| List selectNodes(String xpathExpression) | 得到指定所有节点 |
| Node selectSingleNode(String xpathExpression) | 得到单个节点 |
Element root = document.getRootElement(); ListElementnodeList = document.selectNodes(xpath);
| 方法 | 描述 |
|---|---|
| Element element(String name) | 返回当前元素的指定名称的第一个子元素 |
| List | 返回当前元素的所有子元素 |
| List | 返回当前元素的所有指定名称的子元素 |
| Attribute attribute(String name) | 返回当前元素指定名称的属性 |
| String attributeValue(String name) | 返回指定属性值,如果属性不存在,返回空字符串 |
示例代码,使用前面的book.xml文件
import java.io.InputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class XpathTest {
public static void main(String[] args) throws Exception {
InputStream is = Dom4jTest.class.getResourceAsStream("/books.xml");
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(is);
System.out.println("***选择所有name元素***");
List list = document.selectNodes("//name");
for(Element e : list) {
System.out.println(e.getName()+":"+e.getText());
}
System.out.println("***选择所有book元素id为2的name元素***");
List list2 = document.selectNodes("/bookstore/book[@id=2]/name");
for(Element e : list2) {
System.out.println(e.getName()+":"+e.getText());
}
}
}
解析示例
-
config.xml文件
-
解析
public static void main(String[] args)throws Exception {
InputStream is = Dom4jTest.class.getResourceAsStream("/config.xml");
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(is);
// /config/action:XPath语言
//其中的第一个/为根节点
List nodeList = document.selectNodes("/config/action");
for (Element actionElement : nodeList) {
//attributeValue根据元素属性名称得到属性值
String path = actionElement.attributeValue("path");
String type = actionElement.attributeValue("type");
System.out.println(path + ":" + type);
List forwardList = actionElement.selectNodes("forward");
for (Element forwardElement : forwardList) {
String name = forwardElement.attributeValue("name");
String forwardPath = forwardElement.attributeValue("path");
String redirect = forwardElement.attributeValue("redirect");
System.out.println("t"+name + ":" + forwardPath + ":" + redirect);
}
}
}



