2014-09-30 103 views
2

我想跨不同的應用程序共享Java對象。使用不同的軟件包名稱在不同的應用程序中解析/序列化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類看起來都在不同的項目中平等,讓每個相同serialID。

+0

這些問題可能會有所幫助:http://stackoverflow.com/a/13262989/446554和http://stackoverflow.com/a/13263036/446554 – 2014-09-30 16:20:15

+0

我的問題是:爲什麼覆蓋「readClassDescriptor」方法無法解決所描述的問題。那就是:原來的類不再可用於原始名稱下的jvm ... – matthiasboesinger 2014-09-30 16:28:59

回答

4

我的第一個建議是讓你的實現變得簡單,並停止與框架對抗 - 在各種應用程序中使用相同的包名稱。我建議從可序列化的類中創建一個庫,並在實現中分享它們。

如果你必須對不同包名的應用程序進行序列化/反序列化,那麼我的建議是放棄內置的Java序列化,它與類名和包名緊密相關,並使用類似Gson的序列化/反序列化。

Gson允許您指定TypeAdaper。您可以爲每個要序列化/反序列化的類創建並註冊TypeAdapter,並在序列化時將類名(不帶包名)指定爲'type',如下例所示,但使用getSimpleName()而不是getCanonicalName )

反序列化時,你必須正確的包名稱添加到「類型」

你必須爲每個應用程序單獨做TypeAdapters。

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); 
     } 
    } 
} 
0

該類的包名稱是其全名的基本部分。

如果matthiasboesinger是你的名字,那麼matthias只是你的名字來標識你,但boesinger部分是你的唯一名稱標識符。

類似地,在類中,編譯器用它們的完整名稱而不僅僅是名字來標識類和它們的序列化對象。

如果您更改包名稱,您將失去該類的完整性,因爲不同的類可以存在於具有相同名稱的不同包中。

所以你正在嘗試的是不可能的。

除非您編寫一個適配器類,它從包名稱的原始類中提取數據並將數據抽入到您的新包名稱類中。

但那只是在布什附近跳動。

+0

我的問題是:爲什麼被覆蓋的'readClassDescriptor'方法無法解決所描述的問題。那就是:原來的類在jvm的原名下不再可用了...... – matthiasboesinger 2014-09-30 16:29:23

相關問題