+【原创】序列化+网络通信

本文探讨了序列化在网络通信中的重要角色,解释了如何通过序列化将对象转化为可传输的格式,以便在网络中进行数据交换。同时,讨论了不同序列化技术的优缺点及其在实际应用中的选择策略。
摘要由CSDN通过智能技术生成
1 序列化概念
  • 序列化就是一个把Java对象编码成一串二进制的过程
    • 序列化的用途:可以将对象放入文件存储、或者放入网络传输
  • 反序列化就是一个解码的过程
  • 序列化没有固定的标准,有各种各样序列化的方法
Java自带序列化接口
  • 创建一个User类
  • 在main方法里创建User对象,通过ObjectOutputStream把对象写入到文件中
    • 编译报错
    • 因为该对象不能被序列化
  • 让User类实现 Serializable 接口
  • 把User对象写入到文件成功!
  • 我们发现写入后的文件大小比对象所有的属性值大很多
    • 因为java的Serializable会把类的继承体系也写到文件里,多了很多额外的信息
    • 会变得更臃肿,不利于大数据的数据在分布式系统中传输
    [Actionscript3]  纯文本查看  复制代码
    ?
    1
    2
    3
    4
    5
    6
    7
    private static void encoding() throws Exception {
         ObjectOutputStream os = new ObjectOutputStream( new FileOutputStream( "E:/test/obj1.txt" ));
         SerializableUser user = new SerializableUser();
         user. set ( "9521" , "周星星" , 23 , 10000D);
         os.writeObject(user);
         os.close();
    }

     
[Java]  纯文本查看  复制代码
?
1
2
3
4
5
6
7
private static void decoding() throws Exception {
     ObjectInputStream oi = new ObjectInputStream( new FileInputStream( "E:/test/obj1.txt" ));
     Object object = oi.readObject();
     SerializableUser user = (SerializableUser) object;
     System.out.println(user);
     oi.close();
}


自定义序列化(FileOutputStream)
  • 我们通过把对象的属性拼接成字符串
  • 通过 FileOutputStream 将字符串写入文件中
  • 写入后发现文件大小变小了很多(由150字节 --> 50字节)
    • 因为所有的属性都变成字符串格式,没有额外的信息
  • 反序列化的时候读取一行数据自己切割后放入对象
  • 存在一个问题,如果是一个Int类型的值,它变成字符串后字节长度变长了
将对象转成 json 格式再序列化
  • 通过把对象转成 json 格式序列化后可以很方便的对数据进行操作
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
private static void encoding2() throws Exception {
     SerializableUser user = new SerializableUser();
     user.set( "9521" , "周星星" , 23 , 10000D);
     Gson gson = new Gson();
     String json = gson.toJson(user);
     System.out.println(json);
     FileOutputStream fos = new FileOutputStream( "E:/test/obj2.txt" );
     fos.write(json.getBytes( "utf-8" ));
     fos.flush();
     fos.close();
}
 
[Java]  纯文本查看  复制代码
?
1
2
3
4
5
6
7
8
private static void decoding2() throws Exception {
     BufferedReader br = new BufferedReader( new InputStreamReader(( new FileInputStream( "E:/test/obj2.txt" ))));
     String json = br.readLine();
     br.close();
     Gson gson = new Gson();
     SerializableUser user = gson.fromJson(json, SerializableUser. class );
     System.out.println(user);
}

通过 DataOutputStream 优化上述代码
  • 将对象中的每一个属性按照它原来的类型进行逐个编码
    • 可以对基本数据类型按类型机制编解码
  • 我们通过 DataOutputStream 把属性一个一个写入到文件
  • 发现通过这种方式序列化后文件更加小了(再由50字节 --> 29字节)
  • 字符串在原来长度上多2个字符,用于表示字符串的边界
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
private static void encoding3() throws Exception {
     SerializableUser user = new SerializableUser();
     user.set( "9521" , "周星星" , 23 , 10000D);
     
     DataOutputStream dos = new DataOutputStream( new FileOutputStream( "E:/test/obj3.txt" ));
     dos.writeUTF(user.getId());
     dos.writeUTF(user.getName());
     dos.writeInt(user.getAge());
     dos.writeDouble(user.getSalary());
     
     dos.flush();
     dos.close();
}
 
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
private static void decoding3() throws Exception {
     SerializableUser user = new SerializableUser();
     
     DataInputStream dis = new DataInputStream( new FileInputStream( "E:/test/obj3.txt" ));
     String id = dis.readUTF();
     String name = dis.readUTF();
     int age = dis.readInt();
     double salary = dis.readDouble();
     user.set(id, name, age, salary);
     System.out.println(user);
     
     dis.close();
}

