11_XML & 反射

目标
  • 使用反射模拟servlet执行
XML
  • 在servlet中,为了灵活实现不同的路径执行不同的资源,我们需要使用xml进行配置
  • 为了限定XML的内容,我们需要使用xml的约束(DTD约束或schema约束)
  • 为了获得xml的内容,需要使用dom4j进行操作
XML简介
  • xml:可扩展标记语言
  • xml使用的是1.0版本,因为1.1发布了基本没人用(不向下兼容),所以一直都是用1.0版本
  • xml一开始作数据传输,后来数据传输json应用更广泛,现在xml多用于配置文件
  • xml区分大小写,需要有根元素
  • xml属性值必须要有引号
XML语法
  • 文档声明
    • <?xml version="1.0" encoding="utf-8"?>
DTD约束
  • Document Type Definition
  • 开发中我们很少自己写DTD文档,都是根据(框架)给定的DTD文件,自己写配置文件(借助工具来实现)
  • DTD文件:
<?xml version="1.0" encoding="UTF-8"?>
<!--
    模拟servlet2.3规范,如果开发人员需要在xml使用当前DTD约束,必须包括DOCTYPE。
    格式如下:
    <!DOCTYPE web-app SYSTEM "web-app_2_3.dtd">
-->
<!ELEMENT web-app (servlet*,servlet-mapping* , welcome-file-list?) >
<!ELEMENT servlet (servlet-name,description?,(servlet-class|jsp-file))>
<!ELEMENT servlet-mapping (servlet-name,url-pattern+) >
<!ELEMENT servlet-name (#PCDATA)>
<!ELEMENT servlet-class (#PCDATA)>
<!ELEMENT url-pattern (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT jsp-file (#PCDATA)>

<!ELEMENT welcome-file-list (welcome-file+)>
<!ELEMENT welcome-file (#PCDATA)>

<!ATTLIST web-app version CDATA #IMPLIED>
  • 通过工具生成的xml文档
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app SYSTEM "web-app_2_3.dtd">
<web-app version="1.0">
    <servlet>
        <servlet-name></servlet-name>
        <servlet-class></servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name></servlet-name>
        <url-pattern></url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file></welcome-file>
    </welcome-file-list>
</web-app>
shema约束
  • scheam是新的xml文档约束

  • schema比DTD更加强大,是DTD的替代

  • schema本身也是xml文档,但scheam的扩展名为xsd

  • schema功能更加强大,数据类型更加完善

  • schema支持命名空间

  • schema文档

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
    模拟servlet2.5规范,如果开发人员需要在xml使用当前Schema约束,必须包括指定命名空间。
    格式如下:
    <web-app xmlns="http://www.example.org/web-app_2_5" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
            version="2.5">
-->
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.org/web-app_2_5"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://www.example.org/web-app_2_5" 
    elementFormDefault="qualified">
    
    <xsd:element name="web-app">
        <xsd:complexType>
            <xsd:choice minOccurs="0" maxOccurs="unbounded">
                <xsd:element name="servlet">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="servlet-name"></xsd:element>
                            <xsd:element name="servlet-class"></xsd:element>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
                <xsd:element name="servlet-mapping">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="servlet-name"></xsd:element>
                            <xsd:element name="url-pattern" maxOccurs="unbounded"></xsd:element>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
                <xsd:element name="welcome-file-list">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="welcome-file" maxOccurs="unbounded"></xsd:element>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:choice>
            <xsd:attribute name="version" type="double" use="optional"></xsd:attribute>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>
  • 根据约束生成的xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://www.example.org/web-app_2_5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
    version="2.5">

    <servlet>
        <servlet-name>helloServlet</servlet-name>
        <servlet-class>xxxxxxxxxx</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>
xml解析
  • html解析的方式
    1. DOM:整个xml文档加载到内存,解析成一个document对象
      • 优点:元素与元素之间保留结构关系,能够进行增删改查操作
      • 缺点:xml文件过大会导致内存溢出
    2. SAX:逐行解析xml文件
      • 优点:解析速度快,可以处理大文件
      • 缺点:不能进行增删改查操作
    3. PULL:Android内置的解析方式,类似于SAX解析
  • 使用dom4j解析xml文件
    • 需要使用dom4j就需要导入相应的jar包
    • dom4j的核心类是SaxReader,读取xml文件后获得Document对象,通过Document获取根元素后进行操作
    • SaxReader:
      • read(...):加载xml文档
    • Document:
      • getRootElement():获取根元素
    • Element:
      • elements(...):获取自定名称的所有元素
      • element(...):获取指定名称的第一个元素
      • getName():获取当前元素的元素名
      • attribeValue():获取指定属性的属性值
      • elementText(...):获取指定元素的问本值
      • getText():获取当前元素的文本内容
public void testReadWebXML() {
    try {
        // 1.获取解析器
        SAXReader saxReader = new SAXReader();
        // 2.获得document文档对象
        Document doc = saxReader.read("src/cn/itheima/xml/schema/web.xml");
        // 3.获取根元素
        Element rootElement = doc.getRootElement();
        // System.out.println(rootElement.getName());//获取根元素的名称
        // System.out.println(rootElement.attributeValue("version"));//获取根元素中的属性值
        // 4.获取根元素下的子元素
        List<Element> childElements = rootElement.elements();
        // 5.遍历子元素
        for (Element element : childElements) {
            //6.判断元素名称为servlet的元素
            if ("servlet".equals(element.getName())) {
                //7.获取servlet-name元素
                Element servletName = element.element("servlet-name");
                //8.获取servlet-class元素
                Element servletClass = element.element("servlet-class");
                System.out.println(servletName.getText());
                System.out.println(servletClass.getText());
            }
        }
    } catch (DocumentException e) {
        e.printStackTrace();
    }
}
反射
  • 通过接口来解耦
  • 获得Class对象
    1. Class.forName("已知类的完整路径名");
    2. 已知类.class
    3. 已知对象.getClass()
  • 使用默认的构造方法
    • newInstance()
  • Constructor对象
    • Constructor对象是构造方法的描述对象
    • 获取构造方法对象:
      • Constructor<T> getConstructor(Class<T> ...parameterTypes),可变参数用于确定参数列表
      • Constructor<T> getDeclaredConstructor(Class<T> ...parameterTypes)
      • newInstance(Object...initargs):可变参数用于确定实际参数列表
  • Method对象
    • Method对象是普通方法的描述对象
    • 获取方法:
      • Method getMethod(String name,Class<T>...params)
      • Method getDelcaredMethod(String name,Class<T>...params)
      • Ojbect invoke(Object obj,Object...args)
  • Filre对象
    • 字段描述对象
    • 获得方法:
      • File getFile(String name)
      • File getDeclaredFile(String name)
    • 操作:
      • Object get(Object obj)
      • void set(Object obj,Object...value)
public class TestMyServlet2 {
    //8.创建一个map集合
    private HashMap<String, String> data = new HashMap<String,String>();
    
    @Before
    public void testReadWEBXml(){
        try {
            //1.创建解析器对象
            SAXReader saxReader = new SAXReader();
            //2.使用解析器加载web.xml文件得到document对象
            Document document = saxReader.read("src/cn/itheima/web/servlet1/web.xml");
            //3.获取根元素节点
            Element rootElement = document.getRootElement();
            //4.获取子节点(servlet和servlet-mapping)
            List<Element> childElements = rootElement.elements();
            //5.遍历
            for (Element element : childElements) {
                //6.判断元素的名称为servlet的元素节点
                if("servlet".equals(element.getName())){
                    //7.分别获取servlet元素节点的servlet-name和servlet-class的值
                    String servletName = element.element("servlet-name").getText();
                    String servletClass = element.element("servlet-class").getText();
                    /*System.out.println(servletName);
                    System.out.println(servletClass);*/
                    data.put(servletName, servletClass);
                }
                //9.判断元素的名称为servlet-mapping的元素节点
                if("servlet-mapping".equals(element.getName())){
                    //10.分别获取servlet元素节点的servlet-name和servlet-class的值
                    String servletName = element.element("servlet-name").getText();
                    String urlPattern = element.element("url-pattern").getText();
                    //11.将servletName作为key来获取servletClass的值
                    String servletClass = data.get(servletName);
                    //12.将url-pattern作为key,servletClass作为value存到map中去
                    data.put(urlPattern, servletClass);
                    //13.移除servletName
                    data.remove(servletName);
                }
            }
            //System.out.println(data);
            
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
    
    @Test
    public void testMyServlet(){
        try {
            //1.模拟在浏览器输入一个url
            String url1 = "/myServlet2";
            //2.将urlPattern作为key来获取servletClass
            String className = data.get(url1);
            //3.通过servletClass获取字节码文件
            Class clazz = Class.forName(className);
            //4.通过字节码文件创建实例对象
            Object obj = clazz.newInstance();
            //5.通过字节码文件获取方法(两个参数:第一个是方法名称;第二个参数是方法的参数)
            Method method = clazz.getMethod("service", null);
            //6.调用invoke方法执行实例对象里面的方法(前面写的方法init)【两个参数:第一个是调用方法的实例对象,第二个是方法的实参】
            method.invoke(obj, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 1. XML简介 以下内容来自于http://www.w3school.com.cn/xml 基本知识 XML 和...
    WebSSO阅读 1,894评论 1 7
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • Xml Schema的用途 1. 定义一个Xml文档中都有什么元素 2. 定义一个Xml文档中都会有什么属性 ...
    _东邪_阅读 2,298评论 2 4
  • 我们的人生就像是交错的线,线的方向是我们未来的走向,而在这些线交织的地方,我们可以把它理解成最熟悉的词语——故事。...
    猢桃夹子阅读 894评论 1 3