✨ 添加新特性。支持多数据源切换代码生成

This commit is contained in:
冷冷 committed 2019-03-31 20:12:12 +08:00
1 parent af87934310
commit 04d0b833ca
15 files changed
+469 -9

No files matched your search

@@ -15,3 +15,9 @@ spring:
url: jdbc:mysql://pigx-mysql:3306/coffeewx?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8
resources:
static-locations: classpath:/static/,classpath:/views/
pigx:
tenant:
column: tenant_id
tables:
- sys_datasource_conf
+4
View File
@@ -49,6 +49,10 @@
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-security</artifactId>
</dependency>
<dependency>
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-log</artifactId>
</dependency>
<!--代码生成模板引擎-->
<dependency>
<artifactId>velocity</artifactId>
@@ -17,8 +17,8 @@
package com.pig4cloud.pigx.codegen;
import com.pig4cloud.pigx.common.security.annotation.EnablePigxResourceServer;
import com.pig4cloud.pigx.common.security.annotation.EnablePigxFeignClients;
import com.pig4cloud.pigx.common.security.annotation.EnablePigxResourceServer;
import com.pig4cloud.pigx.common.swagger.annotation.EnablePigxSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
@@ -0,0 +1,25 @@
package com.pig4cloud.pigx.codegen.config;
import com.pig4cloud.pigx.codegen.util.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @author lengleng
* @date 2019-03-31
* <p>
* 动态数据源类
*/
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {
/**
* 指定路由Key
*
* @return
*/
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSourceType();
}
}
@@ -0,0 +1,97 @@
package com.pig4cloud.pigx.codegen.config;
import com.zaxxer.hikari.HikariDataSource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* @author lengleng
* @date 2019-03-31
* <p>
* 动态数据源切换配置
*/
@Slf4j
@Configuration
@AllArgsConstructor
public class DynamicDataSourceConfig implements TransactionManagementConfigurer {
private final Map<Object, Object> dataSourceMap = new HashMap<>(8);
private final DataSourceProperties dataSourceProperties;
@Bean("dynamicDataSource")
public DynamicDataSource dataSource() {
DynamicDataSource ds = new DynamicDataSource();
HikariDataSource cads = new HikariDataSource();
cads.setJdbcUrl(dataSourceProperties.getUrl());
cads.setDriverClassName(dataSourceProperties.getDriverClassName());
cads.setUsername(dataSourceProperties.getUsername());
cads.setPassword(dataSourceProperties.getPassword());
ds.setDefaultTargetDataSource(cads);
dataSourceMap.put(0, cads);
ds.setTargetDataSources(dataSourceMap);
return ds;
}
/**
* 组装默认配置的数据源,查询数据库配置
*/
@PostConstruct
public void init() {
DriverManagerDataSource dds = new DriverManagerDataSource();
dds.setUrl(dataSourceProperties.getUrl());
dds.setDriverClassName(dataSourceProperties.getDriverClassName());
dds.setUsername(dataSourceProperties.getUsername());
dds.setPassword(dataSourceProperties.getPassword());
String sql = "select * from sys_datasource_conf where del_flag = '0' ";
List<Map<String, Object>> dbList = new JdbcTemplate(dds).queryForList(sql);
log.info("开始 -> 初始化动态数据源");
Optional.of(dbList).ifPresent(list -> list.forEach(db -> {
log.info("数据源:{}", db.get("name"));
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(String.valueOf(db.get("url")));
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUsername(String.valueOf(db.get("username")));
ds.setPassword(String.valueOf(db.get("password")));
dataSourceMap.put(db.get("id"), ds);
}));
log.info("完毕 -> 初始化动态数据源,共计 {} 条", dataSourceMap.size());
}
/**
* 重新加载数据源配置
*/
public void reload() {
init();
DynamicDataSource dataSource = dataSource();
dataSource.setTargetDataSources(dataSourceMap);
dataSource.afterPropertiesSet();
}
@Bean
public PlatformTransactionManager txManager() {
return new DataSourceTransactionManager(dataSource());
}
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return txManager();
}
}
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.codegen.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.codegen.config.DynamicDataSourceConfig;
import com.pig4cloud.pigx.codegen.entity.SysDatasourceConf;
import com.pig4cloud.pigx.codegen.service.SysDatasourceConfService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* 数据源管理
*
* @author pigx code generator
* @date 2019-03-31 16:00:20
*/
@RestController
@AllArgsConstructor
@RequestMapping("/dsconf")
public class SysDsConfController {
private final DynamicDataSourceConfig dynamicDataSourceConfig;
private final SysDatasourceConfService sysDatasourceConfService;
/**
* 分页查询
*
* @param page 分页对象
* @param sysDatasourceConf 数据源表
* @return
*/
@GetMapping("/page")
public R getSysDatasourceConfPage(Page page, SysDatasourceConf sysDatasourceConf) {
return new R<>(sysDatasourceConfService.page(page, Wrappers.query(sysDatasourceConf)));
}
/**
* 查询全部数据源
*
* @return
*/
@GetMapping("/list")
public R list() {
return new R<>(sysDatasourceConfService.list());
}
/**
* 通过id查询数据源表
*
* @param id id
* @return R
*/
@GetMapping("/{id}")
public R getById(@PathVariable("id") Integer id) {
return new R<>(sysDatasourceConfService.getById(id));
}
/**
* 新增数据源表
*
* @param sysDatasourceConf 数据源表
* @return R
*/
@SysLog("新增数据源表")
@PostMapping
public R save(@RequestBody SysDatasourceConf sysDatasourceConf) {
sysDatasourceConfService.save(sysDatasourceConf);
dynamicDataSourceConfig.reload();
return new R<>();
}
/**
* 修改数据源表
*
* @param sysDatasourceConf 数据源表
* @return R
*/
@SysLog("修改数据源表")
@PutMapping
public R updateById(@RequestBody SysDatasourceConf sysDatasourceConf) {
sysDatasourceConfService.updateById(sysDatasourceConf);
dynamicDataSourceConfig.reload();
return new R<>();
}
/**
* 通过id删除数据源表
*
* @param id id
* @return R
*/
@SysLog("删除数据源表")
@DeleteMapping("/{id}")
public R removeById(@PathVariable Integer id) {
sysDatasourceConfService.removeById(id);
dynamicDataSourceConfig.reload();
return new R<>();
}
}
@@ -28,7 +28,6 @@ import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 代码生成器
@@ -46,11 +45,12 @@ public class SysGeneratorController {
* 列表
*
* @param tableName 参数集
* @param id 数据源编号
* @return 数据库表
*/
@GetMapping("/page")
public R getPage(Page page, String tableName) {
return new R<>(sysGeneratorService.getPage(page, tableName));
public R getPage(Page page, String tableName, Integer id) {
return new R<>(sysGeneratorService.getPage(page, tableName, id));
}
/**
@@ -60,7 +60,6 @@ public class SysGeneratorController {
@PostMapping("/code")
public void generatorCode(@RequestBody GenConfig genConfig, HttpServletResponse response) {
byte[] data = sysGeneratorService.generatorCode(genConfig);
response.reset();
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s.zip", genConfig.getTableName()));
response.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(data.length));
@@ -26,6 +26,10 @@ import lombok.Data;
*/
@Data
public class GenConfig {
/**
* 数据源ID
*/
private Integer id;
/**
* 包名
*/
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.codegen.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
/**
* 数据源表
*
* @author pigx code generator
* @date 2019-03-31 16:00:20
*/
@Data
@TableName("sys_datasource_conf")
@EqualsAndHashCode(callSuper = true)
public class SysDatasourceConf extends Model<SysDatasourceConf> {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId
private Integer id;
/**
* 名称
*/
private String name;
/**
*
*/
private String url;
/**
*
*/
private String username;
/**
*
*/
private String password;
/**
* 创建时间
*/
private LocalDateTime createDate;
/**
* 更新
*/
private LocalDateTime updateDate;
/**
* 删除标记
*/
@TableLogic
private String delFlag;
/**
* 租户ID
*/
private Integer tenantId;
}
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.codegen.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pig4cloud.pigx.codegen.entity.SysDatasourceConf;
/**
* 数据源表
*
* @author pigx code generator
* @date 2019-03-31 16:00:20
*/
public interface SysDatasourceConfMapper extends BaseMapper<SysDatasourceConf> {
}
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.codegen.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.codegen.entity.SysDatasourceConf;
/**
* 数据源表
*
* @author pigx code generator
* @date 2019-03-31 16:00:20
*/
public interface SysDatasourceConfService extends IService<SysDatasourceConf> {
}
@@ -39,8 +39,10 @@ public interface SysGeneratorService {
/**
* 分页查询表
*
* @param tableName 表名
* @param id 数据源ID
* @return
*/
IPage<List<Map<String, Object>>> getPage(Page page, String tableName);
IPage<List<Map<String, Object>>> getPage(Page page, String tableName, Integer id);
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.codegen.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.codegen.entity.SysDatasourceConf;
import com.pig4cloud.pigx.codegen.mapper.SysDatasourceConfMapper;
import com.pig4cloud.pigx.codegen.service.SysDatasourceConfService;
import org.springframework.stereotype.Service;
/**
* 数据源表
*
* @author pigx code generator
* @date 2019-03-31 16:00:20
*/
@Service
public class SysDatasourceConfServiceImpl extends ServiceImpl<SysDatasourceConfMapper, SysDatasourceConf> implements SysDatasourceConfService {
}
@@ -21,8 +21,10 @@ import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.codegen.entity.GenConfig;
import com.pig4cloud.pigx.codegen.mapper.SysDatasourceConfMapper;
import com.pig4cloud.pigx.codegen.mapper.SysGeneratorMapper;
import com.pig4cloud.pigx.codegen.service.SysGeneratorService;
import com.pig4cloud.pigx.codegen.util.DynamicDataSourceContextHolder;
import com.pig4cloud.pigx.codegen.util.GenUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
@@ -41,18 +43,20 @@ import java.util.zip.ZipOutputStream;
@Service
@AllArgsConstructor
public class SysGeneratorServiceImpl implements SysGeneratorService {
private final SysDatasourceConfMapper sysDatasourceConfMapper;
private final SysGeneratorMapper sysGeneratorMapper;
/**
* 分页查询表
*
* @param tableName 查询条件
* @param id
* @return
*/
@Override
public IPage<List<Map<String, Object>>> getPage(Page page, String tableName) {
return sysGeneratorMapper.queryList(page,tableName);
public IPage<List<Map<String, Object>>> getPage(Page page, String tableName, Integer id) {
DynamicDataSourceContextHolder.setDataSourceType(id);
return sysGeneratorMapper.queryList(page, tableName);
}
/**
@@ -63,6 +67,7 @@ public class SysGeneratorServiceImpl implements SysGeneratorService {
*/
@Override
public byte[] generatorCode(GenConfig genConfig) {
DynamicDataSourceContextHolder.setDataSourceType(genConfig.getId());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream);
@@ -0,0 +1,26 @@
package com.pig4cloud.pigx.codegen.util;
import lombok.experimental.UtilityClass;
/**
* @author lengleng
* @date 2019-03-31
* <p>
* 保存上线文中数据库路由
*/
@UtilityClass
public class DynamicDataSourceContextHolder {
private final ThreadLocal<Integer> CONTEXT_HOLDER = new ThreadLocal<>();
public void setDataSourceType(Integer dataSourceType) {
CONTEXT_HOLDER.set(dataSourceType);
}
public Integer getDataSourceType() {
return CONTEXT_HOLDER.get();
}
public void clearDataSourceType() {
CONTEXT_HOLDER.remove();
}
}