1.xml
1.1)什么是xml
xml全称为:Extensible Markup Language,即可扩展的标记语言。xml语法上和html相识,但html的标签是固定的,而xml的标签是用户自定义的
xml常用于:配置文件(例如:Servlet的配置),存放数据(极少,现在大多数使用json)
1.2)xml语法
文档声明:
a.必须以”<?xml“开头,以“?>”结束,
b.文档声明必须从文档的0行0列开始
c.文档声明只有三个属性:version(必须,xml版本,value=1.0),encoding(可选,编码方式,默认:UTF-8)
<?xml version="1.0" encoding="UTF-8"?>
元素:
a.元素的结构为标签-元素体-结束标签,例如:<hello>你好</hello>
b.元素体可以是元素,也可以是文本,例如:<a><b>hi</b></a>
c.空元素只有开始标签没有结束标签,自己闭合,例如:<a/>
d.命名规则:区分大小写,不能使用空格和冒号,以.xml文件名结尾,只有一个根元素(像html中的<head>)
属性:
a.属性是元素的一部分,出现在标签中,
b.格式:属性名="属性值",使用单引或双引
c.一个标签中可以有多个不同的属性,属性名不能有冒号、空格等特殊字符,必须以字母开头
注释:
<!-- 这是一行注释->d
转义字符:
在需要使用:“<”,“>”,“'”,“"”,“&”等,符号时就要用到转义字符。
<(<),>(>),'("),"('),&(&)
如果有大量转义字符时,我们使用CDATA区
<![CDATA[
任意字符
]]>
1.3)xml约束
我们一般根据xml的约束文档编xml文件:常见的xml约束有:DTD约束,Schema约束,约束中的符号对照表
a.DTD约束
开发中我们很少自己编写DTD约束文档,通常使用框架提供的DTD约束文档:struts2,hibernate等框架
<?xml version="1.0" encoding="UTF-8"?>
<!--
Servlet的DTD实例文档,提供头部文件如下:SYSTEM(DTD在本地),PUBLIC(DTD在网络上)
<!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>
Servlet的web.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>
b.Schema约束(重点掌握)
Schema是新的xml文档约束,是DTD的替代者,文件后缀名为(.xsd),支持名称空间(像java中的package),采用框架有sprin等
<?xml version="1.0" encoding="UTF-8"?>
<!--
Schema实例文档。模拟servlet2.5规范,头文件如下
<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>
Servlet的web.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>
2.dom4j解析
当数据存储在xml后我们就希望获取xml中的内容,这时就需要对xml文件进行解析。
导入jar包:dom4j-1.6.1.jar,jaxen-1.1-beta-6.jar
2.2)解析方式和解析器
a.常见的解析方式
DOM:把整个xml文档加载到内存 并解析成一个Document对象,优点(元素间保留了结构关系,可以进行增、删、改操作)缺点(xml文档过大会有内存溢出情况)
SAX:速度快,边扫描边解析,优点(处理速度快,可以处理大文件)缺点(只能读,扫描后即会释放资源)(了解)
PULL:android内置的解析方式,类似SAX(了解)
b.常见的解析开发包
JAXP:sun公司提供支持DOM和SAX开发包
JDom:dom4j兄弟
jsoup:一种处理html特定解析开发包
dombi:比较常用的解析开发包,hibernate底层采用
2.3)xml DOM
xml DOM 和 html DOM类似,是将整个xml加载到内存,生成一个DOM树,并获得一个Document对象,通过Document对象就可以对DOM进行操作
文档(Document),元素(Element),属性(Attrbute),文本(text)
DOM中的核心概念就是节点,在xml文档中的元素、属性、文本等,在DOM中都是节点!
2.4)API
a.SAXReader对象
read(...):加载执行xml文档
b.Document对象
getRootElement():获取根元素
c.Element对象
elements(...):获取指定名称所有的子元素,可以不指定名称
element(...):获取指定名称第一个子元素,可以不指定名称
getName():获取当前元素名称
element(...):获取指定属性名称的属性值
elementText(...):获取指定名称的子元素的文本值
getText():获取当前元素的文本内容
@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();
}
}
3.反射
java反射机制:动态获取指定类及类中的方法和属性,并运行其内容,极大的提高了程序的扩展性
运行状态中,对于任意一个类都能知道其属性和方法,并且能够调用属性和方法
使用反射,可以在运行时对类Class,构造方法Constructor,普通方法Method,字段Field进行操作
栗子:程序已经运行,无法在其中new对象的建立,就无法使用对象。根据配置文件的类全名去找对应的字节码文件,并加载进内存,并创建该类的实例。
@Test
public void testMyServlet(){
try {
//1.通过servletClass获取字节码文件
Class clazz = Class.forName("com.imwj.servlet.ImServlet");
//2.通过字节码文件创建实例对象
Object obj = clazz.newInstance();
//3.通过字节码文件获取方法(两个参数:第一个是方法名称;第二个参数是方法的参数)
Method method = clazz.getMethod("service", null);
//4.调用invoke方法执行实例对象里面的方法(前面写的方法init)【两个参数:第一个是调用方法的实例对象,第二个是方法的实参】
method.invoke(obj, null);
} catch (Exception e) {
e.printStackTrace();
}
}
3.2)四大对象操作
a.Class对象:是对Class文件(字节码文件)的描述对象
获得Class对象:
已知类的全名(完整路径名):Class.forName(...)
Class clazz = Class.forName(className);
常用方法:
newInstance():使用默认的构造方法创造对象实例
Object obj = clazz.newInstance();
b.Constructor对象:是构造方法的描述对象
常用方法:
newInstance(Object...initargs)
c.Method对象:普通方法的描述对象
获得公共方法:
getMethod("方法名", 方法参数)
Method method = clazz.getMethod("方法名", null);
执行指定方法:
invoke(指定对象, 方法的实参(一般为null))
method.invoke(实例化对象, null);
d.Field对象:字段的描述对象(属性)
获得方法:
所有字段:getField("String name"),可以指定字段名称
声明字段:getDeclaredField("String name"),可以指定字段名称
Field field = clazz.getDeclaredField("age");
常用方法:
获取内容:get(Object obj),obj即实例化对象
设置内容:set(Object obj),obj即实例化对象
field.set(obj, 789);/对私有访问,必须取消对其的访问控制检查field.setAccessible(true);
一个有点长的例子:有一个ImServletImpl方法(servlet需要在web.xml中配置),通过dom4j解析web.xml文件得到ImServletImpl方法的全民(包含路径),再利用反射调用其中的service方法打印消息。
public class testServlet2 {
//8.创建一个map集合
private HashMap<String, String> data = new HashMap<String,String>();
//@Test执行前会执行@Before
@Before
public void testReadWEBXml(){
try {
//1.创建解析器对象
SAXReader saxReader = new SAXReader();
//2.使用解析器加载web.xml文件得到document对象
Document document = saxReader.read("src/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);
System.out.println(urlPattern);
System.out.println(servletClass);
//13.移除servletName
data.remove(servletName);
}
}
//System.out.println(data);
} catch (DocumentException e) {
e.printStackTrace();
}
}
@Test
public void testMyServlet(){
try {
//1.模拟在浏览器输入一个url
String url1 = "/ImServletImpl";
//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();
}
}
}