【RPC框架Hessian二】Hessian 对象序列化和反序列化

编程技术  /  houtizong 发布于 3年前   65

 任何一个对象从一个JVM传输到另一个JVM,都要经过序列化为二进制数据(或者字符串等其他格式,比如JSON),然后在反序列化为Java对象,这最后都是通过二进制的数据在不同的JVM之间传输(一般是通过Socket和二进制的数据传输),本文定义一个比较符合工作中。

 

1. 定义三个POJO

   Person类

package com.tom.hessian.common;import java.io.Serializable;import java.util.Date;public class Person implements Serializable{    private int age;    private String name;    /**     * transient字段不会序列化     */    private transient String sensitiveInformation;    private Date birthDay;    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getSensitiveInformation() {        return sensitiveInformation;    }    public void setSensitiveInformation(String sensitiveInformation) {        this.sensitiveInformation = sensitiveInformation;    }    public Date getBirthDay() {        return birthDay;    }    public void setBirthDay(Date birthDay) {        this.birthDay = birthDay;    }}

 

   Point类

package com.tom.hessian.common;import java.io.Serializable;public class Point implements Serializable{    private int x;    private int y;    public int getX() {        return x;    }    public void setX(int x) {        this.x = x;    }    public int getY() {        return y;    }    public void setY(int y) {        this.y = y;    }}

 

    ComplexModel

   

package com.tom.hessian.common;import java.io.Serializable;import java.util.List;public class ComplexModel<T> implements Serializable{    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    private Integer id;    private Person person;    private List<T> points;    public Person getPerson() {        return person;    }    public void setPerson(Person person) {        this.person = person;    }    public List<T> getPoints() {        return points;    }    public void setPoints(List<T> points) {        this.points = points;    }}

 

 2. 服务接口

package com.tom.hessian.common;public interface IComplexModelService {        //持久化    public void save(ComplexModel model);        //读取    public ComplexModel read(Integer modelId);}

 

3. 服务器端代码

package com.tom.hessian.server;import com.tom.hessian.common.ComplexModel;import com.tom.hessian.common.IComplexModelService;import java.util.HashMap;import java.util.Map;public class ComplexModelService implements IComplexModelService {    private Map<Integer,ComplexModel> models = new HashMap<Integer, ComplexModel>();    @Override    public void save(ComplexModel model) {        if (model.getId() == null){            throw new IllegalArgumentException("id could not be null");        }        models.put(model.getId(), model);    }    @Override    public ComplexModel read(Integer modelId) {        return models.get(modelId);    }}

 

4. 客户端代码

package com.tom.hessian.client;import com.caucho.hessian.client.HessianProxyFactory;import com.tom.hessian.common.ComplexModel;import com.tom.hessian.common.IComplexModelService;import com.tom.hessian.common.Person;import com.tom.hessian.common.Point;import java.util.ArrayList;import java.util.Date;import java.util.List;public class ComplextModelServiceTest {    public static void main(String[] args) throws Exception {        //RPC访问地址        String url = "http://localhost:8668/web/hessian_complex";        //接口的动态代理工厂        HessianProxyFactory factory = new HessianProxyFactory();        IComplexModelService service = (IComplexModelService) factory.create(IComplexModelService.class, url);        ComplexModel<Point> model = new ComplexModel<Point>();        model.setId(1);        Person person = new Person();        person.setName("Tom");        person.setAge(86);        person.setBirthDay(new Date());        person.setSensitiveInformation("This should be private over the wire");        model.setPerson(person);        List<Point> points = new ArrayList<Point>();        Point point = new Point();        point.setX(3);        point.setY(4);        points.add(point);        point = new Point();        point.setX(100);        point.setY(100);        points.add(point);        //远程方法调用        model.setPoints(points);        service.save(model);        model = service.read(model.getId());        List<Point> points1 = model.getPoints();        for(Point elem : points1) {            System.out.println(elem.getX() + "\t" + elem.getY());        }    }}

 

5. web.xml配置服务

 

6. 运行

启动Jetty,运行ComplextModelTest的main方法,看到如下的异常,表示ComplexModel,Person以及Point都必须可序列化的(实现Serializable接口),

 

 

Exception in thread "main" java.lang.IllegalStateException: Serialized class com.tom.hessian.common.ComplexModel must implement java.io.Serializableat com.caucho.hessian.io.SerializerFactory.getDefaultSerializer(SerializerFactory.java:353)at com.caucho.hessian.io.SerializerFactory.loadSerializer(SerializerFactory.java:334)at com.caucho.hessian.io.SerializerFactory.getSerializer(SerializerFactory.java:234)at com.caucho.hessian.io.HessianOutput.writeObject(HessianOutput.java:322)at com.caucho.hessian.io.HessianOutput.call(HessianOutput.java:132)at com.caucho.hessian.client.HessianProxy.sendRequest(HessianProxy.java:293)at com.caucho.hessian.client.HessianProxy.invoke(HessianProxy.java:171)at com.sun.proxy.$Proxy0.save(Unknown Source)at com.tom.hessian.client.ComplextModelServiceTest.main(ComplextModelServiceTest.java:47)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

 

7. 问题

对于范型的ComplexModel,Hessian是可以正确的序列化和反序列化的,这让我纳闷了,既然范型是编译时的行为,为什么序列化和反序列化能够成功?

 

我的理解:对于JVM而言,运行时没有范型信息,也就是说不管是否使用范型,它的字节码是完全一样的,当把一个没有范型信息的对象序列化为二进制数据,然后再把它反序列回来,它的数据就是反序列化前的样子。因此ComplexModel的List如果是Point类型的元素,那么反序列化后也是Point类型,这属于字节码级别的序列化和反序列化。反序化时为什么能够知道List元素的类型呢?原因是在序列化时,List中的每个元素的类型都会作为序列化的数据的一部分,这部分类型信息就是反序列化到正确类型的依据

 

 

 

 

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客