使用不同的包名称对不同应用程序中的java对象进行de / serialize
我想在不同的应用程序之间共享java对象。
只要我在不同的项目中使用相同的包名称,它就可以正常工作。 但是,如果我更改包名称,它将不再起作用。
我试图通过扩展ObjectInputStream
类并重写readClassDescriptor
方法来解决这个问题。
但通过这样做,我收到以下错误:
java.io.StreamCorruptedException: invalid type code: 00
……不知道如何解决这个问题。
这是我用于扩展ObjectInputStream类的代码:
public class MyObjectInputStream extends ObjectInputStream { public static Map classNameMapping = initclassNameMapping(); private static Map initclassNameMapping(){ Map res = new HashMap(); //ipxTest is the name of the package where the objects got serialized res.put("ipxTest.IPX", interprojectxchangeTest.IPX.class); res.put("ipxTest.A", interprojectxchangeTest.A.class); return Collections.unmodifiableMap(res); } public MyObjectInputStream(InputStream in) throws IOException { super(in); enableResolveObject(true); } protected MyObjectInputStream() throws IOException, SecurityException { super(); enableResolveObject(true); } @Override protected java.io.ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { ObjectStreamClass desc = super.readClassDescriptor(); if (classNameMapping.containsKey(desc.getName())) return ObjectStreamClass.lookup(classNameMapping.get(desc.getName())); return desc; } }
IPX和A类在不同的项目中看起来相同,并且每个类都具有相同的serialID。
我的第一个建议是简化您的实现并停止对抗框架 – 在应用程序中使用相同的包名称。 我建议从可序列化的类中创建一个库,并在实现之间共享它。
如果你必须在具有不同软件包名称的应用程序之间进行序列化/反序列化,那么我的建议是放弃内置的Java序列化,它与类名和包名紧密相关,并使用类似Gson的序列化/反序列化。
Gson允许您指定TypeAdaper。 您可以为要序列化/反序列化的每个类创建和注册TypeAdapter,并在序列化时将类名称(不包名称)指定为“类型”,如下例所示,但使用getSimpleName()而不是getCanonicalName( )
反序列化时,您必须将正确的包名称添加到“类型”
您必须为每个应用程序单独执行TypeAdapter。
public class GsonTypeAdapter implements JsonSerializer , JsonDeserializer { @Override public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) { JsonObject result = new JsonObject(); result.add("type", new JsonPrimitive(src.getClass().getCanonicalName())); result.add("properties", context.serialize(src, src.getClass())); return result; } @Override public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); String type = jsonObject.get("type").getAsString(); JsonElement element = jsonObject.get("properties"); try { return context.deserialize(element, Class.forName(type)); } catch (ClassNotFoundException cnfe) { throw new JsonParseException("Unknown element type: " + type, cnfe); } } }
类的包名称是其全名的基本部分。
如果matthiasboesinger是你的名字,那么matthias只是你的第一个名字来识别你,但是boesinger部分是你唯一的名字标识符。
类似地,在类中,编译器使用其完整名称而不仅仅是名字来标识类及其序列化对象。
如果您更改包名称,则会丢失类的完整性,因为不同的类可以存在于具有相同名称的不同包中。
所以你正在尝试的是不可能的。
除非你编写一个适配器类,它从包含名称的原始类中获取数据,并将数据泵入新的包名类。
但那只是在灌木丛中跳动。
- 如何处理大字符串和有限的内存
- Java Restful Service eclipse tomcat HTTP Error 404
- Java非阻塞内存分配
- 开源Jalopy Eclipse插件是否与Ganymede兼容?
- 有没有办法让eclipse报告一般的“catch(exceptione)”作为错误/警告(在java中)?
- 如何使用新的Bouncy Castle库从PKCS10CertificationRequest获取PublicKey?
- 为什么Integer.parseInt(“\ uD835 \ uDFE8”)失败?
- ThreadLocal HashMap vs ConcurrentHashMap用于线程安全的未绑定缓存
- 睡眠的目的是什么(long millis,int nanos)?