【RedisTemplate】SpringDataRedis(Spring中对Redis模块的整合)

SpringDataRedis简介:

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis。

官网地址:https://spring.io/projects/spring-data-redis

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现

RedisTemplate对Redis操作类型:

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:
在这里插入图片描述

SpringDataRedis的使用步骤:

1、引入spring-boot-starter-data-redis依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--jedis或者redis底层都会基于commons库来实现连接池效果-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

2、在配置文件中配置Redis信息

server.port=8087
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=123456
#连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.pool.max-idle=8
#连接池中的最小空闲连接
spring.redis.pool.min-idle=0
#连接超时时间(毫秒)
spring.redis.timeout=30000

 =====另一种配置方式======
 spring:
  redis:
    host: 127.0.0.1 # ip
    port: 6379 # 端口
    password: 123456 # 密码
    lettuce: # 默认的客户端是lettuce,若要使用jedis需要添加依赖
      pool:
        max-active: 8  # 最大连接
        max-idle: 8 # 最大空闲连接
        min-idle: 0 # 最小空闲连接
        max-wait: 100ms # 连接等待时间
    database: 0 # 选择库

3、注入RedisTemplate后,即可正常调用方法

@SpringBootTest
class RedisTemplateApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void testString() {
        redisTemplate.opsForValue().set("name","李四");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }

}

=========输出结果========
name = 李四

RedisTemplate的序列化方式:

现象: 在控制台能够看见正常的key和value,但是我们通过redis客户端查看时发现结果是这样的。
在这里插入图片描述原因: RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化;
通过查看RedisTemplate源码可以发现常见的类型都实现了序列化:
在这里插入图片描述查看源码RedisTemplate可以发现默认是采用JDK序列化;这种方式会在写入前把Object序列化为字节的形式,然后进行存储,缺点很明显:可读性差、占用内存。所以我们需要修改默认的JDK序列化方式:
在这里插入图片描述我们希望在redis中存的,所见及所得,而不是进行jdk序列化之后的样子,所以我们需要改变序列化方式。

在这里插入图片描述如上图所示,是主要的集中序列化方式。其中,key为字符串的时候我们通常使用StringRedisSerializer方式,value为字符串的时候,通常使用GenericJackson2JsonRedisSerializer方式。

1、自定义RedisTemplate序列化方法:

1、配置Json序列化的依赖Jackson:

<!--  jackson依赖  -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

2、RedisConfig配置类:

@Configuration
public class RedisConfig {

    /**
      * 描述信息: key和hashKey采用string序列化方式 alue和hashValue采用Json序列化方式
      *
      * @date  2023/05/17
      * @param redisConnectionFactory
      * @return org.springframework.data.redis.core.RedisTemplate<java.lang.String,java.lang.Object>
      **/
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        //创建Template
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        //设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //设置序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //key和hashKey采用string序列化方式
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        //value和hashValue采用Json序列化方式
        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        return redisTemplate;
    }
}

3、测试:
在这里插入图片描述

2、对象序列化:

    @Test
    void testSaveUser() {
        redisTemplate.opsForValue().set("user:100",new User("小红",29));
        User user = (User) redisTemplate.opsForValue().get("user:100");
        System.out.println("user = " + user);
    }

在这里插入图片描述尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,如图:

在这里插入图片描述当我们传入的Value为实体类对象的时候,会用 GenericJackson2JsonRedisSerializer序列化器把java对象转为JSON格式,然后再存入Redis库中,在我们使用redisTemplate.opsForValue().get方法获取数据时,通过存入的@class属性,把JSON反序列化成JAVA对象。

这样一来我们在IDEA的控制器上很直观的就可以看到数据,但是也存在了一个缺点->浪费内存,因为我们要存放@class这一段额外的数据来反序列化JSON字符串。

为了节省内存空间,我们一般实际中并不会使用JSON序列化器(GenericJackson2JsonRedisSerializer序列化器)来处理value,而是统一使用String序列化器(RedisSerializer.string序列化器),要求只能存储String类型的key和value。我们只需要在存入数据时,手动的把JAVA对象转变为JSON格式字符串,然后取数据时,再把JSON转回JAVA对象就好了。

在这里插入图片描述Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的过程:

@SpringBootTest
class RedisStringRTDemoApplicationTests {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final ObjectMapper mapper = new ObjectMapper();

