diff --git a/README.md b/README.md
index 266a5a6..af84ebe 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,33 @@
# kafka可视化管理平台
目前支持部分acl功能管理操作
实现:spring boot + scala + vue + kafka
+# 打包、部署
+## 打包
+环境要求
+* maven 3+
+* jdk 8
+```
+git clone https://github.com/xxd763795151/kafka-console-ui.git
+cd kafka-console-ui
+sh package.sh
+```
+打包成功,输出文件:target/kafka-console-ui.tar.gz
+## 部署
+```
+# 解压缩
+tar -zxvf kafka-console-ui.tar.gz
+# 进入解压缩后的目录
+cd kafka-console-ui
+# 编辑配置
+vim config/application.yml
+# 启动
+sh bin/start.sh
+# 停止
+sh bin/shutdown.sh
+```
+# 开发环境
+* jdk 8
+* idea
+* scala 2.13
+* maven 3+
+* webstorm
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 9c968d5..c66e164 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,6 +23,7 @@
1.8
2.8.0
3.0.0
+ 3.4.2
@@ -52,6 +53,18 @@
test
+
+ com.baomidou
+ mybatis-plus-boot-starter
+ ${mybatis-plus-boot-starter.version}
+
+
+
+ com.h2database
+ h2
+ runtime
+
+
org.apache.kafka
kafka-clients
diff --git a/src/main/java/com/xuxd/kafka/console/KafkaConsoleUiApplication.java b/src/main/java/com/xuxd/kafka/console/KafkaConsoleUiApplication.java
index 57c4199..953d031 100644
--- a/src/main/java/com/xuxd/kafka/console/KafkaConsoleUiApplication.java
+++ b/src/main/java/com/xuxd/kafka/console/KafkaConsoleUiApplication.java
@@ -1,9 +1,13 @@
package com.xuxd.kafka.console;
+import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+@MapperScan("com.xuxd.kafka.console.dao")
@SpringBootApplication
+@EnableScheduling
public class KafkaConsoleUiApplication {
public static void main(String[] args) {
diff --git a/src/main/java/com/xuxd/kafka/console/beans/dos/KafkaUserDO.java b/src/main/java/com/xuxd/kafka/console/beans/dos/KafkaUserDO.java
new file mode 100644
index 0000000..53e09c5
--- /dev/null
+++ b/src/main/java/com/xuxd/kafka/console/beans/dos/KafkaUserDO.java
@@ -0,0 +1,26 @@
+package com.xuxd.kafka.console.beans.dos;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * kafka-console-ui.
+ *
+ * @author xuxd
+ * @date 2021-09-06 15:09:23
+ **/
+@Data
+@TableName("t_kafka_user")
+public class KafkaUserDO {
+
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private String username;
+
+ private String password;
+
+ private String updateTime;
+}
diff --git a/src/main/java/com/xuxd/kafka/console/config/CronConfig.java b/src/main/java/com/xuxd/kafka/console/config/CronConfig.java
new file mode 100644
index 0000000..230e877
--- /dev/null
+++ b/src/main/java/com/xuxd/kafka/console/config/CronConfig.java
@@ -0,0 +1,19 @@
+package com.xuxd.kafka.console.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * kafka-console-ui.
+ *
+ * @author xuxd
+ * @date 2021-09-06 16:23:30
+ **/
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "cron")
+public class CronConfig {
+
+ private String clearDirtyUser;
+}
diff --git a/src/main/java/com/xuxd/kafka/console/dao/KafkaUserMapper.java b/src/main/java/com/xuxd/kafka/console/dao/KafkaUserMapper.java
new file mode 100644
index 0000000..48272be
--- /dev/null
+++ b/src/main/java/com/xuxd/kafka/console/dao/KafkaUserMapper.java
@@ -0,0 +1,15 @@
+package com.xuxd.kafka.console.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.xuxd.kafka.console.beans.dos.KafkaUserDO;
+
+/**
+ * kafka-console-ui.
+ *
+ * @author xuxd
+ * @date 2021-09-06 15:12:19
+ **/
+public interface KafkaUserMapper extends BaseMapper {
+
+
+}
diff --git a/src/main/java/com/xuxd/kafka/console/schedule/KafkaAclSchedule.java b/src/main/java/com/xuxd/kafka/console/schedule/KafkaAclSchedule.java
new file mode 100644
index 0000000..b49414a
--- /dev/null
+++ b/src/main/java/com/xuxd/kafka/console/schedule/KafkaAclSchedule.java
@@ -0,0 +1,45 @@
+package com.xuxd.kafka.console.schedule;
+
+import com.xuxd.kafka.console.dao.KafkaUserMapper;
+import java.util.Set;
+import kafka.console.KafkaConfigConsole;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+/**
+ * kafka-console-ui.
+ *
+ * @author xuxd
+ * @date 2021-09-06 16:22:33
+ **/
+@Slf4j
+@Component
+public class KafkaAclSchedule {
+
+ private final KafkaUserMapper userMapper;
+
+ private final KafkaConfigConsole configConsole;
+
+ public KafkaAclSchedule(KafkaUserMapper userMapper, KafkaConfigConsole configConsole) {
+ this.userMapper = userMapper;
+ this.configConsole = configConsole;
+ }
+
+ @Scheduled(cron = "${cron.clear-dirty-user}")
+ public void clearDirtyKafkaUser() {
+ log.info("Start clear dirty data for kafka user from database.");
+ Set userSet = configConsole.getUserList(null);
+ userMapper.selectList(null).forEach(u -> {
+ if (!userSet.contains(u.getUsername())) {
+ log.info("clear user: {} from database.", u.getUsername());
+ try {
+ userMapper.deleteById(u.getId());
+ } catch (Exception e) {
+ log.error("userMapper.deleteById error, user: " + u, e);
+ }
+ }
+ });
+ log.info("Clear end.");
+ }
+}
diff --git a/src/main/java/com/xuxd/kafka/console/service/impl/AclServiceImpl.java b/src/main/java/com/xuxd/kafka/console/service/impl/AclServiceImpl.java
index 5c8b849..30da112 100644
--- a/src/main/java/com/xuxd/kafka/console/service/impl/AclServiceImpl.java
+++ b/src/main/java/com/xuxd/kafka/console/service/impl/AclServiceImpl.java
@@ -4,7 +4,9 @@ import com.xuxd.kafka.console.beans.AclEntry;
import com.xuxd.kafka.console.beans.CounterList;
import com.xuxd.kafka.console.beans.CounterMap;
import com.xuxd.kafka.console.beans.ResponseData;
+import com.xuxd.kafka.console.beans.dos.KafkaUserDO;
import com.xuxd.kafka.console.config.KafkaConfig;
+import com.xuxd.kafka.console.dao.KafkaUserMapper;
import com.xuxd.kafka.console.service.AclService;
import java.util.Arrays;
import java.util.Collections;
@@ -20,6 +22,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.kafka.clients.admin.UserScramCredentialsDescription;
import org.apache.kafka.common.acl.AclBinding;
import org.apache.kafka.common.acl.AclOperation;
+import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -44,6 +47,12 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton {
@Autowired
private KafkaConfig kafkaConfig;
+ private final KafkaUserMapper kafkaUserMapper;
+
+ public AclServiceImpl(ObjectProvider kafkaUserMapper) {
+ this.kafkaUserMapper = kafkaUserMapper.getIfAvailable();
+ }
+
@Override public ResponseData> getUserList() {
try {
return ResponseData.create(Set.class).data(configConsole.getUserList(null)).success();
@@ -55,7 +64,24 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton {
@Override public ResponseData addOrUpdateUser(String name, String pass) {
log.info("add or update user, username: {}, password: {}", name, pass);
- return configConsole.addOrUpdateUser(name, pass) ? ResponseData.create().success() : ResponseData.create().failed();
+ if (!configConsole.addOrUpdateUser(name, pass)) {
+ log.error("add user to kafka failed.");
+ return ResponseData.create().failed("add user to kafka failed");
+ }
+ // save user info to database.
+ KafkaUserDO userDO = new KafkaUserDO();
+ userDO.setUsername(name);
+ userDO.setPassword(pass);
+ try {
+ Map map = new HashMap<>();
+ map.put("username", name);
+ kafkaUserMapper.deleteByMap(map);
+ kafkaUserMapper.insert(userDO);
+ }catch (Exception e) {
+ log.error("kafkaUserMapper.insert error.", e);
+ return ResponseData.create().failed(e.getMessage());
+ }
+ return ResponseData.create().success();
}
@Override public ResponseData deleteUser(String name) {
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 0898d33..031d6ce 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -24,6 +24,26 @@ kafka:
spring:
application:
name: kafka-console-ui
+ # h2 database
+ datasource:
+# url: jdbc:h2:file:/data/demo
+ url: jdbc:h2:mem:testdb
+ driver-class-name: org.h2.Driver
+ username: sa
+ password: password
+ schema: classpath:db/schema-h2.sql
+# data: classpath:db/data-h2.sql
+ h2:
+ console:
+ enabled: true
+
logging:
- home: ./
\ No newline at end of file
+ home: ./
+
+cron:
+# clear-dirty-user: 0 * * * * ?
+ clear-dirty-user: 0 0 1 * * ?
+
+
+#spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
\ No newline at end of file
diff --git a/src/main/resources/db/data-h2.sql b/src/main/resources/db/data-h2.sql
new file mode 100644
index 0000000..a9a1360
--- /dev/null
+++ b/src/main/resources/db/data-h2.sql
@@ -0,0 +1,5 @@
+-- DELETE FROM t_kafka_user;
+--
+-- INSERT INTO t_kafka_user (id, username, password) VALUES
+-- (1, 'Jone', 'p1'),
+-- (2, 'Jack', 'p2');
\ No newline at end of file
diff --git a/src/main/resources/db/schema-h2.sql b/src/main/resources/db/schema-h2.sql
new file mode 100644
index 0000000..1dbec00
--- /dev/null
+++ b/src/main/resources/db/schema-h2.sql
@@ -0,0 +1,12 @@
+-- DROP TABLE IF EXISTS T_KAKFA_USER;
+
+CREATE TABLE if not exists T_KAFKA_USER
+(
+ ID IDENTITY NOT NULL COMMENT '主键ID',
+ USERNAME VARCHAR(50) NOT NULL DEFAULT '' COMMENT '姓名',
+ PASSWORD VARCHAR(50) NOT NULL DEFAULT '' COMMENT '年龄',
+ UPDATE_TIME TIMESTAMP NOT NULL DEFAULT NOW() COMMENT '更新时间',
+ PRIMARY KEY (ID),
+ UNIQUE (USERNAME)
+);
+
diff --git a/src/test/java/com/xuxd/kafka/console/dao/KafkaUserMapperTest.java b/src/test/java/com/xuxd/kafka/console/dao/KafkaUserMapperTest.java
new file mode 100644
index 0000000..493523a
--- /dev/null
+++ b/src/test/java/com/xuxd/kafka/console/dao/KafkaUserMapperTest.java
@@ -0,0 +1,23 @@
+package com.xuxd.kafka.console.dao;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+/**
+ * kafka-console-ui.
+ *
+ * @author xuxd
+ * @date 2021-09-06 15:14:09
+ **/
+@SpringBootTest
+public class KafkaUserMapperTest {
+
+ @Autowired
+ private KafkaUserMapper userMapper;
+
+ @Test
+ public void testSelect() {
+ userMapper.selectList(null).forEach(System.out::println);
+ }
+}
\ No newline at end of file
diff --git a/ui/src/views/acl/UpdateUser.vue b/ui/src/views/acl/UpdateUser.vue
index 1ab141c..e687cae 100644
--- a/ui/src/views/acl/UpdateUser.vue
+++ b/ui/src/views/acl/UpdateUser.vue
@@ -17,7 +17,7 @@