XML(eXtensible Markup Language)
概述
- 是一种可扩展的标记语言
-
XML常见组成
文档声明(声明在XML第一行)
- <?xml version=”1.0” encoding=”UTF-8” ?>
- version:版本号(必须存在)
- encoding:文件编码
- 注释
- 快捷键:ctrl + /
- 标签
- 标签由一对尖括号和合法标识符组成
- 有内容的标签必须成对出现
- 没有内容的标签可以提前结束
- 属性
- 标签中可以定义属性
- 属性值必须用引号引起来
- 实体字符/转义字符
- <
>
- “ "
- ‘ '
- & &
字符数据区
- <![CDATA[ 内容 ]]>
快捷键 CD :::
<?xml version="1.0" encoding="UTF-8" ?>
<!--这是注释-->
<persons>
<person id = "1">
<name>张三</name>
<age>23</age>
<address>北京</address>
<note/>
</person>
<person id="2">
<name>李四</name>
<age>24</age>
<address>上海</address>
<message>
<![CDATA[
<<"李四来自天津">>
]]>
</message>
</person>
</persons>
DTD约束(不能验证数据类型)
XML的标签和属性可以随意扩展,通过XML约束来限定XML文件中可使用的标签以及属性
导入DTD文件的两种格式
<!DOCTYPE 根元素 SYSTEM “DTD文件路径”> 本地的约束
- <!DOCTYPE 根元素 PUBLIC “文件描述” “DTD文件路径”> 网络上的约束 ::: ```xml <?xml version=”1.0” encoding=”UTF-8” ?>
<!DOCTYPE books SYSTEM “bookshelf.dtd”>
<book>
<name>Python</name>
<price>19.9</price>
<author>匿名</author>
</book>
```xml
<!ELEMENT books (book+)>
<!ELEMENT book (name,price,author)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ELEMENT author (#PCDATA)>
Schema约束
概述
- <根标签
- xmlns=”命名空间”
- xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
- xsi:schemaLocation=”命名空间 schema约束文件名”>
- </根标签>
::: ```xml <?xml version=”1.0” encoding=”UTF-8” ?>
<书架 xmlns=”http://www.itcast.cn/“ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“ xsi:schemaLocation=”http://www.itcast.cn/ bookshelf.xsd”> <书> <书名>大数据应用开发</书名> <作者>匿名</作者> <售价>99.9</售价> </书>
<书>
<书名>C#</书名>
<作者>匿名</作者>
<售价>29.9</售价>
</书>
</书架>
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itcast.cn/"
elementFormDefault="qualified">
<xs:element name='书架'>
<xs:complexType>
<xs:sequence maxOccurs='unbounded'>
<xs:element name='书'>
<xs:complexType>
<xs:sequence>
<xs:element name='书名' type='xs:string'/>
<xs:element name='作者' type='xs:string'/>
<xs:element name='售价' type='xs:double'/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
dom4j
DOM解析
-
dom4j解析XML-得到Document对象
SAXReader对象
- SAXReader() 创建解析器
- Document read(File url) 解析XML文档
Document对象
List
elements() 得到当前元素下所有子元素 - List
elements(String name) 得到当前元素下指定名字的子元素返回集合 - Element element(String name) 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个
- String getName() 得到元素名字
- String attributeValue(String name) 通过属性名直接得到属性值
- String elementText(子元素名) 得到指定名称的子元素的文本
String getText() 得到文本 :::
public static void main(String[] args) throws DocumentException { // 1.创建解析器 SAXReader reader = new SAXReader(); // 2.使用解析器解析XML Document document = reader.read(new File("study_day14\\src\\Contact.xml")); // getRootElement: 获取根元素 Element rootElement = document.getRootElement(); // System.out.println(rootElement); // getName(): 获取元素名称 // System.out.println(rootElement.getName()); // element(name): 获取一个指定名称的子元素 // System.out.println(rootElement.element("name")); // elements(): 获取所有子元素 // System.out.println(rootElement.elements()); // elements(name): 获取所有指定名称的子元素 // System.out.println(rootElement.elements("name")); ArrayList<Contact> contactList = new ArrayList<>(); List<Element> elementList = rootElement.elements("contact"); for (Element e : elementList) { // attributeValue(属性名): 通过属性名得到属性值 // System.out.println(e.getName()); String strid = e.attributeValue("id"); String strvip = e.attributeValue("vip"); // elementText(子元素): 得到子元素的文本 String name = e.elementText("name"); String gender = e.elementText("gender"); String email = e.elementText("email"); int id = Integer.parseInt(strid); boolean vip = Boolean.parseBoolean(strid); // 将数据保存到Contact对象中 Contact con = new Contact(id, vip, name, gender, email); // 将对象保存到集合中 contactList.add(con); } contactList.forEach(System.out::println); }
XPath
概述:
XPath使用路径表达式来选取XML文档中的元素节点或属性节点。节点是通过沿着路径 (path) 来选取的
Document中和XPath相关API
Node selectSingleNode(“XPath表达式”) 获取符合表达式的唯一元素
List
selectNodes(“XPath表达式”) 获取符合表达式的元素集合 绝对路径
/根元素/子元素/孙元素 从根元素开始,一级一级向下查找,不能跨级
相对路径
./子元素/孙元素 从当前元素开始,一级一级向下查找,不能跨级
全文搜索
//元素 找元素,无论元素在哪里,可以跳级
//元素/子元素 找contact,无论在哪一级,但name一定是contact的子节点
属性查找
//@属性名 查找属性对象,无论是哪个元素,只要有这个属性即可。
- //元素[@属性名] 查找元素对象,全文搜索指定元素名和属性名。
//元素[@属性名=’值’] 查找元素对象,全文搜索指定元素名和属性名,并且属性值相等。 :::
public class Demo02 { // 定义Document类型的成员变量 public static Document document; // 在所有测试方法前执行一次给document赋值 @BeforeClass public static void init() { //解析XML SAXReader reader = new SAXReader(); try { //单元测试运行,相对路径不需要写模块名 document = reader.read(new File("src\\Contact.xml")); } catch (DocumentException e) { e.printStackTrace(); } } // XPath:绝对路径 @Test public void test01() { // 定义 XPath 表达式:/contactList/contact/name // 调用Document对象的selectNodes()方法执行XPath获得节点 List<Node> nodes = document.selectNodes("/contactList/contact/name"); for (Node node : nodes) { System.out.println(node.getName() + " : " + node.getText()); } } // XPath:相对路径, 以调selectNodes方法用者作为参照往后找 @Test public void test02() { // 获得根节点对象 // 定义 XPath 表达式:./contact/email Element rootElement = document.getRootElement(); // 调用Document对象的selectNodes()方法执行XPath获得节点 List<Node> nodes = rootElement.selectNodes("./contact/email"); for (Node node : nodes) { System.out.println(node.getName() + " : " + node.getText()); } } // XPath:全文搜索 @Test public void test03() { // 创建XPath表达式: //name // 调用Document对象的selectNodes()方法执行XPath获得节点 List<Node> nodes = document.selectNodes("//name"); for (Node node : nodes) { System.out.println(node.getName() + " : " + node.getText()); } } // XPath:属性查找 //@属性名 全文搜索属性,返回的是属性对象 @Test public void test04() { // 创建XPath表达式: //@id 获取所有的id属性 // 调用Document对象的selectNodes()方法执行XPath获得节点 List<Node> nodes = document.selectNodes("//@id"); for (Node node : nodes) { System.out.println(node.getName() + " : " + node.getText()); } } // XPath:属性查找 //元素[@属性名] 查找具有指定属性名的元素 @Test public void test05() { // 创建XPath表达式: //contact[@id] 获取包含id属性的contact元素 // 调用Document对象的selectNodes()方法执行XPath获得节点 List<Node> nodes = document.selectNodes("//contact[@vip = 'true']"); for (Node node : nodes) { System.out.println(node.getName() + " : " + node.getText()); } } }
工厂设计模式(Factory Pattern)
概述:
工厂设计模式是 Java 中最常用的设计模式之一。简单工厂模式用于创建对象的。通过专门定义一个类来负责创建其他类的实例
工厂模式作用
解决类与类之间的耦合问题,屏蔽了外界对具体类的依赖,让类的创建更加简单 ::: ```java public static void main(String[] args) { // 使用工厂类创建汽车(通过工厂类创建对象,我们主要是使用对象) Car c3 = CarFactory.createCar(1); c3.run(); Car c4 = CarFactory.createCar(2); c4.run(); }
public class CarFactory { public static Car createCar(int type) { if (type == 1) { return new Benz(); } else if (type == 2) { return new Bmw(); } else { return null; } } }
public interface Car { public abstract void run(); }
public class Bmw implements Car { @Override public void run() { System.out.println(“宝马飞快的跑”); } }
public class Benz implements Car { @Override public void run() { System.out.println(“奔驰飞快的奔驰!”); } }
<a name="Er0ok"></a>
### 动态代理
:::tips
<a name="h1aeJ"></a>
#### proxy类
1. public static Object newProxyInstance(
1. ClassLoader loader,
1. Class<?>[ ] interfaces,
1. InvocationHandler h
1. )
ClassLoader loader: 类加载器, 固定写法 类名.class.getClassLoader()<br />Class<?>[ ] interfaces: 多个接口, 代理对象会实现这些接口<br />InvocationHandler h: 执行处理器接口, 放入匿名内部类
<a name="ibpVv"></a>
#### 动态代理的好处
- 可以在不改变方法源码的情况下,实现对方法功能的增强
- 简化了代码
- 提高了软件系统的可扩展性。
:::
```java
public class Demo041 {
public static void main(String[] args) {
//创建真实对象
CXK cxk = new CXK();
//创建代理对象
//使用动态代理API创建代理对象,创建代理对象会实现传入star接口
Star agency = (Star) Proxy.newProxyInstance(
Demo041.class.getClassLoader(),
new Class[]{Star.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//Object proxy:代理对象,不用理会
//Method method:代理对象调用的方法
//Object[] args:代理对象调用方法是传入的参数
System.out.println("练习时长俩年半");
System.out.println("签署合同");
//在代理方法invoke中对功能进行增强
//调用真实对象功能
Object ret = method.invoke(cxk, args);
System.out.println("结尾款\n");
return ret;
}
}
);
agency.sing("鸡你太美");
agency.dance();
agency.filmer();
}
}