2012-03-01 20 views
0

好的,所以我正在嘗試使用類在Java中執行我的網絡數據包處理。爲了從我的流中讀取數據,我使用了一個DataInputStream。我對我的服務器讀線程看起來是這樣的:按照Java中的部分名稱獲取類

public void run() 
    { 
     while(client.isActive()) 
     { 
      try{ 
       handle(is.readShort()); 
      }catch (IOException e){ 
       client.stop(e); 
       break; 
      } 
     } 
    } 

現在,我已經有了一個方法處理:

public void handle(short id) throws IOException 
{ 
    InPacket packet = null; 

    try { 
     packet = ClassUtils.newInstance(InPacket.class, "server.client.InPacket"+id); 
    }catch (Exception e){ 
     e.printStackTrace(); 
    } 

    if (packet!=null){ 
     packet.handle(this); 
    } 
    else{ 
     throw new IOException("Invalid packet"); 
    } 
} 

我嘗試使用

packet = ClassUtils.newInstance(InPacket.class, "server.client.InPacket"+id); 

行實例化一個新的類。

在ClassUtils這是一個功能:

public static <T> T newInstance(Class<? extends T> type, String className) throws 
ClassNotFoundException, 
InstantiationException, 
IllegalAccessException { 
    Class<?> clazz = Class.forName(className); 
    Class<? extends T> targetClass = clazz.asSubclass(type); 
    T result = targetClass.newInstance(); 
    return result; 
} 

我的問題是:當我試圖獲得與名稱的唯一部分類(我試圖通過「InPacket1」得到它,而類被稱爲「InPacket1Connect」),它找不到它。是否有可能在Java中做到這一點,如果是的話如何?如果沒有,您建議如何處理我的網絡數據包?

+0

你能解釋一下爲什麼你需要爲此使用'newInstance()'嗎? – Jivings 2012-03-01 09:10:30

+0

我需要創建一個Packet類的實例,然後處理該實例,因爲我想在每個數據包的不同類中處理我的網絡。 – Gmfreaky 2012-03-01 09:28:19

回答

0

另一種方法是使用地圖(或枚舉),它的ID映射到完整的類名。

從註釋中提取東西,確保這個映射類作爲一個jar(或者可能位於包含分組處理程序的實現的同一個jar中)作爲「消息傳遞層」jar提供。

+0

因爲我需要很多數據包,並且在Client和Server項目中都必須將每個數據包映射到類名是低效的。 – Gmfreaky 2012-03-01 09:32:20

+0

@Gmfreaky,效率如何?一個做映射的類(你可以使用枚舉),更重要的是你會有明確的控制(和保證行爲)。國際海事組織我不認爲這是非常清楚你期望達到什麼,我個人從未遇到過這個設計在近5年的分佈式系統工作.... – Nim 2012-03-01 10:00:48

+0

對不起,如果我不清楚,但我的意思是它是有效的實現額外的包。對於我添加的每個數據包,我必須編輯兩個額外的類(一個用於服務器和客戶端)。爲了穩定性,我想我會選擇這個解決方案。謝謝你回答:-) – Gmfreaky 2012-03-01 10:04:26

0

像這樣,也許?

packet = ClassUtils.newInstance(InPacket.class, "server.client.InPacket"+id+"Connect"); 
                      ^^^^^^^^^^ 

(但我可能誤解了你的問題)

+0

這裏的問題是我不知道類的全名,我只是將我的類命名爲InPacket0Function或InPacket1Test。該數字表示代碼中數據包的ID。因此,例如,我想選擇名爲InPacket4Foo的類。我知道id是4,但是我不知道它在那之後叫做Foo。 – Gmfreaky 2012-03-01 09:31:13

0

爲什麼你不能創建完整的類名?

packet = ClassUtils.newInstance(InPacket.class, "server.client.InPacket"+id + "Connect" 

通過編寫自己的類加載器,您可以實現您似乎要求的功能 - 一種「模糊」類名匹配。類加載器可以在某些目錄中搜索與類型部分匹配的類文件。

我的感覺是,這可能是一個脆弱的解決方案,有加載意外類的危險。如果不能使用algorthimic類名生成器,我更喜歡Nim建議顯式地使用映射表。

+0

哇,謝謝你的快速回答!我將這些數據包命名爲他們所做的。例如,InPacket1Connect是來自客戶端的數據包,其客戶端名稱指示他已連接。明確地爲所有數據包製作一個映射會使得向軟件添加數據包變得更加困難,因爲我必須將它添加到地圖中,無論是在我的服務器和客戶端項目中。 – Gmfreaky 2012-03-01 09:25:17

+0

這是一個折衷。以更多的工作爲代價來控制更多的脆弱性。隨着系統的發展,我傾向於支持運營穩定性和清晰度。如果你從一個文件中獲得映射,這是一個更新文件的快速編輯 - 開銷不會很大。 – djna 2012-03-01 10:20:39