SpringBoot整合Redis,redis连接池和RedisTemplate序列化

SpringBoot整合Redis

  • 1、SpringBoot整合redis
    • 1.1 pom.xml
    • 1.2 application.yml
    • 1.3 配置类RedisConfig,实现RedisTemplate序列化
    • 1.4 代码测试
  • 2、SpringBoot整合redis几个疑问?
    • 2.1、Redis 连接池讲解
    • 2.2、RedisTemplate和StringRedisTemplate
  • 3、RedisTemplate实现redis客户端工具类

1、SpringBoot整合redis

1.1 pom.xml

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--redis相关依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency></dependencies>

1.2 application.yml

server:port: 8080spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rooturl: jdbc:mysql://127.0.0.1:3306/alarm?useUnicode=true&autoReconnect=true&failOverReadOnly=false&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=CONVERT_TO_NULLredis:host: 127.0.0.1port: 6379password:database: 0timeout: 1000mslettuce:pool:max-active: 8 # 连接池最大连接数max-idle: 8 # 连接池最大空闲连接数min-idle: 0 # 连接池最小空闲连接数max-wait: -1ms # 连接池最大阻塞等待时间,负值表示没有限制mybatis:type-aliases-package: cn.yx.zg.pojomapperLocations: classpath:mappers/*.xml

1.3 配置类RedisConfig,实现RedisTemplate序列化

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/*** redisConfig** @author zhanggang* @since 2023/11/18 19:15*/
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();RedisSerializer<String> redisSerializer = new StringRedisSerializer();Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper ();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);template.setConnectionFactory(factory);//key序列化方式template.setKeySerializer(redisSerializer);//value序列化template.setValueSerializer(jackson2JsonRedisSerializer);//key hashmap序列化template.setHashKeySerializer (redisSerializer);//value hashmap序列化template.setHashValueSerializer(jackson2JsonRedisSerializer);return template;}
}

1.4 代码测试

经过上面三个步骤的配置,已经把Redis和SpringBoot整合好了,使用下面代码,既可以操作Redis了。
import cn.yx.zg.SpringBootMybatisApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;/*** @author zhanggang* @since 2023/11/21 10:29*/
@SpringBootTest(classes = SpringBootMybatisApplication.class)
@RunWith(SpringRunner.class)
public class RedisTest {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void testRedis01() {redisTemplate.opsForValue().set("name", "zg");}
}

2、SpringBoot整合redis几个疑问?

2.1、Redis 连接池讲解

Redis 的客户端,常用的有两种:Jedis 和 Lettuce。

Spring Boot 1.5.x 版本,默认的 Redis 客户端,实现上是直接连接 Redis Server,如果在多线程环境下是非线程安全的,这时候要使用连接池为每个 jedis 实例增加物理连接;
Lettuce:Spring Boot 2.x 版本后默认的 Redis 客户端,基于 Netty 实现,连接实例可以在多个线程间并发访问,一个连接实例不够的情况下也可以按需要增加连接实例。

上面代码是实现了Lettuce连接池,直接哪来用就行。
如下图,通过debug可以看出是使用了Lettuce连接池。

在这里插入图片描述

2.2、RedisTemplate和StringRedisTemplate

RedisTemplate实际就是类似java的jdbc,封装了对redis操作的一些方法。

在1.3 新建配置类RedisConfig中,我们给RedisTemplate进行了序列化,为什么要序列化呢?如果不序列化,我们通过RedisTemplate存到redis的数据,都是是二进制存储的。你只用把我那个配置直接哪来用就可以了。

StringRedisTemplate一般只用来存储key和value都是String类型,当存入对象时,会报错 :can not cast into String。
RedisTemplate则是既可以存字符串又可以存对象,一般我们都使用RedisTemplate就够用了。

3、RedisTemplate实现redis客户端工具类

