2016-04-07 13 views
0

Ich entwickle eine REST-API-Schnittstelle, die in einigen Teilen mit MQTT über die Paho-Client-Bibliothek interagieren muss. Durch die Konstruktion kann Paho Client nur ein Rückruf für jede Nachricht empfangen:Best Practices beim Umgang mit MQTT-Nachrichten mit der Paho Java-Bibliothek

mqttClient = new MqttClient(MQTT_ADDRESS, MQTT_CLIENT_ID); 
mqttClient.setCallback(new MqttCallbackImpl()); 
... 
private static class MqttCallbackImpl implements MqttCallback { 

    @Override 
    public void connectionLost(Throwable cause) { } 

    @Override 
    public void messageArrived(String topic, MqttMessage message) throws Exception { 
     switch(topic) { 
      // Endless list of cases... 
     } 
    } 

    @Override 
    public void deliveryComplete(IMqttDeliveryToken token) { } 
} 

Ich kämpfe den „richtigen“ Weg, herauszufinden, die empfangene Nachricht und entsprechend reagieren zu verarbeiten - wie würde ich meinen Rückruf schreiben durch die Vermeidung von eine gigantische switch() auf einige Teile der Nutzlast oder das Thema?

+0

In welchem ​​Usecase haben Sie genug Themen abonniert, dass eine If/Switch-Anweisung ein Problem darstellt? Sie müssen die Filterung irgendwo vornehmen – hardillb

+0

Haben Sie nichts gegen das Thema: meine Zweifel sind immer noch vorhanden, wenn Sie einige Informationen über die Nutzlast sowie –

Antwort

2

Kurze Antwort: Große if/switch-Anweisung ist die Lösung.

Wenn Sie Entscheidungen basierend auf der Nutzlast treffen müssen, müssen Sie die Nutzlast analysieren, egal was. Wenn Sie Payload-Typen basierend auf Themen filtern können, vereinfachen Sie die Dinge, indem Sie das Payload-Parsing an separate Methoden übergeben.

+0

OK, so scheint es, meine Frage war nicht so dumm, immerhin ... Ich bin etwas erleichtert :) –

2

Sie könnten die if/switch-Anweisung vermeiden, indem Sie einen Versand Map verwenden.

Definieren Sie eine einfache Schnittstelle (dies ist auch ein functional or Single Abstract Method interface) Ihre Nutzlasten

interface MqttMessageProcessor { 
    void processMessage(String topic, MqttMessage message) throws Exception; 
} 

Dann verschiedene konkrete Klassen implementieren auf Ihre Anforderungen und Karte jedes Thema mit der entsprechenden Instanz basiert zu handhaben. Wenn eine Nachricht eintrifft, wird sie an den richtigen Handler gesendet.

Map<String,MqttMessageProcessor> dispatchMap = new HashMap<>(); 
dispatchMap.put("topic1", new Payload1MessageProcessor()); 
dispatchMap.put("topic2", new Payload2MessageProcessor()); 


@Override 
public void messageArrived(String topic, MqttMessage message) throws Exception { 
    dispatchMap.get(topic).processMessage(topic, message); 
} 

Wenn Sie Java8 verwenden, können Sie Map.getOrDefault Methode verwenden, um leicht den Fall zu behandeln, wenn Sie einen allgemeinen Handler mögen.

@Override 
public void messageArrived(String topic, MqttMessage message) throws Exception { 
    dispatchMap.getOrDefault(topic, generalMessageProcessor).processMessage(topic, message); 
} 

Dies ist leichter zu pflegen, wenn neue Themen oder Payload-Formate hinzugefügt werden, da Sie nur eine einzige Zeile Code hinzufügen müssen, anstatt in riesige graben if/else Wasserfälle.

Dasselbe gilt, wenn Sie Nachrichten basierend auf einer Payload-Eigenschaft versenden müssen. Sie analysieren die Payload in messageArrived Callback und verwenden Sie dann eine Dispatcher-Map.

0

Dispatch-Karte schien eine gute Idee zu mir, bis ich, dass Sie gefunden kann tatsächlich getrennte Hörer pro Abonnement, zB:

client.subscribe(topic, new IMqttMessageListener() { 

     @Override 
     public void messageArrived(String topic, MqttMessage message) throws Exception { 
      // do something 
     } 

}); 

Dies sollten Sie Ihre Nachrichten-Handler, wenn Anweisungen ohne hässlich trennen helfen .