Xml,Xml解析,设计模式

本文介绍了XML的基本概念,包括其组成格式和约束方式,如DTD和Schema约束,并详细讲解了DOM解析的文本对象模型。此外,文章还探讨了设计模式,如单例、工厂、静态代理和动态代理模式,阐述了它们的作用和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Xml

XML是可扩展标记语言的缩写,它是一种数据表示格式(可以自定义数据格式),可以描述非常复杂的数据结构,常用于传输和存储数据,也可以作为软件的配置文件。

    组成格式要求:

  • 文件后缀必须是xml
  • 文档声明必须是第一行
  • 必须存在一个根标签,有且只能有一个
  • XML文件中可以定义注释信息:<!-- 注释内容 -->
  • 标签必须成对出现,有开始,有结束标签
  • 必须能够正确地嵌套。

xml一般作为软件的配置文件来使用的,用来记录程序的配置信息。

xml约束:就是用来约束xml文件的标签该怎么写的。

Xml文档约束方式一:DTD约束

  1. 编写DTD约束文档,后缀必须是.dtd
  2. 在需要编写的XML文件中导入该DTD约束文档
  3. 按照约束的规定编写XML文件的内容
  4. 问题:可以约束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文件,本身也受到其他约束文件的要求,所以编写的更加严谨

  1.  编写schema约束文档,后缀必须是.xsd
  2. 在需要编写的XML文件中导入该schema约束文档
  3. 按照约束内容编写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. 对外提供一个方法,用于获取本类对象(懒汉式)
/**
 * 懒汉式单例设计模式:让某一个类的对象只能存在一个(有线程安全问题)
 *  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;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值