学习目标
1.能够说出XML的作用
2.了解XML的组成元素
3.能够说出有哪些XML约束技术
4.能够说出解析XML文档DOM方式原理
5.熟悉Document对象常用方法
6.能够使用xpath解析XML或HTML文档
一,XML入门【熟悉】
可以完成一个xml编写
1.xml概述
- HTML : 超文本标记语言 , html提供一组固定的标签. < a>
- XML : 可扩展标记语言, 标签可以自定义的
2.xml和html区别
-
html所有标签都是预定义的,xml所有标签都是自定义的
-
html语法松散,xml语法严格,区分大小写
-
html做页面展示,xml描述数据
3.xml作用
-
作为配置文件。
-
存储数据。
-
用来传输数据.
-
描述数据
4.xml语法规范
- xml以xml文件的形式存在,扩展名为xml. 例如: users.xml
4.1文档声明
<?xml version = "1.0" encoding = "utf-8" standalone="yes" ?>
- 必须写在xml文档的第一行第一列
- 写法:<?xml version="1.0" ?>
- 属性:
- version:版本号 固定值 1.0
- encoding:指定文档的码表。默认值为 iso-8859-1
- standalone:指定文档是否独立 yes 或 no(了解)
4.2元素:xml文档中的标签
- 文档中必须有且只能有一个根元素,其他标签都是这个根标签的子标签或孙标签
- 元素需要正确闭合
- 包含标签主体:somecontent
- 不含标签主体:
- 元素需要正确嵌套,不允许有交叉嵌套。
- 元素名称要遵守
- 元素名称区分大小写
- 数字不能开头 , 字母开头, _开头, 不建议"XML"开头
- 标签之间不能有空格,特殊字符(冒号 : )
4.3属性
- 属性值必须用引号引起来。单双引号都行
- 在一个标签里面属性不能重复
4.4注释
语法<!-- 注释的内容-->
快捷键: Ctrl+Shift+/
- 文档声明前面不能有注释
- 注释不能嵌套
4.5特殊字符和CDATA区
1.在 XML 中有 5 个预定义的实体引用:
必须记忆一个
& jdbc:mysql://localhost:3306/day18_db?k=v&k2=v2
---
<
>
2.CDATA 内部的所有东西都会被解析器忽略,当做文本
语法:<![CDATA[ 内容 ] ]>
<!>
<![]>
<![[]]>
<![CDATA[ ... ]]>
二,xml约束【了解】
可以根据约束文档写出xml文档
1.xml约束概述
-
约束就是xml的书写规则, (别人(框架)提供模板)
-
约束文档定义了在XML中允许出现的元素(标签)名称、属性及元素(标签)出现的顺序等等。
-
常见约束技术:
- DTD : 老约束文档 , 使用框架有 MyBatis
- Schema : 新约束文档, 使用框架有 Spring / JavaWEB
2.常用约束分类
2.1dtd约束
2.1.1 引入方式
- 内部引入
<!DOCTYPE 根元素 [元素声明]>
- 外部引入; dtd是一个独立的文件 .dtd
- 本地DTD
<!DOCTYPE 根元素 SYSTEM "文件名"> ``` - 网络DTD
<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文档的URL">
2.1.2语法
- 元素:<!ELEMENT 元素名称 元素组成>
- 元素组成:EMPTY,ANY ,(子元素) ,(#PCDATA)
- PCDATA 就是字符串
- 如果出现子元素:
? (出现0次或1次),
* (出现0次或多次),
+ (出现1次或多次) 表示子元素出现的个数.
| 或者(只能出现一个)
, 代表子元素出现必须按照顺序
- 属性<!ATTLIST 元素名称 属性名称 属性类型 属性使用规则>
-
属性类型: ID,枚举,CDATA
-
使用规则: #REQUIRED:属性值是必需的
#IMPLIED :属性不是必需的 (可选)
#FIXED value:属性值是固定的ID使用:字母开头
CDATA : 字符
2.2schema
2.2.1 dtd和schema的区别
-
XML Schema约束符合XML语法结构。
-
DOM、SAX等XML API很容易解析出XML Schema文档中的内容。
-
XML Schema对名称空间支持得非常好。
- 就是给自己起个名,方便进行标识.
- table 表格/桌子/人名 等
<html:table> </html:table> <life:table> <!--桌子--> </life:table>
-
XML Schema比XML DTD支持更多的数据类型,并支持用户自定义新的数据类型。
-
XMLSchema定义约束的能力非常强大,可以对XML实例文档作出细致的语义限制。
-
但Xml Schema现在已是w3c组织的标准,它正逐步取代DTD。
-
XMLSchema不能像DTD一样定义实体,比DTD更复杂,
2.2.1根据schema约束写xml文件步骤
- 查出Schema文档,找出根元素
- 根元素来自哪个名称空间
- 这个名称空间和哪个xsd文件对应(指定约束的路径)
- schemaLocation不是关键字,来自一个标准的名称空间
三,XML解析【掌握】
解析使用的XML不能有约束
1.xml解析方式
1.1DOM解析
将xml文档加载到内存,形成一颗dom树(document对象),将文档的各个组成部封装为一些对象。
优点: 因为,在内存中会形成dom树,可以对dom树进行增删改查。
缺点: 如果xml文件太大, dom树非常占内存,解析速度慢 , 可能会发生内存溢出。
==Document==:文档节点
==Element==:元素(标签)节点
Text:文本节点
Attribute:属性节点
Comment:注释节点
1.2SAX解析
逐行读取,基于事件(函数或者方法)驱动
优点:内存占用很小,速度快
缺点:只能读取,不能回写
2.常用xml解析器(jar包)
JAXP:sun公司提供的解析。支持dom和sax。
JDOM
DOM4J:document for java 民间方式,但是是事实方式。非常好。 支持dom和sax.
JSOUP: 爬虫, 解析html
3.Dom4J的使用【重点】
3.1使用步骤
- 导入jar包 dom4j-1.6.1j.jar
- 创建解析器
SAXReader reader = new SAXReader(); - 读取xml 获得document对象
Document document = reader.read(xml对应的流) - 得到根元素
Element rootElement = document.getRootElement();
3.2常见的API
- List<Element> list=element.elements(); 获取所有子元素节点
- element.attributeValue("属性名")或者element.attribute("属性名").getValue(); 获取节点属性的值
- element.getText(); 获得节点的文本值
3.3示例代码
- xml(把xml放在src目录下, 方便读取)
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="b1">
<name>四十二章经</name>
<autor>不详</autor>
<price>10000</price>
</book>
<book id="b2">
<name>葵花宝典</name>
<autor>小李子</autor>
<price>8888</price>
</book>
<apple>
<name>苹果</name>
</apple>
</books>
- Dom4JDemo
public class Dom4JDemo {
@Test
//步骤
public void fun01() throws Exception {
//1. 创建SaxReader对象
SAXReader saxReader = new SAXReader();
//2. 读取需要解析的xml文件, 获得文档对象
InputStream is = Dom4JDemo.class.getClassLoader().getResourceAsStream("books.xml");
Document document = saxReader.read(is);
//3. 获得根元素 books
Element rootElement = document.getRootElement();
}
// 获得第一本书id的属性值 b1
@Test
public void fun02() throws Exception {
//1. 创建SaxReader对象
SAXReader saxReader = new SAXReader();
//2. 读取需要解析的xml文件, 获得文档对象
InputStream is = Dom4JDemo.class.getClassLoader().getResourceAsStream("books.xml");
Document document = saxReader.read(is);
//3. 获得根元素 books
Element rootElement = document.getRootElement();
//4. 获得根元素(books)所有的 子标签
List<Element> elements = rootElement.elements();
//5. 获得第一本book(第一个孩子)
Element bookEle = elements.get(0);
//6.获得获得第一本书id的属性值
String id = bookEle.attributeValue("id");
System.out.println(id);
is.close();
}
//获得第二本书 书的名字 葵花宝典
@Test
public void fun03() throws Exception {
//1. 创建SaxReader对象
SAXReader saxReader = new SAXReader();
//2. 读取需要解析的xml文件, 获得文档对象
InputStream is = Dom4JDemo.class.getClassLoader().getResourceAsStream("books.xml");
Document document = saxReader.read(is);
//3. 获得根元素 books
Element rootElement = document.getRootElement();
//4.获得第二本数
Element bookEle = (Element) rootElement.elements().get(1);
//5. 获得第二本书 标签里面的name标签(第一个孩子)
Element nameEle = (Element) bookEle.elements().get(0);
//6. 获得name标签里面的文本
System.out.println(nameEle.getText());
is.close();
}
}
4.XPath的使用,基于dom4J【掌握】
4.1介绍
Xpath定义了一种规则,专门用于查询xml, 可以认为xpath是dom4J的扩展
4.2使用步骤
- 导入jar包 jaxen…jar(当前资料里是: jaxen-1.1-beta-6.jar) 注意: 两个(dom4j的jar包和xpath的jar包)
- 创建解析器
SAXReader reader = new SAXReader(); - 解析xml 获得document对象
Document document = reader.read(is);
4.3常见的API
- document.selectSingleNode(“xpath语法”); 获得一个节点(标签,元素)
- document.selectNodes(“xpath语法”); 获得多个节点(标签,元素)
4.4 xpath 语法
4.5示例代码
public class XpathDemo {
@Test
//环境准备
public void fun01() throws Exception{
//1. 创建解析器对象
SAXReader saxReader = new SAXReader();
//2. 读取要解析的xml文件, 得到document
InputStream is = Dom4JDemo.class.getClassLoader().getResourceAsStream("books.xml");
Document document = saxReader.read(is);
//3. 根据xpath, 获得标签
//获得一个
document.selectSingleNode("xpath语法");
//获得多个
document.selectNodes("xpath语法");
}
@Test
//获得apple标签里面name标签的值 苹果
public void fun02() throws Exception{
//1. 创建解析器对象
SAXReader saxReader = new SAXReader();
//2. 读取要解析的xml文件, 得到document
InputStream is = Dom4JDemo.class.getClassLoader().getResourceAsStream("books.xml");
Document document = saxReader.read(is);
//3. 根据xpath, 获得标签
Element nameEle = (Element) document.selectSingleNode("/books/apple/name");
//4. 获得值
System.out.println(nameEle.getText());
}
@Test
//获得apple标签里面name标签的值 苹果
public void fun03() throws Exception{
//1. 创建解析器对象
SAXReader saxReader = new SAXReader();
//2. 读取要解析的xml文件, 得到document
InputStream is = Dom4JDemo.class.getClassLoader().getResourceAsStream("books.xml");
Document document = saxReader.read(is);
//3. 根据xpath, 获得标签
Element nameEle = (Element) document.selectSingleNode("//apple/name");
//4. 获得值
System.out.println(nameEle.getText());
}
@Test
//获得第一本书的 id属性值 b1
public void fun04() throws Exception{
Class clazz = Class.forName("");
//1. 创建解析器对象
SAXReader saxReader = new SAXReader();
//2. 读取要解析的xml文件, 得到document
InputStream is = Dom4JDemo.class.getClassLoader().getResourceAsStream("books.xml");
Document document = saxReader.read(is);
//3. 根据xpath, 获得标签
Element booEle = (Element) document.selectSingleNode("//book[1]");
//4. 获得id的属性值
System.out.println(booEle.attributeValue("id"));
}
}
四,动态代理
对目标类进行增强
- 装饰者设计模式 : 最指定接口进行增强. 可以对一组内容进行增强. new 增强类 ( 参数 )
- 增强的类就是改造厂,可以改造任意车.
- 代理 : 对指定类(1个)进行增强.
1.代理模式概述
1.1什么是代理模式
ProxyPattern(即:代理模式),23种常用的面向对象软件的设计模式之一
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
作用:增强一个类中的某个方法.对程序进行扩展. Spring框架中AOP.
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201031104222195.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MTk4NzIz,size_16,color_FFFFFF,t_70#pic_center)
1.2动态代理介绍
动态代理它可以直接给某一个目标(被代理 对象)对象(实现了某个或者某些接口)生成一个代理对象,而不需要代理类存在。
动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一个代理对象。
- 动态代理的分类
jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象
spring中动态代理:cglib (后面会讲)
2.jdk中的动态代理的使用
2.1API介绍
Java.lang.reflect.Proxy类可以直接生成一个代理对象
- Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一个代理对象
- 参数1:ClassLoader loader 代理对象的类加载器 一般使用被代理对象的类加载器
- 参数2:Class<?>[] interfaces 代理对象的要实现的接口 一般使用的被代理对象实现的接口
- 参数3:InvocationHandler h (接口)执行处理类
- InvocationHandler中的invoke(Object proxy, Method method, Object[] args)方法:调用代理类的任何方法,此方法都会执行
- 参数3.1:代理对象(慎用)
- 参数3.2:当前执行的方法
- 参数3.3:当前执行的方法运行时传递过来的参数
- 返回值:当前方法执行的返回值
2.2代码实现
package com.lin.proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.junit.Test;
public class Demo01 {
@Test
public void fun01(){
final Qq qq = new Qq();
Car car = (Car) Proxy.newProxyInstance(qq.getClass().getClassLoader(), qq.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("run".equals(method.getName())){
System.out.println("QQ加了鸡血可以跑100迈...");
return null;
}
Object result = method.invoke(qq, args);
System.out.println("result="+result);
return "哈哈哈";
}
});
//car.run();
String str = car.addOil(93);
System.out.println("str="+str);
}
interface Car{
void run();
void stop();
String addOil(int num);
}
class Qq implements Car{
@Override
public void run() {
System.out.println("Qq可以跑60迈...");
}
@Override
public void stop() {
System.out.println("Qq刹车....");
}
@Override
public String addOil(int num) {
return "qq加"+num+"号油...";
}
}
}