SpringBoot笔记:SpringBoot 集成 Dataway 多数据源配置(二)

文章目录

  • 前言
  • 核心代码和配置
    • yml 配置
    • 注入多数据源
    • 常用Spi实现
    • swagger 配置
    • 自定义 Udf
    • 指定数据源进行查询

前言

之前简单介绍了一下 Dataway 使用,本文继续介绍一下它的多数据源配置和使用。

核心代码和配置

yml 配置

# springboot多环境配置
#端口,项目上下文
server:port: 8080servlet:context-path: /springboot-dataway# 全局服务编码设置encoding:charset: utf-8enabled: trueforce: true# mysql 连接信息配置
spring:# mysql 数据库连接信息,本地使用 mysql 服务版本为:8.0.28datasource:username: rootpassword: 6tojyh*A3eQ6url: jdbc:mysql://localhost:3306/dataway?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowPublicKeyRetrieval=truedriver-class-name: com.mysql.cj.jdbc.Driver# druid 数据连接池配置druid:initial-size: 3min-idle: 3max-active: 10max-wait: 6000# 配置druid监控页aop-patterns: com.demo.* #监控springBeanstat-view-servlet: # 配置监控页功能enabled: true # 默认开启,这里显示说明login-username: admin # 登录名login-password: 6tojyh*A3eQ6 # 登录密码reset-enable: false # 禁用重置按钮web-stat-filter: # 监控 webenabled: trueurl-pattern: /* # 监控所有exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'  #放行filter:stat: # 对上面 filters 里的 stat 的详细配置slow-sql-millis: 1000 # 慢 sql 时间是毫秒单位的,执行时间 1 秒以上的为慢 SQLlog-slow-sql: true # 日志记录enabled: truewall:enabled: trueconfig:drop-table-allow: false # 禁用删除表的 sql# 除主数据源外,第1个数据源db1:username: rootpassword: 6tojyh*A3eQ6url: jdbc:mysql://localhost:3306/console?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowPublicKeyRetrieval=truedriver-class-name: com.mysql.cj.jdbc.Driver# 除主数据源外,第 2 个数据源db2:username: postgrespassword: UFWOd75qD7url: jdbc:postgresql://localhost:32770/postgres?binaryTransfer=false&forceBinary=false&reWriteBatchedInserts=truedriver-class-name: org.postgresql.Driver# mdataway 配置
# 是否启用 Dataway 功能(必选:默认false)
HASOR_DATAQL_DATAWAY: true
# 开启 ui 管理功能(注意生产环境必须要设置为 false,否则会造成严重的生产安全事故)
HASOR_DATAQL_DATAWAY_ADMIN: true
# dataway  API工作路径(可选,默认:/api/)
HASOR_DATAQL_DATAWAY_API_URL: /api/
# dataway-ui 的工作路径(可选,默认:/interface-ui/)
HASOR_DATAQL_DATAWAY_UI_URL: /interface-ui/
# SQL执行器方言设置(可选,建议设置)
HASOR_DATAQL_FX_PAGE_DIALECT: mysql
# 登陆认证方式在 basic 模式下的时候,配置的登陆账号
HASOR_DATAQL_DATAWAY_AUTHORIZATION_USERNAME: admin
# 登陆认证方式在 basic 模式下的时候,配置的登陆密码,默认密码admin
HASOR_DATAQL_DATAWAY_AUTHORIZATION_PASSWORD: 6tojyh*A3eQ6# 日志输出配置
logging:level:root: debugorg:springframework:security: WARNweb: ERROR# 设置自己的 com.demo.mapper 目录 输出sql日志com.demo.mapper: debugfile:path: ./logsname: './logs/springboot-dataway.log'pattern:file: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n'console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n'

注入多数据源

