[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[备忘]java序列化和反序列化时,替换包名

上一篇:[备忘]netty发送大包超时,channelRead和channelReadComplete的区别
下一篇:[备忘]mybatis多数据源,报错NoUniqueBeanDefinitionException

添加日期:2021/4/20 9:58:52 快速返回   返回列表 阅读951次
原包名是com.xxx,新包名是com.yyy
为了兼容,从老系统获取到字节流时,替换包名为com.yyy,得到新系统的bean。
序列化传递给老系统之前,先替换包名为com.xxx。


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

/**
 * <b>功能:</b>对象序列化工具类<br>
 */
public final class SerializeUtil {
    
    private SerializeUtil(){
    };
    
     /** 
     * <b>功能描述:</b>对象序列化<br>
     * @param object 源数据对象
      * @return 
     */
    public static byte[] serialize(Object object) {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;

        String OLD_PACKAGE = "com.xxx";
        String NEW_PACKAGE = "com.yyy";
        try {
            // 序列化
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            byte[] bytes = baos.toByteArray();
            return changePathInSerializedData(bytes, NEW_PACKAGE, OLD_PACKAGE);
        } catch (Exception e) {
            throw new RuntimeException("aaaaa", e);
        }
    }

     /** 
     * <b>功能描述:</b>对象反序列化<br>
     * @param bytes 源数据对象
      * @return 
     */
    public static Object unserialize(byte[] bytes) {
        ByteArrayInputStream bais = null;
        try {
            // 反序列化
            bais = new ByteArrayInputStream(bytes);
            MyObjectInputStream ois = new MyObjectInputStream(bais);
            return ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException("bbbb", e);
        }
    }

    /**
     * 替换包名.
     * @param buffer 字节流
     * @param fromPath 源包名
     * @param toPath 目标包名
     * @return 替换后的字节流
     * @throws IOException
     */
    public static byte[] changePathInSerializedData(byte[] buffer, String fromPath, String toPath) throws IOException {
        byte[] search = fromPath.getBytes("UTF-8");
        byte[] replace = toPath.getBytes("UTF-8");

        ByteArrayOutputStream f = new ByteArrayOutputStream();

        for (int i = 0; i < buffer.length; i++) {
            // Search 2 bytes ahead to let us modify the 2 bytes length of the class
            // name (see Serialize format http://www.javaworld.com/community/node/2915
            // )
            boolean found = false;
            int searchMaxIndex = i + search.length + 2;
            if (searchMaxIndex <= buffer.length) {
                found = true;
                for (int j = i + 2; j < searchMaxIndex; j++) {
                    if (search[j - i - 2] != buffer[j]) {
                        found = false;
                        break;
                    }
                }
            }
            if (found) {
                int high = ((int) (buffer[i]) & 0xff);
                int low = ((int) (buffer[i + 1]) & 0xff);
                int classNameLength = (high << 8) + low;
                classNameLength += replace.length - search.length;
                // Write new length
                f.write((classNameLength >> 8) & 0xff);
                f.write((classNameLength) & 0xff);
                // Write replacement path
                f.write(replace);
                i = searchMaxIndex - 1;
            } else {
                f.write(buffer[i]);
            }
        }

        f.flush();
        f.close();

        return f.toByteArray();
    }
}

/**
 * 替换包名.
 */
class MyObjectInputStream extends ObjectInputStream {
    private static Logger logger = LoggerFactory.getLogger(MyObjectInputStream.class);
    private static final String OLD_PACKAGE = "com.xxx";
    private static final String NEW_PACKAGE = "com.yyy";

    public MyObjectInputStream(InputStream arg0) throws IOException {
        super(arg0);
    }

    @Override
    public Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
        String name = desc.getName();
        try {
            if (name.startsWith(OLD_PACKAGE)) {
                name = name.replace(OLD_PACKAGE, NEW_PACKAGE);
                return Class.forName(name);
            }
        } catch (ClassNotFoundException ex) {
            logger.warn(ex.getMessage());
        }

        return super.resolveClass(desc);
    }
}

 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved