当前位置: 首页 > article >正文

SpringBoot+shardingsphere实现按月分表功能

SpringBoot+shardingsphere实现按月分表功能

文章目录


前言

ShardingSphere 是一套开源的分布式数据库中间件解决方案,旨在简化数据库分片、读写分离、分布式事务等复杂场景的管理。它由 Apache 软件基金会支持,广泛应用于需要处理大规模数据的系统中


一、ShardingSphere 是什么?

主要是为了防止一张表的数据量过大而设计的,数据库本身就支持,但是由于自行设计需要满足跨表查询,事务一致性,分页聚合等很多的复杂场景,还需要很多的配套监控,设计,扩容等方案,所以总体来说是一个任务量很大的任务,故而这里采用ShardingSphere 来实现。

二、使用步骤

1.引入库

<!-- 分库分表 --><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.2.0</version></dependency>

2.环境配置+Mysql表

CREATE TABLE `user` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`username` varchar(255) NOT NULL,`password` varchar(255) NOT NULL,`gender` tinyint(4) NOT NULL COMMENT '0:男 1:女',`createTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`updateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1890651990057906179 DEFAULT CHARSET=utf8mb4;
# 配置服务器端口
server:port: 9999# Spring框架下的ShardingSphere配置
spring:shardingsphere:# 模式配置,设置为独立模式mode:type: Standalone# 数据源配置datasource:# 定义数据源名称names: ds0# 数据源ds0的具体配置ds0:# 数据源类型为HikariCPtype: com.zaxxer.hikari.HikariDataSource# 数据库驱动类名称driver-class-name: com.mysql.cj.jdbc.Driver# 数据库连接URL,包含时区设置jdbc-url: jdbc:mysql://localhost:3306/sharding_db?serverTimezone=Asia/Shanghai# 数据库用户名username: root# 数据库密码password: root# 规则配置rules:# 分片规则配置sharding:# 定义分片的表tables:user:# 只配置基础表,其他表会动态创建actual-data-nodes: ds0.user,ds0.user_202401,ds0.user_202402,ds0.user_202403,ds0.user_202404,ds0.user_202405table-strategy:standard:sharding-column: createtimesharding-algorithm-name: user_inline# 添加主键生成策略key-generate-strategy:column: idkey-generator-name: snowflakesharding-algorithms:user_inline:type: CLASS_BASEDprops:strategy: standardalgorithmClassName: com.hhh.sharding.standa.UserShardingAlgorithm# 配置主键生成器key-generators:snowflake:type: SNOWFLAKEprops:worker-id: 123# 添加默认分片策略default-sharding-column: gender# 属性配置props:# 是否显示SQL语句sql-show: true# MyBatis-Plus配置
mybatis-plus:configuration:# 不将下划线转换为驼峰命名map-underscore-to-camel-case: false# 使用标准输出日志实现log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:enable-sql-runner: true

这里有一个注意事项,那就是id一定要使用bigint使用雪花策略算法来实现,至于为什么这样呢,是为了防止分表的主键id一致的情况,这里首先推荐就是使用mybatisPlus来实现,因为他天然支持雪花算法

3.分表代码实现

主要是两个文件一个是自己实现分表算法的UserShardingAlgorithm文件

