add h2 and save user info to db
This commit is contained in:
30
README.md
30
README.md
@@ -1,3 +1,33 @@
|
|||||||
# kafka可视化管理平台
|
# kafka可视化管理平台
|
||||||
目前支持部分acl功能管理操作
|
目前支持部分acl功能管理操作
|
||||||
实现:spring boot + scala + vue + kafka
|
实现: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
|
||||||
13
pom.xml
13
pom.xml
@@ -23,6 +23,7 @@
|
|||||||
<compiler.version>1.8</compiler.version>
|
<compiler.version>1.8</compiler.version>
|
||||||
<kafka.version>2.8.0</kafka.version>
|
<kafka.version>2.8.0</kafka.version>
|
||||||
<maven.assembly.plugin.version>3.0.0</maven.assembly.plugin.version>
|
<maven.assembly.plugin.version>3.0.0</maven.assembly.plugin.version>
|
||||||
|
<mybatis-plus-boot-starter.version>3.4.2</mybatis-plus-boot-starter.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -52,6 +53,18 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>${mybatis-plus-boot-starter.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.kafka</groupId>
|
<groupId>org.apache.kafka</groupId>
|
||||||
<artifactId>kafka-clients</artifactId>
|
<artifactId>kafka-clients</artifactId>
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package com.xuxd.kafka.console;
|
package com.xuxd.kafka.console;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
|
@MapperScan("com.xuxd.kafka.console.dao")
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
|
@EnableScheduling
|
||||||
public class KafkaConsoleUiApplication {
|
public class KafkaConsoleUiApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
19
src/main/java/com/xuxd/kafka/console/config/CronConfig.java
Normal file
19
src/main/java/com/xuxd/kafka/console/config/CronConfig.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -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<KafkaUserDO> {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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<String> 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,9 @@ import com.xuxd.kafka.console.beans.AclEntry;
|
|||||||
import com.xuxd.kafka.console.beans.CounterList;
|
import com.xuxd.kafka.console.beans.CounterList;
|
||||||
import com.xuxd.kafka.console.beans.CounterMap;
|
import com.xuxd.kafka.console.beans.CounterMap;
|
||||||
import com.xuxd.kafka.console.beans.ResponseData;
|
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.config.KafkaConfig;
|
||||||
|
import com.xuxd.kafka.console.dao.KafkaUserMapper;
|
||||||
import com.xuxd.kafka.console.service.AclService;
|
import com.xuxd.kafka.console.service.AclService;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
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.clients.admin.UserScramCredentialsDescription;
|
||||||
import org.apache.kafka.common.acl.AclBinding;
|
import org.apache.kafka.common.acl.AclBinding;
|
||||||
import org.apache.kafka.common.acl.AclOperation;
|
import org.apache.kafka.common.acl.AclOperation;
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -44,6 +47,12 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private KafkaConfig kafkaConfig;
|
private KafkaConfig kafkaConfig;
|
||||||
|
|
||||||
|
private final KafkaUserMapper kafkaUserMapper;
|
||||||
|
|
||||||
|
public AclServiceImpl(ObjectProvider<KafkaUserMapper> kafkaUserMapper) {
|
||||||
|
this.kafkaUserMapper = kafkaUserMapper.getIfAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
@Override public ResponseData<Set<String>> getUserList() {
|
@Override public ResponseData<Set<String>> getUserList() {
|
||||||
try {
|
try {
|
||||||
return ResponseData.create(Set.class).data(configConsole.getUserList(null)).success();
|
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) {
|
@Override public ResponseData addOrUpdateUser(String name, String pass) {
|
||||||
log.info("add or update user, username: {}, password: {}", name, 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<String, Object> 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) {
|
@Override public ResponseData deleteUser(String name) {
|
||||||
|
|||||||
@@ -24,6 +24,26 @@ kafka:
|
|||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: kafka-console-ui
|
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:
|
logging:
|
||||||
home: ./
|
home: ./
|
||||||
|
|
||||||
|
cron:
|
||||||
|
# clear-dirty-user: 0 * * * * ?
|
||||||
|
clear-dirty-user: 0 0 1 * * ?
|
||||||
|
|
||||||
|
|
||||||
|
#spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||||
5
src/main/resources/db/data-h2.sql
Normal file
5
src/main/resources/db/data-h2.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
-- DELETE FROM t_kafka_user;
|
||||||
|
--
|
||||||
|
-- INSERT INTO t_kafka_user (id, username, password) VALUES
|
||||||
|
-- (1, 'Jone', 'p1'),
|
||||||
|
-- (2, 'Jack', 'p2');
|
||||||
12
src/main/resources/db/schema-h2.sql
Normal file
12
src/main/resources/db/schema-h2.sql
Normal file
@@ -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)
|
||||||
|
);
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<a-input
|
<a-input
|
||||||
placeholder="username"
|
placeholder="username"
|
||||||
:allowClear="true"
|
:allowClear="true"
|
||||||
:maxLength="50"
|
:maxLength="30"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
'username',
|
'username',
|
||||||
{
|
{
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<a-input
|
<a-input
|
||||||
placeholder="password"
|
placeholder="password"
|
||||||
:allowClear="true"
|
:allowClear="true"
|
||||||
:maxLength="50"
|
:maxLength="30"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
'password',
|
'password',
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user