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解析方式分为两种: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: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 ArrayListbookList = 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); } } /** * 调用处理XML文档元素的开始标签和结束标签之间的文本数据 */ @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----"); } } }
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. Rowling 2005 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两种方式。因为利用了相同的接口,它们的调用方式是一样的。
SAXReader saxReader = new SAXReader(); Document document = saxReader.read(参数);
方法 | 描述 |
---|---|
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(); ListnodeList = 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元素***"); Listlist = 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语言 //其中的第一个/为根节点 ListnodeList = 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); } } }