package com.hhh.sharding.standa;import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.hhh.sharding.domain.User;
import com.hhh.sharding.service.UserService;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection;
import org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
import org.apache.shardingsphere.mode.manager.ContextManager;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.rule.ShardingRule;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;@Component
@Slf4j
public class DynamicShardingManager {@Resourceprivate DataSource dataSource;@Resourceprivate UserService userService;private static final String LOGIC_TABLE_NAME = "user";private static final String DATABASE_NAME = "sharding_db"; // 配置文件中的数据库名称@PostConstructpublic void initialize() {log.info("初始化动态分表配置...");updateShardingTableNodes();}/*** 获取所有用户相关的表名* 此方法旨在动态地收集所有用户表的表名,以支持可能存在的不同性别用户表* 如果无法获取动态表名或列表为空,则默认返回包含单一的默认用户表名"user"** @return 包含所有用户表名的集合*/private Set<String> fetchAllUserTableNames() {//获取所有动态化表名Set<String> tableNames = new HashSet<>();try {// 获取用户列表List<User> users = userService.list();// 如果用户列表不为空,则映射每个用户到对应的表名,并收集到集合中if (users != null) {tableNames = users.stream().map(user -> "user_" + user.getGender()).collect(Collectors.toSet());}// 确保至少包含默认表tableNames.add("user");} catch (Exception e) {// 记录获取表名时发生的错误log.error("获取所有动态化表名失败", e);// 发生异常时至少返回默认表tableNames.add("user");}// 返回收集到的表名集合return tableNames;}/*** 动态更新分片表节点配置* * 本方法旨在根据当前的用户表名称,动态地更新分片表的节点配置* 它首先获取所有用户表的名称,然后构建新的分片表节点配置,并尝试更新到数据库的元数据中*/private void updateShardingTableNodes() {try {// 获取所有用户表的名称Set<String> tableNames = fetchAllUserTableNames();if (tableNames.isEmpty()) {// 如果未获取到任何表名,则使用默认的表配置log.warn("未获取到任何表名,将使用默认表配置");tableNames.add("user");}// 确保包含所有可能的表tableNames.add("user");tableNames.add("user_0");tableNames.add("user_1");// 构建新的分片表节点配置String newActualDataNodes = tableNames.stream().distinct().map(tableName -> "ds0." + tableName).collect(Collectors.joining(","));log.info("动态分表 actual-data-nodes 配置: {}", newActualDataNodes);// 获取 ContextManager 实例ContextManager contextManager = getContextManager();if (contextManager == null) {log.error("获取 ContextManager 失败");return;}// 获取 MetaDataContexts 实例var metaDataContexts = contextManager.getMetaDataContexts();if (metaDataContexts == null) {log.error("获取 MetaDataContexts 失败");return;}// 获取 MetaData 实例var metaData = metaDataContexts.getMetaData();if (metaData == null) {log.error("获取 MetaData 失败");return;}// 检查数据库是否存在var databases = metaData.getDatabases();if (databases == null || !databases.containsKey(DATABASE_NAME)) {log.error("数据库 {} 不存在", DATABASE_NAME);return;}// 获取 ShardingSphere 的规则元数据ShardingSphereRuleMetaData ruleMetaData = databases.get(DATABASE_NAME).getRuleMetaData();if (ruleMetaData == null) {log.error("获取规则元数据失败");return;}// 查找 ShardingRuleOptional<ShardingRule> shardingRule = ruleMetaData.findSingleRule(ShardingRule.class);if (shardingRule.isPresent()) {// 获取分片规则配置ShardingRuleConfiguration ruleConfig = (ShardingRuleConfiguration) shardingRule.get().getConfiguration();if (ruleConfig.getTables() == null || ruleConfig.getTables().isEmpty()) {log.error("分片规则配置为空");return;}// 更新分片表规则配置List<ShardingTableRuleConfiguration> updatedRules = ruleConfig.getTables().stream().map(oldTableRule -> {if (LOGIC_TABLE_NAME.equals(oldTableRule.getLogicTable())) {ShardingTableRuleConfiguration newTableRuleConfig = new ShardingTableRuleConfiguration(LOGIC_TABLE_NAME, newActualDataNodes);newTableRuleConfig.setDatabaseShardingStrategy(oldTableRule.getDatabaseShardingStrategy());newTableRuleConfig.setTableShardingStrategy(oldTableRule.getTableShardingStrategy());newTableRuleConfig.setKeyGenerateStrategy(oldTableRule.getKeyGenerateStrategy());newTableRuleConfig.setAuditStrategy(oldTableRule.getAuditStrategy());return newTableRuleConfig;}return oldTableRule;}).collect(Collectors.toList());ruleConfig.setTables(updatedRules);// 尝试更新分片规则配置try {contextManager.alterRuleConfiguration(DATABASE_NAME, Collections.singleton(ruleConfig));contextManager.reloadDatabase(DATABASE_NAME);log.info("动态分表规则更新成功!");} catch (Exception e) {log.error("更新分片规则失败", e);}} else {log.error("未找到 ShardingSphere 的分片规则配置,动态分表更新失败。");}} catch (Exception e) {log.error("更新分片规则时发生异常", e);}}/*** 获取 ShardingSphere ContextManager*/private ContextManager getContextManager() {try {if (dataSource == null) {log.error("数据源未注入");return null;}var connection = dataSource.getConnection();if (connection == null) {log.error("获取数据库连接失败");return null;}ShardingSphereConnection shardingConnection = connection.unwrap(ShardingSphereConnection.class);if (shardingConnection == null) {log.error("无法获取 ShardingSphereConnection");connection.close();return null;}ContextManager contextManager = shardingConnection.getContextManager();connection.close();return contextManager;} catch (SQLException e) {log.error("获取 ShardingSphere ContextManager 失败", e);return null;}}/*** 根据用户信息创建用户表* 表名基于用户创建时间生成,格式为:LOGIC_TABLE_NAME_YYYYMM* 如果表已存在,则不进行创建操作* * @param user 用户对象,包含用户创建时间等信息*/public void createUserTable(User user) {// 获取用户创建时间Date createTime = user.getCreatetime();// 创建日期格式化对象,用于生成表名SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMM");// 生成完整的表名String tableName = LOGIC_TABLE_NAME + "_" + dateFormat.format(createTime);try {// 首先检查表是否已存在String checkTableSql = "SHOW TABLES LIKE '" + tableName + "'";List<Map<String, Object>> tables = SqlRunner.db().selectList(checkTableSql);// 如果表存在,记录日志并结束方法if (tables != null && !tables.isEmpty()) {log.info("表 {} 已经存在,无需创建", tableName);return;}// 创建表String createTableSql = "CREATE TABLE IF NOT EXISTS " + tableName + " LIKE user";log.info("开始创建表,SQL: {}", createTableSql);SqlRunner.db().update(createTableSql);log.info("表 {} 创建成功", tableName);// 更新分片配置updateShardingTableNodes();} catch (Exception e) {log.error("创建分表 {} 失败: {}", tableName, e.getMessage(), e);// 检查异常消息,如果表已存在,则记录日志并结束方法if (e.getMessage() != null && e.getMessage().contains("already exists")) {log.info("表 {} 已经存在,继续处理", tableName);return;}// 如果异常与表已存在无关,则抛出运行时异常throw new RuntimeException("创建分表失败: " + e.getMessage(), e);}}}
package com.hhh.sharding.standa;import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Properties;@Slf4j
public class UserShardingAlgorithm implements StandardShardingAlgorithm<Date> {private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMM");@Overridepublic String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> preciseShardingValue) {Date createTime = preciseShardingValue.getValue();String logicTableName = preciseShardingValue.getLogicTableName();log.info("分片算法执行 - 可用目标表: {}, 分片值: {}, 逻辑表名: {}", availableTargetNames, createTime, logicTableName);if (createTime == null) {log.info("createTime为空,返回逻辑表名: {}", logicTableName);return logicTableName;}// 根据 createTime 动态生成分表名String suffix = DATE_FORMAT.format(createTime);String realTableName = "user_" + suffix;log.info("计算得到的实际表名: {}", realTableName);if (availableTargetNames.contains(realTableName)) {log.info("找到匹配的目标表: {}", realTableName);return realTableName;} else {log.warn("未找到匹配的目标表,返回逻辑表名: {}", logicTableName);return logicTableName;}}@Overridepublic Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Date> rangeShardingValue) {return new ArrayList<>();}@Overridepublic Properties getProps() {return new Properties();}@Overridepublic void init(Properties properties) {// 可以添加初始化逻辑}
}

