RuoYi-Vue-Plus(基础知识点jackson、mybatisplus、redis)
一、JacksonConfig 全局序列化反序列化配置
1.1yml中配置
#时区
spring.jackson.time-zone=GMT+8
#日期格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
#默认转json的属性,这里设置为非空才转json
spring.jackson.default-property-inclusion=non_null
#设置属性命名策略,对应jackson下PropertyNamingStrategy中的常量值,SNAKE_CASE-返回的json驼峰式转下划线,json body下划线传到后端自动转驼峰式
spring.jackson.property-naming-strategy=SNAKE_CASE
#对象为空时是否报错,默认true
spring.jackson.serialization.fail-on-empty-beans=true
#返回的java.util.date转换成timestamp
spring.jackson.serialization.write-dates-as-timestamps=true
#json中含pojo不存在属性时是否失败报错,默认true
spring.jackson.deserialization.fail-on-unknown-properties=false
#是否允许出现单引号,默认false
spring.jackson.parser.allow-single-quotes=true
1.2配置文件中配置
光标定位置在builder后面,ALT + ENTER,选择 replace lambda with anonymous class可以显示 lambda为普通方法。此处定义了一下常见类型的序列化方法
@Slf4j
@Configuration
public class JacksonConfig {@Beanpublic Jackson2ObjectMapperBuilderCustomizer customizer() {return new Jackson2ObjectMapperBuilderCustomizer() {@Overridepublic void customize(Jackson2ObjectMapperBuilder builder) {// 全局配置序列化返回 JSON 处理JavaTimeModule javaTimeModule = new JavaTimeModule();javaTimeModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));builder.modules(javaTimeModule);builder.timeZone(TimeZone.getDefault());log.info("初始化 jackson 配置");}};}}
ruoyi-admin/src/main/resources/application.yml 中配置jackon jackson:# 日期格式化date-format: yyyy-MM-dd HH:mm:ssserialization:# 格式化输出indent_output: false# 忽略无法转换的对象fail_on_empty_beans: falsedeserialization:# 允许对象忽略json中不存在的属性fail_on_unknown_properties: false
点击Jackson2ObjectMapperBuilderCustomizer, 可以查看自动配置类:JacksonAutoConfiguration
@Configuration(proxyBeanMethods = false)@ConditionalOnClass(Jackson2ObjectMapperBuilder.class)static class JacksonObjectMapperBuilderConfiguration {@Bean@Scope("prototype")@ConditionalOnMissingBeanJackson2ObjectMapperBuilder jacksonObjectMapperBuilder(ApplicationContext applicationContext,List<Jackson2ObjectMapperBuilderCustomizer> customizers) {Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();builder.applicationContext(applicationContext);customize(builder, customizers);return builder;}private void customize(Jackson2ObjectMapperBuilder builder,List<Jackson2ObjectMapperBuilderCustomizer> customizers) {for (Jackson2ObjectMapperBuilderCustomizer customizer : customizers) {customizer.customize(builder);}}}
1.3常见jackon注解
@JsonIgnore 忽略序列化,用于属性上 @JsonInclude(JsonInclude.Include.NON_EMPTY) 不为空时候才进行序列化和反序列化 @JsonSerialize(using = DictDataJsonSerializer.class) 序列化,如下DictDataJsonSerializer 是字典序列化的处理工具/*** 字典数据json序列化工具** @author itino* @deprecated 建议使用通用翻译注解*/ @Deprecated @Slf4j public class DictDataJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {private String dictType;@Overridepublic void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {try {DictService dictService = SpringUtils.getBean(DictService.class);if (ObjectUtil.isNotNull(dictService)) {String label = dictService.getDictLabel(dictType, value);gen.writeString(StringUtils.isNotBlank(label) ? label : value);} else {gen.writeString(value);}} catch (BeansException e) {log.error("字典数据未查到, 采用默认处理 => {}", e.getMessage());gen.writeString(value);}}@Overridepublic JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {DictDataMapper anno = property.getAnnotation(DictDataMapper.class);if (Objects.nonNull(anno) && StrUtil.isNotBlank(anno.dictType())) {this.dictType = anno.dictType();return this;}return prov.findValueSerializer(property.getType(), property);} }
@JsonProperty( value = "pass") 接受和序列化都用 pass ,而不是 password@JsonIgnore @JsonProperty( value = "pass") public String getPassword() {return password; }
@JsonFormat(pattern = "yyyy-MM-dd") 系列化格式
1.4 若依jackson工具包
com.ruoyi.common.utils.JsonUtils ,提供序列化和反序列化 一些常用方法
二、MybatisPlus
依赖
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis-plus.version}</version></dependency>
ruoyi-admin/src/main/resources/application.yml 配置文件:
- 配置了Mapper 接口的扫描
- 配置Mapper对应XML的扫描
- 配置实体类domain扫描
- 配字段驼峰规则
- 以及 p6spy的日志分析
- 配置主键生成规则,以及CRUD策略
# MyBatisPlus配置
# https://baomidou.com/config/
mybatis-plus:# 不支持多包, 如有需要可在注解配置 或 提升扫包等级# 例如 com.**.**.mapper com.ruoyi.system.mappermapperPackage: com.ruoyi.**.mapper# 对应的 XML 文件位置mapperLocations: classpath*:mapper/**/*Mapper.xml# 实体扫描,多个package用逗号或者分号分隔typeAliasesPackage: com.ruoyi.**.domain# 启动时是否检查 MyBatis XML 文件的存在,默认不检查checkConfigLocation: falseconfiguration:# 自动驼峰命名规则(camel case)映射mapUnderscoreToCamelCase: true# MyBatis 自动映射策略# NONE:不启用 PARTIAL:只对非嵌套 resultMap 自动映射 FULL:对所有 resultMap 自动映射autoMappingBehavior: PARTIAL# MyBatis 自动映射时未知列或未知属性处理策# NONE:不做处理 WARNING:打印相关警告 FAILING:抛出异常和详细信息autoMappingUnknownColumnBehavior: NONE# 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl# 关闭日志记录 (可单纯使用 p6spy 分析) org.apache.ibatis.logging.nologging.NoLoggingImpl# 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpllogImpl: org.apache.ibatis.logging.nologging.NoLoggingImplglobal-config:# 是否打印 Logo bannerbanner: truedbConfig:# 主键类型# AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUIDidType: ASSIGN_ID# 逻辑已删除值logicDeleteValue: 2# 逻辑未删除值logicNotDeleteValue: 0# 字段验证策略之 insert,在 insert 的时候的字段验证策略# IGNORED 忽略 NOT_NULL 非NULL NOT_EMPTY 非空 DEFAULT 默认 NEVER 不加入 SQLinsertStrategy: NOT_NULL# 字段验证策略之 update,在 update 的时候的字段验证策略updateStrategy: NOT_NULL# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件where-strategy: NOT_NULL
com.ruoyi.framework.config.MybatisPlusConfig 配置文件,主要配置以下:自行查看
// 数据权限处理 // 分页插件 // 乐观锁插件- // 指定字段的填充策略
使用网卡信息绑定雪花生成器,防止集群雪花ID重复
1.1 常见注解
@TableName("sys_user") 标注数据库表名称@TableId(value = "user_id") 主键@Version 乐观锁(比如查询携带上 version字段,才回去更新版本)@TableLogic 删除标志(0代表存在 2代表删除):上面 yml配置的逻辑删除, 标注该注解的字段,数据库要默认设置 0
@TableField
属性 fill 指定字段的填充策略,如自动填充创建时间、更新时间等。需要实现 MyBatis-Plus 提供的
MetaObjectHandler
接口,并重写
insertFill
和updateFill
方法。若依具体实现类:com.ruoyi.framework.handler.CreateAndUpdateMetaObjectHandler
exist 标记是否为数据库表字段,默认为
true
。如果设置为false
,则表示该字段不是数据库表的字段,不会参与 SQL 语句的生成示例: @TableField(exist = false) private List<SysRole> roles;value
- 数据库字段名,用于指定实体类字段对应的数据库字段名。当实体类字段名与数据库字段名不一致时使用。
- 示例:
@TableField("db_column_name")
update
- 用于 SQL 的 SET 语句,设置字段更新的策略。通常与
@TableLogic
注解一起使用,实现逻辑删除。- 示例:
@TableField(update = "deleted=1")
nsertStrategy 和 updateStrategy
- 字段的插入和更新策略。
FieldStrategy
是一个枚举类,包含以下值:IGNORED
(忽略)、NOT_NULL
(非 NULL 则更新)、NOT_EMPTY
(非空则更新)、ALWAYS
(总是更新)。- 示例:
- @TableField( insertStrategy = FieldStrategy.NOT_EMPTY, updateStrategy = FieldStrategy.NOT_EMPTY, whereStrategy = FieldStrategy.NOT_EMPTY )
select
- 是否进行 select 查询。默认为
true
,表示该字段会参与查询。如果设置为false
,则查询时不会包含该字段。- 示例:
@TableField(select = false)
jdbcType
- 字段的 JDBC 类型。通常用于指定某些特殊类型的字段,如枚举类型。
- 示例:
@TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)el
- 支持 EL 表达式,用于复杂字段的映射处理。
- 示例:
@TableField(el = "column + '_suffix'")
condition
- 用于 SQL WHERE 语句的条件,通常与
@Select
注解一起使用,实现动态 SQL。- 示例:
@TableField(condition = "name != null and name = #{name}")
strategy
- 字段验证策略,与
insertStrategy
和updateStrategy
功能类似,但用于全局配置。- 示例:
@TableField(strategy = FieldStrategy.NOT_EMPTY)
1.2 BaseMapperPlus
若依继承了 mybatis-plus的BaseMapper<T> 接口 ,自定义了 BaseMapperPlus<M, T, V> Mapper接口:com.ruoyi.common.core.mapper.BaseMapperPlus
- 提供泛型的转换
- 提供BaseMapper原有接口的封装
- 提供其他新增的查询方法
1.3分布式主键 雪花ID
1-yml中配置雪花: dbConfig:# 主键类型# AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUIDidType: ASSIGN_ID2-com.ruoyi.framework.config.MybatisPlusConfig 类中注入IdentifierGenerator ,具体实现自行查看
/*** 使用网卡信息绑定雪花生成器* 防止集群雪花ID重复*/@Beanpublic IdentifierGenerator idGenerator() {return new DefaultIdentifierGenerator(NetUtil.getLocalhost());}
1.4 wapper
关于条件构造器: wapper 学习文章可以参考
mybatis-plus中wrapper的用法(详细)_mybatisplus wrapper-CSDN博客https://blog.csdn.net/qq_39715000/article/details/120090033上文未提及一些常用函数
1-apply() 函数 :将要添加到 SQL 语句中的 SQL 片段作为参数传递给它即可
//简单查询
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.apply("id = 1 or name like '%test%'");
List<User> userList = userMapper.selectList(wrapper);//日期
apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2020-10-08")apply("date_format(dateColumn,{0}) = {1}", "%Y-%m-%d", "2020-10-08")
2-func 函数:可以添加if 等判断
LambdaQueryWrapper<SysOperLog> lqw = new LambdaQueryWrapper<SysOperLog>().like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle()).eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0,SysOperLog::getBusinessType, operLog.getBusinessType()).func(f -> {if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) {f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes()));}})
3- nested 嵌套查询: nested函数中语句会加上()作为整体提升优先级
public void complexQuery() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("status", 1) .nested(i -> i.eq("name", "John").or().like("email", "example%")) .orderByAsc("id"); List<User> userList = userMapper.selectList(queryWrapper); }
SELECT * FROM user WHERE status = 1 AND (name = 'John' OR email LIKE 'example%') ORDER BY id ASC
三、BeanCopyUtils
com.ruoyi.common.utils.BeanCopyUtils 包中 ,提供:(基于 cglib 性能优异)
- Bean to Bean
- Bean to Map
- Map to Bean
- Map to Map
- List copy
四、Redis
1.1 Redisson
功能丰富:Redisson提供了Redis各种数据结构的Java实现,以及分布式锁、计数器等高级功能,满足复杂场景需求。
易于集成:友好的API和与多种Java框架的集成支持,使得开发者能够轻松地将Redis集成到Java应用中。
高性能与可扩展:基于Redis的内存存储和集群支持,Redisson实现了高读写速度和水平扩展能力,适用于高并发和大规模应用。
依赖
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-data-27</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>lock4j-redisson-spring-boot-starter</artifactId></dependency>
1.2 Redisson 配置文件和配置类
配置文件 yml中,com.ruoyi.framework.config.properties.RedissonProperties 是其配置类。
下面分别是单机 和集群配置类。
/*** 单机服务配置*/ private SingleServerConfig singleServerConfig;/*** 集群服务配置*/ private ClusterServersConfig clusterServersConfig;
redisson:# redis key前缀keyPrefix: ruoyi-vue-plus# 线程池数量threads: 4# Netty线程池数量nettyThreads: 8# 单节点配置singleServerConfig:# 客户端名称clientName: ${ruoyi.name}# 最小空闲连接数connectionMinimumIdleSize: 8# 连接池大小connectionPoolSize: 32# 连接空闲超时,单位:毫秒idleConnectionTimeout: 10000# 命令等待超时,单位:毫秒timeout: 3000# 发布和订阅连接池大小subscriptionConnectionPoolSize: 50
com.ruoyi.framework.config.RedisConfig 类,是redisson的配置类。
@Beanpublic RedissonAutoConfigurationCustomizer redissonCustomizer() {return config -> {config.setThreads(redissonProperties.getThreads()).setNettyThreads(redissonProperties.getNettyThreads()).setCodec(new JsonJacksonCodec(objectMapper));RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();if (ObjectUtil.isNotNull(singleServerConfig)) {// 使用单机模式config.useSingleServer()//设置redis key前缀.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())).setTimeout(singleServerConfig.getTimeout()).setClientName(singleServerConfig.getClientName()).setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout()).setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize()).setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize()).setConnectionPoolSize(singleServerConfig.getConnectionPoolSize());}// 集群配置方式 参考下方注释RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();if (ObjectUtil.isNotNull(clusterServersConfig)) {config.useClusterServers()//设置redis key前缀.setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())).setTimeout(clusterServersConfig.getTimeout()).setClientName(clusterServersConfig.getClientName()).setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout()).setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize()).setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize()).setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize()).setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize()).setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize()).setReadMode(clusterServersConfig.getReadMode()).setSubscriptionMode(clusterServersConfig.getSubscriptionMode());}log.info("初始化 redis 配置");};}
1.3 redis 和redisson集群配置文件
/*** redis集群配置 yml** --- # redis 集群配置(单机与集群只能开启一个另一个需要注释掉)* spring:* redis:* cluster:* nodes:* - 192.168.0.100:6379* - 192.168.0.101:6379* - 192.168.0.102:6379* # 密码* password:* # 连接超时时间* timeout: 10s* # 是否开启ssl* ssl: false** redisson:* # 线程池数量* threads: 16* # Netty线程池数量* nettyThreads: 32* # 集群配置* clusterServersConfig:* # 客户端名称* clientName: ${ruoyi.name}* # master最小空闲连接数* masterConnectionMinimumIdleSize: 32* # master连接池大小* masterConnectionPoolSize: 64* # slave最小空闲连接数* slaveConnectionMinimumIdleSize: 32* # slave连接池大小* slaveConnectionPoolSize: 64* # 连接空闲超时,单位:毫秒* idleConnectionTimeout: 10000* # 命令等待超时,单位:毫秒* timeout: 3000* # 发布和订阅连接池大小* subscriptionConnectionPoolSize: 50* # 读取模式* readMode: "SLAVE"* # 订阅模式* subscriptionMode: "MASTER"*/
1.4 RedisUtils 工具类
所在包 :com.ruoyi.common.utils.redis.RedisUtils
1、 订阅发布测试类以及结果如下;
@Testvoid subPub(){String key = "key";//模拟订阅消息 启动后会一直监听消息RedisUtils.subscribe(key, String.class, consumer -> {Console.log("key:{}", key);Console.log("consumer:{}", consumer);});//模拟发布RedisUtils.publish(key,"发布一则消息1!");RedisUtils.publish(key,"发布一则消息2!");RedisUtils.publish(key,"ok", conumer->{Console.log("consumer3:{}", conumer);});}
key:key
consumer:发布一则消息1!
key:key
consumer:发布一则消息2!
consumer3:ok
key:key
consumer:ok
2、设置缓存
@Testvoid setCacheObject(){//ttl = -1 ,永久有效印版不用RedisUtils.setCacheObject("java", "helloWord");//ttl 自定义, 60秒有效期RedisUtils.setCacheObject("java", "helloWord", Duration.ofSeconds(60));//是否保留TTL有效期(例如: set之前ttl剩余60 set之后还是为60),false 表示永久RedisUtils.setCacheObject("java", "helloWord", true);//果不存在则设置 并返回 true 如果存在则返回 falseboolean ifAbsent = RedisUtils.setObjectIfAbsent("java", "helloWord", Duration.ofSeconds(60));}
3、设置监听
redis中配置 ,key 监听器配置 : notify-keyspace-event ,如下:(接口中红线标注要包含的 字母,其他接口自行查看)
# Redis服务器配置 # 绑定IP地址
#解除本地限制 注释bind 127.0.0.1
#bind 127.0.0.1 # 服务器端口号
port 6379 #配置密码,不要可以删掉
#requirepass #key 监听器配置
notify-keyspace-events Exg# 服务器运行模式,Redis以守护进程方式运行,默认为no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败,如果后面redis启动失败,就将这个注释掉
daemonize no#当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定(自定义)
#pidfile /data/dockerData/redis/run/redis6379.pid #默认为no,redis持久化,可以改为yes
appendonly yes
监听测试类:
package com.ruoyi.demo.listener;import cn.hutool.core.lang.Console;
import com.ruoyi.common.utils.redis.RedisUtils;
import org.redisson.api.DeletedObjectListener;
import org.redisson.api.ExpiredObjectListener;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;/*** <简述>* <详细描述>** @author syf* @date 2024年03月18日 22:38*/
@Component
public class ExpiredListener {@PostConstructpublic void expireListener(){Console.log("启动监听器。。。。");//用于监听 Redisson 分布式缓存中对象的过期事件RedisUtils.addObjectListener("java", new ExpiredObjectListener() {@Overridepublic void onExpired(String name) {Console.log("ExpiredObjectListener:{}", name);}});//监听删除RedisUtils.addObjectListener("java", new DeletedObjectListener() {@Overridepublic void onDeleted(String name) {Console.log("DeletedObjectListener:{}", name);}});}
}
结果:监听到删除
4-对象操作
常用操作
@Testvoid getObject(){RedisUtils.setCacheObject("java", "helloWord");//6-校验对象是否存在RedisUtils.isExistsObject("java");//1-设置过期时间RedisUtils.expire("java", Duration.ofSeconds(10));//2-获取对象Object name = RedisUtils.getCacheObject("name");Console.log("name:{}", name);//3-获取剩余存活时间long time = RedisUtils.getTimeToLive("name");Console.log("time:{}", time);//4-删除RedisUtils.deleteObject("name");//5-删除集合List<String> list = new ArrayList<>();list.add("java1");list.add("java2");RedisUtils.setCacheObject("java1", "helloWord1");RedisUtils.setCacheObject("java2", "helloWord2");RedisUtils.deleteObject(list);}
5-数组操作
数组操作是拼接,不会覆盖,对象操作则是覆盖,注意使用场景
提供集合的操作下:
@Testvoid saveList(){//这个实际保存是对象 (覆盖之前 list1)List<String> list = Arrays.asList("java1", "java2");RedisUtils.setCacheObject("list1", list, Duration.ofSeconds(60));//保存是数组 (不会覆盖之前的数据 list2)RedisUtils.setCacheList("list2", list);//取List<String> list2 = RedisUtils.getCacheList("list2");//set集合 值不重复Set<String> set = new HashSet<>();set.add("java1");set.add("java2");RedisUtils.setCacheSet("set", set);RedisUtils.getCacheSet("set");//MapMap<String, Object> map = new HashMap<>();map.put("java1", "String");map.put("java2", "Integer");//存RedisUtils.setCacheMap("map", map);//取Object value = RedisUtils.getCacheMapValue("map", "java1");//修改map 里面值RedisUtils.setCacheMapValue("java1", "map", "null");//取map 里面值(自定义map 用得少)Set<String> objects = new HashSet<>();objects.add("java1");objects.add("java2");Map<String, Object> map2 = RedisUtils.getMultiCacheMapValue("map", objects);//取Map<String, Object> cacheMap = RedisUtils.getCacheMap("map");//遍历keySet<String> map1 = RedisUtils.getCacheMapKeySet("map");}
6-原子操作
原子操作,创建后,利用 增加 减少方法去修改
@Testvoid steAtom(){//原子操作RedisUtils.setAtomicValue("count" ,1);//增加RedisUtils.incrAtomicValue("count");//减少RedisUtils.decrAtomicValue("count");//获取long atomicValue = RedisUtils.getAtomicValue(":count");}
7-根据前缀获取
@Testvoid getKeys() {//getString prefix = "ruoyi-vue-plus:sys";Collection<String> keys = RedisUtils.keys(prefix + "*");List<String> list = new ArrayList<>(keys);for (String s : list) {Console.log("value:{}", s);}//删除String prefix1 = "list1";RedisUtils.deleteKeys(prefix1 + "*");}
结果:
value:sys_config
value:sys_oss_config
value:sys_oss:default_config
value:sys_dict
8-是否存在
@Testvoid getExists() {//是否存在boolean hasKey = RedisUtils.hasKey("list2");boolean existsObjectis = RedisUtils.isExistsObject("list2");}
相关文章:

RuoYi-Vue-Plus(基础知识点jackson、mybatisplus、redis)
一、JacksonConfig 全局序列化反序列化配置 1.1yml中配置 #时区 spring.jackson.time-zoneGMT8 #日期格式 spring.jackson.date-formatyyyy-MM-dd HH:mm:ss #默认转json的属性,这里设置为非空才转json spring.jackson.default-property-inclusionnon_null #设置属性…...
使用verillog编写KMP字符串匹配算法
设计思路如下: 定义模块的输入输出信号:包括时钟信号clk、复位信号rst、模式串pattern、文本串text以及输出信号match。定义所需寄存器和变量:使用寄存器来存储状态机的状态以及其他控制变量,如模式串数组P、失配函数数组F、模式串位置p_index、文本串位置t_index等。在时钟…...
《每天十分钟》-红宝书第4版-对象、类与面向对象编程(五)
对象迭代 在 JavaScript 有史以来的大部分时间内,迭代对象属性都是一个难题。ECMAScript 2017 新增了两个静态方法,用于将对象内容转换为序列化的——更重要的是可迭代的——格式。这两个静态方法Object.values()和 Object.entries()接收一个对象&#…...

华为ensp中rip动态路由协议原理及配置命令(详解)
CSDN 成就一亿技术人! 作者主页:点击! ENSP专栏:点击! CSDN 成就一亿技术人! ————前言————— RIP(Routing Information Protocol,路由信息协议)是一种距离矢…...

学习要不畏难
我突然发现,畏难心是阻碍我成长的最大敌人。事未难,心先难,心比事都难,是我最大的毛病。然而一念由心生,心不难时,则真难事也不再难。很多那些自认为很难的事,硬着头皮做下来的时候,…...

mysql迁移达梦数据库 Java踩坑合集
达梦数据库踩坑合集 文章目录 安装达梦设置大小写不敏感Spring boot引入达梦驱动(两种方式)将jar包打入本地maven仓库使用国内maven仓库(阿里云镜像) 达梦驱动yml配置springboot mybatis-plus整合达梦,如何避免指定数据库名&…...

arm 解决Rk1126 画框颜色变色问题(RGB转NV12)
在Rv1126上直接对Nv12图像进行绘制时,颜色是灰色。故将Nv12转BGR后绘制图像,绘制完成后转成Nv12,BGR的图像颜色是正常的,但是NV12的图像颜色未画全,如图: 1.排查发现是RGB转NV12的函数出现问题,…...

113 链接集10--ctrl+左键单击多选
1.ctrl左键单击多选,单击单选 精简代码 <div class"model-list"><divmousedown.prevent"handleClick(item, $event)"class"model-list-item"v-for"item in modelList":key"item.id":class"{ model…...

详解JavaScript中this指向
this 原理 this 是一个指针型变量,它指向当前函数的运行环境。 1.内存的数据结构 var obj { foo: 5 };2.函数 var obj { foo: function () {} };引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性。 由于函数是一个单独的…...
c语言之在函数中传递指针
c语言中定义一个函数,如果说是形参一个数组,这个数组在编译后会变成一个指针变量 比如下面的代码例子 #include<stdio.h> void ff(char a[]) {a[1]r;a[4]r;printf("%d\n",a); }int main() {char a[]"peogeam";ff(a);printf(…...
vue2 插槽(默认插槽 slot 、具名插槽 v-slot 、作用域插槽 slot-scope -- 插槽传值 )
插槽:用于在子组件的指定位置插入指定内容,类似在电梯里挂的若干广告显示屏,可以给指定的位置传入指定的广告 单插槽(匿名/默认插槽) 父组件中( 此时的 ) <Child><template><p…...
(第79天)单机转 RAC:19C 单机 到 19C RAC
前言 单机转 RAC 分为两种: 同版本迁移:可以使用 RMAN 或者 ADG 方式升级迁移:建议使用数据泵 或者 XTTS 方式升级迁移使用数据泵的方式与 (第72天)数据泵升级:11GR2 到 19C 步骤基本一致,这里不作演示,只演示使用 ADG 来进行同版本迁移。 升级前准备 本次测试尽量按…...
Spring Cloud微服务Actuator和Vue
目录 前言一、引入Actuator依赖二、暴露Actuator端点1. 配置文件2. 监控端点 三、自定义健康检查自定义健康检查类 四、vue前端代码五、监控器的优势六、监控指标的可视化1. Grafana2. Prometheus 七、安全性考虑安全配置示例 八、总结 前言 随着微服务架构的流行,…...

Iterator对象功能学习
package config;import java.util.Iterator; import java.util.Properties; import java.util.Set;/*** 这个类演示了如何使用Properties类来存储和访问键值对。* Properties类继承自Hashtable,因此它可以用来存储键值对数据,且支持同步。*/ public clas…...

Linux的一些基本指令
目录 前言: 1.以指令的形式登录 2.ls指令 语法: 功能: 常用选项: 3.pwd指令 4.cd指令 4.1 绝对路径与相对路径 4.2 cd .与cd ..(注意cd后先空格,然后两个点是连一起的࿰…...
【tips】Git使用指南
文章目录 一、Git介绍1. 什么是Git2.Git对比SVN3.Git安装 二.Git常用命令1. git config2. 初始化本地库3. 工作区、暂存区和版本库4. git add5. git commit6. git reset 与 git revertgit resetgit revert 三. Git 分支1.初识分支2.创建分支3.切换分支4.合并分支5.删除分支 四.…...
【字节序】
字节序 高字节(低字节)高地址(低地址)大端模式(小端模式) 高字节(低字节) 一个16位(双字节)的数据,比如0xAABB,那么高位字节就是0xAA,低位是0xBB …...

数据结构(五)——树森林
5.4 树和森林 5.4.1 树的存储结构 树的存储1:双亲表示法 用数组顺序存储各结点,每个结点中保存数据元素、指向双亲结点(父结点)的“指针” #define MAX_TREE_SIZE 100// 树的结点 typedef struct{ElemType data;int parent; }PTNode;// 树的类型 type…...

vscode配置c/c++调试环境
本文记录win平台使用vscode远程连接ubuntu server服务器下,如何配置c/c调试环境。 过程 1. 服务器配置编译环境 这里的前置条件是vscode已经能够连接到服务器,第一步安装编译构建套件(gcc、g、make、链接器等)和调试器…...
食品输送带的材质
食品输送带的材质:确保安全与卫生的关键选择 在食品生产和加工过程中,食品输送带扮演着至关重要的角色。它负责将原材料、半成品和成品在各个环节之间进行有效传输,确保生产流程的顺畅进行。然而,在食品行业中,输送带…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...