    @Test
    void testObject() throws JsonProcessingException {
        // 1.创建对象
        Student s1 = new Student("李四", '男', 22);
        // 2.手动序列化
        String json = mapper.writeValueAsString(s1);
        // 3.存储一条数据
        stringRedisTemplate.opsForValue().set("student:2", json);
        // 4.获取数据
        String jsonStudent = stringRedisTemplate.opsForValue().get("student:2");
        // 5.手动反序列化
        Student s = mapper.readValue(jsonStudent, Student.class);
        System.out.println("s:" + s);
    }
}

在这里插入图片描述在这里插入图片描述参考链接:https://blog.csdn.net/weixin_43811057/article/details/130735304

Redis的String数据结构 相关的使用方法:

1、set(K var1, V var2)

新增一个字符串类型的值var1是keyvar2是值key存在就覆盖,不存在新增

redisTemplate.opsForValue().set("BBB","你好");

2、set(K key, V value, Duration timeout)

新增一个字符串类型的值,同时设置过期时间var1是keyvar2是值key存在就覆盖,不存在新增

redisTemplate.opsForValue().set("BBB","你好", Duration.ofMinutes(1));

3、set(K var1, V var2, long var3, TimeUnit var5)

新增一个字符串类型的值,同时设置过期时间var1是key,var2是值,key存在就覆盖,不存在新增

redisTemplate.opsForValue().set("BBB","你好", 1, TimeUnit.MINUTES);

TimeUnit.DAYS //天
TimeUnit.HOURS //小时
TimeUnit.MINUTES //分钟
TimeUnit.SECONDS //秒
TimeUnit.MILLISECONDS //毫秒

4、append(K var1, String var2)

给对应的key追加value,key不存在直接新增

redisTemplate.opsForValue().append("AAA", "哈哈哈");

5、set(K key1, V v1, long v2)

将key的值从下标1往后替换为新的value,key不存在相当于新增

redisTemplate.opsForValue().set("BBB","您的",1);

6、setBit(K var1, long var2, boolean var4)

key键对应的值value对应的ascii码,在offset的位置(从左向右数)变为value

redisTemplate.opsForValue().setBit("BBB", 0, true);

7、getBit(K var1, long var2)

判断指定的位置ASCII码的bit位是否为1

redisTemplate.opsForValue().getBit("BBB", 1);

8、setIfAbsent(K var1, V var2);

如果key不存在则新增,存在则不改变已经有的值

redisTemplate.opsForValue().setIfAbsent("BBB", "好的");

9、setIfAbsent(K var1, V var2, long var3, TimeUnit var5)

如果key不存在则新增,存在则不改变已经有的值,同时设置过期时间

redisTemplate.opsForValue().setIfAbsent("AAA", "好的", 1, TimeUnit.MINUTES);

10、setIfAbsent(K key, V value, Duration timeout)

如果key不存在则新增,存在则不改变已经有的值,同时设置过期时间

redisTemplate.opsForValue().setIfAbsent("BBB", "好的", Duration.ofMinutes(1));

11、setIfPresent(K var1, V var2)

如果key存在则修改,不存在则不改变已经有的值

redisTemplate.opsForValue().setIfPresent("BBB", "好的");

12、setIfPresent(K var1, V var2, long var3, TimeUnit var5)

如果key存在则修改,不存在则不改变已经有的值,同时设置过期时间

redisTemplate.opsForValue().setIfPresent("BBB", "好的",1, TimeUnit.MINUTES);

13、setIfPresent(K key, V value, Duration timeout)

如果key存在则修改,不存在则不改变已经有的值,同时设置过期时间

redisTemplate.opsForValue().setIfPresent("BBB", "好的",Duration.ofMinutes(1));

14、getAndSet(K var1, V var2)

获取key对应的值,如果key存在则修改,不存在则新增

redisTemplate.opsForValue().getAndSet("BBB", "心情");

15、increment(K var1)

以增量的方式(默认增量为1)将long值存储在变量中(value为其他类型时报错),返回最新值

redisTemplate.opsForValue().increment("AAA");

16、increment(K var1, long var2)

以指定增量的方式将Long值存储在变量中,返回最新值

redisTemplate.opsForValue().increment("AAA",2);

17、increment(K var1, double var2)

以指定增量的方式将Double值存储在变量中,返回最新值

redisTemplate.opsForValue().increment("AAA", 3.2);

18、decrement(K var1)

以递减的方式(默认为1)将long值存储在变量中(value为其他类型时报错,Double也不行,只能为Long),返回最新值

redisTemplate.opsForValue().decrement("AAA");

19、decrement(K var1, long var2)

以指定递减量递减的方式将long值存储在变量中(value为其他类型时报错,Double也不行,只能为Long),返回最新值

redisTemplate.opsForValue().decrement("AAA",2);

20、size(K var1)

获取指定key对应值的长度

redisTemplate.opsForValue().size("BBB");

21、get(Object var1)

获取指定的key对应的值

String BBB = (String) redisTemplate.opsForValue().get("BBB");
System.out.println("BBB = " + BBB);

22、get(K var1, long var2, long var4)

获取key指定下标之间对应的值

String BBB = redisTemplate.opsForValue().get("BBB",0,1);
System.out.println("BBB = " + BBB);

23、multiSet(Map<? extends K, ? extends V> var1)

将map中的key分别作为不同的key存到Redis中(见截图)
在这里插入图片描述

若某个key已经存在则替换为新值,其他不存在的则新增
map中5个key,3个存在Redis中,2个没有,结果就是3个值被修改,2个新增

Map valueMap = new HashMap();
valueMap.put("valueMap1","aa");
valueMap.put("valueMap2","bb");
valueMap.put("valueMap3","cc");
valueMap.put("valueMap4","ee");
redisTemplate.opsForValue().multiSet(valueMap);

24、multiSetIfAbsent(Map<? extends K, ? extends V> var1)

将map中的key分别作为不同的key存到Redis中

若某个key已经存在不做修改,不存在的则新增(map中的key在Redis中都不存在时才新增)

map中5个key,3个存在Redis中,2个没有,结果就是不会新增不会修改,若map中5个key,5个都不存在Redis中,则新增

Map valueMap = new HashMap();
valueMap.put("valueMap1","aa");
valueMap.put("valueMap2","bb");
valueMap.put("valueMap3","cc");
valueMap.put("valueMap4","ee");
valueMap.put("valueMap5","ff");
redisTemplate.opsForValue().multiSetIfAbsent(valueMap);

25、multiGet(Collection var1)

根据集合中的key取出对应的value值

List paraList = new ArrayList();
paraList.add("valueMap1");
paraList.add("valueMap2");
paraList.add("valueMap3");
List list = redisTemplate.opsForValue().multiGet(paraList);

26、存入JSON字符串(对象集合)

对象和对象集合一定要转成JSON存放,容易解析

List<MPEntity> list = mpService.list();
redisTemplate.opsForValue().set("BBB", JSON.toJSONString(list));

在这里插入图片描述

获取解析JSON字符串

String bbb = (String) redisTemplate.opsForValue().get("BBB");
List<MPEntity> mpEntities = JSON.parseArray(bbb, MPEntity.class);
System.out.println("mpEntities = " + mpEntities);

在这里插入图片描述

参考链接:https://blog.csdn.net/qq_37131747/article/details/125673505

27、type:返回传入key所存储的值的类型

redisTemplate.opsForValue().type(key);

28、rename:修改redis中key的名称

 public void renameKey(String oldKey, String newKey) {
    redisTemplate.opsForValue().rename(oldKey, newKey);
}

29、renameIfAbsent:如果旧值key存在时,将旧值改为新值

public Boolean renameOldKeyIfAbsent(String oldKey, String newKey) {
    return redisTemplate.opsForValue().renameIfAbsent(oldKey, newKey);
}

30、hasKey:判断是否有key所对应的值,有则返回true,没有则返回false

redisTemplate.hasKey(key)

31、delete:删除单个key值

redisTemplate.delete(key)

批量删除key:
redisTemplate.delete(keys) //其中keys:Collection<K> keys

32、expire:设置过期时间

public Boolean expire(String key, long timeout, TimeUnit unit) {
    return redisTemplate.expire(key, timeout, unit);
 }
 public Boolean expireAt(String key, Date date) {
    return redisTemplate.expireAt(key, date);
  }

33、getExpire:返回当前key所对应的剩余过期时间

redisTemplate.getExpire(key);


//返回剩余过期时间并且指定时间单位  
public Long getExpire(String key, TimeUnit unit) {
    return redisTemplate.getExpire(key, unit);
}

34、getPatternKey:查找匹配的key值,返回一个Set集合类型

public Set<String> getPatternKey(String pattern) {
    return redisTemplate.keys(pattern);
}

35、persistKey:将key持久化保存

public Boolean persistKey(String key) {
    return redisTemplate.persist(key);
}

36、moveToDbIndex:将当前数据库的key移动到指定redis中数据库当中

public Boolean moveToDbIndex(String key, int dbIndex) {
    return redisTemplate.move(key, dbIndex);
}

Redis的Hash类型 相关的使用方法:

Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
Redis 中每个 hash 可以存储 2^32 - 1 键值对(40多亿)。

1、get:获取变量中的指定map键是否有值,如果存在该map键则获取值,没有则返回null

redisTemplate.opsForHash().get(key, field)

2、entries:获取变量中的键值对

public Map<Object, Object> hGetAll(String key) {
    return redisTemplate.opsForHash().entries(key);
}

3、put:新增hashMap值

redisTemplate.opsForHash().put(key, hashKey, value)

4、以map集合的形式添加键值对

public void hPutAll(String key, Map<String, String> maps) {
    redisTemplate.opsForHash().putAll(key, maps);
}

5、putIfAbsent:仅当hashKey不存在时才设置

public Boolean hashPutIfAbsent(String key, String hashKey, String value) {
    return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
}

6、delete:删除一个或者多个hash表字段

public Long hashDelete(String key, Object... fields) {
    return redisTemplate.opsForHash().delete(key, fields);
}

7、hasKey:查看hash表中指定字段是否存在

public boolean hashExists(String key, String field) {
    return redisTemplate.opsForHash().hasKey(key, field);
}

8、increment:给哈希表key中的指定字段的整数值加上增量

public Long hashIncrBy(String key, Object field, long increment) {
    return redisTemplate.opsForHash().increment(key, field, increment);
}
 public Double hIncrByDouble(String key, Object field, double delta) {
    return redisTemplate.opsForHash().increment(key, field, delta);
}

9、keys:获取所有hash表中字段

redisTemplate.opsForHash().keys(key)

10、opsForHash().values:获取hash表中存在的所有的值

public List<Object> hValues(String key) {
    return redisTemplate.opsForHash().values(key);
}

11、size:获取hash表中字段的数量

redisTemplate.opsForHash().size(key)

12、opsForHash().scan:匹配获取键值对,ScanOptions.NONE为获取全部键对

public Cursor<Entry<Object, Object>> hashScan(String key, ScanOptions options) {
    return redisTemplate.opsForHash().scan(key, options);
}

Redis的List类型 相关的使用方法:

1、index:通过索引获取列表中的元素

redisTemplate.opsForList().index(key, index)

2、range:获取列表指定范围内的元素(start开始位置, 0是开始位置,end 结束位置, -1返回所有)

redisTemplate.opsForList().range(key, start, end)

3、leftPush:存储在list的头部,即添加一个就把它放在最前面的索引处

redisTemplate.opsForList().leftPush(key, value)

4、leftPushAll:把多个值存入List中(value可以是多个值,也可以是一个Collection value)

redisTemplate.opsForList().leftPushAll(key, value)

5、leftPushIfPresent:List存在的时候再加入

redisTemplate.opsForList().leftPushIfPresent(key, value)

6、rightPush:按照先进先出的顺序来添加(value可以是多个值,或者是Collection var2)

redisTemplate.opsForList().rightPush(key, value)
redisTemplate.opsForList().rightPushAll(key, value)

7、set:设置指定索引处元素的值

redisTemplate.opsForList().set(key, index, value)

8、leftPop:移除并获取列表中第一个元素(如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止)

redisTemplate.opsForList().leftPop(key)
redisTemplate.opsForList().leftPop(key, timeout, unit)

9、rightPop:移除并获取列表最后一个元素

redisTemplate.opsForList().rightPop(key)
redisTemplate.opsForList().rightPop(key, timeout, unit)

10、rightPopAndLeftPush:从一个队列的右边弹出一个元素并将这个元素放入另一个指定队列的最左边

redisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey)
redisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey, timeout, unit)

11、删除集合中值等于value的元素

(index=0, 删除所有值等于value的元素; index>0, 从头部开始删除第一个值等于value的元素; index<0, 从尾部开始删除第一个值等于value的元素)

redisTemplate.opsForList().remove(key, index, value)

12、trim:将List列表进行剪裁

redisTemplate.opsForList().trim(key, start, end)

13、获取当前key的List列表长度

redisTemplate.opsForList().size(key)

Redis的Set类型 相关的使用方法:

1、add:添加元素

redisTemplate.opsForSet().add(key, values)

2、remove:移除元素(单个值、多个值)

redisTemplate.opsForSet().remove(key, values)

3、size:获取集合的大小

redisTemplate.opsForSet().size(key)

4、isMember:判断集合是否包含value

redisTemplate.opsForSet().isMember(key, value)

5、intersect:获取两个集合的交集

(key对应的无序集合与otherKey对应的无序集合求交集)

redisTemplate.opsForSet().intersect(key, otherKey)

//获取多个集合的交集(Collection var2)
redisTemplate.opsForSet().intersect(key, otherKeys)      

6、intersectAndStore:集合与otherKey集合的交集存储到destKey集合中(其中otherKey可以为单个值或者集合)

redisTemplate.opsForSet().intersectAndStore(key, otherKey, destKey)

//key集合与多个集合的交集存储到destKey无序集合中
redisTemplate.opsForSet().intersectAndStore(key, otherKeys, destKey)

7、获取两个或者多个集合的并集(otherKeys可以为单个值或者是集合)

redisTemplate.opsForSet().union(key, otherKeys)

8、unionAndStore:key集合与otherKey集合的并集存储到destKey中(otherKeys可以为单个值或者是集合)

redisTemplate.opsForSet().unionAndStore(key, otherKey, destKey)

9、difference:获取两个或者多个集合的差集(otherKeys可以为单个值或者是集合)

redisTemplate.opsForSet().difference(key, otherKeys)

10、differenceAndStore:差集存储到destKey中(otherKeys可以为单个值或者集合)

redisTemplate.opsForSet().differenceAndStore(key, otherKey, destKey)

11、members:获取集合中的所有元素

redisTemplate.opsForSet().members(key)

12、randomMembers:随机获取集合中count个元素

redisTemplate.opsForSet().randomMembers(key, count)

//随机获取集合中的一个元素
redisTemplate.opsForSet().randomMember(key)

13、scan:遍历set类似于Interator(ScanOptions.NONE为显示所有的)

redisTemplate.opsForSet().scan(key, options)

Redis的zSet类型 相关的使用方法:

ZSetOperations提供了一系列方法对有序集合进行操作

1、add:添加元素(有序集合是按照元素的score值由小到大进行排列)

redisTemplate.opsForZSet().add(key, value, score)

2、remove:删除对应的value,value可以为多个值

redisTemplate.opsForZSet().remove(key, values)

3、incrementScore:增加元素的score值,并返回增加后的值

redisTemplate.opsForZSet().incrementScore(key, value, delta)

4、rank:返回元素在集合的排名,有序集合是按照元素的score值由小到大排列

redisTemplate.opsForZSet().rank(key, value)

5、reverseRank:返回元素在集合的排名,按元素的score值由大到小排列

redisTemplate.opsForZSet().reverseRank(key, value)

6、reverseRangeWithScores:获取集合中给定区间的元素(start 开始位置,end 结束位置, -1查询所有)

redisTemplate.opsForZSet().reverseRangeWithScores(key, start,end)

7、reverseRangeByScore:按照Score值查询集合中的元素,结果从小到大排序

redisTemplate.opsForZSet().reverseRangeByScore(key, min, max)

//从高到低的排序集中获取分数在最小和最大值之间的元素
redisTemplate.opsForZSet().reverseRangeByScore(key, min, max, start, end)

8、count:根据score值获取集合元素数量

redisTemplate.opsForZSet().count(key, min, max)

9、size:获取集合的大小

redisTemplate.opsForZSet().size(key)

10、score:获取集合中key、value元素对应的score值

redisTemplate.opsForZSet().score(key, value)

11、removeRange:移除指定索引位置处的成员

redisTemplate.opsForZSet().removeRange(key, start, end)

12、removeRangeByScore:移除指定score范围的集合成员

redisTemplate.opsForZSet().removeRangeByScore(key, min, max)

13、unionAndStore:获取key和otherKey的并集并存储在destKey中(其中otherKeys可以为单个字符串或者字符串集合

redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey)

14、intersectAndStore:获取key和otherKey的交集并存储在destKey中(其中otherKeys可以为单个字符串或者字符串集合)

redisTemplate.opsForZSet().intersectAndStore(key, otherKey, destKey)

15、遍历集合(和iterator一模一样)

Cursor<TypedTuple<Object>> scan = opsForZSet.scan("test3", ScanOptions.NONE);
while (scan.hasNext()){
ZSetOperations.TypedTuple<Object> item = scan.next();
System.out.println(item.getValue() + ":" + item.getScore());
}

参考链接:https://blog.csdn.net/lanfeng_lan/article/details/121152461

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++学习之路(十四)C++ 用Qt5实现一个工具箱(增加一个Base64图片编码预览功能)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《Base64加解密功能》功能。为了继续丰富我们的工具箱&#xff0c;今天我们就再增加一个平时经常用到的功能吧&#xff0c;就是「 Base64图片编码预览 」功能。下面我们就来看看如何来规划开发一个这样的小功能并且添加…

Redis的高可用模式

1. 什么是高可用&#xff1f; 高可用&#xff08;High Availability, HA&#xff09;是指在信息技术中确保系统、服务或应用程序在绝大多数时间内都是可操作和可访问的能力。这通常涉及以下几个关键方面&#xff1a; 最小化停机时间: 高可用系统的目标是减少因硬件故障、系统升…

无mac电脑生成uniapp云打包私钥证书的攻略

uniapp顾名思义是一个跨平台的开发工具&#xff0c;大部分uniapp的开发者&#xff0c;其实并没有mac电脑来开发&#xff0c;但是生成ios的证书&#xff0c;官网的教程却是需要mac电脑的&#xff0c;那么有没有办法无需mac电脑即可生成uniapp云打包的私钥证书呢&#xff1f; 下…

小白都能看懂的手把手详细Git安装教程

什么是Git Git是一个源代码管理系统&#xff0c;旨在帮助开发人员协同工作。它是一个分布式的版本控制系统&#xff0c;可以有效地将代码库分支、合并和版本控制&#xff0c;同时还可以跟踪文件的更改、修改内容并保留历史记录。Git能够让多个开发人员同时对同一代码库进行协作…

Linux基础篇-开机自动挂载

目录 开机挂载的几种方法/etc/fstab/etc/rc.local或/etc/rc.d/rc.local 开机挂载的几种方法 修改配置文件/etc/fstab &#xff08;如果是磁盘信息输错&#xff0c;那么系统重启时会进入维护模式&#xff0c;影响操作系统的正常运行.&#xff09; 在/etc/rc.local内添加挂载命令…

基于ASP.NET MVC技术的图书管理系统的设计与实现

基于ASP.NET MVC技术的图书管理系统的设计与实现 摘要&#xff1a;图书管理系统是一套高新科学技术和图书知识信息以及传统历史文化完美结合的体现。它改变了传统图书收藏的静态书本式图书服务特征&#xff0c;实现了多媒体存取、远程网络传输、智能化检索、跨库无缝链接、创造…

WebSocket入门介绍及编程实战

HTTP的限制 全双工和半双工&#xff1a; 全双工&#xff1a;全双工&#xff08;Full Duplex&#xff09;是允许数据在两个方向上同时传输。 半双工&#xff1a;半双工&#xff08;Half Duplex&#xff09;是允许数据在两个方向上传输&#xff0c;但是同一个时间段内只允许一个…

三维模型的顶层合并构建的轻量化技术方法探讨

三维模型的顶层合并构建的轻量化技术方法探讨 倾斜摄影超大场景的三维模型的顶层合并构建通常会生成庞大的数据量&#xff0c;给存储、传输和处理带来很大的挑战。为了解决这个问题&#xff0c;可以采用轻量化处理技术&#xff0c;以减小数据体积、提高处理效率&#xff0c;并方…

GAN:WGAN-GP-带有梯度惩罚的WGAN

论文&#xff1a;https://arxiv.org/pdf/1704.00028.pdf 代码&#xff1a;GitHub - igul222/improved_wgan_training: Code for reproducing experiments in "Improved Training of Wasserstein GANs" 发表&#xff1a;2017 WGAN三部曲的终章-WGAN-GP 摘要 WGAN在…

APITable免费开源的多维表格与可视化数据库本地部署公网远程访问

APITable免费开源的多维表格与可视化数据库公网远程访问 文章目录 APITable免费开源的多维表格与可视化数据库公网远程访问前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台&#xff0c…

QQ小程序分销商城源码系统 带完整的搭建教程

互联网的快速发展&#xff0c;电商行业也迅速崛起&#xff0c;如今线上购物已经成为许多人日常生活的一部分。然而&#xff0c;随着竞争的加剧&#xff0c;电商企业需要不断创新和优化&#xff0c;以吸引更多的消费者和提高销售额。在这个背景下&#xff0c;我们开发了QQ小程序…

JavaEE——简单认识CSS

文章目录 一、简单了解什么是 CSS二、CSS 选择器1.标签选择器2.类选择器3.ID 选择器4.后代选择器5.子选择器6.伪类选择器 三、字体属性1.设置字体家族2.设置字体大小3.设置字体粗细4.文字倾斜 四、文本属性1.文本对齐2.文本装饰3.文本缩进4.背景设置 五、圆角矩形六、CSS 盒子模…

将不同时间点的登录状态记录转化为不同时间段的相同登录状态SQL求解

题目 有不同时间点的登录状态记录表state_log如下 请使用sql将其转化为如下表的不同时间段的相同登录状态记录 思路分析&#xff1a; 此类问题需要用到lag或lead函数取上下行对应的数据&#xff0c;然后对前后结果做比较打标签&#xff08;0或1&#xff09;&#xff0c;再…

List集合,遍历,数据结构

一.List常见的方法&#xff1a; 二. List集合的遍历方式 除了 迭代器遍历 增强for遍历 Lambda表达式遍历&#xff0c;还有自己独有的普通for遍历&#xff0c;列表迭代器遍历 1.迭代器遍历 2.增强for遍历 3.Lambda表达式遍历 4.普通for遍历 5.列表迭代器遍历 列表迭代器相对于…

【网络安全】用永恒之蓝(Eternal blue)测试windows系统的安全性

一、kali默认账户和密码都为kali 攻击机&#xff1a;Linux 的 kali 目标机&#xff1a;Windows7 x64 二、kali、metasploit、metasploit 攻击 windows操作系统、metasploit 攻击 永恒之蓝 全流程 ①kali&#xff1a;是黑客攻击机。开源免费的Linux操作系统&#xff0c;含有300…

Linux Ubuntu protobuf 安装方法

文章目录 安装方法检验安装意外状况 安装方法 去GitHub官网找下载地址 安装 protobuf 21.11 GitHub 资源地址 选择安装版本 &#xff08;是一个URL网址&#xff09; 例如这里选用&#xff1a;protobuf-all-21.11.zip 资源 安装依赖库&#xff0c;执行指令 6. sudo apt-get …

class-dump 混淆加固、保护与优化原理

​ 进行逆向时&#xff0c;经常需要dump可执行文件的头文件&#xff0c;用以确定类信息和方法信息&#xff0c;为hook相关方法提供更加详细的数据.class-dump的主要用于检查存储在Mach O文件的Objective-C中的运行时信息&#xff0c;为类&#xff0c;类别和协议生成声明信息&am…

Redis7--基础篇5(管道、发布订阅)

管道是什么 管道(pipeline)可以一次性发送多条命令给服务端&#xff0c;服务端依次处理完完毕后&#xff0c;通过一条响应一次性将结果返回&#xff0c;通过减少客户端与redis的通信次数来实现降低往返延时时间。pipeline实现的原理是队列&#xff0c;先进先出特性就保证数据的…

10-微信小程序 图片 相机 二维码 动画相关API(实现选择相册、拍照、录像、动画)

10-微信小程序 图片 相机 二维码 动画相关API(实现选择相册、拍照、录像、动画) 文章目录 10.1选择图片wx.chooseImage(Object object)object.success 回调函数代码效果 10.2 预览图片wx.previewImage(Object object)代码效果 10.3 相机APICameraContext wx.createCameraContex…

科技平权,哪吒汽车又双叒OTA了

OTA升级“学霸”再有新动作。11月30日&#xff0c;平均一、两个月就会OTA升级一次的哪吒汽车再度“进化”&#xff0c;同时启动哪吒S和哪吒GT的新一轮OTA升级。此轮OTA升级&#xff0c;哪吒汽车不但将百万豪车才有的赛道级技术&#xff0c;价值数万元的哪吒卫士、一键遥控泊车功…