-
2020-09-15 15:18:10
1.静态数据和动态数据都是指系统运行过程中的数据,其区别在于二者一个可变化一个不可变化。
2.静态数据是指在运行过程中主要作为控制或参考用的数据,它们在很长的一段时间内不会变化,一般不随运行而变。
3.动态数据包括所有在运行中发生变化的数据以及在运行中需要输入、输出的数据及在连机操作中要改变的数据。更多相关内容 -
静态数据和动态数据
2020-12-28 18:01:35一、静态数据 1、概念: 一些永久性的数据,一般存储在硬盘中。...动态数据指在程序运行过程中,动态产生的临时数据,一般存储在内存中,内存的存储空间一般都比较小,现在普通计算机的内存只有8G左右,一、静态数据
1、概念:
一些永久性的数据,一般存储在硬盘中。硬盘的存储空间一般都比较大,现在普通计算机的硬盘都有500G左右,因此硬盘中可以存放一些比较大的文件。
2、存储时长:
计算机关闭之后再开启,这些数据依旧还在,只要你不主动删除或者硬盘没坏,这些数据永远都在。
3、哪些是静态数据
静态数据一般是以文件的形式存储在硬盘上,比如:文档,照片,视频。二、动态数据
1、概念:
动态数据指在程序运行过程中,动态产生的临时数据,一般存储在内存中,内存的存储空间一般都比较小,现在普通计算机的内存只有8G左右,因此要谨慎使用内存,不要占用太多的内存空间。
2、存储的时长
计算机关闭之后,这些临时数据就会被清除。
3、哪些是动态数据
当运行某个程序(软件)时,整个程序就会被加载到内存中,在程序运行过程中,会产生各种各样的临时数据,这些临时数据都是存储在内存中的。当程序停止运行或者计算机被强制关闭时,这个程序产生的多有的临时数据都会被清除。为什么不把所有的应用程序加载到硬盘中执行?
因为内存的访问速度比硬盘快N倍。 -
什么是动态加载的数据?(爬虫学习)举例,为什么使用selenium
2022-01-22 20:24:45以稀土掘金网站为例, 当我们写网络爬虫对https://juejin.cn/这个url发起请求时,即访问的下方这个名为juejin.cn的文件,对应的...使用selenium可以获取到动态加载的数据,但是动态加载的数据是动态的,所以每一次访问以稀土掘金网站为例,
当我们写网络爬虫对https://juejin.cn/这个url发起请求时,即访问的下方这个名为juejin.cn的文件,对应的response一栏中,是我们能获取到的数据。
以网页上的“2022 首次更文挑战”的字段,在这个response中是不存在的。即使用requests访问上边的url是获取不到该数据的,该数据即为动态加载的。点击search进行搜索,
可以找到该数据所在的url。
使用selenium可以获取到动态加载的数据,但是动态加载的数据是动态的,所以每一次访问返回的数据未必相同,但是会有。
-
Spring动态数据源与运行时动态添加数据源
2019-08-05 11:34:361、多数据源与动态数据源 当项目不只是要用到一个数据库的时候就需要使用到多个数据源了,这种场景很多,比如要查找的数据不在同一个数据库库中,或者是要做数据库读写分离。应对上面的问题主要有两种解决方法。 ...1、多数据源与动态数据源
当项目不只是要用到一个数据库的时候就需要使用到多个数据源了,这种场景很多,比如要查找的数据不在同一个数据库库中,或者是要做数据库读写分离。应对上面的问题主要有两种解决方法。
第一种:在Spring中注入多个DataSource,然后根据不同的DataSource生成不同的SqlSessionFactory,把要操作不同数据库的mapper接口放在不同的包下,并且使用MyBatis的@MapperScan注解,使用不同的SqlSessionFactory扫描不同包下的mapper接口。
例如:
第一步:向Spring中注入多个数据源 @Bean("db1-DataSource") @Primary//注意这个@Primary注解是必须的,必须要有一个数据源加上这个注解,否则SpringBoot无法启动 @ConfigurationProperties(prefix = "datasource.db1") fun db1DataSource(): DataSource { return DataSourceBuilder.create().build() } @Bean("db2-DataSource") @ConfigurationProperties(prefix = "datasource.db2") fun db2DataSource(): DataSource { return DataSourceBuilder.create().build() } 第二步:生成多个SqlSessionFactory并注入Spring @Bean("db1-SqlSessionFactory") fun db1SqlSessionFactory(@Qualifier("db1-DataSource") ds: DataSource): SqlSessionFactory { val fb = SqlSessionFactoryBean() fb.setDataSource(ds) fb.setMapperLocations("你的mapper的xml文件位置") return fb.getObject() } @Bean("db2-SqlSessionFactory") fun db2SqlSessionFactory(@Qualifier("db2-DataSource") ds: DataSource): SqlSessionFactory { val fb = SqlSessionFactoryBean() fb.setDataSource(ds) fb.setMapperLocations("你的mapper的xml文件位置") return fb.getObject() } 第三步:@MapperScan使用不同的SqlSessionFactory扫描不同包下的mapper接口生成代理对象,假设要操作db1数据库的mapper接口放在app.mapper.db1包下,要操作db2数据库的mapper接口放在app.mapper.db2包下 @MapperScan(value = ["app.mapper.db1"], sqlSessionFactoryRef = "db1-SqlSessionFactory") @MapperScan(value = ["app.mapper.db2"], sqlSessionFactoryRef = "db2-SqlSessionFactory") 这样不同包下的mapper接口就可以操作不同的数据库了。
接下来详细介绍第二种方法。
第二种:使用Spring提供的动态数据源AbstractRoutingDataSource
AbstractRoutingDataSource是一个抽象类,他实现了DataSource接口,内部可以存放多个DataSource,可以在需要的时候返回不同的DataSource。
接下来解析AbstractRoutingDataSource的部分源码:
//AbstractRoutingDataSource的内部使用了一个map存放多个数据源,key是数据源的唯一名字(可以任意命名,但是要保证唯一),value是对应的DataSource private Map<Object, Object> targetDataSources;
//提供一个默认使用的数据源 private Object defaultTargetDataSource;
//这个是我们要实现的一个抽象方法,返回值是DataSource的唯一名字,表示使用该名字对应的DataSource protected abstract Object determineCurrentLookupKey();
//这个是决定使用哪个数据源的方法,根据determineCurrentLookupKey的返回值来决定 protected DataSource determineTargetDataSource() { Object lookupKey = determineCurrentLookupKey(); DataSource dataSource = this.resolvedDataSources.get(lookupKey); if (dataSource == null && (this.lenientFallback || lookupKey == null)) { dataSource = this.resolvedDefaultDataSource; } if (dataSource == null) { throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]"); } return dataSource; }
//可以设置存放多个数据源的map public void setTargetDataSources(Map<Object, Object> targetDataSources) { this.targetDataSources = targetDataSources; } //设置默认的数据源 public void setDefaultTargetDataSource(Object defaultTargetDataSource) { this.defaultTargetDataSource = defaultTargetDataSource; }
我们要做的就是继承这个AbstractRoutingDataSource抽象类,并且实现determineCurrentLookupKey() 这个方法,通过返回值来动态改变需要使用的数据源。
现在来假设一种应用场景,我们需要拦截标注了@Transactional注解的方法,如果这个方法是以"add"、"update"、 "delete",作为前缀,那么就使用db1-DataSource,如果是以 "get" 做为前缀,则使用db2-DataSource。这相当于进行了一个简单的读写分离。
也就是说我们需要在标注了@Transactional注解的事务方法执行之前,根据方法签名去动态改变使用的DataSource。
这里可以编写一个切面去拦截该要执行的事务方法,然后在切面当中去判断执行的方法名,将获取的结果信息保存在一个ThreradLocal当中,这样就可以在AbstractRoutingDataSource的determineCurrentLookupKey方法中从ThreadLocal中获取这个信息并且返回对应的数据源的名字。使用ThreadLocal的主要原因是因为事务方法总是并发执行的,为了防止相互的干扰。
具体的示例代码如下:
我编写了一个DynamicDataSource去继承了AbstractRoutingDataSource,并且实现了determineCurrentLookupKey方法。
class DynamicDataSource : AbstractRoutingDataSource() { override fun determineCurrentLookupKey(): Any { //这个MultipleDataSourceConfig是配置了多个数据源、sqlSessionFactory等的一个配置类 val key = MultipleDataSourceConfig.threadLocal.get() println(" DynamicDataSource 当前使用的数据库为 : ${key} ") if (key == null) { println("error dataSource key ") return "db1"//这个是默认数据源的key } return key } }
这个是配置类。
EnableTransactionManagement @Configuration open class MultipleDataSourceConfig { companion object { val threadLocal: ThreadLocal<String> = ThreadLocal() } @Bean("db1-DataSource") @Primary open fun masterDataSource(): DataSource? { 根据配置信息返回一个数据源 } @Bean("db2-DataSource") open fun masterDataSource(): DataSource? { 根据配置信息返回一个数据源 } @Bean("dataSource") open fun dataSource(@Qualifier("db1-DataSource") db1: DataSource, @Qualifier("db2-DataSource") db2: DataSource): DynamicDataSource { val map = 把db1与db2放入一个map当中,key是db1和db2,value是对应的数据源 return DynamicDataSource().apply { this.setTargetDataSources(map) this.setDefaultTargetDataSource(db1) } } @Bean("sqlSessionFactory") open fun sqlSessionFactory(@Qualifier("dataSource") ds: DataSource): SqlSessionFactory { val bean = SqlSessionFactoryBean() bean.setDataSource(ds) return bean.getObject() } @Bean open fun transactionManager(@Qualifier("dataSource") ds: DataSource): DataSourceTransactionManager { return DataSourceTransactionManager(ds) } }
这个是拦截事务方法的切面。
@Component @Aspect @Order(1)//这个注解的作用稍后会进行讲解 class SelectDataSourceAspect { @Before("@annotation(org.springframework.transaction.annotation.Transactional)") fun before(jp: JoinPoint) { println(" SelectDataSourceAspect 拦截的方法名为 ${jp.signature.name} ") try { println(" SelectDataSourceAspect 执行${jp.signature.name}方法 : 事务已经开启 -> " + TransactionInterceptor.currentTransactionStatus().toString()) //println(TransactionInterceptor.currentTransactionStatus().toString() + " " + txm) } catch (e: Exception) { println(" SelectDataSourceAspect 执行${jp.signature.name}方法 : 事务没有开启 ") } if (如果 jp.signature.name 是以add、update、delete作为前缀) { MultipleDataSourceConfig.threadLocal.set("db1") } else { MultipleDataSourceConfig.threadLocal.set("db2") } } }
到这里好像看起来没问题,但是有一个重大的bug。
Spring当中有一个事务切面来帮我们处理事务方法,他主要是在事务方法执行之前从数据源中拿取connection,设置开启事务,如果成功执行则提交,抛出异常则回滚(具体的源码在Spring的事务管理器DataSourceTransactionManager中)。
而我们的切面是要在事务方法执行之前进行使用数据源判断的,也就是是说这两个切面是有执行的先后顺序的。
例如:假设开始的时候Spring的事务切面先执行,他从数据源中拿取connection,因为ThreadLocal当中没有值,所以拿取到的connection是默认数据源db1的,在他拿取connection之后我们才改变了使用的数据源,这个显然是错误的。
那么如何改变切面的执行顺序呢?
查阅官方文档有这样的一段描述:
大致内容就是可以给切面加上@Order注解,@Order注解内部有一个int类型的值表示优先级,该值越小则切面越优先被执行。
因此给我们配置的切面加上@Order(1)注解,就可以保证我们的优先执行了。
这就是第二种方法的全部内容以及一些注意事项。
说明:
1、并不是一定要使用AOP来判断使用的数据源,你可以在filter、controller、controller的拦截器等等 当中进行判断。
2、示例当中通过方法名来判断使用的数据源显然不是很优美,你可以编写一个自己的注解,例如@Read、@Write,然后在AOP中获取Method,利用反射拿出注解内容再进行判断,这样的话代码也会好看很多。注意:只有环绕的通知(@Around)才能拿到Method,像前置通知@Before只能拿到方法签名。
2、运行时动态添加数据源
针对上面使用的spring动态数据源,我有一个突发奇想,能不能在项目运行的时候添加数据源呢?也就是在不需要停止web应用的情况的通过网络传输一些数据源的配置信息给web应用,然后web应用就可以使用这个新加数据源操作对应的数据库。
我们前面提到的AbstractRoutingDataSource中使用了[Map<Object, Object> targetDataSources]来保存多个数据源,考虑在运行的时候往这个map里面put新的数据源就可以。
在具体的实现上,发送数据源配置信息我决定使用apollo,在apollo上添加的配置会同步到web应用中,当然你可以使用其他的方法,比如通过controller接受数据源配置或者通过dubbo这样的rpc框架、或者是写个listener监听端口使用原生的socket进行信息传输等等,喜欢那种就用那种。我使用apollo主要因为,我的项目的配置信息全部放在apollo上进行了统一管理。
使用一个ConcureentHashMap来存放这些数据源,把它注册进Spring的容器当中,并且通过setTargetDataSources方法set进AbstractRoutingDataSource中。使用ConcureentHashMap而不使用HashMap的主要是因为增加数据源操作和事务切面获取数据源操作之间可能会有并发执行的情况,为了线程安全考虑。
代码示例如下:
向Spring中注入一个ConcureentHashMap
@Bean("slaves") open fun runtimeDataSource(): ConcurrentHashMap<Any, Any> { val map = ConcurrentHashMap<Any, Any>() val cfg = ConfigService.getAppConfig() val set = cfg.propertyNames for (key in set) { //配置的前缀是db.slave.,这里是获取已经配置了的数据源 if (key.startsWith("db.slave.")) { val value = cfg.getProperty(key, "") //编写一个getDataSource方法解析自定义的配置,kv中key表示数据源的名字,value表示数据源。 val kv = getDataSource(key, value) if (kv != null) { map.put(kv.key, kv.value) } } } //这里是监听随时通过网络发送过来的数据源配置 cfg.addChangeListener(ConfigChangeListener { changeEvent -> //使用同步方法的主要原因是,把更新后的数据及时刷新回主存当中。 //因为执行synchronized之前,需要的数据会从主存中获取而不是缓存中获取,执行完成之后会及时的刷新回主存。(周志明的深入理解jvm中有提到) //而且也是防止一次性添加多个数据源并发的时候发生一些错误。 synchronized(this) { for (key in changeEvent.changedKeys()) { val change = changeEvent.getChange(key) if (change.changeType.equals(PropertyChangeType.ADDED) && change.propertyName.startsWith("db.slave.")) { //编写一个getDataSource方法解析自定义的配置,kv中key表示数据源的名字,value表示数据源。 val kv = getDataSource(change.propertyName, change.newValue) if (kv != null) { //把数据源put进行map当中 map.put(kv.key, kv.value) } } } } }) return map }
在我们的切面当中注入这个map。
@Component @Aspect @Order(1) class SelectDataSourceAspect { @Autowired @Qualifier("slaves") lateinit var dbs: ConcurrentHashMap<Any, Any> @Before("@annotation(org.springframework.transaction.annotation.Transactional)") fun before(jp: JoinPoint) { println(" SelectDataSourceAspect 拦截的方法名为 ${jp.signature.name} ") try { println(" SelectDataSourceAspect 执行${jp.signature.name}方法 : 事务已经开启 -> " + TransactionInterceptor.currentTransactionStatus().toString()) } catch (e: Exception) { println(" SelectDataSourceAspect 执行${jp.signature.name}方法 : 事务没有开启 ") } val methodName = jp.signature.name if (methodName 是一个add、updat、delete方法 || dbs.size == 1) { MultipleDataSourceConfig.threadLocal.set("db1") } else { val li = mutableListOf<String>() for (k in dbs.keys) { if (!"db1".equals(k.toString())) { li.add(k.toString()) } } //如果是读取方法则随便从其他的数据源当中返回一个。 //读写分离,写的话必须走主库,读的话随便挑一个从库。 //当然可以编写更有效率的路由选择算法来替换这个随机选择算法。 val idx = Math.abs(random.nextInt()) % li.size MultipleDataSourceConfig.threadLocal.set(li[idx]) } } }
DynamicDataSource中的代码保持不变,只需要从ThreadLocal中获取只然后返回就可以了。
但是!测试的发现并不会选择到动态添加的数据源,只有提前配置好的数据源才可以,但是DynamicDataSource中已经返回了正确的数据源的key。
打开AbstractRoutingDataSource源码查看选择数据源的过程:
//可以看到,获取connection是从一个determineTargetDataSource返回的数据源中拿的 @Override public Connection getConnection() throws SQLException { return determineTargetDataSource().getConnection(); } //这个determineTargetDataSource是根据determineCurrentLookupKey返回的key来获取数据源 //但是!他是从resolvedDataSources中获取的,那么这个resolvedDataSources又是从哪里来的呢? protected DataSource determineTargetDataSource() { Object lookupKey = determineCurrentLookupKey(); DataSource dataSource = this.resolvedDataSources.get(lookupKey); if (dataSource == null && (this.lenientFallback || lookupKey == null)) { dataSource = this.resolvedDefaultDataSource; } if (dataSource == null) { throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]"); } return dataSource; } //原来resolvedDataSources只是从targetDataSources中copy了一份过去而已 @Override public void afterPropertiesSet() { if (this.targetDataSources == null) { throw new IllegalArgumentException("Property 'targetDataSources' is required"); } this.resolvedDataSources = new HashMap<Object, DataSource>(this.targetDataSources.size()); for (Map.Entry<Object, Object> entry : this.targetDataSources.entrySet()) { Object lookupKey = resolveSpecifiedLookupKey(entry.getKey()); DataSource dataSource = resolveSpecifiedDataSource(entry.getValue()); this.resolvedDataSources.put(lookupKey, dataSource); } if (this.defaultTargetDataSource != null) { this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource); } }
知道原因之后就可以进行修改了,干脆在DynamicDataSource把determineTargetDataSource方法也重写了,然后从注入的map当中选择数据源,就不用通过resolvedDataSources获取了。
修改后的DynamicDataSource代码如下:
class DynamicDataSource : AbstractRoutingDataSource() { @Autowired @Qualifier("slaves") lateinit var dbs: ConcurrentHashMap<Any, Any> override fun determineCurrentLookupKey(): Any { val key = MultipleDataSourceConfig.threadLocal.get() if (key == null) { println("error dataSource key ") return "db1" } return key } //重写这个方法,其实这个在父类中是protect,这是一个很明显的提示 override fun determineTargetDataSource(): DataSource? { val lookupKey = determineCurrentLookupKey() var dataSource = dbs[lookupKey] if (dataSource is DataSource) { return dataSource } return null } }
到此整个过程就分享完毕了,我进行了一些场景的测试都得到了正确的结果。
3、工程的源代码
代码托管在github上面:工程源码
-
openGauss动态数据脱敏
2021-11-08 14:01:29数据脱... -
Python爬虫:什么是静态网页(数据),什么是动态网页(数据)
2022-04-01 16:27:31如果打印出的结果和我用浏览器看到的结果基本差不多(这里的结果是指数据信息),通常情况下可以称呼这个网页是一个静态网页(当然有些网站页面上有些数据你有可能获取不到,这个涉及到动态网页部分了,可以看小编的第2... -
Spring动态切换多数据源Demo
2015-02-03 15:24:55请自行修改com/resources/datasource.properties中数据库配置,Demo中配置的两个数据源,一个是Mysql,一个是Oracle。 运行之前请自行建立数据库的表。 -
Vue中Echarts动态数据的实现
2022-04-21 22:01:33最终效果 实现过程 引入Echarts依赖 npm install echarts --save ...Echarts 动态数据</h1> <button @click="start">开始执行</button> <button @click="stop">停止执行</button&g -
spring动态加载数据源+动态添加数据源
2016-11-24 09:07:17动态加载数据源关键一点:在系统运行时加载多一个数据源,加载此数据源的对象必须和系统启动时加载数据源的同一个,在我这里加载数据源的对象是类DynamicDataSource,可在这里添加一个加载数据源的方法: ... -
ECharts 动态更新数据
2020-08-16 16:29:29序言:本篇继续介绍Echarts的使用,主要解决数据更新! 目录序言:本篇继续介绍Echarts的使用,主要解决数据更新!一、echarts动态更新二、echarts-for-react动态更新 一、echarts动态更新 二、echarts-for-react... -
JdbcTemplate动态多数据源配置
2019-09-04 22:44:24一、前言 多数据源的配置,是一个相对比较常见的需求。 什么是数据源?数据源就是javax.sql.DataSource,所有实现了这个接口的DataSource就叫做数据源,现在...而这些场景下的业务sql通常是属于动态数据源,它们的... -
这 5 款动态数据可视化工具,哪一款是你的最爱
2022-01-20 14:54:22视频当道的时代,数据可视化自然也要动起来。我常用的动态可视化工具主要有「Tableau、Echarts、Flourish、Python」这几个,另外加上地图可视化神器「kepler.gl」。这五款可视化工具差异很大,在各自领域都是学霸级... -
vue中Echarts动态数据
2021-04-15 18:16:18在真正的开发中,我们使用的数据都是从后端获取过来的,有时候还需要做到实时刷新,今天我也遇到这种问题了,做个总结。 方法一:通过computed computed: { options() { let that = this; let option = { ... -
SpringBoot动态从数据库中获取数据源,动态切换数据源
2020-11-04 19:09:30SpringBoot动态多数据源 1.简介 SpringBoot静态数据源指的是...动态数据源指的是将数据源信息配置在关系型数据库中或者缓存数据库中,在项目启动时只初始化一个默认数据源,在项目运行过程中动态的从数据库中读取数据源信 -
LabView学习笔记(四):动态数据类型
2021-01-10 16:23:30在LabView中,动态数据类型表示为深蓝色,只有Express VI才能产生和接收Express...使用获取动态数据ExpressVI获取动态数据的属性,使用设置动态数据属性ExpressVI设置动态数据的属性,如信号名、时间标识、时间模式等。 -
hive使用动态分区插入数据详解
2018-05-20 15:21:57往hive分区表中插入数据时,如果需要创建的分区很多,比如以表中某个字段进行分区存储,则需要复制粘贴修改很多sql去执行,效率低。因为hive是批处理系统,所以hive提供了一个动态分区功能,其可以基于查询参数的... -
动态网页数据抓取
2019-11-15 15:06:49动态网页数据抓取 一、网页 1.传统网页: 如果需要更新内容,则需要重新加载网页。 2.动态网页: 使用AJAX则不需要加载更新整个网页,实现部分内容更新。 二、什么是AJAX? AJAX(Asynchronouse JavaScript ... -
什么是动态数据类型
2016-07-02 13:02:45动态数据类型 Python是动态数据类型,变量不需要指定类型。 Python的变量,可变的是指向,不可通过变量名修改其指向数据单元的内容。 //函数id() 的作用是查看变量指向的内存地址。见help(id) //内存中... -
oracle 数据字典、数据字典视图,动态性能视图(展示数据库的活动状态信息)
2022-03-30 06:51:13动态性能视图2.1 概念2.2 常见的动态性能视图v$parameterv$processv$sessionv$sysstatv$logv$logfilev$lockv$transactionv$fixed_view_definition 一.数据字典 1.1 概念 数据字典记录数据库最基本的信息,包括数据... -
Android 根据EditText搜索框ListView动态显示数据
2014-09-18 20:13:59Android 根据EditText搜索框ListView动态显示数据 根据SimpleAdapter创建ListView。简单粗暴 -
动态面板数据模型
2019-11-20 20:30:432、含外生变量的动态面板模型 这里要注意的是Yi,t−1Y_{i,t-1}Yi,t−1和Xi,tX_{i,t}Xi,t是有相关性的,所以求出来的ρ1\rho1ρ1是有偏的。 3、根据T与N的关系进行分类, 3.2、短动态面板模型 可以知道ΔYi,t... -
spring中动态数据源切换失效问题剖析
2020-01-16 11:03:36我们在使用spring中动态数据源的时候,往往在业务代码中需要指定数据源,在进行业务操作的时候就会去指定的数据源操作数据:代码如下 数据源,两个数据源,ds1,ds2: @Bean public DataSource ... -
Python之分享常用的五款动态数据可视化工具
2022-03-03 20:24:48它已经成为商业BI界的TOP选手,很多大型公司像阿里、谷歌都在使用,能快速搭建数据系统。 可以通过设置页面动画,来制作动态可视化图表。 官网地址:Tableau。 二、Echarts 百度旗下基于 JavaScript 的开源 Web ... -
聊聊我常用的5款动态数据可视化工具
2022-02-19 19:39:10视频当道的时代,数据可视化自然也要动起来。 我常用的动态可视化工具主要有Tableau、Echarts、Flourish、Python这几个,另外一个地图可视化神器kepler.gl,是技术群小伙伴的分享。 【注】文末提供技术交流方式 这五... -
Spring项目中使用两种方法动态切换数据源,多数据源切换
2018-08-13 22:03:55本文介绍两种切换数据库的方法。 方法1:数据库信息都配置在spring xml中,适用于一般数据库切换。...方法2:将数据库信息配置在默认数据源中,适用于切换数据库操作同一方法,相当于批量执行方法。... -
easyui datagrid动态加载数据、清空数据
2018-06-29 09:42:25一、datagrid动态数据加载easyui datagrid实现动态加载数据,通常有两种方式。一种方式是通过动态改变datagrid的url属性,进行数据重载;另一种方式,是通过ajax动态加载json数据。1、改变url属性重载数据。var url=... -
Easyui combobox下拉框动态绑定数据
2018-09-27 15:37:53easyui-combobox根据数据库查询绑定数据,如下: 1、html <select id="st_cmpy" editable="false" class="easyui-combobox" name="compyId" data-options=&... -
ucharts动态渲染数据
2020-02-28 19:48:25ucharts引入方式分两种 第一种按插件的例子引入 <view class="qiun-columns"> <view class="qiun-bg-white qiun-title-bar qiun-common-mt" > <view class="qiun-title-dot-light">... -
动态下拉框,从后台获取数据
2019-06-13 18:38:22动态下拉框,从后台获取数据 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>下拉框示例</title> <script type="text/javascript" src... -
SpringBoot多数据源切换,AOP实现动态数据源切换
2018-10-30 16:32:25SpringBoot多数据源切换,AOP实现动态数据源切换 操作数据一般都是在DAO层进行处理,可以选择直接使用JDBC进行编程 或者是使用多个DataSource 然后创建多个SessionFactory,在使用Dao层的时候通过不同的...