我想在不同的应用程序之间共享java对象。
只要我在不同的项目中使用相同的包名称,它就可以正常工作。 但是,如果我更改包名称,它就不再起作用了。
我尝试通过扩展ObjectInputStream
类并覆盖readClassDescriptor
方法来解决此问题。
但是这样做会出现以下错误:
java.io.StreamCorruptedException: invalid type code: 00
......不知道如何解决这个问题。
以下是我用于扩展ObjectInputStream类的代码:
public class MyObjectInputStream extends ObjectInputStream {
public static Map<String, Class> classNameMapping = initclassNameMapping();
private static Map<String, Class> initclassNameMapping(){
Map<String, Class> res = new HashMap<String, Class>();
//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类在不同项目中看起来相同,并且每个类都具有相同的序列ID。
答案 0 :(得分:7)
我的第一个建议是简化您的实现并停止对抗框架 - 在应用程序中使用相同的包名称。我建议从可序列化的类中创建一个库,并在实现之间共享它。
如果必须在具有不同软件包名称的应用程序之间进行序列化/反序列化,那么我的建议是放弃内置的Java序列化,它与类名和包名紧密相关,并使用类似Gson的序列化/反序列化。
Gson允许您指定TypeAdaper。您可以为要序列化/反序列化的每个类创建和注册TypeAdapter,并将类名(不包名称)指定为&#39;类型&#39;序列化时,如下例所示,但使用getSimpleName()而不是getCanonicalName()
反序列化时,您必须将正确的包名称添加到&#34;类型&#34;
您必须为每个应用程序单独执行TypeAdapter。
public class GsonTypeAdapter<T> implements JsonSerializer<T>, JsonDeserializer<T> {
@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);
}
}
}
答案 1 :(得分:0)
该类的包名称是其全名的基本部分。
如果matthiasboesinger是你的名字,那么matthias只是你的名字来识别你,但是boesinger部分是你唯一的名字标识符。
类似地,在类中,编译器使用其完整名称而不仅仅是名字来标识类及其序列化对象。
如果您更改包名称,则会失去类的完整性,因为不同的类可以存在于具有相同名称的不同包中。
所以你正在尝试的是不可能的。
除非您编写一个适配器类,该类从包含名称的原始类中获取数据,并将数据泵入新的包名称类。
但那只是在丛林中跳动。