 4.测试用例

package com.hhh.sharding.controller;import cn.hutool.core.util.RandomUtil;
import com.hhh.sharding.domain.User;
import com.hhh.sharding.service.UserService;
import com.hhh.sharding.standa.DynamicShardingManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.text.SimpleDateFormat;@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate UserService userService;@Resourceprivate DynamicShardingManager dynamicShardingManager;@GetMapping("/add")public Boolean user() {// 创建一些2024年的随机日期Date[] dates = {getDate("2024-01-15"),getDate("2024-02-20"),getDate("2024-03-10"),getDate("2024-04-05"),getDate("2024-05-25")};for (int i = 0; i < 10; i++) {User user = new User();user.setUsername(generateRandomUsername());user.setPassword("123456");user.setGender(RandomUtil.randomInt(2));// 随机选择一个2024年的日期Date randomDate = dates[RandomUtil.randomInt(dates.length)];user.setCreatetime(randomDate);user.setUpdatetime(randomDate);//这里每一次新增数据的时候去判断是否要创建出来当月的数据表,这张表一定要在    //application.yml中的actual-data-nodes中去添加dynamicShardingManager.createUserTable(user);userService.save(user);}return true;}private Date getDate(String dateStr) {try {return new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);} catch (Exception e) {return new Date();}}// 生成10位随机数字的用户名private String generateRandomUsername() {return RandomUtil.randomNumbers(10);  // 生成10位数字}@GetMapping("/all")public List<User> all() {return userService.list();}
}

