11_XML & 反射

目標(biāo)
  • 使用反射模擬servlet執(zhí)行
XML
  • 在servlet中,為了靈活實(shí)現(xiàn)不同的路徑執(zhí)行不同的資源,我們需要使用xml進(jìn)行配置
  • 為了限定XML的內(nèi)容,我們需要使用xml的約束(DTD約束或schema約束)
  • 為了獲得xml的內(nèi)容,需要使用dom4j進(jìn)行操作
XML簡(jiǎn)介
  • xml:可擴(kuò)展標(biāo)記語(yǔ)言
  • xml使用的是1.0版本,因?yàn)?.1發(fā)布了基本沒(méi)人用(不向下兼容),所以一直都是用1.0版本
  • xml一開(kāi)始作數(shù)據(jù)傳輸,后來(lái)數(shù)據(jù)傳輸json應(yīng)用更廣泛,現(xiàn)在xml多用于配置文件
  • xml區(qū)分大小寫(xiě),需要有根元素
  • xml屬性值必須要有引號(hào)
XML語(yǔ)法
  • 文檔聲明
    • <?xml version="1.0" encoding="utf-8"?>
DTD約束
  • Document Type Definition
  • 開(kāi)發(fā)中我們很少自己寫(xiě)DTD文檔,都是根據(jù)(框架)給定的DTD文件,自己寫(xiě)配置文件(借助工具來(lái)實(shí)現(xiàn))
  • DTD文件:
<?xml version="1.0" encoding="UTF-8"?>
<!--
    模擬servlet2.3規(guī)范,如果開(kāi)發(fā)人員需要在xml使用當(dāng)前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>
  • 通過(guò)工具生成的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更加強(qiáng)大,是DTD的替代

  • schema本身也是xml文檔,但scheam的擴(kuò)展名為xsd

  • schema功能更加強(qiáng)大,數(shù)據(jù)類(lèi)型更加完善

  • schema支持命名空間

  • schema文檔

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
    模擬servlet2.5規(guī)范,如果開(kāi)發(fā)人員需要在xml使用當(dāng)前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>
  • 根據(jù)約束生成的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:整個(gè)xml文檔加載到內(nèi)存,解析成一個(gè)document對(duì)象
      • 優(yōu)點(diǎn):元素與元素之間保留結(jié)構(gòu)關(guān)系,能夠進(jìn)行增刪改查操作
      • 缺點(diǎn):xml文件過(guò)大會(huì)導(dǎo)致內(nèi)存溢出
    2. SAX:逐行解析xml文件
      • 優(yōu)點(diǎn):解析速度快,可以處理大文件
      • 缺點(diǎn):不能進(jìn)行增刪改查操作
    3. PULL:Android內(nèi)置的解析方式,類(lèi)似于SAX解析
  • 使用dom4j解析xml文件
    • 需要使用dom4j就需要導(dǎo)入相應(yīng)的jar包
    • dom4j的核心類(lèi)是SaxReader,讀取xml文件后獲得Document對(duì)象,通過(guò)Document獲取根元素后進(jìn)行操作
    • SaxReader:
      • read(...):加載xml文檔
    • Document:
      • getRootElement():獲取根元素
    • Element:
      • elements(...):獲取自定名稱(chēng)的所有元素
      • element(...):獲取指定名稱(chēng)的第一個(gè)元素
      • getName():獲取當(dāng)前元素的元素名
      • attribeValue():獲取指定屬性的屬性值
      • elementText(...):獲取指定元素的問(wèn)本值
      • getText():獲取當(dāng)前元素的文本內(nèi)容
