提交 9366cc51 authored 作者: 黄承天's avatar 黄承天

feat(user): 分割了对禅道数据源的依赖 现在禅道数据源为可拆卸

上级 3157c085
......@@ -13,6 +13,11 @@
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.matrix</groupId>
<artifactId>kt-base</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
......@@ -66,18 +71,6 @@
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
......
package org.matrix.local.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.matrix.local.entity.Project;
import org.springframework.stereotype.Repository;
......@@ -13,7 +12,6 @@ import org.springframework.stereotype.Repository;
* @author matrix
* @since 2022-01-15
*/
@DS("master")
@Repository
public interface KsProjectMapper extends BaseMapper<Project> {
......
package org.matrix.local.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.matrix.local.entity.User;
import org.springframework.stereotype.Repository;
......@@ -13,7 +12,6 @@ import org.springframework.stereotype.Repository;
* @author matrix
* @since 2022-01-15
*/
@DS("master")
@Repository
public interface KsUserMapper extends BaseMapper<User> {
}
package org.matrix.local.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.matrix.local.entity.UserProject;
import org.springframework.stereotype.Repository;
......@@ -13,7 +12,6 @@ import org.springframework.stereotype.Repository;
* @author matrix
* @since 2022-01-15
*/
@DS("master")
@Repository
public interface KsUserProjectMapper extends BaseMapper<UserProject> {
}
package org.matrix.local.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.matrix.local.entity.User;
public interface IUserService extends IService<User> {
}
......@@ -2,12 +2,13 @@ package org.matrix.local.service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.SneakyThrows;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.matrix.local.entity.Project;
import org.matrix.local.entity.User;
import org.matrix.local.entity.UserProject;
import org.matrix.local.entity.config.UserConfig;
import org.matrix.local.entity.UserProject;
import org.matrix.local.entity.vo.LoginInfo;
import org.matrix.local.entity.vo.UserInfo;
import org.matrix.local.enums.ConfigType;
......@@ -38,7 +39,7 @@ import static java.util.Objects.nonNull;
*/
@Slf4j
@Service
public class UserService {
public class UserService extends ServiceImpl<KsUserMapper, User> implements IUserService {
public static final String COLLECTION_NAME = "user_config";
@Autowired
......@@ -54,6 +55,7 @@ public class UserService {
/**
* 如果是用户的第一次配置,即库里没有配置项,则全部保存
* ● 如果已有配置项,分为部分更新和全部更新
*
* @param userConfig 用户配置
* @param configType 配置类型
* @return 是否更新/插入成功
......@@ -64,34 +66,34 @@ public class UserService {
// 首先查询该用户是否存在,不存在就抛出异常
User dbUser = ksUserMapper.selectById(userId);
if (Objects.isNull(dbUser)){
if (Objects.isNull(dbUser)) {
throw new RuntimeException(String.format("保存用户配置 -- 数据库里没有用户id = %d 的用户!", userId));
}
// 如果是用户的第一次配置,即配置库里没有配置项,则全部保存
Query userQuery = Query.query(Criteria.where("userId").is(userId));
boolean firstConfig = !mongoTemplate.exists(userQuery, "user_config");
if (firstConfig){
if (firstConfig) {
mongoTemplate.save(userConfig, COLLECTION_NAME);
return true;
}else {
} else {
Update update;
if (configType == ConfigType.ALL){
log.info("[用户配置] 正在给id = {} 的用户更新<全局>配置,新的配置是 {}",userId,userConfig);
if (configType == ConfigType.ALL) {
log.info("[用户配置] 正在给id = {} 的用户更新<全局>配置,新的配置是 {}", userId, userConfig);
Document doc = new Document();
mongoTemplate.getConverter().write(userConfig,doc);
mongoTemplate.getConverter().write(userConfig, doc);
update = Update.fromDocument(doc);
mongoTemplate.upsert(userQuery, update, COLLECTION_NAME);
return true;
}else {
} else {
// 通过反射获取userConfig的属性值
String propertyName = configType.getPropertyName();
Field field = userConfig.getClass().getDeclaredField(propertyName);
field.setAccessible(true);
Object value = field.get(userConfig);
// 更新mongo中的数据
log.info("[用户配置] 正在给id = {} 的用户更新<{}>配置,新的{}是 {}",userId,configType.getDes(),configType.getDes(),value);
log.info("[用户配置] 正在给id = {} 的用户更新<{}>配置,新的{}是 {}", userId, configType.getDes(), configType.getDes(), value);
update = Update.update(configType.getPropertyName(), value);
mongoTemplate.upsert(userQuery, update, COLLECTION_NAME);
return true;
......
package org.matrix.remote.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.matrix.remote.entity.Change;
import org.springframework.stereotype.Repository;
......@@ -8,7 +7,6 @@ import org.springframework.stereotype.Repository;
/**
* @author c
*/
@DS("zentao")
@Repository
public interface ChangeMapper extends BaseMapper<Change> {
}
package org.matrix.remote.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.matrix.remote.entity.ZtProject;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
......@@ -13,7 +12,6 @@ import org.springframework.stereotype.Repository;
* @author c
* @since 2022-02-15
*/
@DS("zentao")
@Repository
public interface ZtProjectMapper extends BaseMapper<ZtProject> {
......
package org.matrix.remote.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.matrix.remote.entity.ZtUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
......@@ -13,7 +12,6 @@ import org.springframework.stereotype.Repository;
* @author c
* @since 2022-02-15
*/
@DS("zentao")
@Repository
public interface ZtUserMapper extends BaseMapper<ZtUser> {
......
package org.matrix.remote.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.matrix.remote.entity.ZtUserView;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
......@@ -13,8 +12,6 @@ import org.springframework.stereotype.Repository;
* @author c
* @since 2022-02-15
*/
@DS("zentao")
@Repository
public interface ZtUserViewMapper extends BaseMapper<ZtUserView> {
}
......@@ -2,6 +2,9 @@ package org.matrix.remote.service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.matrix.actuators.datasource.DataSourceDTO;
import org.matrix.actuators.datasource.IDataSourceService;
import org.matrix.local.entity.UserProject;
import org.matrix.local.mapper.KsProjectMapper;
import org.matrix.local.mapper.KsUserMapper;
import org.matrix.local.mapper.KsUserProjectMapper;
......@@ -17,6 +20,7 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 禅道数据全量同步工具
......@@ -41,6 +45,8 @@ public class DataAllCollector {
private KsUserProjectMapper ksUserProjectMapper;
@Autowired
private TransHelper transHelper;
@Autowired
private IDataSourceService dataSourceService;
private List<ZtUser> ztUsers = new ArrayList<>();
private List<ZtUserView> ztUserViews = new ArrayList<>();
......@@ -71,8 +77,10 @@ public class DataAllCollector {
* 从禅道数据库读取用户数据
*/
private void collectUser() {
dataSourceService.switchDataSource("zentao");
ztUsers.clear();
ztUsers = ztUserMapper.selectList(Wrappers.lambdaQuery());
dataSourceService.switchMainDataSource();
}
......@@ -80,24 +88,29 @@ public class DataAllCollector {
* 从禅道数据库读取项目数据
*/
private void collectProject() {
dataSourceService.switchDataSource("zentao");
ztProjects.clear();
ztProjects = ztProjectMapper.selectList(Wrappers.<ZtProject>lambdaQuery()
.eq(ZtProject::getDeleted, "0")
.eq(ZtProject::getProject, 0));
dataSourceService.switchMainDataSource();
}
/**
* 从禅道数据库读取用户相关项目关系数据
*/
private void collectUserView() {
dataSourceService.switchDataSource("zentao");
ztUserViews.clear();
ztUserViews = ztUserViewMapper.selectList(Wrappers.lambdaQuery());
dataSourceService.switchMainDataSource();
}
/**
* 将用户数据保存到本地
*/
private void saveUser() {
dataSourceService.switchMainDataSource();
ksUserMapper.delete(Wrappers.lambdaQuery());
ztUsers.stream()
.map(transHelper::user)
......@@ -108,6 +121,7 @@ public class DataAllCollector {
* 将项目数据保存到本地
*/
private void saveProject() {
dataSourceService.switchMainDataSource();
ksProjectMapper.delete(Wrappers.lambdaQuery());
ztProjects.stream()
.map(transHelper::project)
......@@ -118,10 +132,13 @@ public class DataAllCollector {
* 将用户项目关系数据保存到本地
*/
private void saveUserProject() {
ksUserProjectMapper.delete(Wrappers.lambdaQuery());
ztUserViews.stream()
dataSourceService.switchDataSource("zentao");
List<UserProject> userProjectList = ztUserViews.stream()
.flatMap(ztUserView -> transHelper.userProjects(ztUserView).stream())
.forEach(ksUserProjectMapper::insert);
.collect(Collectors.toList());
dataSourceService.switchMainDataSource();
ksUserProjectMapper.delete(Wrappers.lambdaQuery());
userProjectList.forEach(ksUserProjectMapper::insert);
}
}
......@@ -2,6 +2,7 @@ package org.matrix.remote.service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.matrix.actuators.datasource.IDataSourceService;
import org.matrix.local.entity.Project;
import org.matrix.local.entity.User;
import org.matrix.local.entity.UserProject;
......@@ -46,11 +47,14 @@ public class DataTriggerCollector {
private KsUserProjectMapper ksUserProjectMapper;
@Autowired
private TransHelper transHelper;
@Autowired
private IDataSourceService dataSourceService;
/**
* 执行一次增量同步
*/
public void execute() {
dataSourceService.switchDataSource("zentao");
Long count = changeMapper.selectCount(Wrappers.lambdaQuery());
boolean hasChanges = count > 0;
if (hasChanges) {
......@@ -58,6 +62,7 @@ public class DataTriggerCollector {
changes.forEach(this::handle);
}
changeMapper.delete(Wrappers.lambdaQuery());
dataSourceService.switchMainDataSource();
}
//----------------------------------------private-----------------------------------------
......@@ -84,8 +89,10 @@ public class DataTriggerCollector {
}
private void handleUser(Change change) {
dataSourceService.switchDataSource("zentao");
Integer id = Integer.valueOf(change.getId());
ZtUser ztUser = ztUserMapper.selectById(id);
dataSourceService.switchMainDataSource();
String type = change.getType();
switch (type) {
case "insert":
......@@ -108,8 +115,10 @@ public class DataTriggerCollector {
}
private void handleProject(Change change) {
dataSourceService.switchDataSource("zentao");
Integer id = Integer.valueOf(change.getId());
ZtProject ztProject = ztProjectMapper.selectById(id);
dataSourceService.switchMainDataSource();
String type = change.getType();
switch (type) {
case "insert":
......@@ -132,8 +141,10 @@ public class DataTriggerCollector {
}
private void handleUserView(Change change) {
dataSourceService.switchDataSource("zentao");
String account = change.getId();
ZtUserView ztUserView = ztUserViewMapper.selectOne(Wrappers.<ZtUserView>lambdaQuery().eq(ZtUserView::getAccount, account));
dataSourceService.switchMainDataSource();
String type = change.getType();
switch (type) {
case "insert":
......
package org.matrix.remote.service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.matrix.actuators.datasource.IDataSourceService;
import org.matrix.local.entity.Project;
import org.matrix.local.entity.User;
import org.matrix.local.entity.UserProject;
......@@ -30,6 +31,8 @@ public class TransHelper {
private ZtProjectMapper ztProjectMapper;
@Autowired
private KsUserMapper ksUserMapper;
@Autowired
private IDataSourceService dataSourceService;
public User user(ZtUser ztUser) {
return new User(Long.valueOf(ztUser.getId()), ztUser.getRealname(), ztUser.getAccount(), ztUser.getPassword());
......@@ -40,8 +43,10 @@ public class TransHelper {
}
List<UserProject> userProjects(ZtUserView ztUserView) {
dataSourceService.switchMainDataSource();
User user = ksUserMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getAccount, ztUserView.getAccount()));
if (nonNull(user)) {
dataSourceService.switchDataSource("zentao");
Long userId = user.getId();
return toList(ztUserView.getProjects()).stream()
.map(Integer::parseInt)
......
package org.matrix.remote.service;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.matrix.actuators.datasource.IDataSourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
......@@ -16,14 +17,14 @@ import org.springframework.stereotype.Service;
* PS:选择性使用
*/
@SuppressWarnings("SqlNoDataSourceInspection")
@DS("zentao")
@Service
public class TriggerInitial {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private IDataSourceService dataSourceService;
/**
* 创建增量数据表
......@@ -33,6 +34,7 @@ public class TriggerInitial {
* key:该条变化数据的唯一标识(一般为主键值 可以根据该标识在原表查出具体数据再做同步更新、删除操作则只需指定标识)
*/
public void createChangeTable() {
dataSourceService.switchDataSource("zentao");
String dropChangeTableSQL = "DROP TABLE IF EXISTS `zentao`.`kt_change`;\n";
jdbcTemplate.execute(dropChangeTableSQL);
String createChangeTableSQL = "CREATE TABLE `zentao`.`kt_change` (\n" +
......@@ -40,12 +42,14 @@ public class TriggerInitial {
" `entity` VARCHAR(255) NULL,\n" +
" `id` VARCHAR(255) NULL);\n";
jdbcTemplate.execute(createChangeTableSQL);
dataSourceService.switchMainDataSource();
}
/**
* 创建User表的触发器
*/
public void createUserTrigger() {
dataSourceService.switchDataSource("zentao");
String dropInsertTrigger = "DROP TRIGGER IF EXISTS `zentao`.`zt_user_AFTER_INSERT`;\n";
String createInsertTrigger = "CREATE TRIGGER `zentao`.`zt_user_AFTER_INSERT` AFTER INSERT ON `zt_user` FOR EACH ROW\n" +
"BEGIN\n" +
......@@ -70,12 +74,14 @@ public class TriggerInitial {
"END;";
jdbcTemplate.execute(dropDeleteTrigger);
jdbcTemplate.execute(createDeleteTrigger);
dataSourceService.switchMainDataSource();
}
/**
* 创建Project表的触发器
*/
public void createProjectTrigger() {
dataSourceService.switchDataSource("zentao");
String dropInsertTrigger = "DROP TRIGGER IF EXISTS `zentao`.`zt_project_AFTER_INSERT`;\n";
String createInsertTrigger = "CREATE TRIGGER `zentao`.`zt_project_AFTER_INSERT` AFTER INSERT ON `zt_project` FOR EACH ROW\n" +
"BEGIN\n" +
......@@ -100,12 +106,14 @@ public class TriggerInitial {
"END;";
jdbcTemplate.execute(dropDeleteTrigger);
jdbcTemplate.execute(createDeleteTrigger);
dataSourceService.switchMainDataSource();
}
/**
* 创建UserView表的触发器
*/
public void createUserViewTrigger() {
dataSourceService.switchDataSource("zentao");
String dropInsertTrigger = "DROP TRIGGER IF EXISTS `zentao`.`zt_userview_AFTER_INSERT`;\n";
String createInsertTrigger = "CREATE TRIGGER `zentao`.`zt_userview_AFTER_INSERT` AFTER INSERT ON `zt_userview` FOR EACH ROW\n" +
"BEGIN\n" +
......@@ -127,6 +135,7 @@ public class TriggerInitial {
"END;";
jdbcTemplate.execute(dropDeleteTrigger);
jdbcTemplate.execute(createDeleteTrigger);
dataSourceService.switchMainDataSource();
}
......
package org.matrix.remote.task;
import lombok.extern.slf4j.Slf4j;
import org.matrix.actuators.datasource.DataSourceDTO;
import org.matrix.actuators.datasource.IDataSourceService;
import org.matrix.remote.service.DataAllCollector;
import org.matrix.remote.service.DataTriggerCollector;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -19,32 +21,61 @@ public class DataCollectorTask implements CommandLineRunner {
private DataAllCollector dataAllCollector;
@Autowired
private DataTriggerCollector dataTriggerCollector;
@Autowired
private IDataSourceService dataSourceService;
/**
* 禅道数据同步组件是否运行的flag
* 如果未能读取到禅道数据源
* 则置为false
* 从而使禅道数据同步组件停止运行
*/
private boolean running = true;
/**
* 在项目刚启动时进行一次全量同步
* 后续则轮询进行增量同步
*/
@Override
public void run(String... args) {
initDataSource();
allCollect();
}
/**
* 全量同步禅道取的用户和项目数据
* 每小时收集一次
* 在项目启动时执行一次
*/
// @Scheduled(cron = "0 0 */1 * * ?")
public void allCollect() {
private void allCollect() {
if (running) {
dataAllCollector.execute();
}
}
/**
* 增量同步禅道取的用户和项目数据
* 每分钟收集一次
*/
@Scheduled(cron = "0 */1 * * * ?")
public void triggerCollect() {
private void triggerCollect() {
if (running) {
dataTriggerCollector.execute();
}
}
/**
* 在项目刚启动时进行一次全量同步
* 后续则轮询进行增量同步
*/
@Override
public void run(String... args) {
allCollect();
private void initDataSource() {
log.info("初始化禅道数据源...");
try {
String driverClassName = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://192.168.100.247:3306/zentao?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&&zeroDateTimeBehavior=convertToNull";
String username = "root";
String password = "123456";
DataSourceDTO zentao = new DataSourceDTO("zentao", driverClassName, url, username, password);
dataSourceService.add(zentao);
} catch (Exception e) {
log.warn("未能读取到禅道数据源...");
running = false;
}
}
}
......@@ -8,13 +8,10 @@ spring:
datasource:
master: #增加默认数据源
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.100.248:3306/key_stone?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: root
zentao:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.100.247:3306/zentao?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&&zeroDateTimeBehavior=convertToNull
url: jdbc:mysql://192.168.100.247:3306/key_stone?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: 123456
server:
port: 8180
baseJsPath: syntaxCheck.js
\ No newline at end of file
......@@ -2,11 +2,14 @@ package org.matrix.ktzentao;
import org.junit.jupiter.api.Test;
import org.matrix.ZentaoApplication;
import org.matrix.local.entity.User;
import org.matrix.local.service.UserService;
import org.matrix.remote.service.DataAllCollector;
import org.matrix.remote.service.TriggerInitial;
import org.matrix.remote.task.DataCollectorTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.client.RestTemplate;
@SpringBootTest(classes = ZentaoApplication.class)
class KtZentaoApplicationTests {
......@@ -17,13 +20,16 @@ class KtZentaoApplicationTests {
DataCollectorTask dataCollectorTask;
@Autowired
TriggerInitial triggerInitial;
@Autowired
UserService userService;
RestTemplate restTemplate = new RestTemplate();
@Test
void test() {
triggerInitial.createChangeTable();
triggerInitial.createUserTrigger();
triggerInitial.createProjectTrigger();
triggerInitial.createUserViewTrigger();
userService.save(new User(null,"none","none","none"));
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论