需要学会什么?
XML概述:
XML是可扩展标记语言(eXtensible Markup Language)的缩写,它是一种数据表示格式,可以藐视非常复杂的数据结构,常用于传输和存储数据。
<note>
<to>Toveto>
<from>Janifrom>
<heading>Reminderheading>
<body>Don't forget me this weekend!body>
note>
XML的几个特点和使用场景:
总结:
XML的创建:
XML的语法规则:
XML文件的后缀名为:xml
文档声明必须是第一行。
XML的标签(元素)规则:
标签由一对尖括号和合法标识符组成:必须存一个根标签,有且只能有一个。
标签必须成对出现,又开始和结束:
特殊的标签可以不成对,但是必须有结束标记,如:
标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来
标签需要正确的嵌套。
<student>
<name>花千骨name>
<sex>女sex>
<hobby>修仙hobby>
<info>
<address>花莲村address>
<age>16age>
info>
student>
XML的其他组成:
XML文件中可以定义注释信息:
XML文件中可以存在以下特殊字符:
< < 小于
> > 大于
& & 和号
' ' 单引号
" " 双引号
XML文件中可以存在CDATA区:
<student>
<name>花千骨name>
<sex>女sex>
<hobby>修仙hobby>
<info>
<address>花莲村address>
<age>16age>
info>
<sql>
select * from user where age < 18;
sql>
student>
什么是文档约束?
文档约束的分类:
案例:XML文档约束-DTD的使用。
需求:
分析:
编写DTD约束文档,后缀必须是.dtd。
在需要编写的XML文件中导入该DTD约束文档。
按照约束的规定编写XML文件的内容。
data.dtd
hello_world_dtd.xml
DOCTYPE 书架 SYSTEM "data.dtd">
<书架>
<书>
<书名>一往无前书名>
<作者>范海涛作者>
<售价>78售价>
书>
书架>
总结:
文档约束-schema:
案例:XML文档约束-schema的使用。
需求:
分析:
data.xsd
hello_world_schema.xml
<书架 xmlns="http://www.javase.cn">
<书>
<书名>一往无前书名>
<作者>范海涛作者>
<售价>78售价>
书>
书架>
总结:
XML的数据的作用是什么?最终需要怎么处理?
什么是XML解析?
DOM常见的解析工具:
| 名称 | 说明 |
|---|---|
| JAXP | SUM公司提供的一套XML的解析API。 |
| JDOM | JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。 |
| dom4j | 是JDOM的升级品,用来读写XML文件的。具有性能优异、功能强大和极易使用的特点,它得到性能超过SUN公司官方的DOM技术,同时它也是一个开源代码的软件,Hibernate也用它来读写配置文件。 |
| jsoup | 功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便。 |
DOM解析文档对象模型:
<students>
<student id="1">
<name>花千骨name>
<age>16age>
student>
<student id="2">
<name>轻水name>
<age>17age>
student>
students>
dom4j解析XML得到Document对象:
SAXReader类:
| 构造器/方法 | 说明 |
|---|---|
| public SAXReader() | 创建Dom4J的解析器对象。 |
| Document read(String url) | 加载XML文档成为Document对象。 |
Document类:
| 方法名 | 说明 |
|---|---|
| Element getRootElement() | 获取根元素对象。 |
使用dom4j解析出XML文件。
需求:
分析:
students.xml
<students>
<student id="1">
<name>花千骨name>
<age>16age>
student>
<student id="2">
<name>轻水name>
<age>17age>
student>
students>
Dom4jDemo.java
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.Test;
import java.io.InputStream;
/**
* 目标: 学会使用dom4j解析XML文件中的数据.
* 1. 导入dom4j框架.
* 2.准备一个XML文件
*/
public class Dom4jDemo {
@Test
public void parseXMLData() throws Exception {
// 1.创建一个dom4j的解析器对象 代表了整个dom4j框架
SAXReader saxReader = new SAXReader();
// 2.把XML文件加载到内存中成为一个Document文档对象
// getResourceAsStream中 / 是直接去src下寻找文件
InputStream inputStream = Dom4jDemo.class.getResourceAsStream("/students.xml");
Document document = saxReader.read(inputStream);
// 3.获取根元素
Element root = document.getRootElement();
// students
System.out.println(root.getName());
}
}
Dom4j解析XML的元素、属性、文本:
| 方法名 | 说明 |
|---|---|
| List elements() | 得到当前元素下所有子元素。 |
| List elements(String name) | 得到当前元素下制定名字的子元素返回集合。 |
| Element element(String name) | 得到当前元素下指定名字的子元素,如果有很多名字相同的返回第一个。 |
| String getName() | 得到元素名字。 |
| String attributeValue(String name) | 通过属性名直接得到属性值。 |
| String elementText(子元素名) | 得到指定名称的子元素的文本。 |
| String getText() | 得到文本。 |
案例:XML解析案例。
需求:
students.xml
<students>
<student id="1">
<name>花千骨name>
<age>16age>
<sex>女sex>
<email>hqg@changliu.comemail>
student>
<student id="2">
<name>轻水name>
<age>17age>
<sex>女sex>
<email>qs@changliu.comemail>
student>
<student id="3">
<name>孟玄朗name>
<age>20age>
<sex>男sex>
<email>mxl@changliu.comemail>
student>
students>
Student.java
public class Student {
private int id;
private String name;
private int age;
private char sex;
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Student() {
}
public Student(int id, String name, int age, char sex, String email) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.email = email;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", email='" + email + '\'' +
'}';
}
}
Dom4jDemo.java
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
/**
* 需求: 解析XML中的数据成为一个List集合对象
*/
public class Dom4jDemo {
@Test
public void parseToList() throws Exception {
// 1.创建一个dom4j的解析器对象 代表了整个dom4j框架
SAXReader saxReader = new SAXReader();
// 2.把XML文件加载到内存中成为一个Document文档对象
Document document = saxReader.read(Dom4jDemo.class.getResourceAsStream("/students.xml"));
// 3.获取根元素
Element root = document.getRootElement();
// 4.获取students子元素
List<Element> elements = root.elements("student");
// 5.准备一个ArrayList集合封装联系人信息
List<Student> studentArrayList = new ArrayList<>();
// 6.遍历students子元素
for (Element element : elements) {
// 创建Student对象
Student student = new Student();
student.setId(Integer.parseInt(element.attributeValue("id")));
student.setName(element.elementTextTrim("name"));
student.setSex(element.elementTextTrim("sex").charAt(0));
student.setEmail(element.elementText("email"));
// Student对象加入到List集合中
studentArrayList.add(student);
}
// 7.遍历List集合
for (Student student : studentArrayList) {
System.out.println(student);
}
}
}
执行结果:
Student{id=1, name='花千骨', age=0, sex=女, email='hqg@changliu.com'}
Student{id=2, name='轻水', age=0, sex=女, email='qs@changliu.com'}
Student{id=3, name='孟玄朗', age=0, sex=男, email='mxl@changliu.com'}
如果需要从XML中检索需要的某个信息怎么解决?
XPath介绍:
XPath的四大检索方案:
绝对路径:采用绝对路径获取从根节点开始逐层的查找节点列表并打印信息。
| 方法名 | 说明 |
|---|---|
| /根元素/子元素/孙元素 | 从根元素开始,一级一级向下查找,不能跨级。 |
相对路径:先得到students根节点,然后向下一级student节点的name子节点并打印信息。
| 方法名 | 说明 |
|---|---|
| ./子元素/孙元素 | 从当前元素开始,一级一级向下查找,不能跨级。 |
全文检索:直接全文搜索所有的name元素并打印。
| 方法名 | 说明 |
|---|---|
| //元素 | 在全文找这个元素。 |
| //元素1/元素2 | 在全文找元素1下面的一级元素2 |
| //元素1//元素2 | 在全文找元素1下面的全部元素2 |
属性查找:在全文中搜索属性,或者带属性的元素。
| 方法名 | 说明 |
|---|---|
| //@属性名 | 查找属性对象,无论是哪个元素,只要有这个属性即可。 |
| //元素[@属性名] | 查找元素对象,全文搜索指定元素名和属性名。 |
| //元素[@属性名=值] | 查找元素对象,全文搜索指定元素名和属性名,并且属性值相等。 |
案例:使用XPath检索出XML文件。
需求:
分析:
下载jaxen-x.x.x.jar https://search.maven.org/artifact/jaxen/jaxen/1.2.0/bundle
导入jar包(dom4j和jaxen),XPath技术依赖dom4j技术。
通过dom4j的SAXReader获取Document对象。
利用XPath提供的API,结合XPath的语法完成选取XML文档元素节点进行解析操作。
Document中与XPath相关的API如下:
| 方法名 | 说明 |
|---|---|
| Node selectSingleNode(“表达式”) | 获取符合表达式的唯一元素。 |
| List selectNodes(“表达式”) | 获取符合表达式的元素集合。 |
students.xml
<students>
<student id="1">
<name id="111">花千骨name>
<age>16age>
<sex>女sex>
<email>hqg@changliu.comemail>
student>
<student id="2">
<name>轻水name>
<age>17age>
<sex>女sex>
<email>qs@changliu.comemail>
student>
<student id="3">
<name>孟玄朗name>
<age>20age>
<sex>男sex>
<email>mxl@changliu.comemail>
student>
students>
XPathDemoTest.java
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.Test;
import java.util.List;
public class XPathDemoTest {
/**
* 1.绝对路径: /根元素/子元素/子元素.
*/
@Test
public void parse1() throws Exception {
// a.创建解析器对象
SAXReader saxReader = new SAXReader();
// b.把XML加载成Document文档对象
Document document = saxReader.read(XPathDemoTest.class.getResourceAsStream("/students.xml"));
// c.检索全部姓名
List<Node> nameNodes = document.selectNodes("/students/student/name");
for (Node nameNode : nameNodes) {
Element element = (Element) nameNode;
// 花千骨
// 轻水
// 孟玄朗
System.out.println(element.getTextTrim());
}
}
/**
* 2.相对路径: ./子元素/子元素
* '.' 代表当前元素
*/
@Test
public void parse2() throws Exception {
// a.创建解析器对象
SAXReader saxReader = new SAXReader();
// b.把XML加载成Document文档对象
Document document = saxReader.read(XPathDemoTest.class.getResourceAsStream("/students.xml"));
// c.获取根元素 students
Element root = document.getRootElement();
// d.检索全部姓名
List<Node> nameNodes = root.selectNodes("./student/name");
for (Node nameNode : nameNodes) {
Element element = (Element) nameNode;
// 花千骨
// 轻水
// 孟玄朗
System.out.println(element.getTextTrim());
}
}
/**
* 3.全文检索:
* //元素 在全文找这个元素
* //元素1/元素2 在全文找元素1下面的一级元素2
* //元素1//元素2 在全文找元素1下面的全部元素2
*/
@Test
public void parse3() throws Exception {
// a.创建解析器对象
SAXReader saxReader = new SAXReader();
// b.把XML加载成Document文档对象
Document document = saxReader.read(XPathDemoTest.class.getResourceAsStream("/students.xml"));
// c.检索全部姓名
// List nameNodes = document.selectNodes("//name");
// List nameNodes = document.selectNodes("//students/name");
List<Node> nameNodes = document.selectNodes("//students//name");
for (Node nameNode : nameNodes) {
Element element = (Element) nameNode;
// 花千骨
// 轻水
// 孟玄朗
System.out.println(element.getTextTrim());
}
}
/**
* 4.属性查找:
* //@属性名称 在全文检索属性对象
* //元素[@属性名称] 在全文检索包含该属性的元素对象
* //元素[@属性名称=值] 在全文检索包含该属性的元素且属性值为该值的元素对象
*/
@Test
public void parse4() throws Exception {
// a.创建解析器对象
SAXReader saxReader = new SAXReader();
// b.把XML加载成Document文档对象
Document document = saxReader.read(XPathDemoTest.class.getResourceAsStream("/students.xml"));
// c.检索包含id属性
List<Node> nameNodes = document.selectNodes("//@id");
for (Node nameNode : nameNodes) {
Attribute attribute = (Attribute) nameNode;
// id==>1
// id==>111
// id==>2
// id==>3
System.out.println(attribute.getName() + "==>" + attribute.getValue());
}
// 查找包含id属性的name元素
// Node nameNode = document.selectSingleNode("//name[@id]");
Node nameNode = document.selectSingleNode("//name[@id=111]");
Element nameElement = (Element) nameNode;
// 花千骨
System.out.println(nameElement.getTextTrim());
}
}
什么是工厂设计模式?
工厂设计模式的作用:
Computer.java
/**
* 电脑类
*/
public abstract class Computer {
private String name;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Computer() {
}
public Computer(String name, double price) {
this.name = name;
this.price = price;
}
public abstract void start();
}
Mac.java
/**
* Mac电脑类
*/
public class Mac extends Computer{
/**
* 开机
*/
@Override
public void start() {
System.out.println(getName() + "开机,展示苹果Logo!");
}
}
Dell.java
/**
* Dell电脑
*/
public class Dell extends Computer{
/**
* 开机
*/
@Override
public void start() {
System.out.println(getName() + "开机,并展示戴尔Logo!");
}
}
FactoryPattern.java
package com.javase.factorydemo;
/**
* 工厂模式
*/
public class FactoryPattern {
/**
* 创建对象返回
*/
public static Computer createComputer(String info) {
switch (info) {
case "Mac":
Computer mac = new Mac();
mac.setName("Macbook Pro M1 Pro");
mac.setPrice(14899);
return mac;
case "Dell":
Computer dell = new Dell();
dell.setName("Dell 灵越 16 Plus");
dell.setPrice(16298.98);
return dell;
default:
return null;
}
}
}
总结:
工厂设计模式的作用:
什么是装饰设计模式?
装饰设计模式的作用:
作用:装饰模式指的是在不改变原类的基础上,动态地扩展一个类的功能。
InputStream(抽象父类)
FileInputStream(实现子类,读写性能较差)
BufferedInputStream(实现子类,装饰类,读写性能高)
步骤:
InputStream.java
/**
* 共同父类
*/
public abstract class InputStream {
public abstract int read();
public abstract int read(byte[] bytes);
}
FileInputStream.java
import java.util.Arrays;
/**
* 原始类
*/
public class FileInputStream extends InputStream {
@Override
public int read() {
System.out.println("低性能的方式读取了一个字节a");
return 97;
}
@Override
public int read(byte[] bytes) {
bytes[0] = 97;
bytes[1] = 98;
bytes[2] = 99;
System.out.println("低性能的方式读取了一个字节数组" + Arrays.toString(bytes));
return 3;
}
}
BufferedInputStream.java
/**
* 装饰类
*/
public class BufferedInputStream extends InputStream{
private InputStream inputStream;
public BufferedInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public int read() {
System.out.println("提供8KB的缓冲区,提高读数据性能!");
return inputStream.read();
}
@Override
public int read(byte[] bytes) {
System.out.println("提供8KB的缓冲区,提高读数据性能!");
return inputStream.read(bytes);
}
}
DecoratorPattern.java
public class DecoratorPattern {
public static void main(String[] args) {
InputStream inputStream = new BufferedInputStream(new FileInputStream());
System.out.println(inputStream.read());
System.out.println(inputStream.read(new byte[3]));
}
}
执行结果:
提供8KB的缓冲区,提高读数据性能!
低性能的方式读取了一个字节a
97
提供8KB的缓冲区,提高读数据性能!
低性能的方式读取了一个字节数组[97, 98, 99]
3
总结: