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_ID

2-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博客icon-default.png?t=N7T8https://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
  1. 功能丰富:Redisson提供了Redis各种数据结构的Java实现,以及分布式锁、计数器等高级功能,满足复杂场景需求。

  2. 易于集成:友好的API和与多种Java框架的集成支持,使得开发者能够轻松地将Redis集成到Java应用中。

  3. 高性能与可扩展:基于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");}

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

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

相关文章

JetPack之DataBinding基础使用

目录 一、简介二、使用2.1 使用环境2.2 xml文件绑定数据2.3 数据绑定的对象2.3.1 object2.3.2 ObseravbleField2.3.3 ObseravbleCollection 2.4 绑定数据 三、应用场景 一、简介 DataBinding是谷歌15年推出的library,DataBinding支持双向绑定&#xff0c;能大大减少绑定app逻辑…

python灾害应急救援平台flask-django-php-nodejs

灾害应急救援平台的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品&#xff0c;体验高科技时代带给人们的方便&#xff0c;同时也能让用户体会到与以往常规产品不同的体验风格。 与安卓&#xff0c;iOS相比较起来&#xff0c;…

【Selenium(五)】

一、鼠标事件 from selenium import webdriver # 导入ActionChains类进行鼠标悬停操作 from selenium.webdriver.common.action_chains import ActionChains import time# 打开一个浏览器 # 法一、添加环境变量重启电脑 # 法二、填写浏览器驱动的绝对路径 driver webdriver.E…

功率半导体IGBT模块封装工艺

功率器件最近非常火热&#xff0c;作为新型功率半导体器件的主流器件&#xff0c;IGBT应用非常广泛&#xff0c;如家用电器、电动汽车、铁路、充电基础设施、充电桩&#xff0c;光伏、风能&#xff0c;工业制造、电机驱动&#xff0c;以及储能等领域。IGBT模块是新一代的功率半…

undo log

从这篇「执行一条 SQL 查询语句&#xff0c;期间发生了什么&#xff1f; (opens new window)」中&#xff0c;我们知道了一条查询语句经历的过程&#xff0c;这属于「读」一条记录的过程&#xff0c;如下图&#xff1a; 那么&#xff0c;执行一条 update 语句&#xff0c;期间发…

桌面显示器PD芯片:引领桌面显示技术的新篇章

随着科技的飞速发展&#xff0c;桌面显示器作为人们日常工作与生活中不可或缺的重要设备&#xff0c;其性能与品质也在不断提升。其中&#xff0c;PD芯片作为桌面显示器中的核心组件&#xff0c;发挥着至关重要的作用。本文将对桌面显示器PD芯片进行详细介绍&#xff0c;探讨其…

MD5源码(C语言描述)

本文介绍MD5源码&#xff08;C语言描述&#xff09;。 MD5(Message-Digest Algorithm 5)&#xff0c;即消息摘要算法5&#xff0c;是一种被广泛使用的消息散列算法。散列算法的基础原理是&#xff1a;将数据&#xff08;如一段文字&#xff09;经过运算转换为一段固定长度&…

#Linux(VMwareTOOL安装)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09; &#xff08;2&#xff09;打开虚拟机然后安装&#xff0c;出现灰色可能是已经安装过但是自己没有找到 &#xff08;3&#xff09;删除VM…

流畅切换Linux的应用程序

流畅切换Linux的应用程序 流畅切换Linux的应用程序一.Linux启动一个程序在后台执行1. 使用nohup和&&#xff1a;2. 使用ctrlZ&#xff1a;3.使用screen&#xff1a;3.1 创建会话3.2 要重新连接到此会话&#xff1a;3.3 中途退出会话&#xff0c;但程序继续运行:3.4 结束一个…

STM32的简单介绍

STM32是一种基于ARM Cortex-M内核的32位微控制器&#xff0c;由意法半导体公司开发和生产。STM32具有丰富的外设和功能&#xff0c;适用于各种应用场合&#xff0c;如工业控制、消费电子、物联网、人机交互等。STM32的优势包括低功耗、高性能、高可靠性、易于开发等。STM32的系…

上海晋名室外暂存柜助力新技术皮革制品生产行业安全

本周上海晋名又有一台室外危化品暂存柜项目通过验收&#xff0c;此次项目主要用于新技术皮革制品生产行业油桶、化学品等物资的室外暂存安全。 用户单位创立于2004年&#xff0c;是一家从事新技术皮革制品加工、生产的外资企业。 上海晋名作为一家专注工业安全防护领域&#…

基于消失点的相机自标定

基于消失点的相机自标定 附赠最强自动驾驶学习资料&#xff1a;直达链接 相机是通过透视投影变换来将3D场景转换为2D图像。在射影变换中&#xff0c;平行线相交于一点称之为消失点。本文详细介绍了两种利用消失点特性的标定方法。目的是为根据实际应用和初始条件选择合适的标…

SpingBoot集成Rabbitmq及Docker部署

文章目录 介绍RabbitMQ的特点Rabbitmq术语消息发布接收流程 Docker部署管理界面说明Overview: 这个页面显示了RabbitMQ服务器的一般信息&#xff0c;例如集群节点的名字、状态、运行时间等。Connections: 在这里&#xff0c;可以查看、管理和关闭当前所有的TCP连接。Channels: …

component-右侧抽屉组件

1.右侧抽屉组件 点击筛选&#xff0c;右侧抽屉滑出&#xff0c;点击取消或者点击空白处抽屉收起。 2.代码 <template><div class"all" click"hidden()"><!-- 抽屉 --><div class"drawer"><div class"drawerBo…

js处理数组分类

const obj [{"groupingType": "1","remark": "梨花带雨","totalRmbMoney": 7,"kyeGroupingType": "广州一组"},{"groupingType": "2","remark": "99","…

【蓝桥杯】第15届蓝桥杯青少组stema选拔赛C++中高级真题答案(20240310)

一、选择题 第 1 题 第 2 题 表达式1000/3的结果是( A )。 A.333 B.333.3 C.334 D.333.0 第 3 题 下列选项中&#xff0c;判断a等于1并且b等于1正确的表达式是( B )。 A.!((a!1)&&(b!1)) B.!((a!1)||(b!1)) C.!(a1)&&(b1) D.(a1)&&(b1) 【解析】 A…

测试用例设计指南

软件测试设计是测试过程中重要的测试活动&#xff0c;怎么样设计测试用例能提高我们测试的效率和质量&#xff0c;从以下几个方面做了简单的讲解。 1 测试用例设计原则 测试用例设计的基本原则包括&#xff1a;有效性、清晰性、可复用性、可维护性、完整性、兼容性、易操作性…

【数据可视化】Echarts官方文档及常用组件

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 前言2. Echarts官方文档介绍3. ECharts基础架构及常用术语3.1 ECharts的基础架构3.2 ECharts的常用术语3.2.1 ECharts的基本名词3.2.2 ECharts的图表名词 4. 直角坐标系下的网格及坐标轴4.1 直角坐标系下的网格4.2…

360企业安全浏览器兼容模式显示异常某个内容不显示 偶发现象 本地无法复现情况js

360企业安全浏览器兼容模式显示异常 &#xff0c;现象测试环境频发 &#xff0c;本地连测试无法复现&#xff0c;线上反馈问题。 出现问题的电脑为windows且使用360企业安全浏览器打开兼容模式可复现 复现过程&#xff1a; 不直接点击超链接跳转页面 &#xff0c;登录后直接通…

vue3+threejs新手从零开发卡牌游戏(三):尝试在场景中绘制一张卡牌

首先我们思考下&#xff0c;一张最简单的卡牌有哪些东西构成&#xff1a;卡牌样式和卡牌数据。一张卡牌有正面和背面&#xff0c;有名称、属性、种族、攻击力等数据&#xff0c;我们先不考虑数据&#xff0c;先尝试在场景中绘制一张卡牌出来。 一、寻找卡牌素材 为了简单我直…