XML(eXtensible Markup Language)

:::tips

概述

  • 是一种可扩展的标记语言
  • XML被设计用来存储和传输数据

    XML常见组成

  • 文档声明(声明在XML第一行)

    • <?xml version=”1.0” encoding=”UTF-8” ?>
    • version:版本号(必须存在)
    • encoding:文件编码
  • 注释
    • 快捷键:ctrl + /
  • 标签
    • 标签由一对尖括号和合法标识符组成
    • 有内容的标签必须成对出现
    • 没有内容的标签可以提前结束
  • 属性
    • 标签中可以定义属性
    • 属性值必须用引号引起来
  • 实体字符/转义字符
    • < ⁢
    • >

    • “ "
    • ‘ '
    • & &
  • 字符数据区

    • <![CDATA[ 内容 ]]>
    • 快捷键 CD :::

      1. <?xml version="1.0" encoding="UTF-8" ?>
      2. <!--这是注释-->
      3. <persons>
      4. <person id = "1">
      5. <name>张三</name>
      6. <age>23</age>
      7. <address>北京</address>
      8. <note/>
      9. </person>
      10. <person id="2">
      11. <name>李四</name>
      12. <age>24</age>
      13. <address>上海</address>
      14. <message>
      15. <![CDATA[
      16. <<"李四来自天津">>
      17. ]]>
      18. </message>
      19. </person>
      20. </persons>

      DTD约束(不能验证数据类型)

      :::tips

      XML的标签和属性可以随意扩展,通过XML约束来限定XML文件中可使用的标签以及属性

      导入DTD文件的两种格式

  • <!DOCTYPE 根元素 SYSTEM “DTD文件路径”> 本地的约束

  • <!DOCTYPE 根元素 PUBLIC “文件描述” “DTD文件路径”> 网络上的约束 ::: ```xml <?xml version=”1.0” encoding=”UTF-8” ?>

<!DOCTYPE books SYSTEM “bookshelf.dtd”>

Java从入门到入土 99 高司令

<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约束

:::tips

概述

  • Schema 功能更强大,数据类型约束更完善
  • Schema文件本身也是XML文件
  • 一个XML中可以引用多个Schema约束文件

    Schema约束格式

  1. <根标签
  2. xmlns=”命名空间”
  3. xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
  4. xsi:schemaLocation=”命名空间 schema约束文件名”>
  5. </根标签>
    ::: ```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

:::tips

DOM解析

  • 一次性读取XML中的所有数据,在内存中形成一颗DOM树

    dom4j解析XML-得到Document对象

  • SAXReader对象

    • SAXReader() 创建解析器
    • Document read(File url) 解析XML文档
  • Document对象

    • Element getRootElement() 获得根元素

      操作Element

      Element表示XML中的元素对象
  • 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

    :::tips

    概述:

  • 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)

    :::tips

    概述:

  • 工厂设计模式是 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();
    }
}