我正在开发一个REST API接口,在某些部分,它必须通过Paho客户端库与MQTT交互。按照设计,Paho客户端只能对收到的每条消息进行一次回调:
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) { }
}
我正在努力找出处理收到的消息的“正确”方式并做出相应的反应 - 我如何通过避免在有效负载的某些部分或主题上使用巨大的开关()来编写回调?
答案 0 :(得分:3)
您可以使用调度Map
来避免使用if / switch语句。
定义一个简单的界面(这也是functional or Single Abstract Method interface)来处理你的有效载荷
interface MqttMessageProcessor {
void processMessage(String topic, MqttMessage message) throws Exception;
}
然后根据您的要求实现不同的具体类,并将每个主题映射到适当的实例。当消息到达时,它将被分派到正确的处理程序。
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);
}
如果您使用的是Java8,则可以使用Map.getOrDefault方法轻松处理需要常规处理程序的情况。
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
dispatchMap.getOrDefault(topic, generalMessageProcessor).processMessage(topic, message);
}
当添加新主题或有效负载格式时,这更容易维护,因为您只需添加一行代码而不是挖掘到巨大的if / else瀑布。
如果您需要根据某些有效内容属性调度消息,则同样适用。您在messageArrived
回调中解析有效负载,然后使用调度映射。
答案 1 :(得分:2)
简短回答:Big if / switch语句是解决方案。
如果必须根据有效负载做出决策,则必须解析有效负载而不管是什么。如果您可以根据主题过滤有效负载类型,那么您可以通过将有效负载解析移交给单独的方法来简化操作。
答案 2 :(得分:0)
发送地图对我来说似乎是一个好主意,直到我发现你可以每个订阅实际上有单独的侦听器,例如:
client.subscribe(topic, new IMqttMessageListener() {
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
// do something
}
});
这可以帮助您在没有丑陋的if语句的情况下分离您的消息处理程序。