XML
Extensible Market Language 可扩展标记语言
- XML是特殊文件形式,结构化文件
- 做数据保存
- 做信息交互和共享的(重点,数据传输)
- 做系统的配置文件数据
XML作用
- 数据交换:不同的计算机语言之间,不同的操作系统之间,不同的数据库之间,进行数据交换
-
配置文件:在后期我们主要用于各种框架的配置文件
com.zimo.jdbc.Driver jdbc:mysql://localhost:3306/test root 123456
XML的特点
- 用于数据交互,用于数据的存储,用于做系统的配置文件
- 区分大小写
- 非常严谨,只要有错误,解析器就不能解析
- 可以扩展的,所有的标签都是程序员自己创建出来
- XML文件的后缀为.xml
注意:XML以后通过Java来进行解析,很少直接在浏览器上显示
XML由七种组成元素构成:
-
声明(抬头):必须在第一行
version:指定XML文件使用的版本,取值是1.0
encoding:当前xml使用的编码(字符集)
standalone:指定当前这个XML文件是否是一个独立的文件,省略的,默认是独立文件
-
元素(标签)
语法:
开头 内容 结尾
主体部分:标签分为有主体和没有主体的两种,如果没有主题,标签一定要结束
大小写:区分大小写
命名:不能由空格,不能有冒号
根元素:有且只有一个根元素
-
属性
例如:
注释
实体字符
CDATA字符数据区
处理指令
zimo
18
select * from student where age > 18 && age < 30;
18 && age < 30;
]]>
版本说明
w3c在1988年2月发布1.0版本,2004年2月发布1.1版本,因为1.1不能向下兼容1.0版本,所以1.1没有人用,在2004年2月w3c又发布了1.0版本的第三版
-
小结:
-
声明有哪两个常用属性?
version、encoding
-
一个XML有几个根元素?
一个
-
XML标签命名不能有什么符号?
空格、冒号
-
-
一个良好的XML有以下特点
- 必须以XML声明开头
- 必须拥有唯一的根元素
- 开始标签必须与结束标签相匹配
- 元素对大小写敏感
- 所有的元素必须关闭
- 所有的元素必须正确地嵌套
- 特殊字符必须使用实体字符或使用字符数据区
XML约束:
XML文件的标签和属性可以随意扩展,有时我们必须要限制每个文档有哪些元素,每个元素都有哪些子元素,每个元素有哪些属性等,从而保证XML文档格式和数据的正确性和规范性
DTD约束
- DTD:Document Type Definiation 文档类型定义
- 作用:纯文本文件,指定了XML约束规则
导入DTD文件的两种格式 | 说明 |
---|---|
系统DTD文件,通常个人或公司内部使用 | |
公有的DTD文件,在互联网上广泛使用的DTD |
如:hibernate框架的导入方式
"-//Hibernate/Hibrenate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
自定义books.dtd文件
// 书架
// 至少一本书
// 书名
// 作者
// 售价
使用books.dtd文件
<书架>
<书>
<书名>书名>
<作者>作者>
<售价>售价>
书>
书架>
DTD约束:只能约束标签,无法约束类型
Schema约束
- DTD的不足:
- 不能验证数据类型
- 因为DTD是一个文本文件,本身不能验证是否正确
Schema特点
- 约束文件本身也是一个XML文件,它本身也会被其它xsd文档约束
- 内置多种数据类型,可以检查数据类型是否正确
- 支持命名空间,一个XML文件可以同时引入多个xsd的约束文件,让约束规则重用
- 扩展名为xsd:XML Schema Definition
约束文件扩展名XML模式定义:xsd
约束文件本身也是XML文件,所以也有根元素,根元素名字叫:Schema
模式文档和实力文档
- 模式文档:指定约束的XML文档(类似:类)
- 实例文档:被约束的XML文档(类似:对象)
<书架 xmlns="http://www.zimo.cn"
xmlns:xsi="http://www.w2.org/2001/XMLSchema"
xsi:schemaLocation="http://www.zimo.cn books.xsd">
<书>
<书名>11书名>
<作者>aa作者>
<售价>99.8售价>
书>
<书>
<书名>22书名>
<作者>bb作者>
<售价>88.8售价>
书>
书架>
XML的解析方式
- DOM解析:文档对象模型(面向对象解析方式)
- 优点:将整个XML文件加载到内存中,生成DOM树,可以随意访问任意节点
- 缺点:占内存,XML过大可能会内存溢出
- SAX解析:
- 事件驱动型解析方式,读取一行就解析一行,释放内存。可以解析任意大小的XML文件
- 缺点:使用过不能再次访问,不能修改,只能查询
Java中的DOM解析开发包
- JAXP:Oracle官方提供API,同时支持DOM和SAX
- JDOM:开源项目,基于树形结构,利用纯Java的技术对XML文档实现解析、生成、序列化及多种操作
- :是JDOM升级版,性能优异,功能强大,使用简单,性能超过sun公司的dom技术,Habrenate也是用它读写配置
- Jsoup:是一款Java和HTML和XML解析器,可以解析URL地址、HTML文本内容。
DOM4j中DOM树的API
组成 | 说明 |
---|---|
Document | 当前解析的XML文档对象 |
Node | XML中节点,它是其他所有节点对象的父接口 |
Element | 代表一个元素(标签) |
Attribute | 代表一个属性 |
Text | 代表标签中文本 |
Dom4j安装步骤
- 下载dom4j框架,jar包
- 把dom4j核心jar包导入项目
- 项目中创建文件夹:lib
- 将dom4j.jar复制到lib中
- 在jar文件夹上右键,Add As Library
- 类中导包使用
-
Java提供了Class下的一个方法:
public InputStream getResourceAsStream(String path)
| -- 用于加载文件称为一个字节输入流返回!!
-
Document文档:
-
Element getRootElement()
:获取根元素 -
String getName()
:取元素名称 -
List
:获取当前元素下的全部子元素(一级)elements() -
List
:获取当前元素下指定名称的全部子元素(一级)elements(String name) -
Element element(String name)
:获取当前元素下的指定名称的某个子元素,默认取第一个
-
-
Element元素的API:
-
List
:获取元素的全部属性对象attributes() -
Attribute attribute(String name)
:根据名称获取某个元素的属性对象 -
String attributeValue(String var1)
:直接获取某个元素的某个属性名称的值
-
-
Attribute对象的API:
-
String getName()
:获取属性名称 -
String getValue()
:获取属性值
-
-
Element:
-
String elementText(String name)
:可以直接获取当前元素的子元素的文本内容 -
String elementTextTrim(String name)
:去前后空格,直接获取当前元素的子元素的文本内容 -
String getText()
:直接获取当前文本内容 -
String getTextTrim()
:去前后空格,直接获取当前文本内容
-
案例:
/* Contact类 */
/**
*
* 潘金莲
* 女
* [email protected]
*
*/
public class Contact{
private int id;
private boolean vip;
private String name;
private char sex;
private String email;
public Contact(){
}
public Contact(int id, boolean vip, String name, char sex, String email){
this.id = id;
this.vip = vip;
this.name = name;
this.sex = sex;
this.email = email;
}
// 各个属性的get,set方法.....
}
package com.zimo.Dom4j案例解析;
/**
* Dom4j解析XML文件:Contacts.xml成为一个Java对象(集合对象)
* Contacts.xml 解析成 ===>>> List
* 分析:
* 1.定义一个联系人封装联系人数据
* 2.解析成List集合
*/
public class Dom4JDemo{
public static void main(String args[]) throws Exception{
// 1.创建一个dom4j的解析器对象:代表整个dom4j框架
SAXReader sa = new SAXReader();
// 2.通过解析器对象去加载xml文件数据,成为一个document文档树对象
Document d = sa.read(new File("zimo/src/Contacts.xml"));
// 3.获取根元素
Element eRoot = d.getRootElement();
// 4.获取根元素下的全部子元素
List eSon = eRoot.elements();
// 5.遍历子元素 封装成list集合对象
List conList = new ArrayList();
if(eSon != null && eSon.size() > 0){
for(Element e : eSon){
int id = Integer.valueOf(e.attributeValue("id"));
boolean vip = Boolean.valueOf(e.attributeValue("vip"));
String name = String.valueOf(e.elementText("name"));
char sex = e.elementText("sex").charAt(0);
String email = String.valueOf(e.elementText("email"));
Contact contact = new Contact(id,vip,name,sex,email);
conList.add(contact);
}
}
}
}
Dom4j中的XPath
作用:一种用于快速查找XML元素的路径表达式,是用于方便的检索XML文件中的信息
-
XPath使用步骤
- 导入dom4j框架(XPath依赖dom4j技术)
- 导入XPath独有的框架包。jaxen.jar
-
XPath常用的API:
-
List
:检索出一批节点集合selectNodes(String var1) -
Node selectSingleNode(String var1)
:检索出一个节点返回
-
-
XPath提供四种检索数据的写法
绝对路径:/根元素/子元素/子元素
相对路径:./子元素/子元素(.代表了当前元素)
-
全文搜索:
//元素
在全文查找这个元素//元素1/元素2
在全文招元素1下面一级元素2//元素1//元素2
在全文找元素1下面的全部元素2 -
属性查找:
//@属性名称
在全文检索属性对象//元素[@属性名称]
在全文检索包含该属性的元素对象//元素[@属性名称=值]
在全文检索包含该属性的元素且属性值为该值的元素对象
public class Dom4JDemo{
public static void main(String args[]) throws Exception{
// 1.创建一个dom4j的解析器对象
SAXReader sa = new SAXReader();
// 2.通过解析器对象去加载xml文件数据,成为一个document文档树对象
InputStream is = Dom4JDemo.class.getResourceAsStream("/Contacts.xml")
Document d = sa.read(is);
// 3.1 使用绝对路径定位全部的name名称
List nameNodes = d.selectNodes("/contact/name"); // 从文档根路径开始
for(Node n : nameNode){
System.out.println(n.getText());
}
--------------------------------------------------------------------------
// 3.2 使用相对路径定位
// 得到根元素对象
Element root = document.getRootElement();
// 从根元素开始检索
List nameNodes = root.selectNodes("./name");
--------------------------------------------------------------------------
// 3.3全文检索
List nameNodes = document.selectNodes("//name"); // 全文所有name节点
List nameNodes = document.selectNodes("//contact/name"); // 全文所有contact/name节点
List nameNodes = document.selectNodes("//contact//name"); // 全文contact下所有name节点
--------------------------------------------------------------------------
// 3.3全文检索-所有属性
List attr = document.sattelectNodes("//@id"); // 全文所有id属性对象
for(Node att : attr){
Attribute a = (Attribute) att;
System.out.println(n.getText());
}
List nodeEles = document.selectNodes("//contact[@id]"); // 全文所有contact下包含id属性的
for(Node nodeEles : nodeEles){
System.out.println(nodeEles.getName());
}
Node nodeEle = document.selectSingleNode("//contact[@id = 1]"); // 全文所有contact下包含id = 1属性的
Element ele = (Element) nodeEle;
System.out.println(ele.elementTextTrim("name"));
}
解析MyBatis配置文件
public class ParseXMLConfig{
public void parseXML() throws Exception{
// 1.创建一个解析器对象
SAXReader sr = new SAXReader();
// 2.加载类路径下的xml文件成为一个document文档对象
Document d = sr.read(ParseXMLConfig.class.getResourceAsStream("/sqlMapConfig.xml"));
// 3.得到根元素对象
Element root = d.getRootElement();
// 4.获取子元素environments
Element env = root.element("environments");
// 5.获取子元素environment
Element en = env.element("environment");
// 6.获取子元素dataSource
Element data = en.element("dataSource");
// 7.获取dataSource下的全部子元素
List properties = data.elements();
// 8.遍历属性
for(Element p : properties){
System.out.println(p.attributeValue("name") + "===" + p.attributeValue("value"))
}
}
}
工厂模式
- 工厂模式(Factory Pattern)是Java中最常用的设计模式之一
- 这种类型的设计模式属于创建型模式,它提供了一种创建对象的方式
- 之前我们创建类对象时,都是new对象的形式创建,除了new以外工厂模式也可以创建
工厂模式的作用
- 对象通过工厂的方法创建返回,工厂的方法可以为该对象进行加工和数据注入
- 可以实现类与类之间的解耦合操作(核心思想)
小结:
- 优点:工厂模式的存在可以改变创建对象的方式,解决类与类之间的耦合性
- 缺点:工厂设计模式多了一个工厂类
public abstract class Animal{
public abstract void run();
}
public class Car extends Animal{
@Override
public void run(){
System.out.println("能抓鱼");
}
}
public class Dog extends Animal{
@Override
public void run(){
System.out.println("看门");
}
}
- 工厂设计模式
public class FactoryPattern{
// 不用动其他模块的代码,统一由工厂调控
public static Animal createAnimal(){
return new Dog();
}
public static Animal createAnimal1(){
return new Cat();
}
}
public static void main(String args[]){
// 旧方式
Animal a = new Cat();
a.run();
// 工厂模式
Animal a = FactoryPattern.createAnimal();
a.run();
}
装饰模式
在不改变原来类,不适用继承的基础上,动态地扩展一个类的功能
思想:创建要给新类,包装原始类,从而在新类中提升原来的功能
小结:装饰类可以在不改变原类的基础上对类中的方法进行扩展增强,实现原则为:
- 定义父类
- 定义原始类,继承父类,定义功能
- 定义装饰类,继承父类,包装原始类,增强功能
Commons-io包的使用
Commons-io是apache开源基金组织提供的一组有关IO操作的类库,可以提高IO功能开发的效率
- org.apache.commons.io :有关Streams、Readers、Writes、Files的工具类
- org.apache.commons.io.input :输入流相关的实现类,包含Reader和InputStream
- org.apache.commons.io.output :输出流相关的实现类,包含Writer和OutputStream
- org.apache.commons.io.serialization :序列化相关的类
步骤:
- 下载Commons-io相关的jar包
- 复制到指定的Module的lib目录中
- 加入到classpath中
public static void main(String args[]){
// 使用框架复制文件
IOUtils.copy(new FileInputStream("01_Demo/1.txt"), new FileOutputStream("01_Demo/2.txt"));
// 使用框架文件复制到文件夹
FileUtils.copyFileToDirectiry(new File("01_Demo/1.txt"), new File("D:/JavaTest"));
// 使用框架文件夹复制到文件夹
FileUtils.copyFileToDirectiry(new File("D:/zimo"), new File("D:/JavaTest"));
}
小结:IOUtils和FileUtils可以方便的复制文件和文件夹
- JDK1.7开始sun公司自己实现了copy技术
public static void main(String args[]){
File.copy(Paths.get("01_Demo/1.txt"), new FileOutputStream("01_Demo/2.txt"))
}
Base64
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64哥可打印字符来标识二进制数据的方法。
在Java 8中Base64编码已经成为Java类库的标准,Java 8 内置了Base64 编码的编码器和解码器
Base64工具类提供了一套静态方法获取下面三种Base64编解码器:
- 基本:输出被映射到一组字符A-Za-z0-9+/,编码不添加任何行标,输出的解码仅支持A-Za-z0-9+/。
- URL:输出映射到一组字符A-Za-z0-9+/,输出是URL和文件
- MIME:输出映射到MIME友好格式。输出每行不超过76字符,并且使用'\r'并跟随'\n'作为分割。编码输出最后没有行分割
/**
* 目标:https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&
* wd=%E9%BB%91%E9%A9%AC%E7%A8%8B%E5%BA%8F%E5%91%98&rsv_pq=adb2aafb0004cea1&rsv_t=bd4
*
* Base64可以实现编码和解码
* Java 8 内置了Base64编码的解码器和编码器
*
* encode:编码。
* decode:解码。
*/
public class Base64Demo{
public static void main(String args[]){
try{
// 1-1. 基本编码后结果。普通文本
String rs = Base64.getEncoder().encodeToString("哈哈".getByte()); // 5ZOI5ZOI
// 1-2. 基本解码后结果
byte[] decode = Base64.getDecoder().decode(rs);
System.out.println(new String(decode)); // 哈哈
// 2-1. URL编码
String url = Base64.getUrlEncoder().encodeToString("?login=zimo&pass=12345".getBytes());
System.out.println(url); // P2xvZ2luPXppbW8mcGFzcz0xMjM0NQ==
// 2-2. URL解码
byte[] url1 = Base64.getUrlDecoder().decode(url);
System.out.println(new String(url1)); // ?login=zimo&pass=12345
// 3-1. MIME编码(大文件,邮箱等)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append(UUID.randomUUID().toString());
}
String mime = Base64.getMimeEncoder().encodeToString(sb.toString().getBytes());
System.out.println(mime); // M2FmMDM0ZmItM2QyMy00Y2YwLWEwMzEtMWUzNmI3ZDQ1OTgwNjAzMDk0ZjQtOTI0Yy00ZTM3LWI0
// NTMtZWQ5NWQzYTdiN2FkYzg2N2YyYzctOGY1NC00ZmFjLWI2MzctOTk1NDM3YzMxYTQyMTJlZDZk
// MTctYWJkMS00MTgxLWJmYjktNzg2NjM0YzkwZDIwZDMxMjcyNDItYjM2My00YjVjLWEwOGUtMzMz
// ODk3Y2M5NWViZWY3NWFmYjctZmUwZC00YjNlLTk1MWItNjMzOGYwZTI2NmVlMzAzN2MxMTYtZDA3
// OC00M2U0LWJkNGUtMTI2OWJkOGU1NmE1YWYyZmFhMWQtNDA0OS00MjI0LWI2MGItMGRkOTVkYjAz
// NDZjODc1ZmU1OWMtODY5My00NTE4LTkwNmItOGQ2YmM0NzNhZDE2YjJiMTAyNWUtZjc4MC00MTY3
// LWE3ZTEtNDNlMmFiNTFhNmQ0
// 3-2. MIME解码
byte[] mime1 = Base64.getMimeDecoder().decode(mime);
System.out.println(new String(mime1));
// 252b9219-fdfa-4151-811a-884970a9295f
// 7e60291f-d03b-4f13-8839-9254f681a7d2
// c5c2fe56-6e89-4eb2-80a5-c95d4ab3899f
// ebb3651b-e3f4-4861-b9eb-0efedf00b413
// db6b06a4-e3d4-4e9a-a67b-6aecd7435613
// 5200e404-e0e8-4c8a-b297-55a8430c33ed
// c06da559-eb6b-41c8-9ff7-4d9a7f431ca4
// cda1d55b-6df3-4f61-8289-723b24c20795
// 10f59318-571e-4bd1-a45b-cb1cd9c34bcf
// cac21ea5-bf28-45e0-977b-cd18365363fc
}catch(Exception e){
}
}
}