公司最近用上了 dubbo + spring + redis , 由于系统 原来用做图片合成,字体合成操作,在序列化问题上遇到不少麻烦.
图片合成 ,java 图片合成是用 bufferedImage来操作的 ,这个BufferedImage 是不支持序列化的 ,就不能在dubbo间传输了,问题很大。
经过研究 (需要导入jai_codec.jar , jai_core.jar 这是 java jai java图像增强包) 例子为:转为序列化对象,和转回操作,如果需要转为bufferedimage ,需要同时缓存原 type 图片类型。这个类型转换后会丢失(如果设置错误,会变色)。
File imageFile = new File("D:\\abcd.jpg");
BufferedImage picImage = ImageIO.read(imageFile);
BufferedImage picImage = ImageIO.read(imageFile);
int type = picImage.getType(); // type图片类型
SerializableRenderedImage serializableRenderedImage = new SerializableRenderedImage(picImage,true); //转为可序列化图片对象
int width = serializableRenderedImage.getWidth();
int height = serializableRenderedImage.getHeight();
int height = serializableRenderedImage.getHeight();
BufferedImage bi = new BufferedImage(width, height,type);
Graphics2D g = bi.createGraphics();
g.drawRenderedImage(serializableRenderedImage, AffineTransform.getScaleInstance(1, 1)); //将对象转回 bufferedImage;1 为缩放比率 ,也就是1比1 不缩放,可按照要求修改
Graphics2D g = bi.createGraphics();
g.drawRenderedImage(serializableRenderedImage, AffineTransform.getScaleInstance(1, 1)); //将对象转回 bufferedImage;1 为缩放比率 ,也就是1比1 不缩放,可按照要求修改
g.dispose(); //关画笔,清缓存
-------------------------------------------------------------------------------------------------------------------------------------
如果是需要直接输出图片文件,只需要
ImageIO.write(serializableRenderedImage, "jpg", new File("D:\\test.jpg"));
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
将bufferedImage 转为 SerializableRenderedImage ,这个SerializableRenderedImage 支持序列化,但是这个序列化对象是不能在dubbo 间传输的(传输后会变得不可用)。
dubbo 的序列化方式与 java原生的不同。
接下来需要
--------------------------------------------序列化---------------------------
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream ops = new ObjectOutputStream(baos);
ops.writeObject(serializableRenderedImage);
byte[] byteArray = baos.toByteArray(); // 我们要的结果 二进制数组 (这个数组是可以缓存redis的,redis支持二进制缓存,也可以转为json字符串缓存)
---------------------------------------反序列化-----------------------------
ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
ObjectInputStream ois = new ObjectInputStream(bais);
Object objImage = ois.readObject();
SerializableRenderedImage sriOut = (SerializableRenderedImage)objImage; //转回序列化对象
ObjectOutputStream ops = new ObjectOutputStream(baos);
ops.writeObject(serializableRenderedImage);
byte[] byteArray = baos.toByteArray(); // 我们要的结果 二进制数组 (这个数组是可以缓存redis的,redis支持二进制缓存,也可以转为json字符串缓存)
---------------------------------------反序列化-----------------------------
ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
ObjectInputStream ois = new ObjectInputStream(bais);
Object objImage = ois.readObject();
SerializableRenderedImage sriOut = (SerializableRenderedImage)objImage; //转回序列化对象
----------------------------------------------------------------------------------
dubbo 不能直接传输 SerializableRenderedImage 我们用序列化方法序列好后,在dubbo间传输byte[] 数组对象。在需要操作时候,再转回bufferedImage
-------------------------------------------------------------
知识点:
java 序列化要求(可跨工程传输):
1.继承serailzable接口
2.包路径相同,类完全相同