@KafkaListener通过配置加载多个topic

       接到领导的一个需求,希望封装一下kafka的消费者,可以从配置读取topic进行消费;一开始首先想到的是用java kafka的高阶api手工根据topic创建消费者,一个topic创建一个消费者,依赖zookeeper完成kafka内部的balance和其他管理。后来领导又提出不要依赖zookeeper,之前老是rebalance失败。

       调研了一下,手工实现类似spring kafka的kafkaListener功能又成本太高。KafkaListener注解的topics属性又是常量,不能变量引入。之前看了一篇文章,在@PostConstruct或者继承InitializingBean的重写afterPropertiesSet方法的时候,System.setProperty手工添加topic到系统变量里,然后通过:

@org.springframework.kafka.annotation.KafkaListener(topics = "${topicName}")

这样的方式可以把配置中的topic读到注解的参数中,但是尼玛这个方法只能添加单个topic,多个topic怎么办!!!

       因为太生气,原谅我说了那么多废话。最后选择用反射的方式手工设置这个属性,代码如下:

@Service
public class KafkaHandlerService {

@Autowired
private Environment env;

@PostConstruct
public void initKafkaHandler() {

//比如topics是    topic1,topic2
    String topics = env.getProperty("xxx.xxx");
    String[] topicArray = topics.split(",");

//反射,listen是方法名,ConsumerRecord.class是参数的类,找到这个监听方法修改topics的值
    Method listen = KafkaHandlerService.class.getDeclaredMethod("listen", ConsumerRecord.class);
    KafkaListener kafkaListener = listen.getAnnotation(KafkaListener.class);
    InvocationHandler invocationHandler = Proxy.getInvocationHandler(kafkaListener);
    Field hField = invocationHandler.getClass().getDeclaredField("memberValues");
//默认的访问权限是不行的,要修改成true才能修改属性的值
    hField.setAccessible(true);
    Map memberValues = (Map) hField.get(invocationHandler);

    memberValues.put("topics", topicArray);
}

//topics属性都不用设置了,因为已经通过反射设置好了
@KafkaListener
public void listen(ConsumerRecord<?, ?> record) {

    //为所欲为
}

}

猜你喜欢

转载自blog.csdn.net/mrxiky/article/details/87711467