feat(完善多数据源)
commit
dfe5a2eb41
|
@ -7,7 +7,6 @@ import com.muyu.common.swagger.annotation.EnableCustomSwagger2;
|
||||||
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.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
import org.springframework.boot.web.servlet.DynamicRegistrationBean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多数据源启动类
|
* 多数据源启动类
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.muyu.many.config;
|
||||||
|
|
||||||
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import com.muyu.common.core.utils.SpringUtils;
|
||||||
|
import com.muyu.many.config.domai.model.DataSourceInfo;
|
||||||
|
import com.muyu.many.config.domai.model.EntInfo;
|
||||||
|
import com.muyu.many.config.factory.DruidDataSourceFactory;
|
||||||
|
import com.muyu.many.config.role.DynamicDataSource;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多数据源
|
||||||
|
*
|
||||||
|
* @ClassName ManyDataSource
|
||||||
|
* @Author AnNan.Wang
|
||||||
|
* @Date 2024/6/4 14:10
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
public class ManyDataSource {
|
||||||
|
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
new Thread(() ->{
|
||||||
|
try {
|
||||||
|
Thread.sleep(5000);
|
||||||
|
} catch (InterruptedException ignored) {}
|
||||||
|
DruidDataSourceFactory druidDataSourceFactory = SpringUtils.getBean(DruidDataSourceFactory.class);
|
||||||
|
DynamicDataSource dynamicDataSource = SpringUtils.getBean(DynamicDataSource.class);;
|
||||||
|
EntInfo entInfo = EntInfo.builder()
|
||||||
|
.entCode("ent_4588")
|
||||||
|
.ip("123.56.102.11")
|
||||||
|
.port(3308)
|
||||||
|
.build();
|
||||||
|
DataSourceInfo dataSourceInfo = DataSourceInfo.hostAndPortBuild(entInfo.getEntCode(), entInfo.getIp(), entInfo.getPort());
|
||||||
|
DruidDataSource druidDataSource = druidDataSourceFactory.create(dataSourceInfo);
|
||||||
|
dynamicDataSource.put(dataSourceInfo.getKey(), druidDataSource);
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<EntInfo> dataSourceInfoList() {
|
||||||
|
List<EntInfo> list = new ArrayList<>();
|
||||||
|
list.add(
|
||||||
|
EntInfo.builder()
|
||||||
|
.entCode("ent_4587")
|
||||||
|
.ip("123.56.102.11")
|
||||||
|
.port(3310)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
@Bean
|
||||||
|
@Primary
|
||||||
|
public DynamicDataSource dynamicDataSource(DruidDataSourceFactory druidDataSourceFactory) {
|
||||||
|
|
||||||
|
Map<Object, Object> dataSourceMap = new HashMap<>();
|
||||||
|
dataSourceInfoList()
|
||||||
|
.stream()
|
||||||
|
.map(entInfo -> DataSourceInfo.hostAndPortBuild(entInfo.getEntCode(),entInfo.getIp(),entInfo.getPort()))
|
||||||
|
.forEach(dataSourceInfo -> {
|
||||||
|
dataSourceMap.put(dataSourceInfo.getKey(), druidDataSourceFactory.create(dataSourceInfo));
|
||||||
|
});
|
||||||
|
//设置动态数据源
|
||||||
|
DynamicDataSource dynamicDataSource = new DynamicDataSource();
|
||||||
|
// dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
|
||||||
|
dynamicDataSource.setTargetDataSources(dataSourceMap);
|
||||||
|
//将数据源信息备份在defineTargetDataSources中
|
||||||
|
dynamicDataSource.setDefineTargetDataSources(dataSourceMap);
|
||||||
|
return dynamicDataSource;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.muyu.many.config.contents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author DongZl
|
||||||
|
* @description: 数据源常量
|
||||||
|
* @Date 2023-8-1 上午 11:02
|
||||||
|
*/
|
||||||
|
public class DatasourceContent {
|
||||||
|
|
||||||
|
public final static String DATASOURCE_URL = "jdbc:mysql://{}:{}/car?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
|
||||||
|
|
||||||
|
public final static String USER_NAME = "root";
|
||||||
|
|
||||||
|
public final static String PASSWORD = "root";
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.muyu.many.config.domai.model;
|
||||||
|
|
||||||
|
import com.muyu.common.core.utils.StringUtils;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import static com.muyu.many.config.contents.DatasourceContent.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName DataSourceInfo
|
||||||
|
* @Author AnNan.Wang
|
||||||
|
* @Date 2024/6/4 14:20
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DataSourceInfo {
|
||||||
|
/**
|
||||||
|
* 键
|
||||||
|
*/
|
||||||
|
private String key;
|
||||||
|
/**
|
||||||
|
* 地址
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
|
||||||
|
public static DataSourceInfo hostAndPortBuild(String key,String host,Integer port){
|
||||||
|
return DataSourceInfo.builder()
|
||||||
|
.key(key)
|
||||||
|
.url(StringUtils.format(DATASOURCE_URL, host,port))
|
||||||
|
.password(PASSWORD)
|
||||||
|
.userName(USER_NAME)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.muyu.many.config.domai.model;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业信息
|
||||||
|
*
|
||||||
|
* @ClassName EntInfo
|
||||||
|
* @Author AnNan.Wang
|
||||||
|
* @Date 2024/6/4 15:02
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class EntInfo {
|
||||||
|
private String entCode;
|
||||||
|
private String ip;
|
||||||
|
private Integer port;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.muyu.many.config.factory;
|
||||||
|
|
||||||
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import com.muyu.many.config.domai.model.DataSourceInfo;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Druid工厂
|
||||||
|
*
|
||||||
|
* @ClassName DruidDataSourceFactory
|
||||||
|
* @Author AnNan.Wang
|
||||||
|
* @Date 2024/6/4 14:14
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
public class DruidDataSourceFactory {
|
||||||
|
/**
|
||||||
|
* @Description: 根据传递的数据源信息测试数据库连接
|
||||||
|
* @Author AnNan.Wang
|
||||||
|
*/
|
||||||
|
public DruidDataSource create(DataSourceInfo dataSourceInfo) {
|
||||||
|
DruidDataSource druidDataSource = new DruidDataSource();
|
||||||
|
druidDataSource.setUrl(dataSourceInfo.getUrl());
|
||||||
|
druidDataSource.setUsername(dataSourceInfo.getUserName());
|
||||||
|
druidDataSource.setPassword(dataSourceInfo.getPassword());
|
||||||
|
druidDataSource.setBreakAfterAcquireFailure(true);
|
||||||
|
druidDataSource.setConnectionErrorRetryAttempts(0);
|
||||||
|
try {
|
||||||
|
druidDataSource.getConnection(2000);
|
||||||
|
log.info("{} -> 数据源连接成功", dataSourceInfo.getKey());
|
||||||
|
return druidDataSource;
|
||||||
|
} catch (SQLException throwables) {
|
||||||
|
log.error("数据源 {} 连接失败,用户名:{},密码 {}",dataSourceInfo.getUrl(),dataSourceInfo.getUserName(),dataSourceInfo.getPassword());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.muyu.many.config.holder;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源切换处理
|
||||||
|
*
|
||||||
|
* @author Dongzl
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class DynamicDataSourceHolder {
|
||||||
|
/**
|
||||||
|
* 保存动态数据源名称
|
||||||
|
*/
|
||||||
|
private static final ThreadLocal<String> DYNAMIC_DATASOURCE_KEY = new ThreadLocal<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置/切换数据源,决定当前线程使用哪个数据源
|
||||||
|
*/
|
||||||
|
public static void setDynamicDataSourceKey(String key){
|
||||||
|
log.info("数据源切换为:{}",key);
|
||||||
|
DYNAMIC_DATASOURCE_KEY.set(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取动态数据源名称,默认使用mater数据源
|
||||||
|
*/
|
||||||
|
public static String getDynamicDataSourceKey(){
|
||||||
|
String key = DYNAMIC_DATASOURCE_KEY.get();
|
||||||
|
Assert.notNull(key, "请携带数据标识");
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除当前数据源
|
||||||
|
*/
|
||||||
|
public static void removeDynamicDataSourceKey(){
|
||||||
|
log.info("移除数据源:{}",DYNAMIC_DATASOURCE_KEY.get());
|
||||||
|
DYNAMIC_DATASOURCE_KEY.remove();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.muyu.many.config.role;
|
||||||
|
|
||||||
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import com.muyu.many.config.domai.model.DataSourceInfo;
|
||||||
|
import com.muyu.many.config.holder.DynamicDataSourceHolder;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态数据源
|
||||||
|
* 调用AddDefineDataSource组件的addDefineDynamicDataSource()方法,获取原来targetdatasources的map,并将新的数据源信息添加到map中,并替换targetdatasources中的map
|
||||||
|
* 切换数据源时可以使用@DataSource(value = "数据源名称"),或者DynamicDataSourceContextHolder.setContextKey("数据源名称")
|
||||||
|
* @author Dongzl
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class DynamicDataSource extends AbstractRoutingDataSource {
|
||||||
|
//备份所有数据源信息,备份的是个 指针 !!!
|
||||||
|
private Map<Object, Object> defineTargetDataSources;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加数据源
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void put(String key, DruidDataSource value) {
|
||||||
|
defineTargetDataSources.put(key, value);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 决定当前线程使用哪个数据源
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Object determineCurrentLookupKey() {
|
||||||
|
return DynamicDataSourceHolder.getDynamicDataSourceKey();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.muyu.many.server.controller;
|
||||||
|
|
||||||
|
import com.muyu.common.core.domain.Result;
|
||||||
|
import com.muyu.many.config.holder.DynamicDataSourceHolder;
|
||||||
|
import com.muyu.many.server.domain.Enterprise;
|
||||||
|
import com.muyu.many.server.service.EnterpriseService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业表 Controller层
|
||||||
|
*
|
||||||
|
* @ClassName EnterpriseController
|
||||||
|
* @Author AnNan.Wang
|
||||||
|
* @Date 2024/6/4 20:53
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/enterprise")
|
||||||
|
public class EnterpriseController {
|
||||||
|
@Autowired
|
||||||
|
private EnterpriseService enterpriseService;
|
||||||
|
|
||||||
|
@GetMapping("/all/{code}")
|
||||||
|
public Result<List<Enterprise>> all(@PathVariable("code") String code){
|
||||||
|
DynamicDataSourceHolder.setDynamicDataSourceKey(code);
|
||||||
|
return enterpriseService.enterpriseList(code);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package com.muyu.many.server.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.muyu.common.core.web.domain.BaseEntity;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业表
|
||||||
|
*
|
||||||
|
* @ClassName Enterprise
|
||||||
|
* @Author AnNan.Wang
|
||||||
|
* @Date 2024/6/4 20:47
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@TableName(value = "enterprise")
|
||||||
|
public class Enterprise extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
@TableId(value = "id",type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 企业名称
|
||||||
|
*/
|
||||||
|
private String enterpriseName;
|
||||||
|
/**
|
||||||
|
* 法定代表人
|
||||||
|
*/
|
||||||
|
private String legalPerson;
|
||||||
|
/**
|
||||||
|
* 经营执照凭证号码
|
||||||
|
*/
|
||||||
|
private String businessLicenseNumber;
|
||||||
|
/**
|
||||||
|
* 企业成立时间
|
||||||
|
*/
|
||||||
|
private Date establishmentDate;
|
||||||
|
/**
|
||||||
|
* 经营范围
|
||||||
|
*/
|
||||||
|
private String businessScope;
|
||||||
|
/**
|
||||||
|
* 注册地址
|
||||||
|
*/
|
||||||
|
private String address;
|
||||||
|
/**
|
||||||
|
* 企业联系方式
|
||||||
|
*/
|
||||||
|
private String contactPhone;
|
||||||
|
/**
|
||||||
|
* 公司邮箱
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
/**
|
||||||
|
* 企业当前状态
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 企业入驻平台时期
|
||||||
|
*/
|
||||||
|
private Date registrationDate;
|
||||||
|
/**
|
||||||
|
* 企业认证id
|
||||||
|
*/
|
||||||
|
private Long certificationId;
|
||||||
|
/**
|
||||||
|
* 认证时间
|
||||||
|
*/
|
||||||
|
private Date authenticationDate;
|
||||||
|
/**
|
||||||
|
* 服务级别
|
||||||
|
*/
|
||||||
|
private Integer serviceLevel;
|
||||||
|
/**
|
||||||
|
* 开通服务id
|
||||||
|
*/
|
||||||
|
private Long open_serverId;
|
||||||
|
/**
|
||||||
|
* 增值服务id
|
||||||
|
*/
|
||||||
|
private Long add_serverId;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.muyu.many.server.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.muyu.many.server.domain.Enterprise;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enterprise 企业表的Mapper接口层
|
||||||
|
*
|
||||||
|
* @author AnNan.Wang
|
||||||
|
* @ClassName: EnterpriseMapper
|
||||||
|
* @createTime: 2024/6/4 20:58
|
||||||
|
*/
|
||||||
|
public interface EnterpriseMapper extends BaseMapper<Enterprise> {
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.muyu.many.server.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.muyu.common.core.domain.Result;
|
||||||
|
import com.muyu.many.server.domain.Enterprise;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enterprise 企业表Service层接口
|
||||||
|
*
|
||||||
|
* @author AnNan.Wang
|
||||||
|
* @ClassName: EnterpriseService
|
||||||
|
* @createTime: 2024/6/4 20:54
|
||||||
|
*/
|
||||||
|
public interface EnterpriseService extends IService<Enterprise> {
|
||||||
|
Result<List<Enterprise>> enterpriseList(String code);
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.muyu.many.server.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.muyu.common.core.domain.Result;
|
||||||
|
import com.muyu.many.server.domain.Enterprise;
|
||||||
|
import com.muyu.many.server.mapper.EnterpriseMapper;
|
||||||
|
import com.muyu.many.server.service.EnterpriseService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enterprise 企业表的EnterpriseService业务实现层
|
||||||
|
*
|
||||||
|
* @ClassName EnterpriseServiceImpl
|
||||||
|
* @Author AnNan.Wang
|
||||||
|
* @Date 2024/6/4 20:57
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class EnterpriseServiceImpl extends ServiceImpl<EnterpriseMapper, Enterprise>
|
||||||
|
implements EnterpriseService{
|
||||||
|
@Autowired
|
||||||
|
private EnterpriseMapper enterpriseMapper;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<List<Enterprise>> enterpriseList(String code) {
|
||||||
|
return Result.success(
|
||||||
|
enterpriseMapper.selectList(null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue