RuoYi-Vue-Plus (SpringCache、CacheManager、@Cacheable、缓存雪崩、击穿、穿透)

一、概述

        1、SpringCache是Spring提供的一个缓存框架,在Spring3.1版本开始支持将缓存添加到现有的spring应用程序中,在4.1开始,缓存已支持JSR-107注释和更多自定义的选项。

        2、SpringCache利用了AOP,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能了,做到了对代码侵入性做小。

        3、SpringCache框架还提供了CacheManager接口,可以实现降低对各种缓存框架的耦合。它不是具体的缓存实现,它只提供一整套的接口和代码规范、配置、注解等,用于整合各种缓存方案,比如Caffeine、Guava Cache、Ehcache。

二、SpringCache概念

接口:


1、Cache接口:缓存接口,定义缓存操作。实现有 如RedisCache、EhCacheCache、ConcurrentMapCache等

2、cacheResolver:指定获取解析器

3、CacheManager:缓存管理器,管理各种缓存(Cache)组件;如:RedisCacheManager,使用redis作为缓存。指定缓存管理器

注解:

1- @Cacheable:在方法执行前查看是否有缓存对应的数据,如果有直接返回数据,如果没有调用方法获取数据返回,并缓存起来。

2- @CacheEvict:将一条或多条数据从缓存中删除。

3- @CachePut:将方法的返回值放到缓存中

4- @EnableCaching:开启缓存注解功能

5- @Caching:组合多个缓存注解;

6- @CacheConfig:统一配置@Cacheable中的value值

三、spring缓存整合redis 

