顶级架构师学习——第八阶段:XML&反射,什么东东?

打算考研,一直没空出时间来继续学习,今天晚上因为计划出了点问题,空出来不少时间,把这一节补上。

1、XML简介

XML全称为Extensible Markup Language,意思是可扩展标记语言标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言

使用的规则比较简单,不再赘述,下面这个网址挺好的emm

http://www.w3school.com.cn/xml/index.asp

2、XML约束

1.DTD约束

DTD为英文Document Type Definition,中文意思为“文档类型定义”。DTD肩负着两重任务:一方面它帮助你编写合法的代码,另一方面它让浏览器正确地显示器代码。

一个DTD应该放在每一个文档的第一行(包括空白).这样正确地放置,你的DTD才能告诉浏览器的用的是什么标记语言。在通常情况下,如果你编写的是正确代码,并拥有一个合适的DTD,浏览器将会根据W3C的标准显示你的代码。 
  良好的xml文档:符合xml的语法规则。 
  有效的xml文档:符合xml语法规则的同时还需要符合DTD文档类型定义。 
  有效(Valid)的XML文档: 
  首先,XML文档是个格式正规的(Well-formed)XML文档; 
  其次,需要满足DTD的要求,这样的XML文档称为有效的(Valid)XML文档。 
  利用DTD可以对xml文档的各个节点进行约束定义,使开发遵循一套“标准”。 
  DTD可以约束xml文档出现的元素,元素名称,元素的先后顺序,属性等。

DTD文档有三种应用形式:

1.内部DTD文档,仅对当前xml有效
<!DOCTYPE 根元素[定义内容]>
2.外部DTD文档,文档在本地系统上
<!DOCTYPE 根元素 SYSTEM "DTD文件路径">
3.内外部DTD文档结合,文档在网络上,一般都有框架提供
<!DOCTYPE 根元素 SYSTEM "DTD文件路径" [定义内容]>

下面给出一个编写的范例

<!DOCTYPE poem [
    <!ELEMENT poem (author, title, content)>
    <!ELEMENT author (#PCDATA)>
    <!ELEMENT title (#PCDATA)>
    <!ELEMENT content (#PCDATA)>

<!--为元素poem定义了三个子元素author title content,
这三个元素必须要出现并且必须按照这个顺序
少元素不行,多元素也不行
#PCDATA(Parsed Character Data) ,可解析的字符数据,即字符串。
-->
<!--指明author,title,content里面的内容是字符串类型-->


    <!ATTLIST poem poet CDATA #IMPLIED>
<!--给poem(元素)添加poet(属性),属性必须是(文本值),且(可选)-->
<!--属性类型有:ID、CDATA(文本类型)、枚举({e1|e2|e3...}多选一)-->
<!--约束有:#REQUIRED 必须的、#IMPLIED 可选的-->

]>

本部分内容参考https://blog.csdn.net/yeoman92/article/details/53055749

2.SCHEMA约束

schema是新的xml文档约束,比dtd要强大的多,其本身也是xml文档,但其扩展名为xsd,且支持命名空间。常见使用schema的框架有spring等。

直接给一个示范吧:

<?xml version="1.0" encoding="UTF-8"?>
<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、tns等就是对上面定义的命名空间的使用,可以把网址复制下来去看看具体的文件编写-->
	<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>

命名空间用来处理元素和属性重名的问题,与java中包的使用类似。

3、XML解析

常用的解析器有DOM、SAX以及安卓内置的PULL。这里主要介绍用DOM解析XML文件,使用到了dom4j这个解析开发包。

xml dom将整个xml文档加载至内存,生成一个dom树,并获得一个document对象,通过document对象就可以对dom进行操作。

 dom中核心概念就是节点,在xml文档中的元素、属性、文本等在dom中都是节点!

dom4j常用的API有:

SaxReader对象:read() 加载执行xml文档

Document对象:getRootElement() 获得根元素

Element对象:elements() 获得指定名称的所有子元素,也可以不指定名称 
  element() 获得指定名称的第一个子元素,也可以不指定名称
  getName() 获得当前元素的元素名
  attributeValue() 获得指定属性名的属性值
  elementText() 获得指定名称子元素的文本值
  getText() 获得当前元素的文本内容

下面给出一段示例代码:

public class TestDom4j {
	@Test
	public void testReadWebXML() {
		try {
			// 1.获取解析器
			SAXReader saxReader = new SAXReader();
			// 2.获得document文档对象
			Document doc = saxReader.read("src/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();
		}
	}
}

4、反射(PS:本节重点重点重重点)

应用程序已经运行,无法在其中进行new对象的建立,就无法使用对象。这时可以根据配置文件的类全名去找对应的字节码文件,并加载进内存,并创建该类对象实例。这就需要使用反射技术完成,通过反射动态获取指定类以及类中的内容(成员),并运行其内容。

要利用反射,首先要获取到对应的类,这里有三种方法:

1.通过对象具备的getClass方法(源于Object类的方法)。有点不方便,需要用到该类,并创建该类的对象,再调用getClass方法完成。

Person p = new Person();//创建Peron对象
Class clazz = p.getClass();//通过object继承来的方法(getClass)获取Person对应的字节码文件对象

2.每一个类型都具备一个class静态属性,通过该属性即可获取该类的字节码文件对象。比第一种简单了一些,仅用一个静态属性就搞定了。但是,还是有一点不方便,还必须要使用到该类。

Class clazz = Person.class;

3.使用Class.forName(),相对方便的多,不需要直接使用具体的类,只要知道该类的名字即可。而名字完成可以作为参数进行传递 ,这样就可以提高扩展性。所以为了动态获取一个类,第三种方式最为常用。

Class clazz = Class.forName("com.bean.Person");//必须类全名

这里有个来自IT黑马的实例,但是代码有点长我就不复制粘贴了,大家下载之后直接拖到src目录下就可以测试运行了。通过运行实例我们可以清晰的理解反射是如何执行的,即调用class字节码文件动态的更新内容,这在实际生产环境下十分有用。

同样最后不忘打一下广告,欢迎关注:落饼枫林!回复  反射  获取代码!

猜你喜欢

转载自blog.csdn.net/qq_39391192/article/details/84000763
今日推荐