数据传递格式(json + xml)、反射机制、手写SpringIOC框架解析

访客 阅读:254 2021-03-31 14:17:48 评论:0

第一:数据传递格式之json

1.1 JSON 是什么?

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相比于xml这种数据交换格式来说,因为解析xml比较的复杂,而且需要编写大段的代码,所以客户端和服务器的数据交换格式往往通过JSON来进行交换。

示例:

{ 
    "sites": [ 
        { 
            "name": "腾讯云课堂", 
            "url": "https://cloud.tencent.com/" 
        }, 
        { 
            "name": "深信服", 
            "url": "https://www.sangfor.com.cn/" 
        } 
    ] 
}

JSON语法格式说明:JSON的形式是用大括号“{}”包围起来的对象列表,每一个对象间用逗号(,)分隔,而对象的属性就是用冒号(:)分隔的属性名和属性值。这是典型的字典表示形式

1.2 JSON 格式分类:对象和数组,通过这两种结构可以表示各种复杂的数据结构。

对象:对象在json中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,...}的键值对的结构。

数组:数组在json中是中括号“[]”括起来的内容,数据结构为 ["java","javascript","vb",...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是 数字、字符串、数组、对象几种。

1.3 JSON 常用解析框架:fastjson(阿里)、gson(谷歌)、jackson(spring框架自带)

1.3.1 fastjson 框架使用

第一步: 添加fastjson的jar 包依赖

 
<dependency> 
    <groupId>com.alibaba</groupId> 
    <artifactId>fastjson</artifactId> 
    <version>1.2.58</version> 
</dependency> 

第二步: 使用fastjson api

public static final Object parse(String text); // 把JSON文本parse为JSONObject或者JSONArray  
public static final JSONObject parseObject(String text); // 把JSON文本parse成JSONObject     
public static final <T> T parseObject(String text, Class<T> clazz); // 把JSON文本parse为JavaBean  
public static final JSONArray parseArray(String text); // 把JSON文本parse成JSONArray  
public static final <T> List<T> parseArray(String text, Class<T> clazz); //把JSON文本parse成JavaBean集合  
public static final String toJSONString(Object object); // 将JavaBean序列化为JSON文本  
public static final String toJSONString(Object object, boolean prettyFormat); // 将JavaBean序列化为带格式的JSON文本  
public static final Object toJSON(Object javaObject); 将JavaBean转换为JSONObject或者JSONArray。

第三步:解析JSON和拼接JSON

package com.zzg.json; 
 
import com.alibaba.fastjson.JSONArray; 
import com.alibaba.fastjson.JSONObject; 
 
public class FastjsonDemo { 
	static String json ="{\r\n" +  
			"    \"sites\": [\r\n" +  
			"        {\r\n" +  
			"            \"name\": \"腾讯云课堂\",\r\n" +  
			"            \"url\": \"https://cloud.tencent.com/\"\r\n" +  
			"        },\r\n" +  
			"        {\r\n" +  
			"            \"name\": \"深信服\",\r\n" +  
			"            \"url\": \"https://www.sangfor.com.cn/\"\r\n" +  
			"        }\r\n" +  
			"    ]\r\n" +  
			"}"; 
 
	public static void main(String[] args) { 
		JSONObject jsonObject = new JSONObject(); 
		// 将json字符串转为jsonbject 
		JSONObject jsonStrObject = jsonObject.parseObject(json); 
		JSONArray jsonArray = jsonStrObject.getJSONArray("sites"); 
		for (Object object : jsonArray) { 
			JSONObject stObject = (JSONObject) object; 
			String name = stObject.getString("name"); 
			String url = stObject.getString("url"); 
			System.out.println(name + "---" + url); 
		} 
 
	} 
 
} 
package com.zzg.json; 
 
import com.alibaba.fastjson.JSONArray; 
import com.alibaba.fastjson.JSONObject; 
 
public class FastJSONDemo1 { 
 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		JSONObject jsonObject = new JSONObject(); 
		JSONArray jsonArray = new JSONArray(); 
		JSONObject stObject = new JSONObject(); 
		stObject.put("name", "腾讯云课堂"); 
		stObject.put("url", "https://ke.qq.com/"); 
		jsonArray.add(stObject); 
		jsonObject.put("sites", jsonArray); 
		System.out.println(jsonObject.toJSONString()); 
	} 
 
} 

 

2.1 什么是XML

XML 全称为可扩展的标记语言。主要用于描述数据和用作配置文件。
XML 文档在逻辑上主要由一下 5 个部分组成:
第一部分:XML 声明:指明所用 XML 的版本、文档的编码、文档的独立性信息
第二部分:文档类型声明:指出 XML 文档所用的 DTD
第三部分:元素:由开始标签、元素内容和结束标签构成
第四部分:注释:以结束,用于对文档中的内容起一个说明作用