RedisConfig 
类路径: com.ruoyi.framework.config.RedisConfig
1- spring 自动管理缓存机制
@EnableCaching //开启spring缓存,提升性能
@Slf4j
@Configuration
@EnableCaching //1- spring 自动管理缓存机制 ,,提升性能
@EnableConfigurationProperties(RedissonProperties.class)
public class RedisConfig {
 2- 整合自定义缓存管理器
 /*** 2-自定义缓存管理器 整合spring-cache*/@Beanpublic CacheManager cacheManager() {return new PlusSpringCacheManager();}

自定义 管理器PlusSpringCacheManager,实现CacheManager 接口,基于redssion操作缓存

/*** Copyright (c) 2013-2021 Nikita Koksharov** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**    http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.ruoyi.framework.manager;import com.ruoyi.common.utils.redis.RedisUtils;
import org.redisson.api.RMap;
import org.redisson.api.RMapCache;
import org.redisson.spring.cache.CacheConfig;
import org.redisson.spring.cache.RedissonCache;
import org.springframework.boot.convert.DurationStyle;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
import org.springframework.util.StringUtils;import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;/*** A {@link org.springframework.cache.CacheManager} implementation* backed by Redisson instance.* <p>* 修改 RedissonSpringCacheManager 源码* 重写 cacheName 处理方法 支持多参数** @author Nikita Koksharov**/
@SuppressWarnings("unchecked")
public class PlusSpringCacheManager implements CacheManager {//是否自动配置nameprivate boolean dynamic = true;//是否允许nullprivate boolean allowNullValues = true;//事务提交之后执行private boolean transactionAware = true;// 常用缓存配置 ttl;  maxIdleTime; maxSize; 等Map<String, CacheConfig> configMap = new ConcurrentHashMap<>();// 缓存实例ConcurrentMap<String, Cache> instanceMap = new ConcurrentHashMap<>();/*** Creates CacheManager supplied by Redisson instance*/public PlusSpringCacheManager() {}/*** Defines possibility of storing {@code null} values.* <p>* Default is <code>true</code>** @param allowNullValues stores if <code>true</code>*/public void setAllowNullValues(boolean allowNullValues) {this.allowNullValues = allowNullValues;}/*** Defines if cache aware of Spring-managed transactions.* If {@code true} put/evict operations are executed only for successful transaction in after-commit phase.* <p>* Default is <code>false</code>** @param transactionAware cache is transaction aware if <code>true</code>*/public void setTransactionAware(boolean transactionAware) {this.transactionAware = transactionAware;}/*** Defines 'fixed' cache names.* A new cache instance will not be created in dynamic for non-defined names.* <p>* `null` parameter setups dynamic mode** @param names of caches*/public void setCacheNames(Collection<String> names) {if (names != null) {for (String name : names) {getCache(name);}dynamic = false;} else {dynamic = true;}}/*** Set cache config mapped by cache name** @param config object*/public void setConfig(Map<String, ? extends CacheConfig> config) {this.configMap = (Map<String, CacheConfig>) config;}protected CacheConfig createDefaultConfig() {return new CacheConfig();}@Overridepublic Cache getCache(String name) {// 重写 cacheName 支持多参数/*** 演示案例   :  String DEMO_CACHE = "demo:cache#60s#10m#20";*/String[] array = StringUtils.delimitedListToStringArray(name, "#");name = array[0];Cache cache = instanceMap.get(name);if (cache != null) {return cache;}//2- dynamic=false 不会动态生成if (!dynamic) {//return cache;return null;}CacheConfig config = configMap.get(name);if (config == null) {config = createDefaultConfig();configMap.put(name, config);}//setTTLif (array.length > 1) {config.setTTL(DurationStyle.detectAndParse(array[1]).toMillis());}//setMaxIdleTimeif (array.length > 2) {config.setMaxIdleTime(DurationStyle.detectAndParse(array[2]).toMillis());}//setMaxSizeif (array.length > 3) {config.setMaxSize(Integer.parseInt(array[3]));}if (config.getMaxIdleTime() == 0 && config.getTTL() == 0 && config.getMaxSize() == 0) {return createMap(name, config);}return createMapCache(name, config);}private Cache createMap(String name, CacheConfig config) {//1-获取缓存RMap<Object, Object> map = RedisUtils.getClient().getMap(name);//2-没有过期时间传2个参数Cache cache = new RedissonCache(map, allowNullValues);// 3-事务提交 之后执行if (transactionAware) {cache = new TransactionAwareCacheDecorator(cache);}//4-不存在就添加Cache oldCache = instanceMap.putIfAbsent(name, cache);if (oldCache != null) {cache = oldCache;}return cache;}private Cache createMapCache(String name, CacheConfig config) {//1-获取缓存RMapCache<Object, Object> map = RedisUtils.getClient().getMapCache(name);//2-有过期时间传3个参数 ,config 里面有  ttl、maxIdleTime、maxSizeCache cache = new RedissonCache(map, config, allowNullValues);// 3-事务提交 之后执行if (transactionAware) {cache = new TransactionAwareCacheDecorator(cache);}//4-不存在就添加Cache oldCache = instanceMap.putIfAbsent(name, cache);if (oldCache != null) {cache = oldCache;} else {map.setMaxSize(config.getMaxSize());}return cache;}//返回不可修改的集合@Overridepublic Collection<String> getCacheNames() {return Collections.unmodifiableSet(configMap.keySet());}}
3-@Cacheable

以下Cacheable几个属性分别演示了如何使用:(支持SPEL表达式

  • cacheNames 
  • key 
  • sync
  • condition 
  • sync 
/*** <简述>cacheNames: 指定名称 可以是数组*        key: 支持spel表达式,可以获取参数* @author syf* @date 2024/5/7 11:03* @param id* @param pageQuery* @return java.lang.String*/@Cacheable(cacheNames = "cache1", key = "#id + '_cache' + #pageQuery.pageNum")@GetMapping("test1")public  String test1(String id, PageQuery pageQuery){return "ok";}/*** <简述> condition :符合条件进行缓存*        #id != null :表示传入 id不为空才会缓存进入redis,id为空则不缓存* @author syf* @date 2024/5/7 11:03* @param id* @return java.lang.String*/@Cacheable(cacheNames = "cache2", key = "#id + '_cache'" , condition = "#id != null")@GetMapping("test2")public  String test2(String id){return "ok";}/*** <简述> unless 符合条件不缓存*        #result == null :接口返回结果为空则不进行缓存* @author syf* @date 2024/5/7 11:03* @param id* @return java.lang.String*/@Cacheable(cacheNames = "cache3", key = "#id + '_cache'" , unless = "#result == null")@GetMapping("test3")public  String test3(String id){return null;}/*** <简述> sync = true*       同步阻塞:同时进来多个请求, 等待前面调用返回并缓存,才能回进入下个请求*       作用:防止缓存积存* @author syf* @date 2024/5/7 11:03* @param id* @return java.lang.String*/@Cacheable(cacheNames = "cache4", key = "#id + '_cache'", sync = true)@GetMapping("test4")public  String test4(String id){return null;}/*** <简述> 获取类中参数*         比较繁琐,一般是在实现类中传递登录参数,用spel获取* @author syf* @date 2024/5/7 11:03* @return java.lang.String*/@Cacheable(cacheNames = "cache5", key = "T(com.ruoyi.common.helper.LoginHelper).getLoginUser().getLoginId()")@GetMapping("test5")public  String test5(){LoginUser loginUser = LoginHelper.getLoginUser();return "ok";}
4- @CachePut

缓存更新

执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

  /*** <简述> 结果不为空进行更新* @author syf* @date 2024/5/7 11:03* @param id* @return java.lang.String*/@CachePut(cacheNames = "cache2", key = "#id + '_cache'" , condition = "#result != null")@GetMapping("test2")public  String test2(String id){boolean flag = doUpdate();return flag  ? "ok" : null;}
5- @CacheEvict

缓存删除

执行该方法,并将缓存中结果删除。

allEntries  删除所有cacheNames = "cache4",下面缓存
beforeInvocation  默认false,方法执行之后有异常不执行。true:方法执行之后有异常,也执行
  /*** <简述> 删除缓存* @author syf* @date 2024/5/7 11:03* @param id* @return java.lang.String*/@CacheEvict(cacheNames = "cache4", key = "#id + '_cache'")@GetMapping("test7")public  String test7(String id){boolean flag = doDelete();return flag  ? "ok" : null;}/*** <简述> 删除所有缓存* @author syf* @date 2024/5/7 11:03* @param id* @return java.lang.String*/@CacheEvict(cacheNames = "cache4", allEntries = true)@GetMapping("test8")public  String test8(String id){return null;}/*** <简述> beforeInvocation 无论是否有异常都执行操作* @author syf* @date 2024/5/7 11:03* @param id* @return java.lang.String*/@CacheEvict(cacheNames = "cache4", beforeInvocation = true)@GetMapping("test9")public  String test9(String id){return null;}
 6-@Caching:

指定多个Spring Cache相关的注解

三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。

    @Caching(cacheable = {@Cacheable(value = "uer1",key = "#userName")},put = {@CachePut(value = "uer1", key = "#result.id"),@CachePut(value = "uer1", key = "#result.age")})public User getStuByStr(String userName) {List<User> users= listMapper.selectByList(studentExample);return Optional.ofNullable(users).orElse(null).get(0);}

四、若依框架中缓存使用(自定义SpringCache 源码解读)、

CacheNames 缓存名称配置类:
类位置:com.ruoyi.common.constant.CacheNames
key 格式为: cacheNames#ttl#maxIdleTime#maxSize
/*** 缓存组名称常量* <p>* key 格式为 cacheNames#ttl#maxIdleTime#maxSize* <p>* ttl 过期时间 如果设置为0则不过期 默认为0* maxIdleTime 最大空闲时间 根据LRU算法清理空闲数据 如果设置为0则不检测 默认为0   (超过maxIdleTime LRU算法自动清理)* maxSize 组最大长度 根据LRU算法清理溢出数据 如果设置为0则无限长 默认为0* <p>* 例子: test#60s、test#0#60s、test#0#1m#1000、test#1h#0#500*/

PlusSpringCacheManager 实现 CacheManager 接口,重写 getCache 方法,

就是配置了  :ttl、maxIdleTime、maxSize  三个参数吗,如下:

@Overridepublic Cache getCache(String name) {// 重写 cacheName 支持多参数/*** 1-演示案例   :  String DEMO_CACHE = "demo:cache#60s#10m#20";*/String[] array = StringUtils.delimitedListToStringArray(name, "#");name = array[0];Cache cache = instanceMap.get(name);if (cache != null) {return cache;}//2- dynamic=false 不会动态生成if (!dynamic) {//return cache;return null;}CacheConfig config = configMap.get(name);if (config == null) {config = createDefaultConfig();configMap.put(name, config);}//setTTLif (array.length > 1) {config.setTTL(DurationStyle.detectAndParse(array[1]).toMillis());}//setMaxIdleTimeif (array.length > 2) {config.setMaxIdleTime(DurationStyle.detectAndParse(array[2]).toMillis());}//setMaxSizeif (array.length > 3) {config.setMaxSize(Integer.parseInt(array[3]));}if (config.getMaxIdleTime() == 0 && config.getTTL() == 0 && config.getMaxSize() == 0) {return createMap(name, config);}return createMapCache(name, config);}

 重点:下面就是PlusSpringCacheManager ,操作缓存的地方

上面调用了:createMap、createMapCache 2个方法对比:

1-逻辑:

createMapCache 多了个 setMaxSize判断,其他都一样

else {map.setMaxSize(config.getMaxSize());}

2- 返回类型 

createMap 返回  RMap

createMapCache 返回 RMapCache

对比: RMapCache 继承了 RMap 多了对于ttl、maxIdleTime、maxSize 的配置

相同 :都是基于redisson,缓存到redis

private Cache createMap(String name, CacheConfig config) {//1-获取缓存RMap<Object, Object> map = RedisUtils.getClient().getMap(name);//2-没有过期时间传2个参数Cache cache = new RedissonCache(map, allowNullValues);// 3-事务提交 之后执行if (transactionAware) {cache = new TransactionAwareCacheDecorator(cache);}//4-不存在就添加Cache oldCache = instanceMap.putIfAbsent(name, cache);if (oldCache != null) {cache = oldCache;}return cache;}private Cache createMapCache(String name, CacheConfig config) {//1-获取缓存RMapCache<Object, Object> map = RedisUtils.getClient().getMapCache(name);//2-有过期时间传3个参数 ,config 里面有  ttl、maxIdleTime、maxSizeCache cache = new RedissonCache(map, config, allowNullValues);// 3-事务提交 之后执行if (transactionAware) {cache = new TransactionAwareCacheDecorator(cache);}//4-不存在就添加Cache oldCache = instanceMap.putIfAbsent(name, cache);if (oldCache != null) {cache = oldCache;} else {map.setMaxSize(config.getMaxSize());}return cache;}

 上面  TransactionAwareCacheDecorator:

所执行的put操作,是在事务提交之后执行

 public void put(final Object key, @Nullable final Object value) {if (TransactionSynchronizationManager.isSynchronizationActive()) {TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {public void afterCommit() {TransactionAwareCacheDecorator.this.targetCache.put(key, value);}});} else {this.targetCache.put(key, value);}}

 五、缓存工具类

private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class);主要是获取 CacheManager 接口,提供对缓存CRUD操作 :
public interface CacheManager {@NullableCache getCache(String name);Collection<String> getCacheNames();
}
 
package com.ruoyi.common.utils.redis;import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.redisson.api.RMap;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;import java.util.Set;/*** 缓存操作工具类 {@link }** @author Michelle.Chung* @date 2022/8/13*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@SuppressWarnings(value = {"unchecked"})
public class CacheUtils {private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class);/*** 获取缓存组内所有的KEY** @param cacheNames 缓存组名称*/public static Set<Object> keys(String cacheNames) {RMap<Object, Object> rmap = (RMap<Object, Object>) CACHE_MANAGER.getCache(cacheNames).getNativeCache();return rmap.keySet();}/*** 获取缓存值** @param cacheNames 缓存组名称* @param key        缓存key*/public static <T> T get(String cacheNames, Object key) {Cache.ValueWrapper wrapper = CACHE_MANAGER.getCache(cacheNames).get(key);return wrapper != null ? (T) wrapper.get() : null;}/*** 保存缓存值** @param cacheNames 缓存组名称* @param key        缓存key* @param value      缓存值*/public static void put(String cacheNames, Object key, Object value) {CACHE_MANAGER.getCache(cacheNames).put(key, value);}/*** 删除缓存值** @param cacheNames 缓存组名称* @param key        缓存key*/public static void evict(String cacheNames, Object key) {CACHE_MANAGER.getCache(cacheNames).evict(key);}/*** 清空缓存值** @param cacheNames 缓存组名称*/public static void clear(String cacheNames) {CACHE_MANAGER.getCache(cacheNames).clear();}}

 

六、缓存雪崩

概念:

