11_XML & 反射

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

  • schema支持命名空間

  • schema文檔

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
    模擬servlet2.5規(guī)范,如果開發(fā)人員需要在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>
  • 根據(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:整個xml文檔加載到內(nèi)存,解析成一個document對象
      • 優(yōu)點:元素與元素之間保留結(jié)構(gòu)關(guān)系,能夠進行增刪改查操作
      • 缺點:xml文件過大會導致內(nèi)存溢出
    2. SAX:逐行解析xml文件
      • 優(yōu)點:解析速度快,可以處理大文件
      • 缺點:不能進行增刪改查操作
    3. PULL:Android內(nèi)置的解析方式,類似于SAX解析
  • 使用dom4j解析xml文件
    • 需要使用dom4j就需要導入相應(yīng)的jar包
    • dom4j的核心類是SaxReader,讀取xml文件后獲得Document對象,通過Document獲取根元素后進行操作
    • SaxReader:
      • read(...):加載xml文檔
    • Document:
      • getRootElement():獲取根元素
    • Element:
      • elements(...):獲取自定名稱的所有元素
      • element(...):獲取指定名稱的第一個元素
      • getName():獲取當前元素的元素名
      • attribeValue():獲取指定屬性的屬性值
      • elementText(...):獲取指定元素的問本值
      • getText():獲取當前元素的文本內(nèi)容
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()
  • 使用默認的構(gòu)造方法
    • newInstance()
  • Constructor對象
    • Constructor對象是構(gòu)造方法的描述對象
    • 獲取構(gòu)造方法對象:
      • Constructor<T> getConstructor(Class<T> ...parameterTypes),可變參數(shù)用于確定參數(shù)列表
      • Constructor<T> getDeclaredConstructor(Class<T> ...parameterTypes)
      • newInstance(Object...initargs):可變參數(shù)用于確定實際參數(shù)列表
  • 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.創(chuàng)建一個map集合
    private HashMap<String, String> data = new HashMap<String,String>();
    
    @Before
    public void testReadWEBXml(){
        try {
            //1.創(chuàng)建解析器對象
            SAXReader saxReader = new SAXReader();
            //2.使用解析器加載web.xml文件得到document對象
            Document document = saxReader.read("src/cn/itheima/web/servlet1/web.xml");
            //3.獲取根元素節(jié)點
            Element rootElement = document.getRootElement();
            //4.獲取子節(jié)點(servlet和servlet-mapping)
            List<Element> childElements = rootElement.elements();
            //5.遍歷
            for (Element element : childElements) {
                //6.判斷元素的名稱為servlet的元素節(jié)點
                if("servlet".equals(element.getName())){
                    //7.分別獲取servlet元素節(jié)點的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的元素節(jié)點
                if("servlet-mapping".equals(element.getName())){
                    //10.分別獲取servlet元素節(jié)點的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獲取字節(jié)碼文件
            Class clazz = Class.forName(className);
            //4.通過字節(jié)碼文件創(chuàng)建實例對象
            Object obj = clazz.newInstance();
            //5.通過字節(jié)碼文件獲取方法(兩個參數(shù):第一個是方法名稱;第二個參數(shù)是方法的參數(shù))
            Method method = clazz.getMethod("service", null);
            //6.調(diào)用invoke方法執(zhí)行實例對象里面的方法(前面寫的方法init)【兩個參數(shù):第一個是調(diào)用方法的實例對象,第二個是方法的實參】
            method.invoke(obj, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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