第五部分:处理指令:通过处理指令来通知其他应用程序来处理非 XML 格式的数据(比如:根元素或者是注解)

示例:

<?xml version="1.0" encoding="UTF-8"?>   
<students>   
    <student1 id="001">   
        <学号>20140101</学号>   
        <地址>北京海淀区</地址>   
        <座右铭>要么强大,要么听话</座右铭>   
    </student1>   
    <student2 id="002">   
        <学号>20140102</学号>   
        <地址>北京朝阳区</地址>   
        <座右铭>在哭泣中学会坚强</座右铭>   
    </student2>   
</students>  

2.2 XML 解析方式

Dom4j、Sax、Pull

2.3 Dom4j 与Sax 解析差异

       dom4j不适合大文件的解析,因为它是一下子将文件加载到内存中,所以有可能出现内存溢出,sax是基于事件来对xml进行解析的,所以他可以解析大文件的xml,也正是因为如此,所以dom4j可以对xml进行灵活的增删改查和导航,而sax没有这么强的灵活性,所以sax经常是用来解析大型xml文件,而要对xml文件进行一些灵活(crud)操作就用dom4j。

2.4 使用Dom4j 解析

2.4.1 生成xml

package com.zzg.xml; 
 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.UnsupportedEncodingException; 
 
import org.dom4j.Document; 
import org.dom4j.DocumentHelper; 
import org.dom4j.Element; 
import org.dom4j.io.OutputFormat; 
import org.dom4j.io.XMLWriter; 
 
public class Dom4jDemo { 
 
	public static void main(String[] args) throws Exception { 
		// TODO Auto-generated method stub 
		// 第一步:创建一个Document实例 
		Document doc = DocumentHelper.createDocument(); 
		// 第二步:先添加一个根结点,然后再添加子结点,构造成一个树形结构 
		Element root = doc.addElement("students"); 
		// 创建根节点关联的子节点数据 
		Element oneChildern = root.addElement("student1 ").addAttribute("id", "001"); 
		oneChildern.addElement("学号").addText("20140101"); 
		oneChildern.addElement("地址").addText("北京海淀区"); 
		oneChildern.addElement("座右铭").addText("要么强大,要么听话"); 
		 
		Element twoChildern = root.addElement("student2 ").addAttribute("id", "002"); 
		twoChildern.addElement("学号").addText("20140102"); 
		twoChildern.addElement("地址").addText("北京海淀区"); 
		twoChildern.addElement("座右铭").addText("在哭泣中学会坚强"); 
		 
		// 第三步:添加xml文件样式(也可自定义样式),并输出xml文件到指定的路径下 
		OutputFormat format = OutputFormat.createPrettyPrint(); 
 
		XMLWriter writer = new XMLWriter(new FileOutputStream(new File("E:\\dom4j.xml")), format); 
		writer.write(doc); 
		writer.flush(); 
		writer.close(); 
	 
		 
	} 
 
} 

2.4.1 解析xml

package com.zzg.xml; 
 
import java.io.File; 
import java.util.Iterator; 
import java.util.List; 
import org.dom4j.Attribute; 
import org.dom4j.Document; 
import org.dom4j.Element; 
import org.dom4j.io.SAXReader; 
 
public class Dmo4jParseDemo { 
 
	public static void main(String[] args) throws Exception  { 
		// TODO Auto-generated method stub 
		// 第一步:创建一个SAXReader解析器 
		SAXReader reader = new SAXReader(); 
		// 第二步:解析xml文件,重新构建成一个Document对象 
		Document doc = reader.read(new File("E:\\dom4j.xml")); 
		// 第三步:处理Document对象信息,在控制台打印 
		Element rootElement = doc.getRootElement(); 
		 
		getNodes(rootElement); 
		 
	} 
	 
	static public void getNodes(Element rootElement) { 
		System.out.println("当前节点名称:" + rootElement.getName()); 
		// 获取属性ID 
		List<Attribute> attributes = rootElement.attributes(); 
		for (Attribute attribute : attributes) { 
			System.out.println("属性:" + attribute.getName() + "---" + attribute.getText()); 
		} 
		if (!rootElement.getTextTrim().equals("")) { 
			System.out.println(rootElement.getName() + "--" + rootElement.getText()); 
		} 
		// 使用迭代器遍历 
		Iterator<Element> elementIterator = rootElement.elementIterator(); 
		while (elementIterator.hasNext()) { 
			Element next = elementIterator.next(); 
			getNodes(next); 
		} 
 
	} 
 
} 