        缓存集中过期失效(大量key失效)。所有请求直接查询数据库了,而对数据库造成巨大压力,严重可能的会导致数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。

解决:

  • 1、实现Redis的高可用、改为主从+哨兵集群模式
  • 2、允许的话,也可以设置热点数据不过期(或者不同业务设置不同过期时间 例子: test#60s、test#0#60s、test#0#1m#1000、test#1h#0#500)
  • 3、开启Redis的RDB+AOF组合持久化策略,以便快速恢复

 

七、缓存击穿 

概念:

缓存击穿指的是热点key在某个特殊的场景时间内恰好失效了,恰好有大量并发请求过来了,导致大量的请求都打到数据库上,造成数据库极大的压力,这就是缓存击穿问题。

对比缓存雪崩:        

        雪崩大量key失效,击穿 某几个热点key失效

 解决:

互斥锁方案,保证同一时间只有一个业务线程去数据库获取数据填充到Redis中,更新缓存,未能获取互斥锁的请求,需要等待锁释放后重新读取缓存。获取成功直接返回结果获取失败则再次尝试获取锁,重复上述流程

若依框架中的实现:简单举例

        sync = true  同步阻塞:同时进来多个请求, 等待前面调用返回并缓存,才能回进入下个请求
  

   /*** <简述> sync = true*       同步阻塞:同时进来多个请求, 等待前面调用返回并缓存,才能回进入下个请求*   * @author syf* @date 2024/5/7 11:03* @param id* @return java.lang.String*/@Cacheable(cacheNames = "cache4", key = "#id + '_cache'", sync = true)@GetMapping("test4")public  String test4(String id){return null;}

四、缓存穿透

概念:

用户在不断访问一个在缓存和数据库中都没有的数据,缓存无法命中,从而导致一直请求数据库,流量过大就会导致数据库的崩溃,这就是缓存穿透问题。

 解决:

  • 接口层增加校验,如用户鉴权等;
  • 使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在
  • 将空结果(NULL)或默认查询结果存入到缓存中,并设置值过期时间。

布隆过滤器可以参考文章:

redis中布隆过滤器使用详解_redis布隆过滤器使用-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/w1014074794/article/details/129750865 

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

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

相关文章

基于Java的qq截图工具参考论文(论文 + 源码)

【免费】基于Java的qq截图工具.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89304179 基于Java的qq截图工具 摘要 当今时代是飞速发展的信息时代&#xff0c;人们在对信息的处理中对图像的处理量与日俱增&#xff0c;这一点在文档人员上显得非常突出。 本软…

Linux下Telemac-Mascaret源码编译安装及使用

目录 软件介绍 基本依赖 其它可选依赖 一、源码下载 二、解压缩 三、编译安装 3.1 修改环境变量设置文件 3.2 修改配置文件 3.3 编译安装 四、算例运行 软件介绍 TELEMAC-MASCARET是法国电力集团(EDF)的法国国立水利与环境实验室开发的一款研究水动力学和水文学领域的…

宿舍管理系统代码详解(登录界面)

之前已经对这个管理系统进行了大体上的结构的展现&#xff0c;后面的篇章将对其中的前端代码进行详细的介绍与展示。 目录 一、数据库建表 二、登录界面前端代码 1.样式展示 2.代码详解 &#xff08;1&#xff09;template部分 &#xff08;2&#xff09;script部…

DC/DC 隔离定电,压输入电源(0.1-3W)介绍

定电压输入非稳压输出 SMD(0.25-2W)系列&#xff0c;典型性能:直流输入、直流输出隔离型模块电源SMD 表贴型产品&#xff0c;完全实现采用全自动贴片机来组装和满足回流焊工艺&#xff0c;大大提高产能和人工费用。此产品小&#xff0c;效率高&#xff0c;低输出纹波及提供 300…

SSH 免密登录,设置好仍然需要密码登录解决方法

说明&#xff1a; ssh秘钥登录设置好了&#xff0c;但是登录的时候依然需要提供密码 查看系统安全日志&#xff0c;定位问题 sudo cat /var/log/auth.log或者 sudo cat /var/log/secure找到下面的信息 Authentication refused: bad ownership or modes...&#xff08;网上的…

重大升级 | OpenSCA SaaS全面接入供应链安全情报!

结合社区用户反馈及研发小伙伴的积极探索&#xff0c; OpenSCA 项目组再次发力&#xff0c;SaaS版本重大升级啦&#xff01; 用户的需求是OpenSCA前进的动力&#xff0c;欢迎更多感兴趣的朋友们积极试用和反馈~ 更 新 内 容 1.全面接入云脉XSBOM供应链安全情报 2.强大的资产…

嫦娥六号揭秘真相:阿波罗登月是真是假?一文终结所有疑问!

近期&#xff0c;嫦娥六号的成功发射如同璀璨的星辰&#xff0c;再次将人们的视线聚焦于浩瀚的宇宙&#xff0c;与此同时&#xff0c;网络上关于美国阿波罗登月是否造假的争议也如潮水般涌现。一些声音宣称&#xff0c;嫦娥六号的发射为揭示美国阿波罗登月任务的真实性提供了关…

宝塔面板各种疑难杂症处理命令教程

下载地址&#xff1a;宝塔面板各种疑难杂症处理命令教程 这份宝塔面板各种疑难杂症处理命令教程&#xff0c;可以解决市面上遇到的各种难题&#xff0c;建议有技术能行的下载使用&#xff0c;小白也可以下载来学习可以帮助你解决宝塔面板遇到的各种难题

对中介者模式的理解

目录 一、场景1、题目 【[来源](https://kamacoder.com/problempage.php?pid1094)】1.1 题目描述1.2 输入描述1.3 输出描述1.4 输入示例1.5 输出示例 二、不采用中介者设计模式1 代码2 问题 三、中介者设计模式1 代码2 更好的例子 四、个人思考 一、场景 设计模式不是银弹&am…

宝塔纯净版 7.6.0版本无需手机登录 [稳定版本/推荐]

下载地址&#xff1a;宝塔纯净版 7.6.0版本无需手机登录.zip 宝塔纯净版介绍 无需手机登录&#xff1a;不再有手机登录提示&#xff0c;或按照提示输入任意手机号密码即可模拟绑定&#xff1b; 安全&#xff1a;剥离了所有与宝塔官方的通信、上报、下发&#xff1b;并且不与…

有哪些网络兼职适合大学生参与?揭秘几个简单又实用的兼职机会

有哪些网络兼职适合大学生参与&#xff1f;揭秘几个简单又实用的兼职机会 对于大学生而言&#xff0c;除了专注于学业&#xff0c;利用空余时间参与一些网络兼职&#xff0c;不仅能锻炼个人技能&#xff0c;还能为未来的职业生涯积累宝贵的经验。想象一下&#xff0c;步入社会…

Linux-磁盘管理类实训

一、Linux分区和磁盘操作命令 &#xff08;1&#xff09;将系统内所有的分区&#xff08;文件系统&#xff09;列出来&#xff09; &#xff08;2&#xff09;将系统中所有特殊文件格式及名称都列出来 &#xff08;3&#xff09;将/bin下面的可以用的磁盘容量以易读的容量格式…

房屋出租管理系统需求分析及功能介绍

房屋租赁管理系统适用于写字楼、办公楼、厂区、园区、商城、公寓等商办商业不动产的租赁管理及租赁营销&#xff1b;提供资产管理&#xff0c;合同管理&#xff0c;租赁管理&#xff0c; 物业管理&#xff0c;门禁管理等一体化的运营管理平台&#xff0c;提高项目方管理运营效率…

OpenAI之Whisper实时语音分析转文字

1.安装ffmpeg 2.安装python3.11 3.安装whisper pip install whisper conda环境安装whisper conda install whisper 命令行安装openai-whisper pip install openai-whisper 设置环境变量 4.分析语音并输出(默认使用GPU计算&#xff0c;如果没有安装CUDA,请使用CPU) whisper …

吃透前端文件上传与文件相关操作

最近在学文件上传的操作,所以想把学习到东西写成一文章 这片文章是我以小白视角 慢慢学习并熟悉前端文件相关操作的流程总结出来的 前端文件上传 我首先想到是 <input type"file">选择文件</input>如果我们想限制上传文件的格式,大小或进行裁剪分片上传…

2024审计师报名流程图解❗报名时间汇总❗

2024年审计专业技术资格考试报名正在进行中 &#x1f50d;审计报名流程 一、考生注册 打开浏览器登录中国人事考试网进行【考生注册】&#xff0c;按照提示认真填写个人注册信息&#xff0c;确保个人信息真实、完整、准确&#xff0c;并上传已处理好的照片。 二、考生报名 1⃣考…

[C++核心编程-09]----C++类和对象之继承

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

C++进阶:哈希(1)

目录 1. 简介unordered_set与unordered_map2. 哈希表&#xff08;散列&#xff09;2.1 哈希表的引入2.2 闭散列的除留余数法2.2.1 前置知识补充与描述2.2.2 闭散列哈希表实现 2.3 开散列的哈希桶2.3.1 结构描述2.3.2 开散列哈希桶实现2.3.3 哈希桶的迭代器与key值处理仿函数 3.…

7B2 PRO主题5.4.2 免授权开心版源码 | WordPress主题

简介&#xff1a; B2 PRO 5.4.2 最新免授权版不再需要改hosts&#xff0c;和正版一样上传安装就可以激活。 直接在WordPress上传安装即可 点击下载

巴奴火锅翻车,杜中兵后悔暗讽海底捞

曾经喊出“服务不过度&#xff0c;样样都讲究”、内涵海底捞的巴奴火锅&#xff0c;又改回了2012年的广告语&#xff0c;试图重回“产品主义”。 巴奴火锅于2001年创立于河南安阳&#xff0c;彼时被视作火锅界的黑马。巴奴火锅创始人的杜中兵&#xff0c;坚信“产品主义”一定…