XML
(1)作用
a) 存储数据
b) 传输数据
c) 配置文件
(2)XML和HTML的区别
a) HTML主要用于展示数据
b) XML主要用于存储数据
(3)标签规则
标签必须是包裹嵌套关系,不能是交叉嵌套关系
<student>
<name>zhangsan</name>
<age>18</age>
</student>
(4)注释
<!-- 这是注释信息,XML当中这样写 -->
解析DOM
(1)概述
(2)入门案例
a) 解析步骤
aa) 准备工作:导入 jar 文件,将jar文件添加到 模块当中
bb) 准备工作:存在 xml 文件
cc) 进行解析:获取到 Document 的对象
dd) 进行解析:获取到 根标签
ee) 进行解析:得到单独子标签 以及 属性 等信息
b) 代码
<!-- game.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<lol>
<hero id="1">
<name>亚索</name>
<age>30</age>
<say>哈萨克</say>
</hero>
<hero id="2">
<name>永恩</name>
<age>32</age>
<say>疾风亦有归途</say>
</hero>
<hero id="3">
<name>瑞文</name>
<age>26</age>
<say>人在塔在</say>
</hero>
</lol>
//英雄类
public class Hero {
private int id;
private String name;
private int age;
private String say;
public Hero() {
}
public Hero(int id, String name, int age, String say) {
this.id = id;
this.name = name;
this.age = age;
this.say = say;
}
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 String getSay() {
return say;
}
public void setSay(String say) {
this.say = say;
}
@Override
public String toString() {
return "Hero{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", say='" + say + '\'' +
'}';
}
}
//测试类
public class Test {
public static void main(String[] args) throws Exception {
ArrayList<Hero> list = new ArrayList<>();
String path = "dir\\game.xml";
File f = new File(path);
// --------
// (1). 获取到 Document 的对象
SAXReader reader = new SAXReader();
Document document = reader.read(f);
// (2). 获取到根标签
Element rootElement = document.getRootElement();
// (3). 获取到子标签,属性等信息
List<Element> childElements = rootElement.elements();
for (Element child : childElements) {
String id = child.attribute("id").getValue();
String name = child.element("name").getText();
String age = child.element("age").getText();
String say = child.element("say").getText();
// --------
//创建对象,将数据封装到对象当中,并且将对象封装到集合
Hero hero = new Hero();
hero.setId(Integer.parseInt(id));
hero.setName(name);
hero.setAge(Integer.parseInt(age));
hero.setSay(say);
list.add(hero);
}
// (4). 展示结果
list.forEach(h-> System.out.println(h));
}
}
约束
(1)DTD约束
a) 引入方式
aa) 本地引入 : dtd 文档是存在的
bb) 内部引入 : dtd 文档是不存在, dtd 约束的语法是 写在了 XML 文件里面
cc) 网络引入 : dtd 语法 定义在网上的, 通过网址引入
b) 语法
aa) 定义元素格式:
<!ELEMENT 元素名称 元素类型>
bb) 简单元素
EMPTY: 表示标签体为空
ANY: 表示标签体可以为空,也可以不为空
PCDATA: 表示该元素的内容部分为字符串
cc) 复杂元素 //直接写子元素名称
多个子元素可以使用 “,” 或者 “|” 隔开。 “?” 零次或者多次
","表示定义子元素的顺序。 “+” 一次或者多次, “*” 零次或多次
"|"表示子元素只能出现任意一个 如果不写则表示出现一次
dd) 定义属性
aaa) 格式:<!ATTLIST 元素名称 属性名称 属性的类型 属性的约束>
bbb) 属性的类型
CDATA类型: 普通的字符串
ccc) 属性的约束
#REQUIRED 必须的
#IMPLIED 属性不是必须的
#FIXED value 属性值是固定的
c) 操作步骤
aa) 新建一个 dtd 后缀名称的文件
bb) 在 dtd 文件当中, 定义标签, 指明是 简单元素 还是 复杂元素
cc) 在 xml 文件当中, 引入 dtd 约束
(2)Schema约束
a) 概述
Schema 本质上是一个 XML 文件, 他可以约束其他的XML, 也可以被其他XML文件约束。 Schema 约束文件比 DTD 的约束文件功能要更加的强大, 但是语法更为复杂
b) 属性定义
c) 案例
<!-- person.xsd -->
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://suibian/javase"
elementFormDefault="qualified">
<!-- 定义复杂元素 根标签 persons complexType复杂元素 sequence 顺序 -->
<element name="persons">
<complexType>
<sequence>
<!-- 定义复杂元素 子标签 person complexType复杂元素 sequence 顺序 -->
<element name="person">
<complexType>
<sequence>
<!-- 定义简单元素,name 和 age 都是字符串类型 -->
<element name="name" type="string"></element>
<element name="age" type="string"></element>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
<!-- person.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!-- 在根标签 persons 上面,引入 schema -->
<persons
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://suibian/javase"
xsi:schemaLocation="http://suibian/javase ">
<person>
<name>zhangsan</name>
<age>18</age>
</person>
</persons>
注解
(1)概述:给编译器看的,用于解释说明程序。
(2)常见注解:
@Override 方法重写
@FunctionalInterface 函数式接口
@since 版本信息
@author 作者信息
@SuppressWarnings("all") 压制所有警告
(3)本质
java当中的注解本质上来说就是一个接口,但是这个接口是 继承了Annotation 的接口。注解当中的属性,实际上就是 该接口当中的抽象方法。
(4)特殊属性value
如果我们在 注解当中,定义了 value 属性。 只有这一个 value 属性没有给出 默认值 (default),在使用注解的时候, 可以省略 value= 写法(如果在注解当中, 存在多个属性没有给出default属性值的情况,(其中包含有 value)那么value必须给出。)
例如:
压制警告的注解。底层代码的写法:
public @interface SuppressWarnings {
String[] value();
}
使用注解的时候,就可以这样写:
@SuppressWarnings(value = "all") //正确写法!
@SuppressWarnings("all") //也是正确写法! 可以省略 value=
(5)元注解
a) 概述:给自定义注解,添加注解。添加的注解就叫做元注解。
b) 常见元注解
元注解名称 | 作用说明 |
---|---|
@Target | 指定了注解能够在哪里使用 |
@Retention | 可以理解保留的时间(生命周期) |
@Inherited | 表示修饰的自定义注解 可以被子类继承 |
@Documented | 表示该自定义注解,会出现在 API 文档里面 |
(6)案例
a) 注解方法运行
//定义的注解: 指定元注解
@Target(ElementType.METHOD) //作用在方法上面
@Retention(RetentionPolicy.RUNTIME) //存活在运行时阶段
public @interface ZhuJie {
}
//定义的人类
public class Person {
@ZhuJie
public void eat(){
System.out.println("方法 eat...");
}
public void show(){
System.out.println("方法 show...");
}
@ZhuJie
public void work(){
System.out.println("方法 work...");
}
}
//测试类
public class Test {
public static void main(String[] args) throws Exception{
// (1). 获取到字节码对象,并且采用字节码对象去创建对象
Class<?> clazz = Class.forName("com.it.Person");
Constructor<?> c = clazz.getDeclaredConstructor();
c.setAccessible(true);
Object o = c.newInstance();
// (2). 反射获取到所有的成员方法,判断该方法上面,是否添加注解
Method[] methodArray = clazz.getDeclaredMethods();
for (Method m : methodArray) {
//判断是否添加了注解,如果添加注解,运行方法
if (m.isAnnotationPresent(ZhuJie.class)){
m.invoke(o);
}
}
}
}
b) 注解解析
//自定义注解
@Target(ElementType.TYPE) //作用在类上
@Retention(RetentionPolicy.RUNTIME) //存活时间
public @interface ZhuJie {
String className();
String methodName();
}
//狗类
public class Dog {
public void lookHome(){
System.out.println("狗看家");
}
}
//猫类
public class Cat {
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
//测试类
@ZhuJie(className = "com.it.Dog",methodName = "lookHome")
public class Test {
public static void main(String[] args) throws Exception{
//通过注解添加位置的字节码对象,获取到注解的对象
ZhuJie zhu = Test.class.getAnnotation(ZhuJie.class);
String className = zhu.className();
String methodName = zhu.methodName();
// --------
// (1). 获取字节码的对象, 通过字节码对象 创建对象
Class<?> clazz = Class.forName(className);
Constructor<?> c = clazz.getDeclaredConstructor();
c.setAccessible(true);
Object o = c.newInstance();
// (2). 获取到方法的对象, 暴力反射, 准备调用方法
Method m = clazz.getDeclaredMethod(methodName);
m.setAccessible(true);
m.invoke(o);
}
}
c) 综合案例(结合XML和注解)
<!-- peizhi.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<gen>
<classname>com.itheima07.Teacher</classname>
<methodname>teach</methodname>
</gen>
//当前的注解主要是用于控制访问的是哪一个XML文件
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyZhuJie {
//采用value作为属性,使用注解的时候,可以省略
String value();
}
//学生类
public class Student {
public void study(){
System.out.println("好好学习,天天睡觉");
}
}
//老师类
public class Teacher {
public void teach(){
System.out.println("老铁,66666");
}
}
@MyZhuJie("dir\\peizhi.xml")
public class Test {
public static void main(String[] args) throws Exception{
//解析注解(获取到路径)
MyZhuJie zhuJie = Test.class.getAnnotation(MyZhuJie.class);
String path = zhuJie.value();
//解析XML(获取到类名和方法名)
File f = new File(path);
SAXReader sax = new SAXReader();
Document document = sax.read(f);
Element rootElement = document.getRootElement();
String classname = rootElement.element("classname").getText();
String methodname = rootElement.element("methodname").getText();
//反射准备创建对象,调用方法
Class<?> clazz = Class.forName(classname);
Constructor<?> c = clazz.getDeclaredConstructor();
c.setAccessible(true);
Object o = c.newInstance();
Method m = clazz.getDeclaredMethod(methodname);
m.setAccessible(true);
m.invoke(o);
}
}