前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >制作一个Http动态数据源

制作一个Http动态数据源

作者头像
姜同学
发布2022-12-08 13:43:50
4200
发布2022-12-08 13:43:50
举报
文章被收录于专栏:姜同学

前一段时间姜同学在做一些传统的企业信息化建设,也就是搭建一个新的平台去整合企业下诸如OA,CRM,PLM,U8等一系列数据独立的系统,这个系统除了具有传统的BI系统将整合的数据用作上层系统的展示之外,还可以对外提供HTTP接口用来反哺其它的子系统,所以我们称它为数据中台。

考虑到一些系统是很久之前从其它厂商那里采购来了,还有一些是企业诞生之初便存在的年久失修的系统,具提失修到什么程度,我就不再过多描述,大家懂得都懂。所以为了不影响这些系统,便诞生了这篇文章的主角,Http动态数据源。

用途

image.png
image.png

当然主要的用途还是前两个,至于用作报表系统的Http的数据源就不多件了,毕竟这种应用层协议之间的交互还是存在效率问题的,至于做报表和大屏的的工具,我向大家推荐一个用过感觉还不错的。datart

理论落地

image.png
image.png

理论也非常简单,只要将我们的需求进行分层,管理层用于动态数据源的管理,查询层提供多数据源的查询能力,增加鉴权层为数据安全提供保障。

管理层

管理层建议使用关系型数据库将数据源的连接信息管理起来,但是姜同学这里因为数据源比较少以及为了快速交付考虑,采用了配置文件来管理数据源。

代码语言:javascript
复制
pins:
  dataset:
    - url: jdbc:mysql://127.0.0.1:3306/rds
      user: query
      pwd: 123456
      use: rds
    - url: jdbc:mysql://127.0.0.1:3306/oa
      user: query
      pwd: 123456
      use: oa
    - url: jdbc:sqlserver://127.0.0.1:1433;databasename=UFmeta_003
      user: query
      pwd: "123456"
      use: u8
    - url: jdbc:mysql://127.0.0.1:3306/u8
      user: query
      pwd: 123456
      use: plm
    - url: jdbc:oracle:thin:@127.0.0.1:1521:orcl
      user: query
      pwd: 123456
      use: operation-log
代码语言:javascript
复制
@ConfigurationProperties(prefix = "pins")
@Component
@Data
public class DynamicDatasetProperties {
    private List<DataSet> dataSet;
    private Common common;

    @Data
    public static class DataSet{
        String url;
        String user;
        String pwd;
        String use;
    }
}
java

在程序启动之后将连接生成对应的JdbcTemplate

JdbcTemplateUtils

代码语言:javascript
复制
@Component
@Slf4j
public class JdbcTemplateUtils {

    private final DynamicDatasetProperties dynamicDatasetProperties;

    /**
     * 动态数据源
     */
    private final Map<String, HikariDataSource> pinsDataSources = new HashMap<>();
    /**
     * jdbcTemplate key:数据源唯一标识  oa:jdbcTemplate
     */
    public final static Map<String, JdbcTemplate> pinsJdbcTemplate;


    static {
        pinsJdbcTemplate = new HashMap<>();
    }

    public JdbcTemplateUtils(DynamicDatasetProperties dynamicDatasetProperties) {
        this.dynamicDatasetProperties = dynamicDatasetProperties;
    }

    @PostConstruct
    void init(){
        dynamicDatasetProperties.getDataSet().forEach(
                dataSet -> {
                    makeJdbcTemplate(dataSet.getUrl(), dataSet.getUser(), dataSet.getPwd(), dataSet.getUse());
                }
        );

    }
    @PreDestroy
    void destroy(){
        for (Map.Entry<String, HikariDataSource> entry : pinsDataSources.entrySet()) {
            HikariDataSource hikariDataSource = entry.getValue();
            if (null != hikariDataSource) {
                hikariDataSource.close();
            }
        }
    }


    private void makeJdbcTemplate(String mysqlConnectionUrl, String userName, String password, String uniqueCode) {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(mysqlConnectionUrl);
        hikariConfig.setUsername(userName);
        hikariConfig.setPassword(password);
        hikariConfig.setMaximumPoolSize(50); // 连接池的最大连接数,
        HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
        Connection connection = DataSourceUtils.getConnection(hikariDataSource);
        try {
            boolean closed = connection.isClosed();
            if (!closed) {
                JdbcTemplate jdbcTemplate = new JdbcTemplate(hikariDataSource);
                pinsDataSources.put(uniqueCode, hikariDataSource);
                pinsJdbcTemplate.put(uniqueCode, jdbcTemplate);
            }
        } catch (SQLException e) {
            log.error("Connect Tenant MySql Fail : ", e);
        }
    }

}
java

注意这里的连接池使用了SpringBoot自带的Hikari

查询层

不解释什么了,很简单。

代码语言:javascript
复制
@Service
public class PinsQlService {
    public List<Map<String, Object>> pinsDynamicQuery(String use, String pinsQl) throws NullPointerException {
        return JdbcTemplateUtils.pinsJdbcTemplate.get(use).queryForList(pinsQl);
    }
}
java

Http层

代码语言:javascript
复制
@RestController
@RequestMapping({"pins-ql"})
public class PinsQlController {

    private final PinsQlService pinsQlService;

    public PinsQlController(PinsQlService pinsQlService) {
        this.pinsQlService = pinsQlService;
    }


    @PostMapping({"dynamic/{use}"})
    public Result<List<Map<String, Object>>> dynamicQuery(@PathVariable("use") String use,
                                                            @RequestBody SQL sql) {
        if (use.contains("op")) {
            return Result.fail("高危操作请联系管理员");
        }
        return Result.success(this.pinsQlService.pinsDynamicQuery(use, sql.str));
    }
}
java

其他系统只需要提供要查询的应用类型已经对应的SQL就可以获得结果了。

image.png
image.png

鉴权

动态数据源服务部署方式采用网络的物理隔离不对外提供端口,认证鉴权由网关统一来做。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 用途
  • 理论落地
  • 管理层
    • 在程序启动之后将连接生成对应的JdbcTemplate
    • 查询层
    • Http层
    • 鉴权
    相关产品与服务
    腾讯云 BI
    腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档