mq回调的类,一般都提供onMessage, messageArrived这样的方法让我们重写,
但是我们的需求是通过不同topic,去调用不同的方法,
如果使用if else开发,那都会写到一个文件,
回调和消息处理函数耦合度也很高,也不利于团队的开发,
通过改造可以达到以下效果,业务代码写到单独的文件中,只要加上注解就可以。
此处采用反射调用的方法处理,使业务代码与回调分离,代码看起来更优雅
(如果有其它更优雅的方法记得跟我说哦!大家多交流学习)
最终效果 :
@Slf4j
@MqttEvent
public class MqttConsumer {
@MyMqttTopic("mqtt.info")
public void info(List<Object> params) throws IllegalAccessException {
//处理业务代码
}
}
回调函数中只需要写一句处理消息的代码
建立事件相关的类!
/**
* @author louis
*/
public class Event {
private String name;
private IEventHandler handler;
public Event() {
}
public Event(String name, IEventHandler handler) {
this.name = name;
this.handler = handler;
}
public String getName() {
return name;
}
public void setHandler(IEventHandler handler) {
this.handler = handler;
}
public IEventHandler getHandler() {
return handler;
}
public void setName(String name) {
this.name = name;
}
}
事件触发类
/**
* @author louis
*/
public class EventEmitter {
private List<Event> eventList = new ArrayList<>();
void on(String eventName, IEventHandler iEventHandler) {
if (eventName == null || iEventHandler == null) {
throw new IllegalArgumentException("event is invalid");
}
eventList.add(new Event(eventName, iEventHandler));
}
void emit(String eventName, List<Object> params) throws Exception {
for (Event event : eventList) {
if (event.getName().equals(eventName)) {
event.getHandler().handle(params);
}
}
}
}
事件注册类
/**
* @author louis
*/
public class EventRegister {
private EventRegister() {
}
private static EventEmitter emitter = new EventEmitter();
public static void emit(String event, List<Object> params) throws Exception {
emitter.emit(event, params);
}
@SuppressWarnings("ALL")
public static void regist(String packageName, Class methodAnnotation, Class classAnnotation) throws Exception {
URL scannedUrl = Thread.currentThread().getContextClassLoader().getResource(packageName.replace(".", "/"));
if (scannedUrl == null) {
throw new IllegalArgumentException();
}
File scannedFile = new File(scannedUrl.getFile());
List<Class<?>> classes = ClassUtil.getClass(scannedFile, packageName);
for (Class<?> cls : classes) {
if (cls.isInterface()) {
continue;
}
Annotation classAnnotationObj = cls.getAnnotation(classAnnotation);
if (classAnnotationObj != null) {
Object handler = cls.newInstance();
Method[] methods = cls.getMethods();
for (Method method : methods) {
Annotation methodAnnoationObj = method.getAnnotation(methodAnnotation);
if (methodAnnoationObj != null) {
Method valueMethod = methodAnnoationObj.annotationType().getDeclaredMethod("value");
String value = (String)valueMethod.invoke(methodAnnoationObj);
if (value != null && !"".equals(value)) {
emitter.on(value, params -> {
method.invoke(handler, params);
});
}
}
}
}
}
}
}
事件处理接口
/**
* @author louis
*/
public interface IEventHandler {
void handle(List<?> params) throws Exception;
}
创建类注解
/**
* @author louis
*/
@Target(value = ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MqttEvent {
}
创建方法注解
/**
* @author louis
*/
@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyMqttTopic {
String value();
}
建立一个MessageHandle类,注册事件调用,并触发消息
@Slf4j
public class MessageHandler {
static {
try {
EventRegister.regist(MessageHandler.class.getPackage().getName(), MyMqttTopic.class, MqttEvent.class);
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
public static void handleMqttMessage(String topic, String message) throws Exception {
MqttMessage message1 = JSON.parseObject(message, MqttMessage.class);
if (isNotValidMessage(message1)) {
return;
}
EventRegister.emit("mqtt." + message1.getCmd(), new ArrayList<Object>() {{
add(message1);
}});
}
}
然后就可以编写业务代码