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