hessian 序列化BigDecimal问题
hessian处理BigDecimal时,默认将BigDecimal作为Object对象处理,尝试将BigDecimal的各个字段序列化,会导致传输到客户端的BigDecimal位0。
目前有三种解决方案:
- 对hessian重新打包
- 实现目标对象的序列化和序列化接口
- 添加自定义的
AbstractSerializerFactory
对hessian重新打包
创建META-INF/hessian/serializers
文件,在该文件中添加:
1
java.math.BigDecimal=com.caucho.hessian.io.StringValueSerializer
创建META-INF/hessian/deserializers
文件,在该文件中添加:
1
java.math.BigDecimal=com.caucho.hessian.io.BigDecimalDeserializer
指定使用StringValueSerializer
序列化BigDecimal对象,使用BigDecimalDeserializer
反序列化BigDecimal对象。
实现目标对象的序列化和序列化接口
实现目标对象的序列化(com.caucho.hessian.io.Serializer
)和反序列化接口(com.caucho.hessian.io.Deserializer
)。
- 序列化的类名必须为
cl.getName() + "HessianSerializer"
- 反序列化的类名必须为
cl.getName() + "HessianDeserializer"
- 同时必须和目标类的包路径完全一致。
添加自定义的AbstractSerializerFactory
实现自己的序列化工厂类,并添加到默认的序列化工厂中。有三处改动:
-
自定义
AbstractSerializerFactory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package com.cloudin.hessian.support;
import com.caucho.hessian.io.*;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
/**
* Created by YFHan on 2017/6/15 0015.
*/
public class MyAbstractSerializerFactory extends AbstractSerializerFactory {
private Map<String, Serializer> serializerMap = new HashMap<>();
private Map<String, Deserializer> deserializerMap = new HashMap<>();
public MyAbstractSerializerFactory() {
serializerMap.put(BigDecimal.class.getName(), new StringValueSerializer());
deserializerMap.put(BigDecimal.class.getName(), new BigDecimalDeserializer());
}
public Serializer getSerializer(Class cl) throws HessianProtocolException {
return serializerMap.get(cl.getName());
}
public Deserializer getDeserializer(Class cl) throws HessianProtocolException {
return deserializerMap.get(cl.getName());
}
} -
自定义
HessianServlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package com.cloudin.hessian.support;
import com.caucho.hessian.io.*;
import com.caucho.hessian.server.HessianServlet;
import javax.servlet.ServletException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
/**
* 自定义HessianServlet
* Created by YFHan on 2017/6/12 0012.
*/
public class MyHessianServlet extends HessianServlet {
private SerializerFactory serializerFactory;
public void init(javax.servlet.ServletConfig config) throws ServletException {
super.init(config);
serializerFactory = super.getSerializerFactory();
serializerFactory.addFactory(new MyAbstractSerializerFactory());
}
public SerializerFactory getSerializerFactory() {
return serializerFactory;
}
} -
向
HessianProxyFactory
中添加自定义的序列化工厂实例1
2HessianProxyFactory hessianProxyFactory = new HessianProxyFactory();
hessianProxyFactory.getSerializerFactory().addFactory(new MyAbstractSerializerFactory());
总结
- 第一种方案,不需要写任何代码,但是需要自己维护hessian的打包
- 第二种方案,自定义程度很高,但是需要对hessian的序列化协议非常了解,但是工作量很大,一般不用
- 第三种方案和第一种方案原理一致,虽然需要些代码,但是这些代码可以抽出作为团队公共代码,基本不需要跟随hessian版本升级而做出改动,同时如果有需要,可以随时添加自定义的序列化方式。
个人比较推荐第三种方式。