 5.测试结果

新增数据

 查询数据

 数据库情况

 数据库表数据展示


总结

由于公司有一个需求那就是按月来分表展示数据,看了好多人的博客都没有效果,最终三天得以解决这个功能,故而写下此博客,希望可以真正的帮助到你

相关文章:

SpringBoot+shardingsphere实现按月分表功能

SpringBootshardingsphere实现按月分表功能 文章目录 前言 ShardingSphere 是一套开源的分布式数据库中间件解决方案&#xff0c;旨在简化数据库分片、读写分离、分布式事务等复杂场景的管理。它由 Apache 软件基金会支持&#xff0c;广泛应用于需要处理大规模数据的系统中 一…...

表情识别任务的复现 for 毕设

前言 为了带师弟做毕设&#xff0c;我们复现了表情识别任务。该文章仅用于记录 首先&#xff0c;感谢复现过程中所参考的分享&#xff1a; 【Bilibili】基于卷积神经网络实现的面部表情识别&#xff08;pytorch&#xff09;【Github】 facial-expression-recognition【Blog】…...

教程 | 从零部署到业务融合:DeepSeek R1 私有化部署实战指南

文章目录 1. 什么是 DeepSeek R1&#xff1f;a. 主要介绍a. 版本区别 2. 部署资源要求a. 硬件资源要求 3. 本地安装DeepSeek-R1a. 为什么选择本地部署&#xff1f;b. 部署工具对比c. 演示环境配置d. Ollama安装流程 4. 可视化工具a. 工具对比b. Open-WebUI部署 5. AI API应用a.…...

分布式 NewSQL 数据库(TiDB)

TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议&#xff0c;具有数据强一致的高可用特性&#xff0c;是一个不仅适合 OLTP 场景还适合 OLAP 场景的混合数据库。 TiDB是 PingCAP公司自主设计、研发的开源分布式关系型数据…...

密码管理 - 使用BitWarden/VaultWarden自托管密码服务 - 折腾记录

密码管理 - 使用Bitwarden/Vaultwarden自托管密码服务 - 折腾记录 前言 某天(大约两周前了至少 一直没找到机会记录)逛Github发现了开源的密码管理服务Bitwarden&#xff0c;能自托管、能加密、多端适配。 这&#xff0c;&#xff0c;不是让人如获至宝吗。于是就开始折腾了。…...

C语言-章节 1:变量与数据类型 ——「未初始化的诅咒」

在那神秘且广袤无垠的「比特大陆」上&#xff0c;阳光奋力地穿过「内存森林」中错综复杂的代码枝叶缝隙&#xff0c;洒下一片片斑驳陆离、如梦似幻的光影。林间的空气里&#xff0c;弥漫着一股浓郁的十六进制锈蚀味&#xff0c;仿佛在诉说着这片森林中隐藏的古老秘密。 一位零基…...

机器视觉--Halcon If语句

引言 在机器视觉领域&#xff0c;Halcon 是一款功能强大且广泛应用的软件。在使用 Halcon 进行编程时&#xff0c;条件判断是不可或缺的一部分&#xff0c;而IF语句就是实现条件判断的核心工具之一。通过IF语句&#xff0c;我们能够根据不同的条件执行不同的代码块&#xff0c…...

Linux基础之文件权限的八进制表示法

1. Linux 文件权限概述 在 Linux 中&#xff0c;每个文件或目录都有三种基本权限&#xff0c;分别是&#xff1a; 读权限 - r&#xff1a;允许查看文件内容。写权限 - w&#xff1a;允许修改文件内容。执行权限 - x&#xff1a;允许执行文件或进入目录。 每个文件或目录的权…...

HTML的入门

一、HTML HTML&#xff08;HyperText Markup Language&#xff0c;超文本标记语言&#xff09;是一种用来告知浏览器如何组织页面的标记语言。 超文本&#xff1a;就是超越了文本&#xff1b;HTML不仅仅可以用来显示文本(字符串、数字之类)&#xff0c;还可以显示视频、音频等…...

Vue2/Vue3生命周期对比

Vue2的生命周期钩子 beforeCreate 在实例初始化之后&#xff0c;数据观测&#xff08;data&#xff09;和事件配置之前调用。此时无法访问 data、methods 等。 created 在实例创建完成后调用。此时可以访问 data、methods&#xff0c;但 DOM 还未生成。 beforeMount 在挂载…...

闭源大语言模型的怎么增强:提示工程 检索增强生成 智能体

闭源大语言模型的怎么增强 提示工程 检索增强生成 智能体 核心原理 提示工程:通过设计和优化提示词,引导大语言模型进行上下文学习和分解式思考,激发模型自身的思维和推理能力,使模型更好地理解和生成文本,增强其泛用性和解决问题的能力。检索增强生成:结合检索的准确…...

【图像加密解密】空间混沌序列的图像加密解密算法复现(含相关性检验)【Matlab完整源码 2期】

1、说明 本文给出详细完整代码、完整的实验报告和PPT。 环境&#xff1a;MATLAB2019a 复现文献&#xff1a;[1]孙福艳,吕宗旺.Digital image encryption with chaotic map lattices[J].Chinese Physics B,2011,20(04):136-142. 2、部分报告内容 3 部分源码与运行步骤 3.1 部…...

QxOrm生成json

下载Qxorm-1.5版本 使用vs打开项目&#xff0c;直接生成即可&#xff1a; lib目录中会生成dll和lib文件 新建Qt项目使用Qxorm: 将QxOrm中上面三个目录拷贝到新建的Qt项目中 pro文件添加使用QxOrm第三方库 INCLUDEPATH $$PWD/include/ LIBS -L"$$PWD/lib" LIBS…...

ASP.NET Core Web应用(.NET9.0)读取数据库表记录并显示到页面

1.创建ASP.NET Core Web应用 选择.NET9.0框架 安装SqlClient依赖包 2.实现数据库记录读取: 引用数据库操作类命名空间 创建查询记录结构类 查询数据并返回数据集合 3.前端遍历数据并动态生成表格显示 生成结果:...

uniapp商城之首页模块

文章目录 前言一、自定义导航栏1.静态结构2.修改页面配置3.组件安全区适配二、通用轮播组件1. 静态结构组件2.自动导入全局组件3.首页轮播图数据获取三、首页分类1.静态结构2.首页获取分类数据并渲染四、热门推荐1.静态结构2.首页获取推荐数据并渲染3.首页跳转详细推荐页五、猜…...

以若依移动端版为基础,实现uniapp的flowable流程管理

1.前言 此代码是若依移动端版为基础&#xff0c;实现flowable流程管理&#xff0c;支持H5、APP和微信小程序三端。其中&#xff0c;APP是在安卓在雷电模拟器环境下完成的&#xff0c;其他环境未测试&#xff0c;此文章中所提及的APP均指上述环境。移动端是需要配合若依前后端分…...

C++:高度平衡二叉搜索树(AVLTree) [数据结构]

目录 一、AVL树 二、AVL树的理解 1.AVL树节点的定义 2.AVL树的插入 2.1更新平衡因子 3.AVL树的旋转 三、AVL的检查 四、完整代码实现 一、AVL树 AVL树是什么&#xff1f;我们对 map / multimap / set / multiset 进行了简单的介绍&#xff0c;可以发现&#xff0c;这几…...

2D 游戏艺术、动画和光照

原文&#xff1a;https://unity.com/resources/2d-game-art-animation-lighting-for-artists-ebook 笔记 用Tilemap瓷砖大小为1单元&#xff0c;人物大小在0.5~2单元 PPU &#xff1a;单位像素 pixels per unit 2160 4K分辨率/ 正交相机size*2 完整屏幕显示像素点 有骨骼动…...

学习笔记-人脸识别相关编程基础

通过编程实现人脸识别功能&#xff0c;需要掌握一定的技术基础&#xff0c;包括编程语言、图像处理、机器学习以及相关的库和框架&#xff1a; 1. 编程语言 Python&#xff1a;Python 是实现人脸识别最常用的语言之一&#xff0c;因为它有大量的库和框架支持&#xff0c;如 Op…...

4、C#基于.net framework的应用开发实战编程 - 测试(四、二) - 编程手把手系列文章...

四、 测试&#xff1b; 四&#xff0e;二、实际运行&#xff1b; 在应用调试完毕&#xff0c;Bug基本解决的时候就需要对应用进行实际运行来进行查看使用体验及分发的准备工作。 1、 运行设置&#xff1b; 在启动项目上右键属性&#xff0c;点击生成&#xff0c;将顶部的配置改…...

栈与队列(C语言版)

文章目录 栈与队列1. 栈基本操作实现(基于链表)代码运行结果 应用场景 2. 队列基本操作实现代码运行结果 应用场景 栈与队列 1. 栈 栈是一种操作受限的线性结构。操作受限体现在&#xff0c;栈只能在一端添加和删除元素&#xff0c;符合后进先出 ( LIFO ) 的特性&#xff0c;…...

【算法专场】哈希表

目录 前言 哈希表 1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; 算法分析 算法代码 面试题 01.02. 判定是否互为字符重排 ​编辑算法分析 算法代码 217. 存在重复元素 算法分析 算法代码 219. 存在重复元素 II 算法分析 算法代码 解法二 算法代码 算法…...

【设计模式】【行为型模式】迭代器模式(Iterator)

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f44d; 欢迎点赞、收藏、关注&#xff0c;跟上我的更新节奏 &#x1f3b5; 当你的天空突…...

二次封装axios解决异步通信痛点

为了方便扩展,和增加配置的灵活性,这里将通过封装一个类来实现axios的二次封装,要实现的功能包括: 为请求传入自定义的配置,控制单次请求的不同行为在响应拦截器中对业务逻辑进行处理,根据业务约定的成功数据结构,返回业务数据对响应错误进行处理,配置显示对话框或消息形…...

mac 意外退出移动硬盘后再次插入移动硬盘不显示怎么办

第一步&#xff1a;sudo ps aux | grep fsck 打开mac控制台输入如下指令&#xff0c;我们看到会出现两个进程&#xff0c;看进程是root的这个 sudo ps aux|grep fsck 第二步&#xff1a;杀死进程 在第一步基础上我们知道不显示u盘的进程是&#xff1a;62319&#xff0c;我们…...

如何下载AndroidStudio的依赖的 jar,arr文件到本地

一、通过jitpack.io 下载依赖库 若需要下载 com.github.xxxxx:yy-zzz:0.0.2 的 jar则 https://jitpack.io/com/github/xxxxx/yy-zzz/0.0.2/ 下会列出如下build.logyy-zzz-0.0.2.jaryy-zzz-0.0.2.pomyy-zzz-0.0.2.pom.md5yy-zzz-0.0.2.pom.sha1jar 的下载路径为https://jitpack…...

FFmpeg Video options

FFmpeg视频相关选项 1. -vframes number (output) 设置输出视频帧数 示例&#xff1a; ffmpeg -i input.mp4 -vframes 90 output.mp4 表示输出90帧视频 2. -r[:stream_specifier] fps (input/output,per-stream) 设置帧率(rate) 示例&#xff1a; ffmpeg -i input.mp4…...

CEF132编译指南 MacOS 篇 - 构建 CEF (六)

1. 引言 经过前面一系列的精心准备&#xff0c;我们已经完成了所有必要的环境配置和源码获取工作。本篇作为 CEF132 编译指南系列的第六篇&#xff0c;将详细介绍如何在 macOS 系统上构建 CEF132。通过配置正确的编译命令和参数&#xff0c;我们将完成 CEF 的构建工作&#xf…...

Python大数据可视化:基于python的电影天堂数据可视化_django+hive

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 电影数据 看板展示 我的信息 摘要 电影天堂数据可视化是…...

LLM之循环神经网络(RNN)

在人工智能的领域中&#xff0c;神经网络是推动技术发展的核心力量。今天&#xff0c;让我们深入探讨循环神经网络&#xff08;RNN&#xff09; 一、神经网络基础 &#xff08;1&#xff09;什么是神经网络 神经网络&#xff0c;又称人工神经网络&#xff0c;其设计灵感源于人…...