spring sharding JDBC 动态调整数据库连接

spring sharding JDBC 动态调整数据库连接

通过重写ShardingSphereDataSource类来实现

代码

package org.apache.shardingsphere.driver.jdbc.core.datasource;import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.driver.jdbc.adapter.AbstractDataSourceAdapter;
import org.apache.shardingsphere.driver.jdbc.context.CachedDatabaseMetaData;
import org.apache.shardingsphere.driver.jdbc.context.JDBCContext;
import org.apache.shardingsphere.driver.state.DriverStateContext;
import org.apache.shardingsphere.infra.config.RuleConfiguration;
import org.apache.shardingsphere.infra.config.checker.RuleConfigurationCheckerFactory;
import org.apache.shardingsphere.infra.config.database.DatabaseConfiguration;
import org.apache.shardingsphere.infra.config.database.impl.DataSourceProvidedDatabaseConfiguration;
import org.apache.shardingsphere.infra.config.mode.ModeConfiguration;
import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
import org.apache.shardingsphere.infra.config.scope.GlobalRuleConfiguration;
import org.apache.shardingsphere.infra.datasource.props.DataSourceProperties;
import org.apache.shardingsphere.infra.datasource.props.DataSourcePropertiesCreator;
import org.apache.shardingsphere.infra.instance.definition.InstanceDefinition;
import org.apache.shardingsphere.infra.instance.definition.InstanceType;
import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
import org.apache.shardingsphere.infra.rule.builder.schema.DatabaseRulesBuilder;
import org.apache.shardingsphere.mode.manager.ContextManager;
import org.apache.shardingsphere.mode.manager.ContextManagerBuilderFactory;
import org.apache.shardingsphere.mode.manager.ContextManagerBuilderParameter;
import org.apache.shardingsphere.mode.metadata.persist.MetaDataPersistService;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.spring.boot.ShardingSphereAutoConfiguration;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** @author qyc* @version 1.0*/
@Slf4j
public final class ShardingSphereDataSource extends AbstractDataSourceAdapter implements AutoCloseable {private final String databaseName;private final ContextManager contextManager;private final JDBCContext jdbcContext;private ContextManagerBuilderParameter contextManagerBuilderParameter;private ModeConfiguration modeConfiguration;private Collection<RuleConfiguration> ruleConfigs;private Properties properties;public ShardingSphereDataSource(final String databaseName, final ModeConfiguration modeConfig) throws SQLException {this.databaseName = databaseName;this.modeConfiguration = modeConfig;this.properties = new Properties();this.ruleConfigs = new LinkedList<>();contextManager = createContextManager(databaseName, modeConfig, new HashMap<>(), this.ruleConfigs, this.properties);jdbcContext = new JDBCContext(contextManager.getDataSourceMap(databaseName));}/*** {@link ShardingSphereAutoConfiguration#shardingSphereDataSource(org.springframework.beans.factory.ObjectProvider, org.springframework.beans.factory.ObjectProvider)}** @param databaseName* @param modeConfig* @param dataSourceMap* @param ruleConfigs* @param props* @throws SQLException*/public ShardingSphereDataSource(final String databaseName, final ModeConfiguration modeConfig, final Map<String, DataSource> dataSourceMap,final Collection<RuleConfiguration> ruleConfigs, final Properties props) throws SQLException {checkRuleConfiguration(databaseName, ruleConfigs);this.modeConfiguration = modeConfig;this.databaseName = databaseName;contextManager = createContextManager(databaseName, modeConfig, dataSourceMap, ruleConfigs, null == props ? new Properties() : props);this.ruleConfigs = ruleConfigs;this.properties = props;jdbcContext = new JDBCContext(contextManager.getDataSourceMap(databaseName));}/*** 更新现有的数据库配置** @param addDataSourcePropertiesMap 添加的配置* @param dropDataSourceNames        移除的配置* @param updateSources              修改的配置* @param newDataNodes               新的节点使用配置* @throws Exception */public void updateContextMetaData(final Map<String, DataSourceProperties> addDataSourcePropertiesMap, final Collection<String> dropDataSourceNames, Map<String, DataSourceProperties> updateSources, String newDataNodes) throws Exception {if (CollectionUtils.isEmpty(addDataSourcePropertiesMap) && CollectionUtils.isEmpty(dropDataSourceNames) && CollectionUtils.isEmpty(updateSources)) {if (!StringUtils.isEmpty(newDataNodes)) {this.rebuildShardingSphereRule(newDataNodes);}return;}Map<String, DataSourceProperties> refreshProperties = new HashMap<>();Map<String, DataSource> oldDataSources = new HashMap<>(this.contextManager.getDataSourceMap(databaseName));Map<String, DataSource> closeDataSources = new HashMap<>();if (!CollectionUtils.isEmpty(addDataSourcePropertiesMap)) {log.info("添加新的db:{}", addDataSourcePropertiesMap.keySet());this.contextManager.addResource(this.databaseName, addDataSourcePropertiesMap);refreshProperties.putAll(addDataSourcePropertiesMap);}if (!CollectionUtils.isEmpty(dropDataSourceNames)) {log.info("移除旧的db:{}", dropDataSourceNames);this.contextManager.dropResource(this.databaseName, dropDataSourceNames);dropDataSourceNames.forEach(s -> {closeDataSources.put(s, oldDataSources.get(s));});}if (!CollectionUtils.isEmpty(updateSources)) {log.info("更新db:{}", updateSources.keySet());this.contextManager.dropResource(this.databaseName, updateSources.keySet());this.contextManager.addResource(this.databaseName, updateSources);refreshProperties.putAll(updateSources);}log.info("重新加载shardingRule");this.rebuildShardingSphereRule(newDataNodes);log.info("重新构建managerBuildParameter");Map<String, DataSource> dataSourceMap = this.contextManager.getDataSourceMap(databaseName);this.contextManagerBuilderParameter = this.builderParameter(this.databaseName, this.modeConfiguration, dataSourceMap, this.ruleConfigs, this.properties);closeDataSources.forEach((k, closeDataSource) -> {try {log.info("关闭原dataSources:{}", k);if (closeDataSource instanceof DruidDataSource) {((DruidDataSource) closeDataSource).close();}} catch (Exception e) {log.warn("db:{}close时出现异常,异常为:{}", k, e.getMessage(), e);}});}private Map<String, DataSourceProperties> getDataSourcePropertiesMap(final Map<String, DataSource> dataSourceMap) {Map<String, DataSourceProperties> result = new LinkedHashMap<>(dataSourceMap.size(), 1);for (Map.Entry<String, DataSource> each : dataSourceMap.entrySet()) {result.put(each.getKey(), DataSourcePropertiesCreator.create(each.getValue()));}return result;}@SuppressWarnings("unchecked")private void checkRuleConfiguration(final String databaseName, final Collection<RuleConfiguration> ruleConfigs) {ruleConfigs.forEach(each -> RuleConfigurationCheckerFactory.findInstance(each).ifPresent(optional -> optional.check(databaseName, each)));}private ContextManager createContextManager(final String databaseName, final ModeConfiguration modeConfig, final Map<String, DataSource> dataSourceMap,final Collection<RuleConfiguration> ruleConfigs, final Properties props) throws SQLException {ContextManagerBuilderParameter parameter = this.builderParameter(databaseName, modeConfig, dataSourceMap, ruleConfigs, props);this.contextManagerBuilderParameter = parameter;return ContextManagerBuilderFactory.getInstance(modeConfig).build(parameter);}private ContextManagerBuilderParameter builderParameter(final String databaseName, final ModeConfiguration modeConfig, final Map<String, DataSource> dataSourceMap,final Collection<RuleConfiguration> ruleConfigs, final Properties props) {ContextManagerBuilderParameter parameter = ContextManagerBuilderParameter.builder().modeConfig(modeConfig).databaseConfigs(Collections.singletonMap(databaseName, new DataSourceProvidedDatabaseConfiguration(dataSourceMap, ruleConfigs))).globalRuleConfigs(ruleConfigs.stream().filter(each -> each instanceof GlobalRuleConfiguration).collect(Collectors.toList())).props(props).instanceDefinition(new InstanceDefinition(InstanceType.JDBC)).build();return parameter;}private Optional<CachedDatabaseMetaData> createCachedDatabaseMetaData(final Map<String, DataSource> dataSources) throws SQLException {if (dataSources.isEmpty()) {return Optional.empty();}try (Connection connection = dataSources.values().iterator().next().getConnection()) {return Optional.of(new CachedDatabaseMetaData(connection.getMetaData()));}}@Overridepublic Connection getConnection() throws SQLException {return DriverStateContext.getConnection(databaseName, contextManager, jdbcContext);}@Overridepublic Connection getConnection(final String username, final String password) throws SQLException {return getConnection();}/*** Close data sources.** @param dataSourceNames data source names to be closed* @throws Exception exception*/public void close(final Collection<String> dataSourceNames) throws Exception {Map<String, DataSource> dataSourceMap = contextManager.getDataSourceMap(databaseName);for (String each : dataSourceNames) {close(dataSourceMap.get(each));}contextManager.close();}private void close(final DataSource dataSource) throws Exception {if (dataSource instanceof AutoCloseable) {((AutoCloseable) dataSource).close();}}@Overridepublic void close() throws Exception {close(contextManager.getDataSourceMap(databaseName).keySet());}@Overridepublic int getLoginTimeout() throws SQLException {Map<String, DataSource> dataSourceMap = contextManager.getDataSourceMap(databaseName);return dataSourceMap.isEmpty() ? 0 : dataSourceMap.values().iterator().next().getLoginTimeout();}@Overridepublic void setLoginTimeout(final int seconds) throws SQLException {for (DataSource each : contextManager.getDataSourceMap(databaseName).values()) {each.setLoginTimeout(seconds);}}public Set<String> getDataBaseNames() {return this.contextManager.getDataSourceMap(databaseName).keySet();}private void rebuildShardingSphereRule(String newDataNodes) {if (StringUtils.isEmpty(newDataNodes)) {return;}log.info("重新加载db映射:{}", newDataNodes);MetaDataPersistService metaDataPersistService = this.contextManager.getMetaDataContexts().getPersistService().get();Map<String, DatabaseConfiguration> databaseConfigurationMap = getDatabaseConfigMap(Stream.of(this.databaseName).collect(Collectors.toList()), metaDataPersistService, this.contextManagerBuilderParameter);databaseConfigurationMap.get(this.databaseName).getRuleConfigurations().forEach(rule -> {if (rule instanceof ShardingRuleConfiguration) {Collection<ShardingTableRuleConfiguration> tables = ((ShardingRuleConfiguration) rule).getTables();List<ShardingTableRuleConfiguration> newShardingTableRuleConfigurations = tables.stream().map(table -> {String newActualDataNodes = newDataNodes + "." + table.getLogicTable();ShardingTableRuleConfiguration shardingTableRuleConfiguration = new ShardingTableRuleConfiguration(table.getLogicTable(), newActualDataNodes);shardingTableRuleConfiguration.setDatabaseShardingStrategy(table.getDatabaseShardingStrategy());shardingTableRuleConfiguration.setTableShardingStrategy(table.getTableShardingStrategy());shardingTableRuleConfiguration.setReplaceTablePrefix(table.getReplaceTablePrefix());shardingTableRuleConfiguration.setKeyGenerateStrategy(table.getKeyGenerateStrategy());return shardingTableRuleConfiguration;}).collect(Collectors.toList());((ShardingRuleConfiguration) rule).setTables(newShardingTableRuleConfigurations);}});ConfigurationProperties props = new ConfigurationProperties(metaDataPersistService.getPropsService().load());Collection<ShardingSphereRule> build = DatabaseRulesBuilder.build(databaseName, databaseConfigurationMap.get(this.databaseName), props);List<ShardingSphereRule> oldRules = (List<ShardingSphereRule>) this.contextManager.getMetaDataContexts().getMetaData().getDatabases().get(databaseName).getRuleMetaData().getRules();oldRules.clear();oldRules.addAll(build);}private Map<String, DatabaseConfiguration> getDatabaseConfigMap(final Collection<String> databaseNames, final MetaDataPersistService metaDataPersistService,final ContextManagerBuilderParameter parameter) {Map<String, DatabaseConfiguration> result = new HashMap<>(databaseNames.size(), 1);databaseNames.forEach(each -> result.put(each, createDatabaseConfiguration(each, metaDataPersistService, parameter)));return result;}private DatabaseConfiguration createDatabaseConfiguration(final String databaseName, final MetaDataPersistService metaDataPersistService,final ContextManagerBuilderParameter parameter) {Map<String, DataSource> dataSources = this.contextManager.getDataSourceMap(databaseName);Collection<RuleConfiguration> databaseRuleConfigs = metaDataPersistService.getDatabaseRulePersistService().load(databaseName);return new DataSourceProvidedDatabaseConfiguration(dataSources, databaseRuleConfigs);}
}

通过调用重写的DataSource的updateContextMetaData方法来重新加载连接配置

     * @param addDataSourcePropertiesMap 添加的配置* @param dropDataSourceNames        移除的配置 * @param updateSources              修改的配置* @param newDataNodes               新的节点使用配置
spring:shardingsphere:datasource:names: ${SHARDING_DATA_SOURCE_NAMES:db-0,db-1}db-0:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://${mysql.message0.host}/${mysql.message0.database}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=falseusername: ${mysql.message0.username}password: ${mysql.message0.password}initialSize: 5 # 初始化大小minIdle: 5        # 最小maxActive: 20     # 最大maxWait: 60000    # 获取连接等待超时的时间...db-1:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.jdbc.Driver...
参数说明
参数名说明
addDataSourcePropertiesMap添加的db连接,key->连接id,例如配置中的db-0,db-1,value->根据普通db连接配置构建成的DataSourceProperties
dropDataSourceNames移除的db连接,key->连接id,例如配置中的db-0,db-1
updateSources修改的db连接,key->连接id,例如配置中的db-0,db-1,value->根据普通db连接配置构建成的DataSourceProperties
newDataNodes新的节点使用配置,将配置项中使用的的spring.shardingsphere.datasource.names值更换为该值

DataSourceProperties构建类

getDataSource(),传入的值为普通的db连接配置,例如

        type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://db3Ip/db3DB?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=falseusername: db3Userpassword: db3PwdinitialSize: 5 # 初始化大小minIdle: 5        # 最小maxActive: 20     # 最大maxWait: 60000    # 获取连接等待超时的时间timeBetweenEvictionRunsMillis: 60000    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒(3600000:为1小时)minEvictableIdleTimeMillis: 300000      # 配置一个连接在池中最小生存的时间,单位是毫秒validationQuery: select current_timestamp() #SELECT 1 FROM DUAL  #用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。testWhileIdle: true   #申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。建议配置为true,不影响性能,并且保证安全性。testOnBorrow: false   #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。缺省值:truetestOnReturn: false #归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。缺省值:falsepoolPreparedStatements: true    #打开PSCache,并且指定每个连接上PSCache的大小#是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。5.5及以上版本有PSCache,建议开启。缺省值:falsemaxPoolPreparedStatementPerConnectionSize: 20   # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100。
package com.kittlen.provider.config.sharding;import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.apache.shardingsphere.infra.datasource.pool.creator.DataSourcePoolCreator;
import org.apache.shardingsphere.infra.datasource.props.DataSourceProperties;
import org.apache.shardingsphere.infra.datasource.props.DataSourcePropertiesCreator;
import org.apache.shardingsphere.infra.exception.ShardingSphereException;
import org.apache.shardingsphere.infra.expr.InlineExpressionParser;
import org.apache.shardingsphere.spring.boot.datasource.AopProxyUtils;
import org.apache.shardingsphere.spring.boot.util.PropertyUtil;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.jndi.JndiObjectFactoryBean;
import org.springframework.stereotype.Component;import javax.naming.NamingException;
import javax.sql.DataSource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;/*** @author kittlen* @version 1.0*/
public class MyShardingDataSource {private static final String PREFIX = "spring.shardingsphere.datasource.";private static final String DATA_SOURCE_NAME = "name";private static final String DATA_SOURCE_NAMES = "names";private static final String DATA_SOURCE_TYPE = "type";private static final String JNDI_NAME = "jndi-name";/*** Get data source map.** @param environment spring boot environment* @return data source map*/public static Map<String, DataSource> getDataSourceMap(final Environment environment) {Map<String, DataSource> result = new LinkedHashMap<>();for (String each : getDataSourceNames(environment)) {try {result.put(each, getDataSource(environment, each));} catch (final NamingException ex) {throw new ShardingSphereException("Can't find JNDI data source.", ex);}}return result;}/*** Get data source map.** @param environment spring boot environment* @return data source map*/public static Map<String, DataSourceProperties> getDataSourcePropertiesMap(final Environment environment) {Map<String, DataSourceProperties> result = new LinkedHashMap<>();for (String each : getDataSourceNames(environment)) {try {result.put(each, getDataSourceProperties(environment, each));} catch (final NamingException ex) {throw new ShardingSphereException("Can't find JNDI data source.", ex);}}return result;}private static List<String> getDataSourceNames(final Environment environment) {StandardEnvironment standardEnv = (StandardEnvironment) environment;standardEnv.setIgnoreUnresolvableNestedPlaceholders(true);String dataSourceNames = standardEnv.getProperty(PREFIX + DATA_SOURCE_NAME);if (Strings.isNullOrEmpty(dataSourceNames)) {dataSourceNames = standardEnv.getProperty(PREFIX + DATA_SOURCE_NAMES);}return new InlineExpressionParser(dataSourceNames).splitAndEvaluate();}private static DataSource getDataSource(final Environment environment, final String dataSourceName) throws NamingException {Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, String.join("", PREFIX, dataSourceName), Map.class);Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource [%s] properties.", dataSourceName);if (dataSourceProps.containsKey(JNDI_NAME)) {return getJNDIDataSource(dataSourceProps.get(JNDI_NAME).toString());}return DataSourcePoolCreator.create(new DataSourceProperties(dataSourceProps.get(DATA_SOURCE_TYPE).toString(), PropertyUtil.getCamelCaseKeys(dataSourceProps)));}private static DataSourceProperties getDataSourceProperties(final Environment environment, final String dataSourceName) throws NamingException {Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, String.join("", PREFIX, dataSourceName), Map.class);Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource [%s] properties.", dataSourceName);if (dataSourceProps.containsKey(JNDI_NAME)) {return DataSourcePropertiesCreator.create(getJNDIDataSource(dataSourceProps.get(JNDI_NAME).toString()));}return new DataSourceProperties(dataSourceProps.get(DATA_SOURCE_TYPE).toString(), PropertyUtil.getCamelCaseKeys(dataSourceProps));}public static DataSourceProperties getDataSourceProperties(Map<String, Object> dataSourceProps) throws NamingException {if (dataSourceProps.containsKey(JNDI_NAME)) {return DataSourcePropertiesCreator.create(getJNDIDataSource(dataSourceProps.get(JNDI_NAME).toString()));}return new DataSourceProperties(dataSourceProps.get(DATA_SOURCE_TYPE).toString(), PropertyUtil.getCamelCaseKeys(dataSourceProps));}public static DataSource getDataSource(Map<String, Object> dataSourceProps) throws NamingException {if (dataSourceProps.containsKey(JNDI_NAME)) {return getJNDIDataSource(dataSourceProps.get(JNDI_NAME).toString());}return DataSourcePoolCreator.create(new DataSourceProperties(dataSourceProps.get(DATA_SOURCE_TYPE).toString(), PropertyUtil.getCamelCaseKeys(dataSourceProps)));}private static DataSource getJNDIDataSource(final String jndiName) throws NamingException {JndiObjectFactoryBean bean = new JndiObjectFactoryBean();bean.setResourceRef(true);bean.setJndiName(jndiName);bean.setProxyInterface(DataSource.class);bean.afterPropertiesSet();return (DataSource) AopProxyUtils.getTarget(bean.getObject());}
}

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

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

相关文章

CleanMyMac X免费macOS清理系统管家

近些年伴随着苹果生态的蓬勃发展&#xff0c;越来越多的用户开始尝试接触Mac电脑。然而很多人上手Mac后会发现&#xff0c;它的使用逻辑与Windows存在很多不同&#xff0c;而且随着使用时间的增加&#xff0c;一些奇奇怪怪的文件也会占据有限的磁盘空间&#xff0c;进而影响使用…

心理咨询医院预约和挂号系统

源码下载地址 支持&#xff1a;远程部署/安装/调试、讲解、二次开发/修改/定制 系统分为&#xff1a;患者端、医生端、管理员端。 患者端 医生端 管理员端

JAVA基础(JAVA SE)学习笔记(九)异常处理

前言 1. 学习视频&#xff1a; 尚硅谷Java零基础全套视频教程(宋红康2023版&#xff0c;java入门自学必备)_哔哩哔哩_bilibili 2023最新Java学习路线 - 哔哩哔哩 第三阶段&#xff1a;Java高级应用 9.异常处理 10.多线程 11.常用类和基础API 12.集合框架 13.泛型 14…

虚拟机VMware Workstation Pro安装配置使用服务器系统ubuntu-22.04.3-live-server-amd64.iso

虚拟机里安装ubuntu-23.04-beta-desktop-amd64开启SSH(换源和备份)配置中文以及中文输入法等 ​一、获取Ubuntu服务器版 获取Ubuntu服务器版 二、配置虚拟机 选择Custom(advanced)&#xff1a; 选择Workstation 17.x: 选择“I will install the operating system later.”…

原型制作的软件 Experience Design mac( XD ) 中文版软件特色

​XD是一个直观、功能强大的UI/UX开发工具&#xff0c;旨在设计、原型、用户之间共享材料以及通过数字技术进行设计交互。Adobe XD提供了开发网站、应用程序、语音界面、游戏界面、电子邮件模板等所需的一切。xd mac软件特色 体验设计的未来。 使用 Adobe XD 中快速直观、即取即…

上市公司员工及工资数据(2000-2022年)

参照《经济研究》中毛其淋等&#xff08;2023&#xff09;的做法&#xff0c;团队对上市公司员工、工资数据测算。用上市公司&#xff49;在&#xff54;年的员工人数的对数衡量企业的就业水平&#xff0c;采用企业应付职工薪酬与员工人数的比值衡量企业工资水平 一、数据介绍 …

计算机网络原理

2015-04 40&#xff0e;简述面向连接服务的特点。 答&#xff1a;面向连接服务的特点是&#xff1a;数据传输过程前必须经过建立连接&#xff0c;维护连接和释放连接三个过程&#xff1b;数据传输过程中&#xff0c;各分组不需要携带目的节点的地址&#xff1b;面向连接数据传…

html内连框架

src:引用页面地址 name&#xff1a;框架标识名称 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <!--iframe src&#xff1a;地址 w-h&#xff…

点云处理【七】(点云配准)

点云处理 第一章 点云数据采集 1.点云配准 点云配准是将两个或多个点云数据集融合到一个统一的坐标系统中的过程。这通常是为了创建一个完整的模型或融合从不同视角采集的数据。 点云配准一般分为粗配准和精配准&#xff0c;粗配准指的是在两幅点云之间的变换完全未知的情况下…

数组知识点以及leetcode刷题

数组 二分查找 题目 力扣题目链接 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 适用范围 数组有序&#xff0c;数…

【LeetCode】881 救生艇 中等题

给定数组 people 。people[i]表示第 i 个人的体重 &#xff0c;船的数量不限&#xff0c;每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人&#xff0c;但条件是这些人的重量之和最多为 limit。 返回 承载所有人所需的最小船数 。 示例 1&#xff1a; 输入&#…

【Python机器学习】零基础掌握BaggingRegressor集成学习

如何提升回归模型的稳定性和准确性? 在实际生活中,比如房价预测,经常会遇到一种情况:有大量的特征和样本数据,但模型的预测准确度仍然不尽人意。这时候,单一的模型(如支持向量机回归)可能表现得并不够好。 考虑到这个问题,解决方案可能是使用集成方法,特别是Baggin…

系统架构师论文总结【持续更新】