package com.demo.config;import com.alibaba.druid.pool.DruidDataSource;
import com.demo.chain.*;
import net.hasor.core.ApiBinder;
import net.hasor.core.DimModule;
import net.hasor.core.TypeSupplier;
import net.hasor.dataql.Finder;
import net.hasor.dataql.QueryApiBinder;
import net.hasor.dataql.fx.db.FxSqlCheckChainSpi;
import net.hasor.dataway.spi.LoginPerformChainSpi;
import net.hasor.dataway.spi.LoginTokenChainSpi;
import net.hasor.dataway.spi.PreExecuteChainSpi;
import net.hasor.dataway.spi.ResultProcessChainSpi;
import net.hasor.db.JdbcModule;
import net.hasor.db.Level;
import net.hasor.spring.SpringModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import javax.sql.DataSource;/*** @Classname DatawayModule* @Description 将Hasor模块注入spring,并注入数据源* @Date 2023/7/28 11:43* @Created by Leo825*/
@DimModule  // Hasor 中的标签,表明是一个Hasor的model
@Component  // Spring 中的标签,表明是一个组件
public class DatawayModule implements SpringModule,TypeSupplier {// 默认数据源@Autowiredprivate DataSource dataSource;// 数据源1的配置信息@Value("${spring.datasource.db1.url}")private String jdbcUrl1;@Value("${spring.datasource.db1.driver-class-name}")private String driver1;@Value("${spring.datasource.db1.username}")private String username1;@Value("${spring.datasource.db1.password}")private String password1;// 数据源2的配置信息@Value("${spring.datasource.db2.url}")private String jdbcUrl2;@Value("${spring.datasource.db2.driver-class-name}")private String driver2;@Value("${spring.datasource.db2.username}")private String username2;@Value("${spring.datasource.db2.password}")private String password2;@Resourceprivate ApplicationContext applicationContext;@Overridepublic <T> T get(Class<? extends T> targetType) {return applicationContext.getBean(targetType);}@Overridepublic <T> boolean test(Class<? extends T> targetType) {return applicationContext.getBeanNamesForType(targetType).length > 0;}@Overridepublic void loadModule(ApiBinder apiBinder) throws Throwable {// .DataSource form Spring boot into HasorapiBinder.installModule(new JdbcModule(Level.Full, this.dataSource));// 注入数据源apiBinder.installModule(new JdbcModule(Level.Full, this.dataSource));apiBinder.installModule(new JdbcModule(Level.Full, "dataSource1", getDataSource(jdbcUrl1, driver1, username1, password1)));apiBinder.installModule(new JdbcModule(Level.Full, "dataSource2", getDataSource(jdbcUrl2, driver2, username2, password2)));// 打印sql日志apiBinder.bindSpiListener(FxSqlCheckChainSpi.class, FxSqlCheckChain.getInstance());// 数据权限参数apiBinder.bindSpiListener(PreExecuteChainSpi.class, PreExecuteChain.getInstance());// 返回结果apiBinder.bindSpiListener(ResultProcessChainSpi.class, ResultProcessChain.getInstance());
//        // 登录过滤
//        apiBinder.bindSpiListener(LoginPerformChainSpi.class, LoginPerformChain.getInstance());// 登录 token 过滤
//        apiBinder.bindSpiListener(LoginTokenChainSpi.class, LoginTokenChain.getInstance());// udf/udfSource/import 指令 的类型创建委托给 springQueryApiBinder queryBinder = apiBinder.tryCast(QueryApiBinder.class);queryBinder.bindFinder(Finder.TYPE_SUPPLIER.apply(this));}/*** 注入数据源** @param* @param driver* @param username* @param password* @return*/private DruidDataSource getDataSource(String jdbcUrl, String driver, String username, String password) {DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl(jdbcUrl);dataSource.setUsername(username);dataSource.setPassword(password);dataSource.setDriverClassName(driver);// 用来检测连接是否有效dataSource.setValidationQuery("SELECT 1");// 借用连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能dataSource.setTestOnBorrow(false);// 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能dataSource.setTestOnReturn(false);// 连接空闲时检测,如果连接空闲时间大于timeBetweenEvictionRunsMillis指定的毫秒,// 执行validationQuery指定的SQL来检测连接是否有效// 如果检测失败,则连接将被从池中去除dataSource.setTestWhileIdle(true);dataSource.setTimeBetweenEvictionRunsMillis(60000);//1分钟dataSource.setMaxActive(20);dataSource.setInitialSize(5);return dataSource;}
}

常用Spi实现

FxSqlCheckChainSpi,这里主要用来打印 sql

package com.demo.chain;import lombok.extern.slf4j.Slf4j;
import net.hasor.dataql.fx.db.FxSqlCheckChainSpi;
import net.hasor.utils.StringUtils;/*** @Classname FxSqlCheckChain* @Description 打印sql* @Date 2023/8/3 20:35* @Created by Leo825*/
@Slf4j
public class FxSqlCheckChain implements FxSqlCheckChainSpi {public static FxSqlCheckChain getInstance() {return new FxSqlCheckChain();}@Overridepublic int doCheck(FxSqlInfo fxSqlInfo) throws Throwable {String sourceName = fxSqlInfo.getSourceName();if (StringUtils.isNotEmpty(sourceName)) {log.info("【dataway】dataSource ==>:{}", sourceName);}log.info("【dataway】sql ==>:{}", fxSqlInfo.getQueryString().trim());log.info("【dataway】params ==>: {}", fxSqlInfo.getQueryParams());// 如果存在后续,那么继续执行检查,否则使用 EXIT 常量控制退出后续的检查。return FxSqlCheckChainSpi.NEXT;}
}

PreExecuteChainSpi,这里主要是在接口执行前进行一些权限参数控制

package com.demo.chain;import lombok.extern.slf4j.Slf4j;
import net.hasor.dataway.spi.ApiInfo;
import net.hasor.dataway.spi.PreExecuteChainSpi;
import net.hasor.utils.future.BasicFuture;
import org.apache.commons.collections4.MapUtils;import java.util.HashMap;
import java.util.Map;/*** @Classname PreExecuteChain* @Description 接口执行前* @Date 2023/8/3 20:37* @Created by Leo825*/
@Slf4j
public class PreExecuteChain implements PreExecuteChainSpi {public static PreExecuteChain getInstance() {return new PreExecuteChain();}/*** sql 直接前* @param apiInfo* @param basicFuture*/@Overridepublic void preExecute(ApiInfo apiInfo, BasicFuture<Object> basicFuture) {Map<String, Object> parameter = apiInfo.getParameterMap();// 注入用户权限参数parameter.putAll(MapUtils.emptyIfNull(loginUserAuthParams()));}/*** 获取登录用户权限参数* @return*/private Map<String, Object> loginUserAuthParams () {Map<String, Object> authParams = new HashMap<>();// todo 注入登录用户 权限参数return authParams;}
}

ResultProcessChainSpi,主要是返回值进行一些封装

package com.demo.chain;
import com.demo.common.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import net.hasor.dataway.spi.ApiInfo;
import net.hasor.dataway.spi.ResultProcessChainSpi;
/*** @Classname ReturnProcessChain* @Description 兼* 容 4.1.5之前 dataway版本 dataway 执行结果处理, 让 structure 配置仅使用于   dataway页面调试使用* @Date 2023/8/3 20:47* @Created by Leo825*/
@Slf4j
public class ResultProcessChain implements ResultProcessChainSpi {public static ResultProcessChain getInstance() {return new ResultProcessChain();}/*** 对返回结果进行处理* @param formPre* @param apiInfo* @param result* @return*/@Overridepublic Object callAfter(boolean formPre, ApiInfo apiInfo, Object result) {// apiInfo.isPerform() 为 true 表示,API 调用是从 UI 界面发起的。if (apiInfo.isPerform() || apiInfo.getParameterMap().containsKey("SELF_CALL")) {return result;}apiInfo.getOptionMap().put("resultStructure", false);return AjaxResult.success(result);}/*** 异常* @param formPre* @param apiInfo* @param e* @return*/@Overridepublic Object callError(boolean formPre, ApiInfo apiInfo, Throwable e) {if (apiInfo.isPerform()) {return ResultProcessChainSpi.super.callError(formPre, apiInfo, e);}apiInfo.getOptionMap().put("resultStructure", false);return AjaxResult.error( "系统繁忙");}
}

swagger 配置

package com.demo.config;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;import java.util.ArrayList;
import java.util.List;/*** swagger配置*/
@Component
@Primary
public class SwaggerProvider implements SwaggerResourcesProvider {@Overridepublic List<SwaggerResource> get() {List<SwaggerResource> resources = new ArrayList<>();resources.add(swaggerResource("应用接口", "/v2/api-docs", "1.0"));resources.add(swaggerResource("Dataway接口", "/interface-ui/api/docs/swagger2.json", "1.0"));return resources;}private SwaggerResource swaggerResource(String name, String location, String version) {SwaggerResource swaggerResource = new SwaggerResource();swaggerResource.setName(name);swaggerResource.setLocation(location);swaggerResource.setSwaggerVersion(version);return swaggerResource;}
}

将 Dataway 里面的接口发布到 swagger里面

package com.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;/*** swagger配置*/
@EnableSwagger2
@Configuration()
public class SwaggerConfig {@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2)//.apiInfo(apiInfo())//.select()//.apis(RequestHandlerSelectors.basePackage("com.demo"))//.paths(PathSelectors.any())//.build();}private ApiInfo apiInfo() {return new ApiInfoBuilder()//.title("Spring Boot中使用Swagger2构建RESTful APIs")//.description("参考手册:https://www.hasor.net/doc/display/dataql/")//.termsOfServiceUrl("https://www.hasor.net/doc/display/dataql/")//.contact("zyc@hasor.net").version("1.0")//.build();}
}

自定义 Udf

可以使用自定义udf,并且在管理页面可以直接访问

package com.demo.udf;import com.demo.config.SpringContextUtil;
import com.demo.service.MyUdfService;
import lombok.extern.slf4j.Slf4j;
import net.hasor.dataql.DimUdf;
import net.hasor.dataql.Hints;
import net.hasor.dataql.Udf;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** 自定义 udf,需要在 DatawayModule 添加以下配置代码,否则会出现注入为 null 问题* // udf/udfSource/import 指令 的类型创建委托给 spring* QueryApiBinder queryBinder = apiBinder.tryCast(QueryApiBinder.class);* queryBinder.bindFinder(Finder.TYPE_SUPPLIER.apply(this));*/
@Slf4j
@DimUdf("myNameUdf")
@Service
public class MyNameUdf implements Udf {@Resourceprivate MyUdfService myUdfService;@Overridepublic Object call(Hints readOnly, Object... params) {log.info("获取当前服务信息: " + myUdfService.myName());return "张三";}
}

web管理页面调用方式如下:

import 'com.demo.udf.MyNameUdf' as myNameUdf;
return myNameUdf();

示意图1

据官方文档说可以通过 import ‘bean’ 方式引入,但是尝试了没有成功。

指定数据源进行查询

主要通过 FRAGMENT_SQL_DATA_SOURCE 来指定数据源:

// springboot 整合Dataway 多数据源配置。使用示例:
hint FRAGMENT_SQL_DATA_SOURCE = "dataSource2";
var query = @@sql()<%select * from subjects
%>
return query()

测试2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/36709.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript应用:五子棋游戏实战开发

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责…

面试热题(螺旋矩阵)

给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素 一看到这个大家有没有想到 就是一个螺旋形状&#xff0c;那这道题我们应该怎么解决&#xff1f; 我们先来仔细的看&#xff0c;它这种螺旋形状的遍历是先【右-下-左-上】…

Docker中Tomcat部署步骤

第一次访问没有东西。

为什么我不推荐任何人用C语言作为编程启蒙第一课?

前言 写了20多年的代码&#xff0c;之前做过阿里的高级架构师&#xff0c;在技术这条路上跌跌撞撞了很多&#xff0c;我今天分享一些我个人的自学方法给各位。为什么我会说&#xff1a;不推荐任何人用C语言作为编程启蒙第一课&#xff1f; 这里有很多同学要站出来说了&#x…

VsCode美化 - VsCode自定义 - VsCode自定义背景图

VsCode美化 - VsCode自定义 - VsCode自定义背景图&#xff1a;添加二次元老婆图到VsCode 前言 作为一个二刺螈&#xff0c;VsCode用久了&#xff0c;总觉得少了些什么。是啊&#xff0c;高效的代码生产工具中怎么能没有老婆呢&#xff1f; 那就安装一个VsCode插件把老婆添加…

章节7:Burp Intruder模块

章节7&#xff1a;Burp Intruder模块 参考资料 https://portswigger.net/burp/documentation/desktop/tools/intruder 01 Intruder模块作用与原理 原理 http://xxx.xx.com/bbs/index.php?namewuyanzu&mottogo 对请求参数进行修改&#xff0c;分析响应内容&#xff0…

Linux 内核第一版 (v0.01) 开源代码解读

探索Linux v0.01的内部结构&#xff0c;Linux内核经常被认为是一个庞大的开源软件。在撰写本文时&#xff0c;最新版本是v6.5-rc5&#xff0c;包含36M行代码。不用说&#xff0c;Linux是几十年来许多贡献者辛勤工作的成果。 Linux 内核首个开源版本 (v0.01) 的体积非常小&…

四、Dubbo扩展点加载机制

四、Dubbo扩展点加载机制 4.1 加载机制概述 Dubbo良好的扩展性与框架中针对不同场景使用合适设计模式、加载机制密不可分 Dubbo几乎所有功能组件都是基于扩展机制&#xff08;SPI&#xff09;实现的 Dubbo SPI 没有直接使用 Java SPI&#xff0c;在它思想上进行改进&#xff…

竞赛项目 深度学习的视频多目标跟踪实现

文章目录 1 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的视频多目标跟踪实现 …

全网最牛,Appium自动化测试框架-关键字驱动+数据驱动实战(二)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 util 包 util 包…

数据可视化工具LightningChart .NET正式发布v10.5.1——拥有全新的3D新功能

LightningChart.NET完全由GPU加速&#xff0c;并且性能经过优化&#xff0c;可用于实时显示海量数据-超过10亿个数据点。 LightningChart包括广泛的2D&#xff0c;高级3D&#xff0c;Polar&#xff0c;Smith&#xff0c;3D饼/甜甜圈&#xff0c;地理地图和GIS图表以及适用于科学…

网络安全专业术语英文缩写对照表

因在阅读文献过程中经常遇到各种专业缩写&#xff0c;所以把各种缩写总结了一下。 因能力有限&#xff0c;错误在所难免&#xff0c;欢迎进行纠错与补充&#xff1a;https://github.com/piaolin/CSAbbr 渗透相关 缩写全称解释备注XSSCross Site Script Attack跨站脚本攻击为…

java毕业设计-智慧食堂管理系统-内容快览

首页 智慧食堂管理系统是一种可以提高食堂运营效率的管理系统。它将前端代码使用Vue实现&#xff0c;后端使用Spring Boot实现。这个系统的目的是简化食堂管理&#xff0c;提高食堂服务质量。在现代快节奏的生活中&#xff0c;人们对餐饮服务提出了更高的要求&#xff0c;食堂管…

Docker安装elasticsearch分布式搜索

文章目录 ☀️安装elasticsearch☀️1.部署单点es&#x1f338;1.1.创建网络&#x1f338;1.2.下载镜像&#x1f338;1.3.运行 ☀️2.部署kibana&#x1f338;2.1.部署&#x1f338;2.2.DevTools ☀️3.安装IK分词器&#x1f338;3.1.在线安装ik插件&#xff08;较慢&#xff0…

Rx.NET in Action 中文介绍 前言及序言

Rx 处理器目录 (Catalog of Rx operators) 目标可选方式Rx 处理器(Operator)创建 Observable Creating Observables直接创建 By explicit logicCreate Defer根据范围创建 By specificationRangeRepeatGenerateTimerInterval Return使用预设 Predefined primitivesThrow …

答疑:Arduino IDE配置其他开发板下载速度慢

基于案例&#xff1a;Linux环境Arduino IDE中配置ATOM S3 通常&#xff0c;网络问题较多&#xff0c;可以使用一些技巧。 https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json 没有配置&#xff0c;不支持M5Stack&#xff08;ESP32&…

字节原来这么容易进,是面试官放水,还是公司实在是太缺人?

本人211非科班&#xff0c;之前在字节和腾讯实习过&#xff0c;这次其实没抱着什么特别大的希望投递&#xff0c;没想到字节可以再给我一次机会&#xff0c;还是挺开心的。 本来以为有个机会就不错啦&#xff01;没想到能成功上岸&#xff0c;在这里要特别感谢帮我内推的同学&…

【Python】进阶之 MySQL入门教程

文章目录 数据库概述Mysql概述Mysql安装与使用Navicat安装和使用Mysql终端指令操作Mysql和python交互订单管理案例实现 数据库概述 数据库的由来 发展历程说明人工管理阶段用纸带等进行数据的存储文件系统阶段数据存储在文件中数据库阶段解决了文件系统问题高级数据库阶段分布式…

IDEA 设置字体大小无效

设置字体大小&#xff0c;一般都是从file>settings>editor>font>Size里设置&#xff0c;一般都有效。 但是&#xff0c;如果是更换了主体&#xff0c;则需要从主体颜色菜单那里这是&#xff0c;你看这个页面&#xff0c;上面黄色三角也提示你了&#xff0c;要去颜色…

SpringBoot中间件使用之EventBus、Metric、CommandLineRunner

1、EventBus 使用EventBus 事件总线的方式可以实现消息的发布/订阅功能&#xff0c;EventBus是一个轻量级的消息服务组件&#xff0c;适用于Android和Java。 // 1.注册事件通过 EventBus.getDefault().register(); // 2.发布事件 EventBus.getDefault().post(“事件内容”); …