总结
  • Hadoop内部也有一套自己的序列化框架:提供了一个接口Writable
  • 我们的类只要实现了Writable接口,hadoop内部就能用自己的序列化机制去序列化这个类的对象
2 服务概念
  • 服务: 就是一个业务功能,变成可以通过网络进行请求
  • 核心要素
    • 必须有一个能接收网络请求的服务端
    • 要有一个业务功能类
    • 要有一套请求方和被请求方约定好的协议
    • 要有一个支持该协议的客户端
    [Java]  纯文本查看  复制代码
    ?
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    public class SockerServer1 {
         public static void main(String[] args) throws IOException {
             ServerSocket serverSocket = new ServerSocket( 8888 );
             System.out.println( "服务端启动..." );
             while ( true ) {
                 Socket socket = serverSocket.accept();
                 System.out.println( "服务端收到消息:" );
                 InputStream is = socket.getInputStream();
                 BufferedReader br = new BufferedReader( new InputStreamReader(is));
                 String line = null ;
                 while ((line = br.readLine()) != null ) {
                     System.out.println(line);
                 }
                 br.close();
             }
         }
    }

     
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
public class SocketClient 1 {
     public static void main ( String[] args ) throws IOException {
         Socket socket = new Socket ( "localhost" , 8888 ) ;
         OutputStream os = socket.getOutputStream ( ) ;
         BufferedWriter bw = new BufferedWriter ( new OutputStreamWriter ( os ) ) ;
         bw. write ( "Hello Dog!" ) ;
         bw.flush ( ) ;
         bw. close ( ) ;
     }
}

可以通过浏览器访问,打印出HTTP协议
 
  • http://localhost:8888
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
服务端启动...
服务端收到消息:
GET / HTTP/ 1.1
Host: localhost: 8888
Connection: keep-alive
Cache-Control: max-age= 0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/ 5.0 (Windows NT 10.0 ; Win64; x64) AppleWebKit/ 537.36 (KHTML, like Gecko) Chrome/ 71.0 . 3578.98 Safari/ 537.36
Accept: text/html,application/xhtml+xml,application/xml;q= 0.9 ,image/webp,image/apng,*/*;q= 0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q= 0.9 ,en;q= 0.8


web服务(restApi)
  • 本质上还是socket通信
  • 关键点在于,通信的协议是使用了一套全球通用的规范协议:HTTP
    • 所以,服务端需要能够解析HTTP请求,能够按这种协议封装响应
    • 客户端需要能够封装HTTP协议的请求,能够解析HTTP协议的响应
3 进程与线程
  • 进程:操作系统级别的,程序运行空间(启动一个程序,就是一个进程;再起一个,又是一个进程)
  • 线程:程序内部的执行空间(线程栈);
4 文件格式概念
  • 文件格式,在最底层看来,都是一样的:二进制
    • 上升一层(编码):,就可以有不同的编码
    • 上升一层(数据组织结构):数据组织结构不同
行式存储
  • 一行就是一条数据
列式存储
  • 分文件存储,一个文件保存一列数据
5 迭代器
  • 迭代器的意义:
    • 让使用者可以不了解数据存储的细节的情况下,也能方便地取到数据
  • 迭代器有一个通用的接口: Iterator
  • 还可以再封装一层,实现另一个通用的接口:Iterable
  • Iterable类可以通过iterator()方法获取一个Iterator对象,进行迭代
    • 而且可以直接使用增强for循环进行迭代

 

(来源:黑马程序员广州中心)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值