2016-07-25 49 views
1

因此,我們在spring-amqp中使用漂亮的@RabbitHandler註釋來創建類似於RestControllers編碼風格的端點,但與Rabbit一起使用。它的所有非常漂亮和整潔,特別是在基於簽名的方法處理程序的動態解析方面效果很好。然而,我們在這裏面臨着一些爭議。 所以,想象下面的方法Spring amqp @RabbitListener運行時類型問題

@RabbitHandler 
public void handleEmailDto(EmailDto message) { 
    System.out.println(message); 
} 

這將fromMessage方法對MessagingMessageConverter.java類得到處理。在鏈中的某個點上,消息的類型信息將被要求,以便處理程序解析器確定使用消息的有效載荷調用哪個方法,以及要將有效載荷序列化到哪個類。關鍵是我們正在使用MappingJackson2MessageConverter。儘管如此,我們還是需要一個填充____TypeId____消息的屬性,並使用該類的完全限定名稱。那也不是問題。非常好設計和想出來。

問題出在這個類不在類路徑上時。對於我們來說,這實際上是一個巨大的痛苦,因爲我們正在微服務環境中工作,並且我們的一些服務完全分離。也就是說,我們不想擁有保存我們數據域的「普通」製品,只是爲了我們可以在運行時在消息的發送者和接收者中使用它。我已經查看了代碼,並且看到了這種孔類型的情況是如何處理的,以及它爲什麼按照這種方式完成的。

但是從架構的角度來看,這是相當有限的......這是否意味着我們肯定需要在微服務之間共享代碼,這些代碼之間相互解耦,否則只是爲了滿足序列化/反序列化/方法解析邏輯?

也許我錯過了某些東西或者忽略了另一種做法。如果是這樣,我肯定會接受建議。先謝謝您的幫助。

+0

這聽起來像你可以嘗試java lang本身的內部類型,而不是你自定義的類型。因爲你不會在服務中共享這些類。如果我們把這稱爲模式,它應該在服務之間相同。既然你不分享這些課程,你也不應該使用它們。我的分割使用內部類型,如'java.lang.Map'或'java.lang.List'。但是,您需要做更具體的工作才能獲得那裏的房產。順便說一下,如果你正在從網絡轉移,你可以把它放在地圖中,如果它們不是單一的基本類型。這對你來說足夠聰明。 –

+0

我不太明白你說的背後的邏輯。我試圖消費一些數據並將其解析爲一個對象。當你點擊一個休息控制器時,你不需要與服務器共享相同的類型,是嗎? – Zahari

+0

是的,你是對的。我所說的是你可以讀取你的數據並將它們反序列化成一個映射,而不是將數據反序列化爲一個定製的類類型。例如,你的遠程服務返回一個serilized'A'(例如在json中),其中'A'代表一個自定義的類類型(不是單一的簡單類型,比如'long'),然後你可以將它解析成一個映射不是新的'A'實例。最後,您可以從此地圖獲取屬性。你有什麼我在說什麼? –

回答

1

1.6有new feature其中@RabbitListener的參數類型被提供給JSON消息轉換器,它可以使用它來代替類型ID標頭。

不幸的是,這種機制不適用於@RabbitHandler,因爲在負載已被轉換之後,hander方法(必須)被確定爲之後

您不需要類路徑上的源類型,您可以配置轉換器使用不同的類型;有關我們發送Foo1並收到Foo2的示例,請參閱this test case

收聽者爲here,並且使用自定義轉換器的收聽者工廠配置爲here。瞭解idClassMapping如何設置爲轉換爲Foo2類型。

很明顯,該類型必須與源類型兼容,但它不必是同一類。