@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) {

    //爲所欲爲
}

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章