2016-07-25 4 views
1

So verwenden wir die nette @ RabbitHandler Annotation im Frühjahr-amqp, um Endpunkte zu erstellen, die dem Codierungsstil der RestControllers ähneln, aber mit Kaninchen unter der Haube arbeiten. Alles ist sehr nett und ordentlich und es funktioniert vor allem mit der dynamischen Auflösung von Methodenhandlern auf Signaturen. Allerdings stehen wir hier vor einer Kontroverse. So stellen Sie sich das Verfahren folgendeSpring amqp @RabbitListener Runtime-Typ Probleme

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

Dies wird durch fromMessage Methode auf der MessagingMessageConverter.java Klasse behandelt werden erhalten. An einem bestimmten Punkt in der Kette wird die Typinformation der Nachricht benötigt, damit der Handler-Resolver bestimmen kann, welche Methode mit der Payload der Nachricht aufgerufen werden soll und in welche Klasse die Payload serialisiert werden soll. Die Sache ist, wir verwenden MappingJackson2MessageConverter. Dennoch benötigen wir eine befüllte ____TypeId____-Prop der Nachricht mit dem vollständig qualifizierten Namen des Typs der Klasse. Das ist auch kein Problem. sehr gut durchdacht und durchdacht.

Das Problem tritt auf, wenn diese Klasse nicht im Klassenpfad ist. Das ist ein großer Schmerz für uns, da wir in einer Microservices-Umgebung arbeiten und einige unserer Services vollständig entkoppelt sind. Das ist ... wir wollen kein "gemeinsames" Artefakt haben, das unsere Datendomäne enthält, nur so können wir es zur Laufzeit sowohl im Sender als auch im Empfänger der Nachricht verwenden. Ich habe den Code durchgespielt, und ich sehe, wie diese Lochtyp-Situation gehandhabt wurde und warum sie so gemacht wird, wie sie ist.

Aber aus architektonischer Sicht ist dies ziemlich einschränkend ... Bedeutet das, dass wir definitiv Code zwischen Microservices teilen müssen, die ziemlich entkoppelt sind, nur um die Serialisierungs-/Deserialisierungs-/Methodenauflösungslogik zu erfüllen?

Vielleicht vermisse ich etwas oder übersehen einen anderen Weg, es zu tun. Wenn das der Fall ist, bin ich sicherlich offen für Vorschläge. Vielen Dank im Voraus für die Hilfe.

+0

Es klingt wie Sie können versuchen, interne Typen von Java-Lang selbst statt Ihrer benutzerdefinierten Typen. Weil Sie diese Klassen nicht für mehrere Dienste freigeben. Wenn wir dies ein Schema nennen, sollte es zwischen den Diensten gleich sein. Jetzt, wo Sie diese Klassen nicht teilen, sollten Sie sie auch nicht verwenden. Meine Segmentierung verwendet interne Typen wie 'java.lang.Map' oder' java.lang.List'. Sie müssen jedoch spezifische Aufgaben ausführen, um die Eigenschaften dort zu erhalten. Übrigens, wenn Sie aus dem Netzwerk übertragen werden, können Sie es in eine Map einfügen, wenn es sich nicht um einzelne primitive Typen handelt. Es ist intelligent genug für dich. –

+0

Ich verstehe nicht ganz die Logik hinter dem, was Sie sagen.Ich versuche, einige Daten zu verbrauchen und in ein Objekt zu analysieren. Wenn Sie einen Ruhe-Controller drücken, müssen Sie nicht den gleichen Typ mit dem Server teilen, oder? – Zahari

+0

Ja, Sie haben Recht. Ich möchte damit sagen, dass Sie Ihre Daten lesen und in eine Karte deserialisieren können, anstatt die Daten in einen benutzerdefinierten Klassentyp zu deserialisieren. Zum Beispiel gibt Ihr Remote-Dienst ein seriiertes 'A' zurück (zum Beispiel in json), welches' A' für einen angepassten Klassentyp (nicht einen einfachen Typ, wie 'long') steht, und dann können Sie es in ein map keine neue 'A'-Instanz. Am Ende können Sie Eigenschaften von dieser Karte erhalten. Hast du, was ich rede? –

Antwort

1

1.6 hat eine new feature, wo der Argumenttyp der @RabbitListener an den JSON-Nachrichtenkonverter geliefert wird, die es statt ID-Header verwenden kann.

Leider ist dieser Mechanismus nicht mit @RabbitHandler s funktioniert, weil die hander Methode ist (muss) bestimmt nach die Nutzlast umgewandelt wurde.

Sie benötigen den Quellentyp nicht für den Klassenpfad. Sie können den Konverter für die Verwendung eines anderen Typs konfigurieren. ein Beispiel, in dem wir eine Foo1 senden und eine Foo2 empfangen, siehe this test case.

Der Listener ist here und die Listener-Factory-Konfiguration mit benutzerdefinierten Konverter ist here. Sehen Sie, wie der idClassMapping eingerichtet ist, um in den Foo2 Typ zu konvertieren.

Offensichtlich muss der Typ mit dem Quelltyp kompatibel sein, aber es muss nicht die gleiche Klasse sein.

Verwandte Themen