新建工具类RedisUtil
import com.hspedu.spring.annotation.Autowired;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** @author zhanggang* @since 2023/11/22 16:33*/
@Component
public class RedisUtil {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;// =============================common============================/*** 指定缓存失效时间** @param key  键* @param time 时间(秒)* @return*/public boolean expire(String key, long time) {try {if (time > 0) {redisTemplate.expire(key, time, TimeUnit.SECONDS);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根据key 获取过期时间** @param key 键 不能为null* @return 时间(秒) 返回0代表为永久有效*/public long getExpire(String key) {return redisTemplate.getExpire(key, TimeUnit.SECONDS);}/*** 判断key是否存在** @param key 键* @return true 存在 false不存在*/public boolean hasKey(String key) {try {return redisTemplate.hasKey(key);} catch (Exception e) {e.printStackTrace();return false;}}/*** 删除缓存** @param key 可以传一个值 或多个*/@SuppressWarnings("unchecked")public void del(String... key) {if (key != null && key.length > 0) {if (key.length == 1) {redisTemplate.delete(key[0]);} else {redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));}}}// ============================= key相关操作 =============================/*** 可以实现分布式锁** @param key* @param value* @return key存在则返回false,不存在则存储key-value并返回true*/public boolean setnx(String key, String value) {return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, value));}/*** 可以实现分布式锁** @param key* @param value* @param timeout* @param unit* @return key存在则返回false,不存在则存储key-value并返回true*/public boolean setnx(String key, String value, long timeout, TimeUnit unit) {return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, value, timeout, unit));}/*** 删除key** @param key*/public void delete(String key) {redisTemplate.delete(key);}/*** 批量删除key** @param keys*/public void delete(Collection<String> keys) {redisTemplate.delete(keys);}/*** 序列化key** @param key* @return*/public byte[] dump(String key) {return redisTemplate.dump(key);}/*** 设置过期时间** @param key* @param timeout* @param unit* @return*/public Boolean expire(String key, long timeout, TimeUnit unit) {return redisTemplate.expire(key, timeout, unit);}/*** 设置过期时间** @param key* @param date* @return*/public Boolean expireAt(String key, Date date) {return redisTemplate.expireAt(key, date);}/*** 查找匹配的key** @param pattern* @return*/public Set<String> keys(String pattern) {return redisTemplate.keys(pattern);}/*** 将当前数据库的 key 移动到给定的数据库 db 当中** @param key* @param dbIndex* @return*/public Boolean move(String key, int dbIndex) {return redisTemplate.move(key, dbIndex);}/*** 移除 key 的过期时间,key 将持久保持** @param key* @return*/public Boolean persist(String key) {return redisTemplate.persist(key);}/*** 返回 key 的剩余的过期时间** @param key* @param unit* @return*/public Long getExpire(String key, TimeUnit unit) {return redisTemplate.getExpire(key, unit);}/*** 从当前数据库中随机返回一个 key** @return*/public String randomKey() {return redisTemplate.randomKey();}/*** 修改 key 的名称** @param oldKey* @param newKey*/public void rename(String oldKey, String newKey) {redisTemplate.rename(oldKey, newKey);}/*** 仅当 newkey 不存在时,将 oldKey 改名为 newkey** @param oldKey* @param newKey* @return*/public Boolean renameIfAbsent(String oldKey, String newKey) {return redisTemplate.renameIfAbsent(oldKey, newKey);}/*** 返回 key 所储存的值的类型** @param key* @return*/public DataType type(String key) {return redisTemplate.type(key);}// ============================String=============================/*** 普通缓存获取** @param key 键* @return 值*/public Object get(String key) {return key == null ? null : redisTemplate.opsForValue().get(key);}/*** 普通缓存放入** @param key   键* @param value 值* @return true成功 false失败*/public boolean set(String key, Object value) {try {redisTemplate.opsForValue().set(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 普通缓存放入并设置时间** @param key   键* @param value 值* @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期* @return true成功 false 失败*/public boolean set(String key, Object value, long time) {try {if (time > 0) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);} else {set(key, value);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 递增** @param key   键* @param delta 要增加几(大于0)* @return*/public long incr(String key, long delta) {if (delta < 0) {throw new RuntimeException("递增因子必须大于0");}return redisTemplate.opsForValue().increment(key, delta);}/*** 递减** @param key   键* @param delta 要减少几(小于0)* @return*/public long decr(String key, long delta) {if (delta < 0) {throw new RuntimeException("递减因子必须大于0");}return redisTemplate.opsForValue().increment(key, -delta);}// ================================Map=================================/*** HashGet** @param key  键 不能为null* @param item 项 不能为null* @return 值*/public Object hget(String key, String item) {return redisTemplate.opsForHash().get(key, item);}/*** 获取hashKey对应的所有键值** @param key 键* @return 对应的多个键值*/public Map<Object, Object> hmget(String key) {return redisTemplate.opsForHash().entries(key);}/*** HashSet** @param key 键* @param map 对应多个键值* @return true 成功 false 失败*/public boolean hmset(String key, Map<String, Object> map) {try {redisTemplate.opsForHash().putAll(key, map);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** HashSet 并设置时间** @param key  键* @param map  对应多个键值* @param time 时间(秒)* @return true成功 false失败*/public boolean hmset(String key, Map<String, Object> map, long time) {try {redisTemplate.opsForHash().putAll(key, map);if (time > 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 向一张hash表中放入数据,如果不存在将创建** @param key   键* @param item  项* @param value 值* @return true 成功 false失败*/public boolean hset(String key, String item, Object value) {try {redisTemplate.opsForHash().put(key, item, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 向一张hash表中放入数据,如果不存在将创建** @param key   键* @param item  项* @param value 值* @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间* @return true 成功 false失败*/public boolean hset(String key, String item, Object value, long time) {try {redisTemplate.opsForHash().put(key, item, value);if (time > 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 删除hash表中的值** @param key  键 不能为null* @param item 项 可以使多个 不能为null*/public void hdel(String key, Object... item) {redisTemplate.opsForHash().delete(key, item);}/*** 判断hash表中是否有该项的值** @param key  键 不能为null* @param item 项 不能为null* @return true 存在 false不存在*/public boolean hHasKey(String key, String item) {return redisTemplate.opsForHash().hasKey(key, item);}/*** hash递增 如果不存在,就会创建一个 并把新增后的值返回** @param key  键* @param item 项* @param by   要增加几(大于0)* @return*/public double hincr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, by);}/*** hash递减** @param key  键* @param item 项* @param by   要减少记(小于0)* @return*/public double hdecr(String key, String item, double by) {return redisTemplate.opsForHash().increment(key, item, -by);}// ============================set=============================/*** 根据key获取Set中的所有值** @param key 键* @return*/public Set<Object> sGet(String key) {try {return redisTemplate.opsForSet().members(key);} catch (Exception e) {e.printStackTrace();return null;}}/*** 根据value从一个set中查询,是否存在** @param key   键* @param value 值* @return true 存在 false不存在*/public boolean sHasKey(String key, Object value) {try {return redisTemplate.opsForSet().isMember(key, value);} catch (Exception e) {e.printStackTrace();return false;}}/*** 将数据放入set缓存** @param key    键* @param values 值 可以是多个* @return 成功个数*/public long sSet(String key, Object... values) {try {return redisTemplate.opsForSet().add(key, values);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 将set数据放入缓存** @param key    键* @param time   时间(秒)* @param values 值 可以是多个* @return 成功个数*/public long sSetAndTime(String key, long time, Object... values) {try {Long count = redisTemplate.opsForSet().add(key, values);if (time > 0)expire(key, time);return count;} catch (Exception e) {e.printStackTrace();return 0;}}/*** 获取set缓存的长度** @param key 键* @return*/public long sGetSetSize(String key) {try {return redisTemplate.opsForSet().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 移除值为value的** @param key    键* @param values 值 可以是多个* @return 移除的个数*/public long setRemove(String key, Object... values) {try {Long count = redisTemplate.opsForSet().remove(key, values);return count;} catch (Exception e) {e.printStackTrace();return 0;}}// ===============================list=================================/*** 获取list缓存的内容** @param key   键* @param start 开始* @param end   结束 0 到 -1代表所有值* @return*/public List<Object> lGet(String key, long start, long end) {try {return redisTemplate.opsForList().range(key, start, end);} catch (Exception e) {e.printStackTrace();return null;}}/*** 获取list缓存的长度** @param key 键* @return*/public long lGetListSize(String key) {try {return redisTemplate.opsForList().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 通过索引 获取list中的值** @param key   键* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推* @return*/public Object lGetIndex(String key, long index) {try {return redisTemplate.opsForList().index(key, index);} catch (Exception e) {e.printStackTrace();return null;}}/*** 将list放入缓存** @param key   键* @param value 值* @return*/public boolean lSet(String key, Object value) {try {redisTemplate.opsForList().rightPush(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存** @param key   键* @param value 值* @param time  时间(秒)* @return*/public boolean lSet(String key, Object value, long time) {try {redisTemplate.opsForList().rightPush(key, value);if (time > 0)expire(key, time);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存** @param key   键* @param value 值* @return*/public boolean lSet(String key, List<Object> value) {try {redisTemplate.opsForList().rightPushAll(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存** @param key   键* @param value 值* @param time  时间(秒)* @return*/public boolean lSet(String key, List<Object> value, long time) {try {redisTemplate.opsForList().rightPushAll(key, value);if (time > 0)expire(key, time);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根据索引修改list中的某条数据** @param key   键* @param index 索引* @param value 值* @return*/public boolean lUpdateIndex(String key, long index, Object value) {try {redisTemplate.opsForList().set(key, index, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 移除N个值为value** @param key   键* @param count 移除多少个* @param value 值* @return 移除的个数*/public long lRemove(String key, long count, Object value) {try {Long remove = redisTemplate.opsForList().remove(key, count, value);return remove;} catch (Exception e) {e.printStackTrace();return 0;}}// ============================= zSet相关操作 =============================/*** 添加元素,有序集合是按照元素的score值由小到大排列** @param key* @param value* @param score* @return*/public Boolean zAdd(String key, String value, double score) {return redisTemplate.opsForZSet().add(key, value, score);}/*** @param key* @param values* @return*/public Long zAdd(String key, Set<ZSetOperations.TypedTuple<Object>> values) {return redisTemplate.opsForZSet().add(key, values);}/*** @param key* @param values* @return*/public Long zRemove(String key, Object... values) {return redisTemplate.opsForZSet().remove(key, values);}/*** 增加元素的score值,并返回增加后的值** @param key* @param value* @param delta* @return*/public Double zIncrementScore(String key, String value, double delta) {return redisTemplate.opsForZSet().incrementScore(key, value, delta);}/*** 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列** @param key* @param value* @return 0表示第一位*/public Long zRank(String key, Object value) {return redisTemplate.opsForZSet().rank(key, value);}/*** 返回元素在集合的排名,按元素的score值由大到小排列** @param key* @param value* @return*/public Long zReverseRank(String key, Object value) {return redisTemplate.opsForZSet().reverseRank(key, value);}/*** 获取集合的元素, 从小到大排序** @param key* @param start 开始位置* @param end   结束位置, -1查询所有* @return*/public Set<Object> zRange(String key, long start, long end) {return redisTemplate.opsForZSet().range(key, start, end);}/*** 获取集合元素, 并且把score值也获取** @param key* @param start* @param end* @return*/public Set<ZSetOperations.TypedTuple<Object>> zRangeWithScores(String key, long start, long end) {return redisTemplate.opsForZSet().rangeWithScores(key, start, end);}/*** 根据Score值查询集合元素** @param key* @param min 最小值* @param max 最大值* @return*/public Set<Object> zRangeByScore(String key, double min, double max) {return redisTemplate.opsForZSet().rangeByScore(key, min, max);}/*** 根据Score值查询集合元素, 从小到大排序** @param key* @param min 最小值* @param max 最大值* @return*/public Set<ZSetOperations.TypedTuple<Object>> zRangeByScoreWithScores(String key, double min, double max) {return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);}/*** @param key* @param min* @param max* @param start* @param end* @return*/public Set<ZSetOperations.TypedTuple<Object>> zRangeByScoreWithScores(String key, double min, double max, long start, long end) {return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max, start, end);}/*** 获取集合的元素, 从大到小排序** @param key* @param start* @param end* @return*/public Set<Object> zReverseRange(String key, long start, long end) {return redisTemplate.opsForZSet().reverseRange(key, start, end);}/*** 获取集合的元素, 从大到小排序, 并返回score值** @param key* @param start* @param end* @return*/public Set<ZSetOperations.TypedTuple<Object>> zReverseRangeWithScores(String key, long start, long end) {return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);}/*** 根据Score值查询集合元素, 从大到小排序** @param key* @param min* @param max* @return*/public Set<Object> zReverseRangeByScore(String key, double min, double max) {return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);}/*** 根据Score值查询集合元素, 从大到小排序** @param key* @param min* @param max* @return*/public Set<ZSetOperations.TypedTuple<Object>> zReverseRangeByScoreWithScores(String key, double min, double max) {return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, min, max);}/*** @param key* @param min* @param max* @param start* @param end* @return*/public Set<Object> zReverseRangeByScore(String key, double min, double max, long start, long end) {return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max, start, end);}/*** 根据score值获取集合元素数量** @param key* @param min* @param max* @return*/public Long zCount(String key, double min, double max) {return redisTemplate.opsForZSet().count(key, min, max);}/*** 获取集合大小** @param key* @return*/public Long zSize(String key) {return redisTemplate.opsForZSet().size(key);}/*** 获取集合大小** @param key* @return*/public Long zZCard(String key) {return redisTemplate.opsForZSet().zCard(key);}/*** 获取集合中value元素的score值** @param key* @param value* @return*/public Double zScore(String key, Object value) {return redisTemplate.opsForZSet().score(key, value);}/*** 移除指定索引位置的成员** @param key* @param start* @param end* @return*/public Long zRemoveRange(String key, long start, long end) {return redisTemplate.opsForZSet().removeRange(key, start, end);}/*** 根据指定的score值的范围来移除成员** @param key* @param min* @param max* @return*/public Long zRemoveRangeByScore(String key, double min, double max) {return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);}/*** 获取key和otherKey的并集并存储在destKey中** @param key* @param otherKey* @param destKey* @return*/public Long zUnionAndStore(String key, String otherKey, String destKey) {return redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey);}/*** @param key* @param otherKeys* @param destKey* @return*/public Long zUnionAndStore(String key, Collection<String> otherKeys, String destKey) {return redisTemplate.opsForZSet().unionAndStore(key, otherKeys, destKey);}/*** 交集** @param key* @param otherKey* @param destKey* @return*/public Long zIntersectAndStore(String key, String otherKey, String destKey) {return redisTemplate.opsForZSet().intersectAndStore(key, otherKey, destKey);}/*** 交集** @param key* @param otherKeys* @param destKey* @return*/public Long zIntersectAndStore(String key, Collection<String> otherKeys, String destKey) {return redisTemplate.opsForZSet().intersectAndStore(key, otherKeys, destKey);}/*** @param key* @param options* @return*/public Cursor<ZSetOperations.TypedTuple<Object>> zScan(String key, ScanOptions options) {return redisTemplate.opsForZSet().scan(key, options);}

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

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

相关文章

python -opencv 中值滤波 ,均值滤波,高斯滤波实战

python -opencv 中值滤波 &#xff0c;均值滤波&#xff0c;高斯滤波实战 cv2.blur-均值滤波 cv2.medianBlur-中值滤波 cv2.GaussianBlur-高斯滤波 直接看代码吧&#xff0c;代码很简单&#xff1a; import copy import math import matplotlib.pyplot as plt import matp…

Linux系统---环境变量+内核进程调度队列(选学)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、环境变量 1.基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数&#xff0c;如: 我们在编写CI/…

Java制作“简易王者荣耀”小游戏

第一步是创建项目 项目名自拟 第二部创建个包名 来规范class 然后是创建类 GameFrame 运行类 package com.sxt;import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; im…

如何使用Cloudreve将个人电脑打造为私有云盘并实现远程访问

文章目录 1、前言2、本地网站搭建2.1 环境使用2.2 支持组件选择2.3 网页安装2.4 测试和使用2.5 问题解决 3、本地网页发布3.1 cpolar云端设置3.2 cpolar本地设置 4、公网访问测试5、结语 1、前言 云存储概念兴起后&#xff0c;现在市面上也已经有了很多公有云盘。但一段时间后…

uniapp实现多时间段设置

功能说明&#xff1a; 1 点击新增时间&#xff0c;出现一个默认时间段模板&#xff0c;不能提交 2 点击“新增时间文本”&#xff0c;弹出弹窗&#xff0c;选择时间&#xff0c;不允许开始时间和结束时间同时为00:00&#xff0c; <view class"item_cont"> …

如何理解2023vivo开发者大会,使用Rust语言编写蓝河操作系统(BlueOS)?

在2023年vivo开发者大会上&#xff0c;vivo宣布使用Rust语言编写其蓝河操作系统&#xff08;BlueOS&#xff09;。 什么是Rust语言&#xff1f; Rust 是一种开放源代码系统编程语言&#xff0c;可用于开发高效、安全的软件。 使用 Rust 可管理内存并控制其低级详细信息。 但你…

Web框架与Django简介

Web框架与Django简介 一、Web应用的组成 我们为了开发一款Web软件首先要了解什么才是Web应用软件呢&#xff1f; 对于传统的应用软件来说&#xff0c;基本都是部署单机使用&#xff0c;而Web应用软件就不一样&#xff0c;Web应用软件是基于B/S架构的&#xff0c;B和S都在不同…

Spring Boot 3.2.0 Tomcat虚拟线程初体验 (部分装配解析)

写在前面 spring boot 3 已经提供了对虚拟线程的支持。 虚拟线程和平台线程主要区别在于&#xff0c;虚拟线程在运行周期内不依赖操作系统线程&#xff1a;它们与硬件脱钩&#xff0c;因此被称为 “虚拟”。这种解耦是由 JVM 提供的抽象层赋予的。 虚拟线程的运行成本远低于平…

记录:Unity脚本的编写8.0

目录 需求分析设计GUI包含账号和密码输入栏&#xff0c;包括登录和注册按键添加背景音乐编写脚本控制音乐 退出按钮编写脚本 背景图片完整代码 一个小demo&#xff0c;登录和注册的实现&#xff08;包括GUI和数据库操控&#xff09; 需求分析 自行设计GUI&#xff0c;要求 1.包…

智能优化算法应用:基于花授粉算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于花授粉算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于花授粉算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.花授粉算法4.实验参数设定5.算法结果6.参考文献7.…

java游戏制作-王者荣耀游戏

一.准备工作 首先创建一个新的Java项目命名为“王者荣耀”&#xff0c;并在src下创建两个包分别命名为“com.sxt"、”com.stx.beast",在相应的包中创建所需的类。 创建一个名为“img”的文件夹来储存所需的图片素材。 二.代码呈现 package com.sxt; import javax.…

深入理解强化学习——马尔可夫决策过程:贝尔曼期望方程-[举例与代码实现]

分类目录&#xff1a;《深入理解强化学习》总目录 在文章《深入理解强化学习——马尔可夫决策过程&#xff1a;贝尔曼期望方程-[基础知识]》中我们讲到了贝尔曼期望方程&#xff0c;本文就举一个贝尔曼期望方程的具体例子&#xff0c;并给出相应代码实现。 下图是一个马尔可夫…

基于springboot实现私人健身与教练预约管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现私人健身与教练预约管理系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应…

深入理解虚拟 DOM:提升前端性能的关键技术

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Vue 定义只读数据 readonly 与 shallowReadonly

readonly 让一个响应式数据变为 **深层次的只读数据**。 shallowReadonly 让一个响应式数据变为 **浅层次的只读数据**&#xff0c;只读第一层。 isReadonly 判断一个数据是不是只读数据。 应用场景&#xff1a;不希望数据被修改时使用。 readonly深层次只读&#xff1a; …

Java实现王者荣耀小游戏

主要功能 键盘W,A,S,D键&#xff1a;控制玩家上下左右移动。按钮一&#xff1a;控制英雄发射一个矩形攻击红方小兵。按钮二&#xff1a;控制英雄发射魅惑技能&#xff0c;伤害小兵并让小兵停止移动。技能三&#xff1a;攻击多个敌人并让小兵停止移动。普攻&#xff1a;对小兵造…

VsCode学习

一、在VsCode 上编写第一个C语言 在VsCode上写代码都是先打开文件夹&#xff0c;这样也方便管理代码和编译器产生的可执行程序&#xff0c;VsCode生成的配置文件等。 1.1打开文件夹 写代码前&#xff0c;首先创立一个文件夹存储以后我们写的VsCode代码&#xff0c;便于管理。…

代码随想录算法训练营 ---第四十九天

前言&#xff1a; 今天是买卖股票的最佳时机系列&#xff0c;本系列之前在学习贪心思想时做过一些。 第一题&#xff1a; 简介&#xff1a; 本题在读题时我们要注意到几个细节 1.本题股票买卖只有一次。2.我们要在最低点买股票&#xff0c;在最高点卖股票。 我的思路&#…

skywalking告警UI界面有告警信息,webhook接口没有回调,400错误

400错误就是回调接口返回数据的属性对应不上 PostMapping(“/webhook”) public void webhook(RequestBody List alarmMessageList) 自定义的实体类AlarmMessage有问题 只能去官网找了 告警实体类官网 Getter EqualsAndHashCode RequiredArgsConstructor NoArgsConstructor(fo…

父进程隐藏——ConsoleApplication903项目

首先我发现用calc来做进程隐藏实验是失败的&#xff0c;父进程一直都是svhost.exe 那么我用我自己生成的cs木马beacon903.exe试试 试试explorer.exe 再试试cmd.exe 可以看到成功变成cmd.exe 可以看到我们可以通过这种方式虚假父进程 以上我们是直接获得的pid&#xff0c;那…