序列化协议
『壹』 什么是java序列化,如何实现java序列化
在java中只要一个类实现了Serializable接口的类就被认为是序列化的类,这种类的对象就是序列化的对象
只有被序列化的数据才允许被存储到文件、数据库之中或者通过网络协议进行传输,没有被序列化的数据是不能存储到硬盘上,不能通过网络协议进行网络传输
『贰』 如何选择传输协议及格式
网络传输数据格式的选择
对于客户端和服务端的数据传输通常会有以下几点考虑:
1.网络数据大小——占用带宽,传输效率:虽然对单个用户来说,数据量传输很小,但是对于服务器端要承受众多的高并发数据传输,必须要考虑到数据占用带宽,尽量不要有冗余数据,这样才能够少占用带宽,少占用资源,少网络IO,提高传输效率;
2.网络数据安全性——敏感数据的网络安全:对于相关业务的部分数据传输都是敏感数据,所以必须考虑对部分传输数据进行加密;
3.编码复杂度——序列化和反序列化复杂度,效率,数据结构的可扩展性,可维护性:对于平台相关业务的代码实现也需要考虑到数据发送方和数据接收方数据处理的复杂度和数据结构的可扩展性,可维护性,人力成本和实施复杂度也必须考虑在内;
4.协议通用性——大众规范:数据类型必须是跨平台,数据格式是通用的,大家普遍能接受上手的;
以下我们通过几种不同类别的协议数据类型进行比较:
自定义二进制
优点:信息体积小,对应以上”1“
缺点:编码复杂度高(自己定义消息格式,自己编写序列化和反序列化方法,自己进行容错处理,可扩展性不强,比如添加个字段,就必须改两端的逻辑处理),对应以上”3“;
提供序列化和反序列化库的开源协议
比如protocol buffers, json, Thrift
优点:是一种流行的通用数据格式,扩展相当方便,序列化和反序列化相当方便(有相应库),错误处理方便(库支持);
文本化协议
比如xml,json
优点:序列化,反序列化容易(库支持),调试方便,可视化强
缺点:相对于二进制存储占用体积大
如果是你,你会选择哪种协议?
我会选择json,因为他是“提供序列化和反序列化库的开源协议还是文本化的协议”,原因如下:
1.自定义二进制格式进行传输的工作,整个过程在定义消息,write,read的过程过于复杂,还很容易出错,对于很多数据交互的程序,会花费大量的时间在上面;
2.自定义二进制格式不便于扩展,但json可以很好地解决这种问题;
3.虽然相比较二进制,json的占用空间稍大,但是我们可以通过网络数据压缩来解决,况且json本身也是轻量级的,传输效率也很高;
4.去看《unix编程艺术》吧,第5章--文本化,好协议产生好实践;第6章--透明性:来点儿光 会告诉你使用文本化协议的好处;
『叁』 java中如何实现序列化,有什么意义
首先我们要把准备要序列化类,实现 Serializabel接口
例如:我们要Person类里的name和age都序列化
import java.io.Serializable;
public class Person implements Serializable { //本类可以序列化
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + ",年龄" + this.age ;
}
}
然后:我们将name和age序列化(也就是把这2个对象转为二进制,统族理解为“打碎”)
package org.lxh.SerDemo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream ;
public class ObjectOutputStreamDemo { //序列化
public static void main(String[] args) throws Exception {
//序列化后生成指定文件路径
File file = new File("D:" + File.separator + "person.ser") ; ObjectOutputStream oos = null ;
//装饰流(流)
oos = new ObjectOutputStream(new FileOutputStream(file)) ;
//实例化类
Person per = new Person("张三",30) ; oos.writeObject(per) ;//把类对象序列化
oos.close() ;
}
}
『肆』 关于Socket编程协议 能否直接传序列化对象
把要写进通道的类实现Serializable接口,利用ObjectInputStream和ObjectOutputStream对象流写入和读取就可以了。
从ObjectOutputStream里读取的对象要强制转换成需要的类。
『伍』 序列化和反序列化,怎么保证数据的正确性
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨。
1.Java序列化与反序列化
Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。
2.为什么需要序列化与反序列化
我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。
当我们明晰了为什么需要Java序列化和反序列化后,我们很自然地会想Java序列化的好处。其好处一是实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里),二是,利用序列化实现远程通信,即在网络上传送对象的字节序列。
3.如何实现Java序列化与反序列化
1)JDK类库中序列化API
java.io.ObjectOutputStream:表示对象输出流
它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
java.io.ObjectInputStream:表示对象输入流
它的readObject()方法源输入流中读取字节序列,再把它们反序列化成为一个对象,并将其返回。
2)实现序列化的要求
只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常。
3)实现Java对象序列化与反序列化的方法
假定一个Student类,它的对象需要序列化,可以有如下三种方法:
方法一:若Student类仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化
ObjectOutputStream采用默认的序列化方式,对Student对象的非transient的实例变量进行序列化。
ObjcetInputStream采用默认的反序列化方式,对对Student对象的非transient的实例变量进行反序列化。
方法二:若Student类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。
ObjectOutputStream调用Student对象的writeObject(ObjectOutputStream out)的方法进行序列化。
ObjectInputStream会调用Student对象的readObject(ObjectInputStream in)的方法进行反序列化。
方法三:若Student类实现了Externalnalizable接口,且Student类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。
ObjectOutputStream调用Student对象的writeExternal(ObjectOutput out))的方法进行序列化。
ObjectInputStream会调用Student对象的readExternal(ObjectInput in)的方法进行反序列化。
4)JDK类库中序列化的步骤
步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流:
ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream(“D:\\objectfile.obj”));
步骤二:通过对象输出流的writeObject()方法写对象:
out.writeObject(“Hello”);
out.writeObject(new Date());
5)JDK类库中反序列化的步骤
步骤一:创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:
ObjectInputStream in = new ObjectInputStream(new fileInputStream(“D:\\objectfile.obj”));
步骤二:通过对象输出流的readObject()方法读取对象:
String obj1 = (String)in.readObject();
Date obj2 = (Date)in.readObject();
说明:为了正确读取数据,完成反序列化,必须保证向对象输出流写对象的顺序与从对象输入流中读对象的顺序一致。
为了更好地理解Java序列化与反序列化,选择方法一编码实现。
Student类定义如下:
[java] view plain
package com.jieke.io;
import java.io.Serializable;
/**
*Title:学生类
*Description:实现序列化接口的学生类
*Copyright: right(c) 2012
*Filename: Student.java
*@author Wang Luqing
*@version 1.0
*/
public class Student implements Serializable
{
private String name;
private char sex;
private int year;
private double gpa;
public Student()
{
}
public Student(String name,char sex,int year,double gpa)
{
this.name = name;
this.sex = sex;
this.year = year;
this.gpa = gpa;
}
public void setName(String name)
{
this.name = name;
}
public void setSex(char sex)
{
this.sex = sex;
}
public void setYear(int year)
{
this.year = year;
}
public void setGpa(double gpa)
{
this.gpa = gpa;
}
public String getName()
{
return this.name;
}
public char getSex()
{
return this.sex;
}
public int getYear()
{
return this.year;
}
public double getGpa()
{
return this.gpa;
}
}
把Student类的对象序列化到文件O:\\Java\\com\\jieke\\io\\student.txt,并从该文件中反序列化,向console显示结果。代码如下:
[java] view plain
import java.io.*;
/**
*Title:应用学生类
*Description:实现学生类实例的序列化与反序列化
*Copyright: right(c) 2012
*Filename: UseStudent.java
*@author Wang Luqing
*@version 1.0
*/
public class UseStudent
{
public static void main(String[] args)
{
Student st = new Student("Tom",'M',20,3.6);
File file = new File("O:\\Java\\com\\jieke\\io\\student.txt");
try
{
file.createNewFile();
}
catch(IOException e)
{
e.printStackTrace();
}
try
{
//Student对象序列化过程
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(st);
oos.flush();
oos.close();
fos.close();
//Student对象反序列化过程
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
Student st1 = (Student) ois.readObject();
System.out.println("name = " + st1.getName());
System.out.println("sex = " + st1.getSex());
System.out.println("year = " + st1.getYear());
System.out.println("gpa = " + st1.getGpa());
ois.close();
fis.close();
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
结果如下所示:
name = Tom
sex = M
year = 20
gpa = 3.6
总结:
1)Java序列化就是把对象转换成字节序列,而Java反序列化就是把字节序列还原成Java对象。
2)采用Java序列化与反序列化技术,一是可以实现数据的持久化,在MVC模式中很是有用;二是可以对象数据的远程通信。
『陆』 javascript什么是序列化
一.什么是对象序列化?
对象序列化是指将对象的状态转换为字符串(来自我这菜鸟的理解,好像有些书上也是这么说的,浅显易懂!);
序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程(来自“网络—序列化“,学术性强,略显高端);
二.为什么会有对象序列化?
世间万物,都有其存在的原因。为什么会有对象序列化呢?因为程序猿们需要它。既然是对象序列化,那我们就先从一个对象说起:
varobj={x:1,y:2};
当这句代码运行时,对象obj的内容会存储在一块内存中,而obj本身存储的只是这块内存的地址的映射而已。简单的说,对象obj就是我们的程序在电脑通电时在内存中维护的一种东西,如果我们程序停止了或者电脑断电了,对象obj将不复存在。那么如何把对象obj的内容保存在磁盘上呢(也就是说在没电时继续保留着)?这时就需要把对象obj序列化,也就是说把obj的内容转换成一个字符串的形式,然后再保存在磁盘上。另外,我们又怎么通过HTTP协议把对象obj的内容发送到客户端呢?没错,还是需要先把对象obj序列化,然后客户端根据接收到的字符串再反序列化(也就是将字符串还原为对象)解析出相应的对象。这也正是”网络—序列化“中描述的两个作用——存储、传输。
三.JavaScript中的对象序列化
JSON的全称是”JavaScriptObjectNotation“——JavaScript对象表示法。ECMAScript5中提供了内置函数JSON.stringify()和JSON.parse()用来序列化和还原JavaScript对象。它们使用起来也很简单:
可以看到,exampleStr和exampleObj2中并没有y:undefined的内容。这说明:JSON的语法是JavaScript语法的子集,它并不能表示JavaScript中的所有值,对于JSON语法不支持的属性,序列化后会将其省略。其详细规则如下:
①对于JavaScript中的五种原始类型,JSON语法支持数字、字符串、布尔值、null四种,不支持undefined;
②NaN、Infinity和-Infinity序列化的结果是null;
③JSON语法不支持函数;
④除了RegExp、Error对象,JSON语法支持其他所有对象;
⑤日期对象序列化的结果是ISO格式的字符串,但JSON.parse()依然保留它们字符串形态,并不会将其还原为日期对象;
⑥JSON.stringify()只能序列化对象的可枚举的自有属性;
从上面的例子也可以看到,在符合以上规则的情况下,还可以通过对象序列化和反序列化完成对象的深拷贝(什么是对象的深拷贝?可以去看:https://www.hu.com/question/23031215,邹润阳的答案)。
以上就是JSON.stringify()和JSON.parse()的常用用法了,但这两个方法并不止这么简单:
四.完整版JSON.stringify()
1.简介
序列化原始值、对象或数组
2.概要
JSON.stringify(o[,filter][,indent])
3.参数
o,要转换成JSON字符串的原始值、对象或数组
filter,可选参数,一个数组或函数
indent,可选参数,一个数值或一个字符串
4.返回
JSON格式的字符串,代表o的值,同时通过了filter的过滤,以及根据indent进行了格式化
5.描述
①当对象o自身带有toJSON()方法时,JSON.stringify()会调用o的toJSON()方法,并使用该方法的返回值而不是该对象本身进行字符串化;
②如果filter存在且是一个函数,那么该函数的返回值将会作为JSON.stringify()方法的返回值。并且该函数接收两个参数,第一个参数是一个空字符串,第二个参数就是对象o。这里,大家也可以参考DouglasCrockford为ES3环境使用JSON写的json2:https://github.com/douglascrockford/JSON-js/blob/master/json2.js#L427。看看JSON.stringify和str的实现应该就明白我这里所说的这两个参数的具体含义了;
③如果filter存在且是一个字符串数组(如果数组中包含数字,数字会自动转化为字符串),那么对象o的某些属性名如果不在这个数组中,则序列化时会将这些属性省略,且返回的字符串中属性的顺序会与该数组中属性的顺序一致;
④JSON.stringify()返回的通常是不带任何空格或换行符的字符串。如果想输出可读性更好的字符串,需要指定第三个参数。如果指定的第三个参数是介于1~10之间的值,则JSON.stringify()会在每一“层级”的输出插入换行符和指定个数的空格。如果指定的第三个参数是非空字符串,则JSON.stringify()会插入换行符和该字符串(只取前十个字符)来缩进层级;
五.完整版JSON.parse()
1.简介
解析JSON格式的字符串
2.概要
JSON.parse(s[,reviver])
3.参数
s,要解析的字符串
reviver,可选参数,用来转换解析值的可选函数
4.返回
一个对象、数组或原始值。该返回值是从s中解析的(还有可能被reviver修改过);
5.描述
①如果指定了reviver函数,该函数会为从s中解析的每一个原始值(不是包含这些原始值的对象或数组)调用一次。调用reviver时带有两个参数,第一个参数是属性名——对象的属性名或转换成字符串的数组序号,第二个参数是对象属性或数组元素的原始值(如果对于这里说的两个参数有疑惑,还是可以参考:https://github.com/douglascrockford/JSON-js/blob/master/json2.js#L460)。并且,reviver函数的返回值将作为JSON.parse()的返回值;
『柒』 protocol buffer怎么序列化
Protocol Buffer(文简称protobuf)Google提供种数据序列化协议面我网找Google官protobuf定义:
Protocol Buffers 种轻便高效结构化数据存储格式用于结构化数据序列化适合做数据存储或 RPC 数据交换格式用于通讯协议、数据存储等领域语言关、平台关、扩展序列化结构数据格式目前提供 C++、Java、Python 三种语言 API
『捌』 序列化主要起什么作用 一般在什么时候用
主要是将内存中的数据组织成为一个或一组可见的数据流。我们常见的有xml序列化和二进制序列化。
而在应用方面,webService就使用的是xml序列化,它将需要进行网络传输的数据信息转化成为具有指定架构(XSD)格式的xml(WSDL),并使用指定的传输协议进行数据传输。
对于二进制序列化,应用的地方也很多,例如许多需要临时保存的内容,而又不需要使用数据库时,我们可以将内存中的对象保存到文件系统中,这时就需要进行二进制序列化。最常见的应用就是我们玩游戏时的保存记录。
『玖』 怎样做才能让Java 序列化机制 更安全
Java 序列化 serialization主要职责就是将一个对象的状态转化为一个字节序列,以方便对象的持久化或网络传输。反序列化的过程正好相反。开发人员所要做的只是实现Serializable接口,然后调用ObjectOutputStream/ObjectInputStream的WriteObject/ReadObject方法即可,其他的工作 JVM会自动帮你做了。
那通过实现Serializable 接口所获取的序列化能力是否有安全隐患?由于这些字节序列已经脱离了Java的安全体系存在于磁盘或网络上,我们能否对序列化后的字节序列进行查看和修改,甚至于注入恶意病毒呢? Java 反序列化机制是否又会对建立的对象进行验证以确保它的安全性、准确性呢? 如果你想到这些问题,那恐怕答案会让你失望了。Java序列化后的字节序列基本都是明文存在的,而且字节序列的组成有很明确的文档进行说明,你可以试着用一些十六进制的文本编辑工具,如Hexeditor 查看一下对象序列化后的内容,你都能看到很多私有变量的实际赋值。关于字节序列的说明,可参考对象序列化流协议 ,这里就不多说了。这篇文章的重点是说一些Java提供的安全机制,通过这些机制,我们能够提升序列化/反序列化的安全指数。