add
This commit is contained in:
7
pom.xml
7
pom.xml
@ -16,6 +16,8 @@
|
||||
<module>qiaoba-auth</module>
|
||||
</modules>
|
||||
|
||||
<description>qiaoba-boot 多租户管理系统</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
@ -39,7 +41,7 @@
|
||||
<druid.version>1.2.17</druid.version>
|
||||
<!-- HuTool工具包 -->
|
||||
<hutool.version>5.8.18</hutool.version>
|
||||
<!-- lock4j -->
|
||||
<!-- Lock4j -->
|
||||
<lock4j.version>2.2.5</lock4j.version>
|
||||
<!-- mysql驱动 -->
|
||||
<mysql-connector.version>8.0.33</mysql-connector.version>
|
||||
@ -75,9 +77,10 @@
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
<!-- Lock4j -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
|
||||
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
||||
<version>${lock4j.version}</version>
|
||||
</dependency>
|
||||
<!-- easy poi -->
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
<artifactId>qiaoba-apis</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<description>api模块, 用于抽取共用部分, 供其他模块调用</description>
|
||||
|
||||
<modules>
|
||||
<module>qiaoba-api-system</module>
|
||||
<module>qiaoba-api-job</module>
|
||||
|
@ -37,7 +37,7 @@ public interface SysMenuApiService {
|
||||
* @param param 条件
|
||||
* @return 菜单列表
|
||||
*/
|
||||
List<SysMenuVo> selectVoList(SysMenuParam param);
|
||||
List<SysMenu> selectList(SysMenuParam param);
|
||||
|
||||
/**
|
||||
* 查询详细
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-application</artifactId>
|
||||
|
||||
<description>总打包模块, 需要打包的模块, 引入到该模块中即可</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
|
@ -37,4 +37,4 @@ mybatis-plus:
|
||||
|
||||
logging:
|
||||
level:
|
||||
com.qiaoba: debug #开发环境输出sql日志
|
||||
com.qiaoba: trace #开发环境输出sql日志
|
||||
|
@ -28,7 +28,7 @@ spring:
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
password:
|
||||
#password:
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
lettuce:
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-auth</artifactId>
|
||||
|
||||
<description>鉴权模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
|
@ -10,8 +10,7 @@ import java.lang.annotation.*;
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface DataScope
|
||||
{
|
||||
public @interface DataScope {
|
||||
/**
|
||||
* 部门表的别名
|
||||
*/
|
||||
|
@ -11,7 +11,6 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 退出处理器
|
||||
|
@ -24,8 +24,8 @@ public interface OnlineUserService {
|
||||
/**
|
||||
* 删除(强退)
|
||||
*
|
||||
* @param username 登录账号
|
||||
* @param deviceSn 设备号
|
||||
* @param username 登录账号
|
||||
* @param deviceSn 设备号
|
||||
* @param deleteOwn 是否是删除自己
|
||||
*/
|
||||
void deleteOne(String username, String deviceSn, Boolean deleteOwn);
|
||||
@ -66,7 +66,7 @@ public interface OnlineUserService {
|
||||
/**
|
||||
* 分页查询列表
|
||||
*
|
||||
* @param pageNum pageNum
|
||||
* @param pageNum pageNum
|
||||
* @param pageSize pageSize
|
||||
* @param username username
|
||||
* @return list
|
||||
|
@ -20,5 +20,6 @@
|
||||
<module>qiaoba-common-poi</module>
|
||||
</modules>
|
||||
|
||||
<description>qiaoba-common: 新建的common统一放在此模块下面</description>
|
||||
|
||||
</project>
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-common-base</artifactId>
|
||||
|
||||
<description>通用-基础模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-common-datasource</artifactId>
|
||||
|
||||
<description>通用-数据源模块</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- Druid -->
|
||||
<dependency>
|
||||
@ -38,7 +40,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-web</artifactId>
|
||||
<artifactId>qiaoba-common-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -1,16 +1,11 @@
|
||||
package com.qiaoba.common.database.interceptors;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
|
||||
import com.qiaoba.common.base.context.BaseContext;
|
||||
import com.qiaoba.common.database.handlers.schema.SchemaHandlerFactory;
|
||||
import org.apache.ibatis.executor.statement.StatementHandler;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -23,7 +18,6 @@ import java.util.Objects;
|
||||
public class SchemaInterceptor implements InnerInterceptor {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void beforePrepare(StatementHandler sh, Connection conn, Integer transactionTimeout) {
|
||||
|
||||
|
@ -1,308 +0,0 @@
|
||||
package com.qiaoba.common.database.mapper;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||
import com.qiaoba.common.web.utils.BeanCopyUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 自定义 Mapper 接口, 实现 自定义扩展
|
||||
*
|
||||
* @param <M> mapper 泛型
|
||||
* @param <T> table 泛型
|
||||
* @param <V> vo 泛型
|
||||
* @author ailanyin
|
||||
* @since 2023-04-23 17:20:32
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> {
|
||||
|
||||
|
||||
/**
|
||||
* currentVoClass
|
||||
*
|
||||
* @return Vo
|
||||
*/
|
||||
default Class<V> currentVoClass() {
|
||||
return (Class<V>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* currentModelClass
|
||||
*
|
||||
* @return model
|
||||
*/
|
||||
default Class<T> currentModelClass() {
|
||||
return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* currentMapperClass
|
||||
*
|
||||
* @return mapper
|
||||
*/
|
||||
default Class<M> currentMapperClass() {
|
||||
return (Class<M>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*
|
||||
* @return all lst
|
||||
*/
|
||||
default List<T> selectList() {
|
||||
return this.selectList(new QueryWrapper<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增
|
||||
*
|
||||
* @param entityList list
|
||||
* @return 结果
|
||||
*/
|
||||
default boolean insertBatch(Collection<T> entityList) {
|
||||
return Db.saveBatch(entityList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新
|
||||
*
|
||||
* @param entityList list
|
||||
* @return 结果
|
||||
*/
|
||||
default boolean updateBatchById(Collection<T> entityList) {
|
||||
return Db.updateBatchById(entityList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量插入或更新
|
||||
*
|
||||
* @param entityList list
|
||||
* @return 结果
|
||||
*/
|
||||
default boolean insertOrUpdateBatch(Collection<T> entityList) {
|
||||
return Db.saveOrUpdateBatch(entityList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量插入(包含限制条数)
|
||||
*
|
||||
* @param entityList list
|
||||
* @param batchSize 最大调数
|
||||
* @return 结果
|
||||
*/
|
||||
default boolean insertBatch(Collection<T> entityList, int batchSize) {
|
||||
return Db.saveBatch(entityList, batchSize);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量更新(包含限制条数)
|
||||
*
|
||||
* @param entityList list
|
||||
* @param batchSize 最大调数
|
||||
* @return 结果
|
||||
*/
|
||||
default boolean updateBatchById(Collection<T> entityList, int batchSize) {
|
||||
return Db.updateBatchById(entityList, batchSize);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量插入或更新(包含限制条数)
|
||||
*
|
||||
* @param entityList list
|
||||
* @param batchSize 最大调数
|
||||
* @return 结果
|
||||
*/
|
||||
default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) {
|
||||
return Db.saveOrUpdateBatch(entityList, batchSize);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 插入或更新
|
||||
*
|
||||
* @param entity entity
|
||||
* @return 结果
|
||||
*/
|
||||
default boolean insertOrUpdate(T entity) {
|
||||
return Db.saveOrUpdate(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询Vo by id
|
||||
*
|
||||
* @param id 主键
|
||||
* @return Vo
|
||||
*/
|
||||
default V selectVoById(Serializable id) {
|
||||
return selectVoById(id, this.currentVoClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 ID 查询
|
||||
*
|
||||
* @param id 主键
|
||||
* @param voClass Vo
|
||||
* @param <C> 泛型
|
||||
* @return Vo
|
||||
*/
|
||||
default <C> C selectVoById(Serializable id, Class<C> voClass) {
|
||||
T obj = this.selectById(id);
|
||||
if (ObjectUtil.isNull(obj)) {
|
||||
return null;
|
||||
}
|
||||
return BeanCopyUtil.copy(obj, voClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过Ids 查询 list
|
||||
*
|
||||
* @param idList ids
|
||||
* @return list
|
||||
*/
|
||||
default List<V> selectVoBatchIds(Collection<? extends Serializable> idList) {
|
||||
return selectVoBatchIds(idList, this.currentVoClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过Ids 查询 list
|
||||
*
|
||||
* @param idList ids
|
||||
* @param voClass Vo
|
||||
* @param <C> 泛型
|
||||
* @return list
|
||||
*/
|
||||
default <C> List<C> selectVoBatchIds(Collection<? extends Serializable> idList, Class<C> voClass) {
|
||||
List<T> list = this.selectBatchIds(idList);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return BeanCopyUtil.copyList(list, voClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* selectVoByMap
|
||||
*
|
||||
* @param map map
|
||||
* @return Vo
|
||||
*/
|
||||
default List<V> selectVoByMap(Map<String, Object> map) {
|
||||
return selectVoByMap(map, this.currentVoClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* selectVoByMap
|
||||
*
|
||||
* @param map map
|
||||
* @param voClass Vo
|
||||
* @param <C> 泛型
|
||||
* @return Vo
|
||||
*/
|
||||
default <C> List<C> selectVoByMap(Map<String, Object> map, Class<C> voClass) {
|
||||
List<T> list = this.selectByMap(map);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return BeanCopyUtil.copyList(list, voClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件查询一条记录
|
||||
*
|
||||
* @param wrapper 条件
|
||||
* @return Vo
|
||||
*/
|
||||
default V selectVoOne(Wrapper<T> wrapper) {
|
||||
return selectVoOne(wrapper, this.currentVoClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件查询一条记录
|
||||
*
|
||||
* @param wrapper 条件
|
||||
* @param voClass Vo
|
||||
* @param <C> 泛型
|
||||
* @return Vo
|
||||
*/
|
||||
default <C> C selectVoOne(Wrapper<T> wrapper, Class<C> voClass) {
|
||||
T obj = this.selectOne(wrapper);
|
||||
if (ObjectUtil.isNull(obj)) {
|
||||
return null;
|
||||
}
|
||||
return BeanCopyUtil.copy(obj, voClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件查询所有
|
||||
*
|
||||
* @param wrapper 条件
|
||||
* @return list
|
||||
*/
|
||||
default List<V> selectVoList(Wrapper<T> wrapper) {
|
||||
return selectVoList(wrapper, this.currentVoClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件查询所有
|
||||
*
|
||||
* @param wrapper 条件
|
||||
* @param voClass Vo
|
||||
* @param <C> 泛型
|
||||
* @return list vo
|
||||
*/
|
||||
default <C> List<C> selectVoList(Wrapper<T> wrapper, Class<C> voClass) {
|
||||
List<T> list = this.selectList(wrapper);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return BeanCopyUtil.copyList(list, voClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询Vo
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param wrapper 条件
|
||||
* @param <P> 泛型
|
||||
* @return IPage
|
||||
*/
|
||||
default <P extends IPage<V>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper) {
|
||||
return selectVoPage(page, wrapper, this.currentVoClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询Vo
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param wrapper 条件
|
||||
* @param voClass Vo
|
||||
* @param <C> 泛型
|
||||
* @param <P> 泛型
|
||||
* @return IPage
|
||||
*/
|
||||
default <C, P extends IPage<C>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper, Class<C> voClass) {
|
||||
IPage<T> pageData = this.selectPage(page, wrapper);
|
||||
IPage<C> voPage = new Page<>(pageData.getCurrent(), pageData.getSize(), pageData.getTotal());
|
||||
if (CollUtil.isEmpty(pageData.getRecords())) {
|
||||
return (P) voPage;
|
||||
}
|
||||
voPage.setRecords(BeanCopyUtil.copyList(pageData.getRecords(), voClass));
|
||||
return (P) voPage;
|
||||
}
|
||||
|
||||
}
|
@ -2,6 +2,8 @@ package com.qiaoba.common.database.monitor;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import com.qiaoba.common.base.constants.TenantConstant;
|
||||
import com.qiaoba.common.base.enums.DataBaseEnum;
|
||||
import com.qiaoba.common.database.config.DynamicDataSourceConfig;
|
||||
@ -34,12 +36,16 @@ public class DatasourceConnectionMonitor {
|
||||
private DynamicDataSourceConfig dynamicDataSourceConfig;
|
||||
@Resource
|
||||
private DynamicDatasourceService dynamicDatasourceService;
|
||||
@Resource
|
||||
private LockTemplate lockTemplate;
|
||||
|
||||
private static Map<String, String> WAIT_UPDATE_DATASOURCE_STATUS = new ConcurrentHashMap<>();
|
||||
|
||||
private static final String LOCK_KEY = "lock4j:datasourceConnectionMonitor";
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// 1s钟运行一次
|
||||
// 1s 运行一次
|
||||
new Timer().schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -47,47 +53,77 @@ public class DatasourceConnectionMonitor {
|
||||
if (!DynamicDataSourceConfig.COMPLETE_LOAD_DATASOURCE) {
|
||||
return;
|
||||
}
|
||||
log.trace("开始运行数据源监控线程, 时间: {}", new Date());
|
||||
for (String tenantId : DynamicDataSourceConfig.TENANT_IDS) {
|
||||
Object primary = DynamicDataSourceConfig.PRIMARY_DATASOURCE_MAP.get(tenantId);
|
||||
if (Objects.isNull(primary)) {
|
||||
// 说明初始化主要数据源的时候出错
|
||||
log.error("租户[{}]-目前主数据源异常, 开始切换备用数据源", tenantId);
|
||||
// 切换备用数据源
|
||||
changePrimary(tenantId);
|
||||
} else {
|
||||
DruidDataSource dataSource = (DruidDataSource) primary;
|
||||
try {
|
||||
Connection connection = dataSource.getConnection();
|
||||
if (check(connection, tenantId)) {
|
||||
// 说明数据源正常
|
||||
log.trace("租户[{}]-目前主数据源正常, 无需切换数据源", tenantId);
|
||||
// 主数据 处理任务
|
||||
if (TenantConstant.DEFAULT_TENANT_ID.equals(tenantId)) {
|
||||
handleJob();
|
||||
}
|
||||
IoUtil.close(connection);
|
||||
continue;
|
||||
}
|
||||
|
||||
log.error("租户[{}]-目前主数据源异常, 开始切换备用数据源", tenantId);
|
||||
IoUtil.close(connection);
|
||||
// 主数据源异常 切换备用数据源
|
||||
if (changePrimary(tenantId)) {
|
||||
// 备用切换成功, 关闭原有异常数据源
|
||||
IoUtil.close(dataSource);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// expire = -1 锁自动续期, 防止数据源过多或异常等待, 超过默认锁 30s
|
||||
final LockInfo lockInfo = lockTemplate.lock(LOCK_KEY, -1, 1000);
|
||||
//申请锁失败 说明集群中其他设备正在执行监控
|
||||
if (null == lockInfo) {
|
||||
return;
|
||||
}
|
||||
//申请锁成功
|
||||
try {
|
||||
// 执行监控
|
||||
datasourceConnectionMonitor();
|
||||
} finally {
|
||||
// 释放锁
|
||||
lockTemplate.releaseLock(lockInfo);
|
||||
}
|
||||
|
||||
log.trace("结束运行数据源监控线程, 时间: {}", new Date());
|
||||
}
|
||||
}, 0, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心监控内容
|
||||
*/
|
||||
private void datasourceConnectionMonitor() {
|
||||
log.trace("开始运行数据源监控线程, 时间: {}", new Date());
|
||||
for (String tenantId : DynamicDataSourceConfig.TENANT_IDS) {
|
||||
Object primary = DynamicDataSourceConfig.PRIMARY_DATASOURCE_MAP.get(tenantId);
|
||||
if (Objects.isNull(primary)) {
|
||||
// 说明初始化主要数据源的时候出错
|
||||
log.error("租户[{}]-目前主数据源异常, 开始切换备用数据源", tenantId);
|
||||
// 切换备用数据源
|
||||
changePrimary(tenantId);
|
||||
} else {
|
||||
DruidDataSource dataSource = (DruidDataSource) primary;
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = dataSource.getConnection();
|
||||
if (check(connection, tenantId)) {
|
||||
// 说明数据源正常
|
||||
log.trace("租户[{}]-目前主数据源正常, 无需切换数据源", tenantId);
|
||||
// 主数据 处理任务
|
||||
if (TenantConstant.DEFAULT_TENANT_ID.equals(tenantId)) {
|
||||
handleJob();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
log.error("租户[{}]-目前主数据源异常, 开始切换备用数据源", tenantId);
|
||||
// 主数据源异常 切换备用数据源
|
||||
if (changePrimary(tenantId)) {
|
||||
// 备用切换成功, 关闭原有异常数据源
|
||||
IoUtil.close(dataSource);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
|
||||
} finally {
|
||||
IoUtil.close(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.trace("结束运行数据源监控线程, 时间: {}", new Date());
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查数据源连接可用性
|
||||
*
|
||||
* @param conn 数据源
|
||||
* @param tenantId 租户ID
|
||||
* @return 结果
|
||||
*/
|
||||
private Boolean check(Connection conn, String tenantId) {
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
|
@ -8,7 +8,13 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* DataSourceProperties
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022-09-22 04:20:28
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "qiaoba")
|
||||
@Data
|
||||
|
@ -5,7 +5,8 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
|
||||
/**
|
||||
* JdbcUtil
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-common-doc</artifactId>
|
||||
|
||||
<description>通用-文档(Knife4j)模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
@ -21,4 +23,4 @@
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-common-poi</artifactId>
|
||||
|
||||
<description>通用-poi(Excel, Word, Pdf等)模块</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- easypoi -->
|
||||
<dependency>
|
||||
|
@ -11,11 +11,13 @@
|
||||
|
||||
<artifactId>qiaoba-common-redis</artifactId>
|
||||
|
||||
<description>通用-Redis模块</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- lock4j -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>lock4j-redis-template-spring-boot-starter</artifactId>
|
||||
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-common-web</artifactId>
|
||||
|
||||
<description>通用-Web模块(有controller的模块必须引入此模块)</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
|
@ -1,227 +0,0 @@
|
||||
package com.qiaoba.common.web.utils;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.SimpleCache;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.cglib.beans.BeanCopier;
|
||||
import org.springframework.cglib.beans.BeanMap;
|
||||
import org.springframework.cglib.core.Converter;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* bean深拷贝工具(基于 cglib 性能优异)
|
||||
* <p>
|
||||
* 重点 cglib 不支持 拷贝到链式对象
|
||||
* 例如: 源对象 拷贝到 目标(链式对象)
|
||||
* 请区分好`浅拷贝`和`深拷贝`再做使用
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023-04-23 15:34:59
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class BeanCopyUtil {
|
||||
|
||||
/**
|
||||
* 单对象基于class创建拷贝
|
||||
*
|
||||
* @param source 数据来源实体
|
||||
* @param desc 描述对象 转换后的对象
|
||||
* @return desc
|
||||
*/
|
||||
public static <T, V> V copy(T source, Class<V> desc) {
|
||||
if (ObjectUtil.isNull(source)) {
|
||||
return null;
|
||||
}
|
||||
if (ObjectUtil.isNull(desc)) {
|
||||
return null;
|
||||
}
|
||||
final V target = ReflectUtil.newInstanceIfPossible(desc);
|
||||
return copy(source, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单对象基于对象创建拷贝
|
||||
*
|
||||
* @param source 数据来源实体
|
||||
* @param desc 转换后的对象
|
||||
* @return desc
|
||||
*/
|
||||
public static <T, V> V copy(T source, V desc) {
|
||||
if (ObjectUtil.isNull(source)) {
|
||||
return null;
|
||||
}
|
||||
if (ObjectUtil.isNull(desc)) {
|
||||
return null;
|
||||
}
|
||||
BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(source.getClass(), desc.getClass(), null);
|
||||
beanCopier.copy(source, desc, null);
|
||||
return desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表对象基于class创建拷贝
|
||||
*
|
||||
* @param sourceList 数据来源实体列表
|
||||
* @param desc 描述对象 转换后的对象
|
||||
* @return desc
|
||||
*/
|
||||
public static <T, V> List<V> copyList(List<T> sourceList, Class<V> desc) {
|
||||
if (ObjectUtil.isNull(sourceList)) {
|
||||
return null;
|
||||
}
|
||||
if (CollUtil.isEmpty(sourceList)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return toList(sourceList, source -> {
|
||||
V target = ReflectUtil.newInstanceIfPossible(desc);
|
||||
copy(source, target);
|
||||
return target;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* bean拷贝到map
|
||||
*
|
||||
* @param bean 数据来源实体
|
||||
* @return map对象
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Map<String, Object> copyToMap(T bean) {
|
||||
if (ObjectUtil.isNull(bean)) {
|
||||
return null;
|
||||
}
|
||||
return BeanMap.create(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* map拷贝到bean
|
||||
*
|
||||
* @param map 数据来源
|
||||
* @param beanClass bean类
|
||||
* @return bean对象
|
||||
*/
|
||||
public static <T> T mapToBean(Map<String, Object> map, Class<T> beanClass) {
|
||||
if (MapUtil.isEmpty(map)) {
|
||||
return null;
|
||||
}
|
||||
if (ObjectUtil.isNull(beanClass)) {
|
||||
return null;
|
||||
}
|
||||
T bean = ReflectUtil.newInstanceIfPossible(beanClass);
|
||||
return mapToBean(map, bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* map拷贝到bean
|
||||
*
|
||||
* @param map 数据来源
|
||||
* @param bean bean对象
|
||||
* @return bean对象
|
||||
*/
|
||||
public static <T> T mapToBean(Map<String, Object> map, T bean) {
|
||||
if (MapUtil.isEmpty(map)) {
|
||||
return null;
|
||||
}
|
||||
if (ObjectUtil.isNull(bean)) {
|
||||
return null;
|
||||
}
|
||||
BeanMap.create(bean).putAll(map);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* map拷贝到map
|
||||
*
|
||||
* @param map 数据来源
|
||||
* @param clazz 返回的对象类型
|
||||
* @return map对象
|
||||
*/
|
||||
public static <T, V> Map<String, V> mapToMap(Map<String, T> map, Class<V> clazz) {
|
||||
if (MapUtil.isEmpty(map)) {
|
||||
return null;
|
||||
}
|
||||
if (ObjectUtil.isNull(clazz)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, V> copyMap = new LinkedHashMap<>(map.size());
|
||||
map.forEach((k, v) -> copyMap.put(k, copy(v, clazz)));
|
||||
return copyMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* BeanCopier属性缓存<br>
|
||||
* 缓存用于防止多次反射造成的性能问题
|
||||
*
|
||||
* @author Looly
|
||||
* @since 5.4.1
|
||||
*/
|
||||
public enum BeanCopierCache {
|
||||
/**
|
||||
* BeanCopier属性缓存单例
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
private final SimpleCache<String, BeanCopier> cache = new SimpleCache<>();
|
||||
|
||||
/**
|
||||
* 获得类与转换器生成的key在{@link BeanCopier}的Map中对应的元素
|
||||
*
|
||||
* @param srcClass 源Bean的类
|
||||
* @param targetClass 目标Bean的类
|
||||
* @param converter 转换器
|
||||
* @return Map中对应的BeanCopier
|
||||
*/
|
||||
public BeanCopier get(Class<?> srcClass, Class<?> targetClass, Converter converter) {
|
||||
final String key = genKey(srcClass, targetClass, converter);
|
||||
return cache.get(key, () -> BeanCopier.create(srcClass, targetClass, converter != null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得类与转换器生成的key
|
||||
*
|
||||
* @param srcClass 源Bean的类
|
||||
* @param targetClass 目标Bean的类
|
||||
* @param converter 转换器
|
||||
* @return 属性名和Map映射的key
|
||||
*/
|
||||
private String genKey(Class<?> srcClass, Class<?> targetClass, Converter converter) {
|
||||
final StringBuilder key = StrUtil.builder()
|
||||
.append(srcClass.getName()).append('#').append(targetClass.getName());
|
||||
if (null != converter) {
|
||||
key.append('#').append(converter.getClass().getName());
|
||||
}
|
||||
return key.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将collection转化为List集合,但是两者的泛型不同<br>
|
||||
* <B>{@code Collection<E> ------> List<T> } </B>
|
||||
*
|
||||
* @param collection 需要转化的集合
|
||||
* @param function collection中的泛型转化为list泛型的lambda表达式
|
||||
* @param <E> collection中的泛型
|
||||
* @param <T> List中的泛型
|
||||
* @return 转化后的list
|
||||
*/
|
||||
private static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) {
|
||||
if (CollUtil.isEmpty(collection)) {
|
||||
return CollUtil.newArrayList();
|
||||
}
|
||||
return collection
|
||||
.stream()
|
||||
.map(function)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package com.qiaoba.common.web.utils;
|
||||
|
||||
import cn.hutool.http.ContentType;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
|
||||
|
@ -20,4 +20,6 @@
|
||||
<module>qiaoba-module-demo</module>
|
||||
</modules>
|
||||
|
||||
<description>qiaoba-modules: 新建的模块, 统一放在这个模块下面</description>
|
||||
|
||||
</project>
|
||||
|
@ -11,6 +11,10 @@
|
||||
|
||||
<artifactId>qiaoba-module-demo</artifactId>
|
||||
|
||||
<description>
|
||||
示例模块
|
||||
此模块主要用于典型案例的demo, 切勿引入到 qiaoba-application 模块中
|
||||
</description>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
@ -24,5 +28,9 @@
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-doc</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
@ -0,0 +1,18 @@
|
||||
package com.qiaoba.module.demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* DemoApplication
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/6/25 8:52
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class DemoApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DemoApplication.class, args);
|
||||
}
|
||||
}
|
@ -2,22 +2,34 @@ package com.qiaoba.module.demo.controller;
|
||||
|
||||
import com.baomidou.lock.annotation.Lock4j;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
import com.qiaoba.module.demo.service.Lock4jService;
|
||||
import com.qiaoba.module.demo.service.DemoLock4jService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Demo-Lock4j web层
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022-09-22 04:20:28
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/demo/lock4j")
|
||||
@RequiredArgsConstructor
|
||||
public class Lock4jController {
|
||||
@Tag(name = "Demo-Lock4j")
|
||||
@Slf4j
|
||||
public class DemoLock4jController {
|
||||
|
||||
private final Lock4jService lock4jService;
|
||||
private final DemoLock4jService demoLock4JService;
|
||||
|
||||
@GetMapping("/api-lock")
|
||||
public AjaxResult apiLock() {
|
||||
lock4jService.apiLock();
|
||||
log.info("开始执行 apiLock, 当前线程{}", Thread.currentThread().getName());
|
||||
demoLock4JService.apiLock();
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ -29,9 +41,10 @@ public class Lock4jController {
|
||||
* @return AjaxResult
|
||||
*/
|
||||
@GetMapping("/annotation-lock")
|
||||
@Lock4j(keys = {"#accountId"}, expire = 20000, acquireTimeout = 10000)
|
||||
@Lock4j(name = "annotationLock", acquireTimeout = 1000)
|
||||
public AjaxResult annotationLock() {
|
||||
lock4jService.annotationLock();
|
||||
log.info("开始执行 annotationLock, 当前线程{}", Thread.currentThread().getName());
|
||||
demoLock4JService.annotationLock();
|
||||
return AjaxResult.success();
|
||||
}
|
||||
}
|
@ -1,6 +1,13 @@
|
||||
package com.qiaoba.module.demo.service;
|
||||
|
||||
public interface Lock4jService {
|
||||
/**
|
||||
* Demo-Lock4j 业务层
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022-09-22 04:20:28
|
||||
*/
|
||||
public interface DemoLock4jService {
|
||||
|
||||
/**
|
||||
* 分布式锁-编程式加锁
|
@ -4,15 +4,22 @@ import cn.hutool.core.thread.ThreadUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
import com.qiaoba.module.demo.service.Lock4jService;
|
||||
import com.qiaoba.module.demo.service.DemoLock4jService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Demo-Lock4j 业务层实现
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022-09-22 04:20:28
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class Lock4jServiceImpl implements Lock4jService {
|
||||
public class DemoLock4jServiceImpl implements DemoLock4jService {
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
@ -20,15 +27,16 @@ public class Lock4jServiceImpl implements Lock4jService {
|
||||
public void apiLock() {
|
||||
//... 各种不需要上锁的操作
|
||||
String lockKey = "lock4j:apiLock";
|
||||
final LockInfo lockInfo = lockTemplate.lock(lockKey);
|
||||
// expire = -1 锁自动续期
|
||||
final LockInfo lockInfo = lockTemplate.lock(lockKey, -1, 1000);
|
||||
//申请锁失败
|
||||
if (null == lockInfo) {
|
||||
throw new ServiceException("业务处理中,请稍后再试...");
|
||||
}
|
||||
//申请锁成功
|
||||
try {
|
||||
ThreadUtil.sleep(10 * 1000);
|
||||
log.info("执行 apiLock, 当前线程{}", Thread.currentThread().getName());
|
||||
ThreadUtil.sleep(30 * 1000);
|
||||
log.info("执行完毕 apiLock, 当前线程{}", Thread.currentThread().getName());
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lockInfo);
|
||||
}
|
||||
@ -38,6 +46,6 @@ public class Lock4jServiceImpl implements Lock4jService {
|
||||
public void annotationLock() {
|
||||
// 休眠 10s
|
||||
ThreadUtil.sleep(10 * 1000);
|
||||
log.info("执行 apiLock, 当前线程{}", Thread.currentThread().getName());
|
||||
log.info("执行完毕 annotationLock, 当前线程{}", Thread.currentThread().getName());
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
path: /swagger-ui.html
|
||||
tags-sorter: alpha
|
||||
operations-sorter: alpha
|
||||
api-docs:
|
||||
path: /v3/api-docs
|
||||
group-configs:
|
||||
- group: 'Demo'
|
||||
paths-to-match: '/**'
|
||||
packages-to-scan: com.qiaoba.module.demo.controller
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-module-file</artifactId>
|
||||
|
||||
<description>文件模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
|
@ -11,5 +11,6 @@
|
||||
|
||||
<artifactId>qiaoba-module-job</artifactId>
|
||||
|
||||
<description>定时任务模块</description>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-module-monitor</artifactId>
|
||||
|
||||
<description>监控模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-module-system</artifactId>
|
||||
|
||||
<description>系统模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
|
@ -41,7 +41,7 @@ public class SysDictTypeController {
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, SysDictTypeParam param) throws Exception {
|
||||
List<SysDictType> list = sysDictTypeService.selectList(param);
|
||||
ExcelUtil.exportExcel(list, SysDictType.class, "字典类型" , response);
|
||||
ExcelUtil.exportExcel(list, SysDictType.class, "字典类型", response);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('system:dict:query')")
|
||||
|
@ -2,7 +2,6 @@ package com.qiaoba.module.system.controller;
|
||||
|
||||
import com.qiaoba.api.system.entity.SysMenu;
|
||||
import com.qiaoba.api.system.entity.param.SysMenuParam;
|
||||
import com.qiaoba.api.system.entity.vo.SysMenuVo;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
import com.qiaoba.module.system.service.SysMenuService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -32,7 +31,7 @@ public class SysMenuController {
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获取列表")
|
||||
public AjaxResult list(SysMenuParam param) {
|
||||
List<SysMenuVo> menus = sysMenuService.selectVoList(param);
|
||||
List<SysMenu> menus = sysMenuService.selectList(param);
|
||||
return AjaxResult.success(menus);
|
||||
}
|
||||
|
||||
@ -67,7 +66,7 @@ public class SysMenuController {
|
||||
@GetMapping("/tree-select")
|
||||
@Operation(summary = "构建菜单树")
|
||||
public AjaxResult treeSelect(SysMenuParam param) {
|
||||
List<SysMenuVo> menus = sysMenuService.selectVoList(param);
|
||||
List<SysMenu> menus = sysMenuService.selectList(param);
|
||||
return AjaxResult.success(sysMenuService.buildMenuTree(menus));
|
||||
}
|
||||
|
||||
@ -76,7 +75,7 @@ public class SysMenuController {
|
||||
public AjaxResult roleMenuTreeSelect(@PathVariable("roleId") String roleId) {
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("checkedKeys", sysMenuService.selectMenuIdsByRoleId(roleId));
|
||||
ajax.put("menus", sysMenuService.buildMenuTree(sysMenuService.selectVoList(new SysMenuParam())));
|
||||
ajax.put("menus", sysMenuService.buildMenuTree(sysMenuService.selectList(new SysMenuParam())));
|
||||
return ajax;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.qiaoba.module.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.qiaoba.api.system.entity.SysMenu;
|
||||
import com.qiaoba.api.system.entity.vo.SysMenuVo;
|
||||
import com.qiaoba.common.database.annotations.SelectOneRow;
|
||||
import com.qiaoba.common.database.mapper.BaseMapperPlus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -15,7 +15,7 @@ import java.util.Set;
|
||||
* @version 1.0
|
||||
* @since 2023/5/5 11:36
|
||||
*/
|
||||
public interface SysMenuMapper extends BaseMapperPlus<SysMenuMapper, SysMenu, SysMenuVo> {
|
||||
public interface SysMenuMapper extends BaseMapper<SysMenu> {
|
||||
|
||||
/**
|
||||
* 校验菜单名称是否唯一
|
||||
|
@ -1,8 +1,6 @@
|
||||
package com.qiaoba.module.system.service;
|
||||
|
||||
import com.qiaoba.api.system.entity.SysUser;
|
||||
import com.qiaoba.api.system.entity.dto.LoginDto;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.qiaoba.module.system.service;
|
||||
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import com.qiaoba.api.system.entity.SysMenu;
|
||||
import com.qiaoba.api.system.entity.vo.RouterVo;
|
||||
import com.qiaoba.api.system.entity.vo.SysMenuVo;
|
||||
import com.qiaoba.api.system.service.SysMenuApiService;
|
||||
@ -24,7 +25,7 @@ public interface SysMenuService extends SysMenuApiService {
|
||||
* @param menus 菜单列表
|
||||
* @return 下拉树结构列表
|
||||
*/
|
||||
List<Tree<String>> buildMenuTree(List<SysMenuVo> menus);
|
||||
List<Tree<String>> buildMenuTree(List<SysMenu> menus);
|
||||
|
||||
/**
|
||||
* 根据角色ID查询菜单树信息
|
||||
|
@ -56,8 +56,8 @@ public class SysMenuServiceImpl implements SysMenuService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysMenuVo> selectVoList(SysMenuParam param) {
|
||||
return sysMenuMapper.selectVoList(param2Wrapper((param)));
|
||||
public List<SysMenu> selectList(SysMenuParam param) {
|
||||
return sysMenuMapper.selectList(param2Wrapper((param)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -81,7 +81,7 @@ public class SysMenuServiceImpl implements SysMenuService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tree<String>> buildMenuTree(List<SysMenuVo> menus) {
|
||||
public List<Tree<String>> buildMenuTree(List<SysMenu> menus) {
|
||||
TreeNodeConfig config = TreeNodeConfig.DEFAULT_CONFIG.setNameKey(BaseConstant.TREE_KEY_NAME);
|
||||
return TreeUtil.build(menus, BaseConstant.DEFAULT_PARENT_ID_VALUE, config, (menu, tree) ->
|
||||
tree.setId(menu.getMenuId())
|
||||
|
@ -11,7 +11,6 @@ import com.qiaoba.api.system.entity.dto.DataScopeDto;
|
||||
import com.qiaoba.api.system.entity.dto.SysRoleDto;
|
||||
import com.qiaoba.api.system.entity.param.SysRoleParam;
|
||||
import com.qiaoba.auth.utils.SecurityUtil;
|
||||
import com.qiaoba.common.base.constants.BaseConstant;
|
||||
import com.qiaoba.common.base.exceptions.ServiceException;
|
||||
import com.qiaoba.common.database.entity.PageQuery;
|
||||
import com.qiaoba.common.database.entity.TableDataInfo;
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.qiaoba.module.system.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.qiaoba.api.system.entity.SysUser;
|
||||
import com.qiaoba.api.auth.service.SysUserDetailsApiService;
|
||||
import com.qiaoba.api.system.entity.SysUser;
|
||||
import com.qiaoba.auth.constants.SecurityConstant;
|
||||
import com.qiaoba.auth.entity.LoginUser;
|
||||
import com.qiaoba.auth.entity.SecurityUser;
|
||||
|
@ -14,7 +14,6 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -103,7 +103,7 @@ public class SysUserServiceImpl implements SysUserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataScope(userAlias = "u",deptAlias = "t2")
|
||||
@DataScope(userAlias = "u", deptAlias = "t2")
|
||||
public TableDataInfo<SysUserVo> selectVoPageList(SysUserParam param, PageQuery pageQuery) {
|
||||
Page<SysUserVo> page = sysUserMapper.selectVoPageList(pageQuery.build(), param);
|
||||
return TableDataInfo.build(page);
|
||||
|
@ -12,8 +12,9 @@
|
||||
</select>
|
||||
|
||||
<select id="selectByIds" resultType="com.qiaoba.api.system.entity.SysConfig">
|
||||
select config_id, config_name, config_key, config_value, config_type, create_user, create_time, update_user, update_time, remark
|
||||
from sys_config where config_id in
|
||||
select config_id, config_name, config_key, config_value, config_type, create_user, create_time, update_user,
|
||||
update_time, remark
|
||||
from sys_config where config_id in
|
||||
<foreach item="configId" collection="list" open="(" separator="," close=")">
|
||||
#{configId}
|
||||
</foreach>
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
<artifactId>qiaoba-module-tenant</artifactId>
|
||||
|
||||
<description>租户模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
|
@ -8,6 +8,13 @@ import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 项目启动完成后-将主库中的租户信息同步到 Redis 中
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022-09-22 04:20:28
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysTenantRunner implements ApplicationRunner {
|
||||
|
@ -72,7 +72,7 @@ public interface SysTenantDatasourceService {
|
||||
/**
|
||||
* 将租户下的除datasourceId之外的其他数据源设置为备用
|
||||
*
|
||||
* @param tenantId tenantId
|
||||
* @param tenantId tenantId
|
||||
* @param excludeId 排除Id
|
||||
*/
|
||||
void setBackupDatasourceExcludeId(String tenantId, String excludeId);
|
||||
|
@ -4,9 +4,6 @@ import com.qiaoba.common.database.entity.PageQuery;
|
||||
import com.qiaoba.common.database.entity.TableDataInfo;
|
||||
import com.qiaoba.module.tenant.entity.SysTenant;
|
||||
import com.qiaoba.module.tenant.entity.param.SysTenantParam;
|
||||
import com.qiaoba.module.tenant.entity.vo.TenantSettingVo;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* 租户管理 服务层
|
||||
|
@ -62,7 +62,7 @@ public class SysTenantDatasourceServiceImpl implements SysTenantDatasourceServic
|
||||
|
||||
@Override
|
||||
public void setBackupDatasourceExcludeId(String tenantId, String excludeId) {
|
||||
sysTenantDatasourceMapper.setBackupDatasourceExcludeId(tenantId,excludeId,BaseEnum.NO.getCode());
|
||||
sysTenantDatasourceMapper.setBackupDatasourceExcludeId(tenantId, excludeId, BaseEnum.NO.getCode());
|
||||
}
|
||||
|
||||
private QueryWrapper<SysTenantDatasource> paramToWrapper(SysTenantDatasourceParam param) {
|
||||
|
Reference in New Issue
Block a user