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语法
  • 文档声明
DTD约束
  • Document Type Definition
  • 开发中我们很少自己写DTD文档,都是根据(框架)给定的DTD文件,自己写配置文件(借助工具来实现)
  • DTD文件:















  • 通过工具生成的xml文档



    
        
        
    
    
        
        
    
    
        
    

shema约束
  • scheam是新的xml文档约束

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

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

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

  • schema支持命名空间

  • schema文档




    
    
        
            
                
                    
                        
                            
                            
                        
                    
                
                
                    
                        
                            
                            
                        
                    
                
                
                    
                        
                            
                        
                    
                
            
            
        
    

  • 根据约束生成的xml



    
        helloServlet
        xxxxxxxxxx
    
    
        helloServlet
        /hello
    

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 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 getConstructor(Class ...parameterTypes),可变参数用于确定参数列表
      • Constructor getDeclaredConstructor(Class ...parameterTypes)
      • newInstance(Object...initargs):可变参数用于确定实际参数列表
  • Method对象
    • Method对象是普通方法的描述对象
    • 获取方法:
      • Method getMethod(String name,Class...params)
      • Method getDelcaredMethod(String name,Class...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 data = new HashMap();
    
    @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 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();
        }
    }
}

你可能感兴趣的:(11_XML & 反射)