系统架构师考试是对计算机从业人员&#xff0c;以考代评的重要考试&#xff0c;近几年一直在参加考试&#xff0c;屡战屡败&#xff0c;后又屡败屡战&#xff0c;记录总结论文相关的知识点&#xff0c;方便考前查看。 一、2010年论文 1&#xff09;论软件的静态演化和动态演化…

【C++ 学习】库文件和头文件编写

库文件和头文件编写 有时候&#xff0c;通过C编写的代码并不一定是直接在自己的控制台文件调用&#xff0c;而是需要在其他程序中调用编写的算法的接口即可。这个时候&#xff0c;可以把自己编写的代码打包成一个库&#xff08;Library&#xff09;&#xff0c;编译后被其他程…

宝塔Python3.7安装模块报错ModuleNotFoundError: No module named ‘Crypto‘解决办法

前言 今晚遇到一个问题&#xff0c;宝塔服务器上安装脚本的模块时&#xff0c;出现以下报错&#xff0c;这里找到了解决办法 Traceback (most recent call last):File "/www/wwwroot/unifysign/fuck_chaoxing/fuck_xxt.py", line 4, in <module>from Crypto.…

[SQL开发笔记]BETWEEN操作符:选取介于两个值之间的数据范围内的值

一、功能描述&#xff1a; BETWEEN操作符&#xff1a;选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。 二、BETWEEN操作符语法详解&#xff1a; BETWEEN操作符语法&#xff1a; SELECT column1, column2,…FROM table_nameWHERE column BETWEEN val…

基于aop 代理 Sentinel Nacos配置控制包装类实现原理

基于aop & 代理 & Sentinel & Nacos配置控制包装类实现原理 Hi&#xff0c;我是阿昌&#xff0c;今天记录下看sentinel源码结合业务实现的思路基于aop & 代理 & Sentinel & Nacos配置控制包装类实现原理&#xff1b;下面并不会手把手的记录方案的实现…

Redis | 数据结构(02)SDS

一、键值对数据库是怎么实现的&#xff1f; 在开始讲数据结构之前&#xff0c;先给介绍下 Redis 是怎样实现键值对&#xff08;key-value&#xff09;数据库的。 Redis 的键值对中的 key 就是字符串对象&#xff0c;而 value 可以是字符串对象&#xff0c;也可以是集合数据类型…

分享一个用HTML、CSS和jQuery构建的漂亮的登录注册界面

作为一个前端开发人员&#xff0c;我们经常需要构建用户的登录和注册界面。一个漂亮、用户友好的登录注册界面对于提升用户体验和网站形象至关重要。以下我们使用HTML、CSS和jQuery来做一个漂亮的登录注册界面。 首先&#xff0c;我们需要创建一个html文档&#xff0c;定义登录…

【算法练习Day29】柠檬水找零根据身高重建队列用最少数量的箭引爆气球

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 柠檬水找零根据身高重建队列…