任何一个对象从一个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.Serializable at 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中的每个元素的类型都会作为序列化的数据的一部分,这部分类型信息就是反序列化到正确类型的依据
相关推荐
NULL 博文链接:https://qinghua0208.iteye.com/blog/493516
介绍自己不会查吗?这里有一个点就是Hessian的序列化与反序列化与原生序列化与反序列化不同,就以使用的Resin链而言,其中的javax.naming.spi
hessian轻量级 rpc实现
Nacos JRaft Hessian 反序列化 RCE 分析.pdf
NULL 博文链接:https://inter12.iteye.com/blog/1555678
Hessian 2.0序列化协议规范
hessian序列化.pdf
RPC是远程过程调用的简称,广泛应用在大规模分布式应用中,作用是有助于系统的垂直拆分...其他的框架结构也类似,区别在于对象的序列化方法,传输对象的通讯协议,以及注册中心的管理与failover设计(利用zookeeper)。
主要通过对二者简单的实现方式的对比,介绍了Java序列化和hessian序列化的差异,具有一定参考价值,需要的朋友可以了解下。
NULL 博文链接:https://san-yun.iteye.com/blog/1688510
与hessian相比,snake-rpc有几个新特点: 能够序列化 InputStream/OutputStream; 无限的 InputStream/OutputStream 参数; 能够重用方法调用返回的远程对象; 例如: Connection con = client.getConnection();...
a --args gadget入参,多个参数使用多次该命令传入,例-a -a Calc-p --protocol [dubbo|http] 通讯协议名称,默认缺省dubbo-s --serialization [hessian|java] 序列化类型,默认缺省hessian-t --target 目标,例:...
SOFA-Hessian 基于原生...包括:增加泛化序列化。增加 ClassNameResolver 和 ClassNameFilter 用于类名的映射、转换、过滤等。增加序列化黑名单(来自蚂蚁金服安全团队)。改进 SerializerFactory 内缓存的锁机制。
hessian.jar,Hessian的序列化输出 ,
远程调用方法就是HttpInvoker:他也是将参数和返回值通过Java的序列化机制进行编组和反编组,它具有RMI的支持所有可序列化对象的优点。试使用Http协议传输二进制流的,同时又具有Hessian、Burlap(传输xml文本)的...
java hessian-3.0.38.jar。修改了原生的jar包,解决了hessian 序列化BigDecimal的精度问题。注意,请在hessian服务端和客户端中分别替换此jar包哦!! 只替换服务端hessian jar包还是会有问题。
-a:生成exploit下的所有payload(例如:hessian下的SpringPartiallyComparableAdvisorHolder, SpringAbstractBeanFactoryPointcutAdvisor, Rome, XBean, Resin) -t:对生成的payloads进行解码测试 -v:verbose mode...
默认就是⾛ dubbo 协议,单⼀⻓连接,进⾏的是 NIO 异步通信,基于 hessian 作为序列化协议。使⽤的场景是:传输数据量⼩ (每次请求在 100kb 以内),但是并发量很⾼。 为了要⽀持⾼并发场景,⼀般是服务提供者就⼏...
实现了四种序列化算法,Json 方式、Kryo 算法、Hessian 算法与 Google Protobuf 方式(默认采用 Kryo方式序列化) 实现了两种负载均衡算法:随机算法与轮转算法 使用 Nacos 作为注册中心,管理服务提供者信息 消费端...