diff --git a/src/main/java/com/xuxd/kafka/console/beans/vo/TopicPartitionVO.java b/src/main/java/com/xuxd/kafka/console/beans/vo/TopicPartitionVO.java new file mode 100644 index 0000000..9dcec1c --- /dev/null +++ b/src/main/java/com/xuxd/kafka/console/beans/vo/TopicPartitionVO.java @@ -0,0 +1,34 @@ +package com.xuxd.kafka.console.beans.vo; + +import java.util.List; +import java.util.stream.Collectors; +import lombok.Data; +import org.apache.kafka.common.Node; +import org.apache.kafka.common.TopicPartitionInfo; + +/** + * kafka-console-ui. + * + * @author xuxd + * @date 2021-09-23 15:15:29 + **/ +@Data +public class TopicPartitionVO { + + private int partition; + + private String leader; + + private List replicas; + + private List isr; + + public static TopicPartitionVO from(TopicPartitionInfo partitionInfo) { + TopicPartitionVO partitionVO = new TopicPartitionVO(); + partitionVO.setPartition(partitionInfo.partition()); + partitionVO.setLeader(partitionInfo.leader().toString()); + partitionVO.setReplicas(partitionInfo.replicas().stream().map(Node::toString).collect(Collectors.toList())); + partitionVO.setIsr(partitionInfo.isr().stream().map(Node::toString).collect(Collectors.toList())); + return partitionVO; + } +} diff --git a/src/main/java/com/xuxd/kafka/console/controller/TopicController.java b/src/main/java/com/xuxd/kafka/console/controller/TopicController.java index 1e9eedd..89b7ae7 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/TopicController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/TopicController.java @@ -31,4 +31,9 @@ public class TopicController { public Object deleteTopic(@RequestParam String topic) { return topicService.deleteTopic(topic); } + + @GetMapping("/partition") + public Object getTopicPartitionInfo(@RequestParam String topic) { + return topicService.getTopicPartitionInfo(topic); + } } diff --git a/src/main/java/com/xuxd/kafka/console/service/TopicService.java b/src/main/java/com/xuxd/kafka/console/service/TopicService.java index cdf16e4..2a48b6d 100644 --- a/src/main/java/com/xuxd/kafka/console/service/TopicService.java +++ b/src/main/java/com/xuxd/kafka/console/service/TopicService.java @@ -16,4 +16,6 @@ public interface TopicService { ResponseData getTopicList(String topic, TopicType type); ResponseData deleteTopic(String topic); + + ResponseData getTopicPartitionInfo(String topic); } diff --git a/src/main/java/com/xuxd/kafka/console/service/impl/TopicServiceImpl.java b/src/main/java/com/xuxd/kafka/console/service/impl/TopicServiceImpl.java index e116698..b9037fa 100644 --- a/src/main/java/com/xuxd/kafka/console/service/impl/TopicServiceImpl.java +++ b/src/main/java/com/xuxd/kafka/console/service/impl/TopicServiceImpl.java @@ -3,6 +3,7 @@ package com.xuxd.kafka.console.service.impl; import com.xuxd.kafka.console.beans.ResponseData; import com.xuxd.kafka.console.beans.enums.TopicType; import com.xuxd.kafka.console.beans.vo.TopicDescriptionVO; +import com.xuxd.kafka.console.beans.vo.TopicPartitionVO; import com.xuxd.kafka.console.service.TopicService; import java.util.Collections; import java.util.Comparator; @@ -70,4 +71,14 @@ public class TopicServiceImpl implements TopicService { Tuple2 tuple2 = topicConsole.deleteTopic(topic); return (Boolean) tuple2._1 ? ResponseData.create().success() : ResponseData.create().failed(tuple2._2); } + + @Override public ResponseData getTopicPartitionInfo(String topic) { + List list = topicConsole.getTopicList(Collections.singleton(topic)); + if (list.isEmpty()) { + return ResponseData.create().success(); + } + TopicDescription topicDescription = list.get(0); + + return ResponseData.create().data(topicDescription.partitions().stream().map(p -> TopicPartitionVO.from(p))).success(); + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 6c70eb8..903115c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -19,9 +19,9 @@ kafka: # 超级管理员密码 admin-password: admin # 启动自动创建配置的超级管理员用户 - admin-create: true + admin-create: false # broker连接的zk地址 - zookeeper-addr: localhost:2181 + zookeeper-addr: 'localhost:2181' sasl-jaas-config: org.apache.kafka.common.security.scram.ScramLoginModule required username="${kafka.config.admin-username}" password="${kafka.config.admin-password}"; spring: diff --git a/src/main/scala/kafka/console/TopicConsole.scala b/src/main/scala/kafka/console/TopicConsole.scala index 594efcf..19f433b 100644 --- a/src/main/scala/kafka/console/TopicConsole.scala +++ b/src/main/scala/kafka/console/TopicConsole.scala @@ -56,6 +56,12 @@ class TopicConsole(config: KafkaConfig) extends KafkaConsole(config: KafkaConfig } } + /** + * delete topic by topic name. + * + * @param topic topic name. + * @return result or : fail message. + */ def deleteTopic(topic: String): (Boolean, String) = { withAdminClientAndCatchError(admin => { admin.deleteTopics(Collections.singleton(topic), new DeleteTopicsOptions().retryOnQuotaViolation(false)).all().get(timeoutMs, TimeUnit.MILLISECONDS) diff --git a/ui/src/utils/api.js b/ui/src/utils/api.js index 1ffbc62..1bdea79 100644 --- a/ui/src/utils/api.js +++ b/ui/src/utils/api.js @@ -65,6 +65,10 @@ export const KafkaTopicApi = { url: "/topic", method: "delete", }, + getPartitionInfo: { + url: "/topic/partition", + method: "get", + }, }; export const KafkaConsumerApi = { diff --git a/ui/src/views/topic/PartitionInfo.vue b/ui/src/views/topic/PartitionInfo.vue new file mode 100644 index 0000000..2c0e31c --- /dev/null +++ b/ui/src/views/topic/PartitionInfo.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/ui/src/views/topic/Topic.vue b/ui/src/views/topic/Topic.vue index af4a3b8..c871c98 100644 --- a/ui/src/views/topic/Topic.vue +++ b/ui/src/views/topic/Topic.vue @@ -46,8 +46,10 @@ 新增/更新 -
- {{ text }} +
@@ -67,6 +69,11 @@
+
@@ -75,9 +82,10 @@ import request from "@/utils/request"; import { KafkaTopicApi } from "@/utils/api"; import notification from "ant-design-vue/es/notification"; +import PartitionInfo from "@/views/topic/PartitionInfo"; export default { name: "Topic", - components: {}, + components: { PartitionInfo }, data() { return { queryParam: { type: "all" }, @@ -92,6 +100,7 @@ export default { resourceType: "", username: "", }, + showPartitionInfo: false, }; }, methods: { @@ -130,6 +139,13 @@ export default { } }); }, + openPartitionInfoDialog(topic) { + this.selectDetail.resourceName = topic; + this.showPartitionInfo = true; + }, + closePartitionInfoDialog() { + this.showPartitionInfo = false; + }, }, created() { this.getTopicList();