最近在公司实习的时候看到代代码里面有这样的实现,记录一下
- 首先我们需要先定义一个注解用来保存 Consumer 的一些参数
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MessageQueue {
String topic();
String tag() default "";
String consumeGroup() default "";
}
- 设置几个 Consumer Bean 并对其中的方法使用注解
@Component
public class Consumer1 {
@MessageQueue(topic = "aa", consumeGroup = "test")
public void test(String msg) {
System.out.println("Consumer1 receive msg:" + msg);
}
}
@Component
public class Consumer2 {
@MessageQueue(topic = "aa", consumeGroup = "test2")
public void test(String msg) {
System.out.println("Consumer2 receive msg:" + msg);
}
}
- 监听
ApplicationStartedEvent遍历所有已初始化完的 Bean 并利用反射获取被注解的方法,之后使用 rocketmq-client 里的 Consumer 在回调函数里面调用这个方法
@Component
public class EventHolder {
// rocketmq proxy
String proxyHost = "127.0.0.1:8081";
Set<PushConsumer> consumers = new HashSet<>();
@EventListener
public void onEvent(ApplicationStartedEvent event) throws ClientException {
ConfigurableApplicationContext context = event.getApplicationContext();
// 遍历所有的Bean
for (String beanName : context.getBeanDefinitionNames()) {
// 获取Bean
Object bean = context.getBean(beanName);
// 使用反射根据注解获取对应的方法Method
Class<?> clazz = bean.getClass();
for (Method method : clazz.getMethods()) {
// 获取注解
MessageQueue messageQueue = method.getAnnotation(MessageQueue.class);
// 如果有注解,就调用对应的方法
if (messageQueue != null) {
String topic = messageQueue.topic();
String tag = messageQueue.tag();
String consumeGroup = messageQueue.consumeGroup();
// 构造一个Consumer
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder().setEndpoints(proxyHost).build();
ClientServiceProvider clientServiceProvider = ClientServiceProvider.loadService();
PushConsumer pushConsumer = clientServiceProvider.newPushConsumerBuilder()
.setClientConfiguration(clientConfiguration)
.setConsumerGroup(consumeGroup)
.setSubscriptionExpressions(Collections.singletonMap(topic, new FilterExpression(tag.isEmpty() ? "*" : tag, FilterExpressionType.TAG)))
.setMessageListener((messageView) -> {
String message = convertByteBufferToString(messageView.getBody());
try {
// 调用方法
method.invoke(bean, message);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
return ConsumeResult.SUCCESS;
})
.build();
consumers.add(pushConsumer);
}
}
}
}
/**
* 将 ByteBuffer 转换为字符串
*
* @param byteBuffer ByteBuffer 对象
* @return 转换后的字符串
*/
public static String convertByteBufferToString(ByteBuffer byteBuffer) {
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes); // 从 ByteBuffer 中读取字节
return new String(bytes, StandardCharsets.UTF_8); // 使用 UTF-8 字符集转换为字符串
}
}