效果展示:

XML 与JSON之间的区别:

Xml是重量级数据交换格式,占宽带比较大。JSON是轻量级交换格式,xml占宽带小。
所有很多互联网公司都会使用json作为数据交换格式
很多银行项目,大多数还是在使用xml。

 

第二、反射机制

2.1 什么是反射机制

就是正在运行,动态获取这个类的所有信息。

 

2.2 反射机制的作用

通过反射机制访问java对象的属性,方法,构造方法等;

 

2.3 反射机制的应用场景

1.Jdbc 加载驱动加载
2.Spring ioc框架(控制反转)

2.4 反射机制获取类的三种方式

package com.zzg.reflex; 
 
import java.io.Serializable; 
import java.util.Date; 
 
@SuppressWarnings("serial") 
public class Person implements Serializable { 
	 
	private String name; 
	 
	private Integer age; 
	 
	private String sex; 
	 
	private String address; 
	 
	private Date birthday; 
 
	public String getName() { 
		return name; 
	} 
 
	public void setName(String name) { 
		this.name = name; 
	} 
 
	public Integer getAge() { 
		return age; 
	} 
 
	public void setAge(Integer age) { 
		this.age = age; 
	} 
 
	public String getSex() { 
		return sex; 
	} 
 
	public void setSex(String sex) { 
		this.sex = sex; 
	} 
 
	public String getAddress() { 
		return address; 
	} 
 
	public void setAddress(String address) { 
		this.address = address; 
	} 
 
	public Date getBirthday() { 
		return birthday; 
	} 
 
	public void setBirthday(Date birthday) { 
		this.birthday = birthday; 
	} 
	 
	 
 
} 
 
package com.zzg.reflex; 
 
import java.lang.reflect.Field; 
 
public class ReflexDemo { 
 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		try { 
			//第一种方式 
			Class one = Class.forName("com.zzg.reflex.Person"); 
			System.out.println("class name is:" + one.getName()); 
			 
			// 第二种方式 
			Class two = Person.class; 
			System.out.println("class name is:" + two.getName()); 
			 
			// 第三种方式 
			Person obj = new Person();   
			Class three = obj.getClass(); 
			System.out.println("class name is:" + three.getName()); 
 
		} catch (ClassNotFoundException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} 
	} 
 
} 

2.5 反射机制创建对象的二种方式

package com.zzg.reflex; 
 
import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationTargetException; 
 
public class ReflexTwo { 
 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		try { 
			// 第一种方式:无参构造函数调用 
			Class<?> forNameOne = Class.forName("com.zzg.reflex.Person"); 
			// 创建对象实例,无参构造函数 
			Person newInstance = (Person) forNameOne.newInstance(); 
			 
			if(newInstance != null) { 
				System.out.println("newInstance is not null"); 
			} 
			 
			//第二种方式:有参构造函数调用 
			Class<?> forNameTwo = Class.forName("com.zzg.reflex.Person"); 
			Constructor<?> constructor = forNameTwo.getConstructor(String.class); 
			Person person = (Person) constructor.newInstance("zzg"); 
			if(person != null) { 
				System.out.println("person is not null"); 
				System.out.println("person name is:" + person.getName()); 
			} 
		} catch (ClassNotFoundException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} catch (InstantiationException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} catch (IllegalAccessException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} catch (NoSuchMethodException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} catch (SecurityException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} catch (IllegalArgumentException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} catch (InvocationTargetException e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
		} 
	} 
 
} 

2.6 反射涉及api 接口

方法名称	作用 
getDeclaredMethods []	获取该类的所有方法 
getReturnType()	获取该类的返回值 
getParameterTypes()	获取传入参数 
getDeclaredFields()	获取该类的所有字段 
setAccessible	允许访问私有成员

2.7 使用反射机制为类的私有属性赋值

package com.zzg.reflex; 
 
import java.lang.reflect.Field; 
 
public class ReflexThree { 
 
	public static void main(String[] args) { 
		// TODO Auto-generated method stub 
		try { 
			// 获取当前类class地址 
			Class<?> forName = Class.forName("com.zzg.reflex.Person"); 
			// 使用反射实例化对象 无参数构造函数 
			Object newInstance = forName.newInstance(); 
			// 获取当前类的 name字段 
			Field declaredField = forName.getDeclaredField("name"); 
			// 允许操作私有成员 
			declaredField.setAccessible(true); 
			// 设置值 
			declaredField.set(newInstance, "zzg"); 
			 
			Person person = (Person) newInstance; 
			System.out.println("person name is :" + person.getName()); 
		}catch(Exception e) { 
			System.out.println("error message is:" + e.getMessage()); 
		} 
	} 
 
} 

第三:手写SpringIOC框架

3.1 什么是SpringIOC:

就是把每一个bean(实体类)的实例化交给第三方容器进行管理。

3.2 SpringIOC 工作原理

1.读取bean的XML配置文件 
2.使用beanId查找bean配置,并获取配置文件中class地址。 
3.使用Java反射技术实例化对象 
4.获取属性配置,使用反射技术进行赋值。

3.3 自定义SpringIOC 实现功能描述:

1.利用传入的参数获取xml文件的流,并且利用dom4j解析成Document对象 
2.对于Document对象获取根元素对象<beans>后对下面的<bean>标签进行遍历,判断是否有符合的id. 
3.如果找到对应的id,相当于找到了一个Element元素,开始创建对象,先获取class属性,根据属性值利用反射建立对象. 
4.遍历<bean>标签下的property标签,并对属性赋值.注意,需要单独处理int,float类型的属性.因为在xml配置中这些属性都是以字符串的形式来配置的,因此需要额外处理. 
5.如果属性property标签有ref属性,说明某个属性的值是一个对象,那么根据id(ref属性的值)去获取ref对应的对象,再给属性赋值. 
6.返回建立的对象,如果没有对应的id,或者<beans>下没有子标签都会返回null

3.4 自定义SpringIOC 源码:

package com.zzg.ioc; 
 
import java.lang.reflect.Field; 
import java.util.List; 
 
import org.apache.commons.lang3.StringUtils; 
import org.dom4j.Document; 
import org.dom4j.Element; 
import org.dom4j.io.SAXReader; 
 
import com.zzg.reflex.Person; 
 
public class ClassPathXmlApplicationContext { 
	// 私有属性 
	private String xmlPath; 
 
	// set 和 get 方法 
	public String getXmlPath() { 
		return xmlPath; 
	} 
 
	public void setXmlPath(String xmlPath) { 
		this.xmlPath = xmlPath; 
	} 
 
	// 构造函数 
	public ClassPathXmlApplicationContext(String xmlPath) { 
		super(); 
		this.xmlPath = xmlPath; 
	} 
 
	// 功能方法 
	public Object getBean(String beanId) throws Exception { 
		// 解析xml器 
		SAXReader saxReader = new SAXReader(); 
		Document read = null; 
		try { 
			// 从项目根目录路径下 读取 
			read = saxReader.read(this.getClass().getClassLoader().getResourceAsStream(xmlPath)); 
		} catch (Exception e) { 
 
		} 
		if (read == null) { 
			return null; 
		} 
 
		// 获取根节点资源 
		Element root = read.getRootElement(); 
		List<Element> elements = root.elements(); 
		if (elements.size() <= 0) { 
			return null; 
		} 
		Object oj = null; 
		for (Element element : elements) { 
			String id = element.attributeValue("id"); 
			if (StringUtils.isEmpty(id)) { 
				return null; 
			} 
			if (!id.equals(beanId)) { 
				// 跳出当前循环 
				continue; 
 
			} 
			// 获取实体bean class地址 
			String beanClass = element.attributeValue("class"); 
			// 使用反射实例化bean 
			Class<?> forNameClass = Class.forName(beanClass); 
			oj = forNameClass.newInstance(); 
			// 获取子类对象 
			List<Element> attributes = element.elements(); 
			if (attributes.size() <= 0) { 
				return null; 
			} 
			for (Element et : attributes) { 
				// 使用反射技术为方法赋值 
				String name = et.attributeValue("name"); 
				String value = et.attributeValue("value"); 
				Field field = forNameClass.getDeclaredField(name); 
				field.setAccessible(true); 
                // 待优化,动态属性值注入 
				field.set(oj, value); 
 
			} 
 
		} 
		return oj; 
 
	} 
	 
	public static void main(String[] args) throws Exception { 
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext( 
				"applicationContext.xml"); 
		Person bean = (Person) applicationContext.getBean("person1"); 
		System.out.println("使用反射获取bean" + bean.getName() + "---" + bean.getSex()); 
 
	} 
 
} 
<beans> 
	<bean id="person1" class="com.zzg.reflex.Person"> 
		<property name="name" value="张三"></property> 
		<property name="sex" value="男"></property> 
	</bean> 
	<bean id="person2" class="com.zzg.reflex.Person"> 
		<property name="name" value="李四"></property> 
		<property name="" value="男"></property> 
	</bean> 
</beans>

 

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
排行榜
KIKK导航

KIKK导航

关注我们