1.Xml
XML是可扩展标记语言的缩写,它是一种数据表示格式(可以自定义数据格式),可以描述非常复杂的数据结构,常用于传输和存储数据,也可以作为软件的配置文件。
组成格式要求:
- 文件后缀必须是xml
- 文档声明必须是第一行
- 必须存在一个根标签,有且只能有一个
- XML文件中可以定义注释信息:<!-- 注释内容 -->
- 标签必须成对出现,有开始,有结束标签
- 必须能够正确地嵌套。
xml一般作为软件的配置文件来使用的,用来记录程序的配置信息。
xml约束:就是用来约束xml文件的标签该怎么写的。
Xml文档约束方式一:DTD约束
- 编写DTD约束文档,后缀必须是.dtd
- 在需要编写的XML文件中导入该DTD约束文档
- 按照约束的规定编写XML文件的内容
- 问题:可以约束XML文件的编写,但是不能约束具体的数据类型
//dtd文件 <!ELEMENT 书架 (书+)> <!ELEMENT 书 (书名,作者,售价)> <!ELEMENT 书名 (#PCDATA)> <!ELEMENT 作者 (#PCDATA)> <!ELEMENT 售价 (#PCDATA)>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE 书架 SYSTEM "xml/books.dtd"> <书架> <书> <书名>Java基础编程</书名> <作者>小明</作者> <售价>18.8</售价> </书> <书> <书名>JavaWeb编程</书名> <作者>小强</作者> <售价>9.9</售价> </书> </书架>
Xml文档约束方式二:Schema约束
- schema可以约束具体的数据类型,可以约束XML文件的标签内容格式,约束能力上更加强大。
- schema本身也是一个xml文件,本身也受到其他约束文件的要求,所以编写的更加严谨
- 编写schema约束文档,后缀必须是.xsd
- 在需要编写的XML文件中导入该schema约束文档
- 按照约束内容编写XML文件的标签
<?xml version="1.0" encoding="UTF-8" ?> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.itcast.com" elementFormDefault="qualified" > <!-- xsd文件--> <!-- targetNamespace:申明约束文档的地址(命名空间)--> <element name='书架'> <!-- 写子元素 --> <complexType> <!-- maxOccurs='unbounded': 书架下的子元素可以有任意多个!--> <sequence maxOccurs='unbounded'> <element name='书'> <!-- 写子元素 --> <complexType> <sequence> <element name='书名' type='string'/> <element name='作者' type='string'/> <element name='售价' type='double'/> </sequence> </complexType> </element> </sequence> </complexType> </element> </schema>
<?xml version="1.0" encoding="UTF-8" ?> <书架 xmlns="http://www.itcast.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.itcast.com books2.xsd"> <书> <书名>JavaSE编程</书名> <作者>小明</作者> <售价>8.8</售价> </书> <书> <书名>JavaSE编程</书名> <作者>小明</作者> <售价>8.8</售价> </书> </书架>
xml解析
xml本质上是一个具有格式的文本。
Dom解析的文本对象模型:
- Document对象:整个XML文档
- Element对象:标签
- Attribute对象:属性
- Text对象:文本内容
使用Dom4J解析出XML文件
/** * XML解析:使用Dom4j框架进行解析 */ public class Demo1 { public static void main(String[] args) throws DocumentException { //1.SAXReader():创建Dom4J的解析器对象 SAXReader saxReader=new SAXReader(); //2.读取配置文件,配置文件在src目录下,名称为Contacts.xml //从src目录下获取指定文件的字节输入流 InputStream in=Demo1.class.getResourceAsStream("/Contacts.xml"); //3.read:加载XML文件成为Document对象 Document document=saxReader.read(in); //4.获取根元素对象 Element rootElement=document.getRootElement(); System.out.println(rootElement); System.out.println("-------------------------------------"); //5.elements():得到当前元素下的所有子元素。 List<Element> list1=rootElement.elements(); for (Element element : list1) { System.out.println(element); } System.out.println("-------------------------------------"); //5.elements(String name):得到当前元素下指定名字的所有子元素。 List<Element> list2=rootElement.elements("contact"); for (Element element : list2) { System.out.println(element); } System.out.println("-------------------------------------"); //6.element(String name):得到当前元素下指定名字的第一个子元素。 Element element = rootElement.element("contact"); //7.getName():得到元素名字 System.out.println("标签名:"+element.getName()); //8.attributeValue(String name):通过属性名直接得到属性值 System.out.println("id值:"+element.attributeValue("id")); System.out.println("vip值:"+element.attributeValue("vip")); System.out.println("姓名:"+element.elementTextTrim("name")); //9.elementText(子元素名):得到指定名字的子元素的文本 System.out.println("性别:"+element.elementText("gender")); System.out.println("邮箱:"+element.elementText("email")); } }
<?xml version="1.0" encoding="UTF-8"?> <contactList> <contact id="1" vip="false"> <name> 潘 金莲 </name> <gender>女</gender> <email>panpan@itcast.cn</email> </contact> <contact id="2" vip="false"> <name>武松</name> <gender>男</gender> <email>wusong@itcast.cn</email> </contact> <contact id="3" vip="false"> <name>武大狼</name> <gender>男</gender> <email>wuda@itcast.cn</email> </contact> <user> <info> <contact id="3" vip="false"> <name>武大狼</name> <gender>男</gender> <email>wuda@itcast.cn</email> </contact> <name>西门庆</name> </info> </user> </contactList>
2.设计模式:
前人总结出来的解决特定问题的经验就称为设计模式
1.单例设计模式
单例设计模式作用:保证在系统中,运用到该模式的类永远只有一个实例(即只创建一个对象):懒汉式,饿汉式。
- 将构造方法私有化
- 在本类中定义一个本类类型的变量
- 对外提供一个方法,用于获取本类对象(懒汉式)
/** * 懒汉式单例设计模式:让某一个类的对象只能存在一个(有线程安全问题) * 1.私有化构造器,目的是不让别人创建这个类的对象 * 2.定义本类类型的变量 * 3.对外提供一个获取本类对象的方法 */ public class Student { //1.被私有的成员只能在本类中被使用 private Student(){} //2.在本类中创建一个本类类型的变量 private static Student student; //3.对外提供一个获取本类对象的方法 public static synchronized Student getStudent(){ if (student==null){ student=new Student(); } return student; } }
public class Demo1 { public static void main(String[] args) { //获取Student类的对象 Student student1 = Student.getStudent(); Student student2 = Student.getStudent(); System.out.println("这两个对象是同一个对象吗:"+(student1==student2)); } }
/** * 饿汉式单例模式 * 1.把构造方法私有化 * 2.在本类中创建一个自己的对象,并将对象公开。 */ public class Teacher { private Teacher() { } public static final Teacher teacher=new Teacher(); }
public class Demo2 { public static void main(String[] args) { Teacher teacher1 = Teacher.teacher; Teacher teacher2 = Teacher.teacher; System.out.println("对象是否是同一个:"+(teacher2==teacher1)); } }
2.工厂设计模式
- 工厂设计模式是属于一种创建型模式,它提供了一种获取对象的方式。
- 作用:可以将创建对象的细节封装起来,调用者需要对象时,找工厂拿就行,对于调用者来说,不用关心对象是怎么创建的,也不用关心对象封装了哪些数据。(实现对象的创建者,使用者之间解耦)
//动物父类 public abstract class Animal { private String name; private int age; public Animal() { } public Animal(String name, int age) { this.name = name; this.age = age; } 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 void show(){ System.out.println(name+","+age); } public abstract void eat(); }
//猫子类 public class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } }
//狗子类 public class Dog extends Animal{ @Override public void eat() { System.out.println("狗吃骨头"); } }
/** *工厂设计模式 */ public class Factory { public static Animal createAnimal(String type){ if (type.equals("狗")){ Dog dog = new Dog(); dog.setName("旺财"); dog.setAge(2); return dog; }else { Cat cat = new Cat(); cat.setName("机器猫"); cat.setAge(3); return cat; } } }
public class Demo2 { public static void main(String[] args) { // Dog dog = new Dog(); // dog.setName("旺财"); // dog.setAge(2); // dog.show(); // // Cat cat = new Cat(); // cat.setName("机器猫"); // cat.setAge(3); // cat.show(); Animal cat = Factory.createAnimal("猫"); cat.show(); Animal dog = Factory.createAnimal("狗"); dog.show(); } }
3.静态代理模式(装饰设计模式)
- 它可以在不改变原有类的基础上,对原有类的功能进行增强
- BufferedInputStream就使用了静态代理模式,它可以对任意继承了InputStream的子类进行功能增强。
//定义大明星接口 public interface Star { public void sing(); public void dance(); }
//实现大明星功能 public class BigStar implements Star{ @Override public void sing(){ System.out.println("大明星唱歌"); } @Override public void dance(){ System.out.println("大明星跳舞"); } }
//对大明星功能进行增强,用代理来实现前置和后置工作 public class Mappyer implements Star{ private Star star; public Mappyer(Star star) { this.star = star; } @Override public void sing() { System.out.println("代理谈合作"); star.sing(); System.out.println("代理收钱"); } @Override public void dance() { System.out.println("代理谈合作"); star.dance(); System.out.println("代理收钱"); } }
/* 静态代理模式: 不改变原有类的代码基础上,对原有来的功能进行增强。 */ public class Demo { public static void main(String[] args) { Star bigStar = new BigStar(); // bigStar.sing(); // bigStar.dance(); Mappyer mappyer=new Mappyer(bigStar); mappyer.sing(); System.out.println("-------------------------"); mappyer.dance(); } }
4.动态代理模式
- 动态代理模式:它可以实现在不改变原有类的基础上,对原有类的功能进行增强
- 和静态代理模式的区别:不需要写包装类,而是直接通过目标对象,生成代理对象
- JDK提供了一个动态代理的工具类(Proxy类),通过Proxy类的newInstance(...)方法可以为实现了同一个接口的类生成代理对象。
public interface Star { public void sing(); public void dance(); }
public class BigStar implements Star{ @Override public void sing(){ System.out.println("大明星唱歌:大碗拉面"); } @Override public void dance(){ System.out.println("大明星跳舞:唱跳rap"); } }
public class Demo { public static void main(String[] args) { Star bigStar = new BigStar(); bigStar.sing(); bigStar.dance(); System.out.println("-----------------------------"); //需求:为bigStart生成代理对象 /** * 参数解释: * 1.类加载器,负责将类的字节码加载到内存 * 2.被代理的类它实现了那些接口,把接口的字节码放在一个数组中作为第二个参数 * 3.进行功能增强的处理程序 */ Star proxy = (Star) Proxy.newProxyInstance(bigStar.getClass().getClassLoader(), new Class[]{Star.class}, new InvocationHandler() { /** * 参数解释 * @param proxy 表示代理对象 * @param method 要执行的目标方法 * @param args 执行目标方法的实际参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理谈合作"); //让目标方法执行 Object result = method.invoke(bigStar, args); System.out.println("代理收钱"); return result; } } ); proxy.sing(); proxy.dance(); } }
枚举:
public enum Teachers { teachers1,teachers2,teachers3 }
/** * 枚举:让一个类的对象有固定的多个(多例) * Java语言有一种类叫枚举类,可以简化多例的写法 * public enum 枚举类{ * //枚举项1,枚举项2,枚举项3 * } * 在枚举类中,每一个枚举项其实就是枚举类的对象,只需要用一些单词表示即可。 * * 作用 * 一般作为信息标志符使用,根据不同的枚举项做出不同的处理。 */ public class Demo { public static void main(String[] args) { Teachers teachers1 = Teachers.teachers1; Teachers teachers2 = Teachers.teachers2; Teachers teachers3 = Teachers.teachers3; teach(teachers2); } public static void teach(Teachers t){ switch (t){ case teachers1: System.out.println("111"); break; case teachers2: System.out.println("222"); break; case teachers3: System.out.println("333"); break; } } }