public void testReadWebXML() {
    try {
        // 1.獲取解析器
        SAXReader saxReader = new SAXReader();
        // 2.獲得document文檔對(duì)象
        Document doc = saxReader.read("src/cn/itheima/xml/schema/web.xml");
        // 3.獲取根元素
        Element rootElement = doc.getRootElement();
        // System.out.println(rootElement.getName());//獲取根元素的名稱(chēng)
        // System.out.println(rootElement.attributeValue("version"));//獲取根元素中的屬性值
        // 4.獲取根元素下的子元素
        List<Element> childElements = rootElement.elements();
        // 5.遍歷子元素
        for (Element element : childElements) {
            //6.判斷元素名稱(chēng)為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();
    }
}
反射
  • 通過(guò)接口來(lái)解耦
  • 獲得Class對(duì)象
    1. Class.forName("已知類(lèi)的完整路徑名");
    2. 已知類(lèi).class
    3. 已知對(duì)象.getClass()
  • 使用默認(rèn)的構(gòu)造方法
    • newInstance()
  • Constructor對(duì)象
    • Constructor對(duì)象是構(gòu)造方法的描述對(duì)象
    • 獲取構(gòu)造方法對(duì)象:
      • Constructor<T> getConstructor(Class<T> ...parameterTypes),可變參數(shù)用于確定參數(shù)列表
      • Constructor<T> getDeclaredConstructor(Class<T> ...parameterTypes)
      • newInstance(Object...initargs):可變參數(shù)用于確定實(shí)際參數(shù)列表
  • Method對(duì)象
    • Method對(duì)象是普通方法的描述對(duì)象
    • 獲取方法:
      • Method getMethod(String name,Class<T>...params)
      • Method getDelcaredMethod(String name,Class<T>...params)
      • Ojbect invoke(Object obj,Object...args)
  • Filre對(duì)象
    • 字段描述對(duì)象
    • 獲得方法:
      • File getFile(String name)
      • File getDeclaredFile(String name)
    • 操作:
      • Object get(Object obj)
      • void set(Object obj,Object...value)
public class TestMyServlet2 {
    //8.創(chuàng)建一個(gè)map集合
    private HashMap<String, String> data = new HashMap<String,String>();
    
    @Before
    public void testReadWEBXml(){
        try {
            //1.創(chuàng)建解析器對(duì)象
            SAXReader saxReader = new SAXReader();
            //2.使用解析器加載web.xml文件得到document對(duì)象
            Document document = saxReader.read("src/cn/itheima/web/servlet1/web.xml");
            //3.獲取根元素節(jié)點(diǎn)
            Element rootElement = document.getRootElement();
            //4.獲取子節(jié)點(diǎn)(servlet和servlet-mapping)
            List<Element> childElements = rootElement.elements();
            //5.遍歷
            for (Element element : childElements) {
                //6.判斷元素的名稱(chēng)為servlet的元素節(jié)點(diǎn)
                if("servlet".equals(element.getName())){
                    //7.分別獲取servlet元素節(jié)點(diǎn)的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.判斷元素的名稱(chēng)為servlet-mapping的元素節(jié)點(diǎn)
                if("servlet-mapping".equals(element.getName())){
                    //10.分別獲取servlet元素節(jié)點(diǎn)的servlet-name和servlet-class的值
                    String servletName = element.element("servlet-name").getText();
                    String urlPattern = element.element("url-pattern").getText();
                    //11.將servletName作為key來(lái)獲取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.模擬在瀏覽器輸入一個(gè)url
            String url1 = "/myServlet2";
            //2.將urlPattern作為key來(lái)獲取servletClass
            String className = data.get(url1);
            //3.通過(guò)servletClass獲取字節(jié)碼文件
            Class clazz = Class.forName(className);
            //4.通過(guò)字節(jié)碼文件創(chuàng)建實(shí)例對(duì)象
            Object obj = clazz.newInstance();
            //5.通過(guò)字節(jié)碼文件獲取方法(兩個(gè)參數(shù):第一個(gè)是方法名稱(chēng)鸽疾;第二個(gè)參數(shù)是方法的參數(shù))
            Method method = clazz.getMethod("service", null);
            //6.調(diào)用invoke方法執(zhí)行實(shí)例對(duì)象里面的方法(前面寫(xiě)的方法init)【兩個(gè)參數(shù):第一個(gè)是調(diào)用方法的實(shí)例對(duì)象吊洼,第二個(gè)是方法的實(shí)參】
            method.invoke(obj, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市制肮,隨后出現(xiàn)的幾起案子冒窍,更是在濱河造成了極大的恐慌,老刑警劉巖豺鼻,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件综液,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡儒飒,警方通過(guò)查閱死者的電腦和手機(jī)谬莹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)桩了,“玉大人附帽,你說(shuō)我怎么就攤上這事【” “怎么了蕉扮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)颗圣。 經(jīng)常有香客問(wèn)我喳钟,道長(zhǎng),這世上最難降的妖魔是什么在岂? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任荚藻,我火速辦了婚禮,結(jié)果婚禮上洁段,老公的妹妹穿的比我還像新娘。我一直安慰自己共郭,他們只是感情好祠丝,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布疾呻。 她就那樣靜靜地躺著,像睡著了一般写半。 火紅的嫁衣襯著肌膚如雪岸蜗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天叠蝇,我揣著相機(jī)與錄音璃岳,去河邊找鬼。 笑死悔捶,一個(gè)胖子當(dāng)著我的面吹牛铃慷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜕该,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼犁柜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了堂淡?” 一聲冷哼從身側(cè)響起馋缅,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绢淀,沒(méi)想到半個(gè)月后萤悴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡皆的,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年覆履,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祭务。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡内狗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出义锥,到底是詐尸還是另有隱情柳沙,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布拌倍,位于F島的核電站赂鲤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏柱恤。R本人自食惡果不足惜数初,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望梗顺。 院中可真熱鬧泡孩,春花似錦、人聲如沸寺谤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至眼俊,卻和暖如春意狠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疮胖。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工环戈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人澎灸。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓院塞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親击孩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子迫悠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1. XML簡(jiǎn)介 以下內(nèi)容來(lái)自于http://www.w3school.com.cn/xml 基本知識(shí) XML 和...
    WebSSO閱讀 1,924評(píng)論 1 7
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)巩梢,斷路器创泄,智...
    卡卡羅2017閱讀 134,701評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法括蝠,內(nèi)部類(lèi)的語(yǔ)法鞠抑,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法忌警,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,663評(píng)論 18 399
  • Xml Schema的用途 1. 定義一個(gè)Xml文檔中都有什么元素 2. 定義一個(gè)Xml文檔中都會(huì)有什么屬性 ...
    _東邪_閱讀 2,335評(píng)論 2 4
  • 我們的人生就像是交錯(cuò)的線搁拙,線的方向是我們未來(lái)的走向,而在這些線交織的地方法绵,我們可以把它理解成最熟悉的詞語(yǔ)——故事箕速。...
    猢桃?jiàn)A子閱讀 915評(píng)論 1 3