RedisTemplate的配置和讲解以及和StringRedisTemplate的区别

本文主要讲redisTempalte的几种常用的序列化方式

  • string,我们大部分情况下都希望存入redis的数据可读性强一些,并且value也不总是一个规则的类型,所以这里也是不用json序列化的原因,可以更自由方便,下边提供配置方法
    package sca.pro.core.redis.configuration;import cn.hutool.core.convert.Convert;
    import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisPassword;
    import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
    import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
    import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
    import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;@Configuration
    @EnableCaching
    public class RedisTemplateConfig {@Value("${spring.redis.database}")private int database;@Value("${spring.redis.host}")private String host;@Value("${spring.redis.password}")private String password;@Value("${spring.redis.port}")private String port;@Value("${spring.redis.timeout}")private String timeout;@Value("${spring.redis.lettuce.pool.max-idle}")private String maxIdle;@Value("${spring.redis.lettuce.pool.min-idle}")private String minIdle;@Value("${spring.redis.lettuce.pool.max-active}")private String maxActive;@Value("${spring.redis.lettuce.pool.max-wait}")private String maxWait;@Beanpublic LettuceConnectionFactory lettuceConnectionFactory() {GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();genericObjectPoolConfig.setMaxIdle(Convert.toInt(maxIdle));genericObjectPoolConfig.setMinIdle(Convert.toInt(minIdle));genericObjectPoolConfig.setMaxTotal(Convert.toInt(maxActive));genericObjectPoolConfig.setMaxWaitMillis(Convert.toLong(maxWait));genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(100);RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();redisStandaloneConfiguration.setDatabase(database);redisStandaloneConfiguration.setHostName(host);redisStandaloneConfiguration.setPort(Convert.toInt(port));redisStandaloneConfiguration.setPassword(RedisPassword.of(password));LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofMillis(Convert.toLong(timeout))).poolConfig(genericObjectPoolConfig).build();LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);return factory;}@Beanpublic RedisTemplate<String, String> redisTemplate(LettuceConnectionFactory factory) {// 配置redisTemplateRedisTemplate<String, String> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(factory);redisTemplate.setKeySerializer(new StringRedisSerializer());//key序列化redisTemplate.setValueSerializer(new StringRedisSerializer());//value序列化//设置hash的key的序列化方式redisTemplate.setHashKeySerializer(new StringRedisSerializer());//设置hash的value的序列化方式redisTemplate.setHashValueSerializer(new StringRedisSerializer());redisTemplate.afterPropertiesSet();//使上面参数生效return redisTemplate;}
    }
    

其实如果key和value都是string,那就等效于我们直接引入StringRedisTemplate 

  • 如果使用字节数组的形式序列化,redistemplate默认使用的jdk的序列化方式,但是jdk的序列化后的字节数组不仅重,而且序列化和反序列化我们用的是protobuf,如下

   pom

<!-- 工具库 -->
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>18.0</version>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><!-- 序列化 -->
<dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-core</artifactId><version>1.1.3</version>
</dependency>
<dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-runtime</artifactId><version>1.1.3</version>
</dependency>

2.自己编写序列化工具

@Slf4j
public class ProtoStuffUtil {/*** 序列化对象** @param obj* @return*/public static <T> byte[] serialize(T obj) {if (obj == null) {log.error("Failed to serializer, obj is null");throw new RuntimeException("Failed to serializer");}@SuppressWarnings("unchecked") Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(obj.getClass());LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);byte[] protoStuff;try {protoStuff = ProtostuffIOUtil.toByteArray(obj, schema, buffer);} catch (Exception e) {log.error("Failed to serializer, obj:{}", obj, e);throw new RuntimeException("Failed to serializer");} finally {buffer.clear();}return protoStuff;}/*** 反序列化对象** @param paramArrayOfByte* @param targetClass* @return*/public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {if (paramArrayOfByte == null || paramArrayOfByte.length == 0) {log.error("Failed to deserialize, byte is empty");throw new RuntimeException("Failed to deserialize");}T instance;try {instance = targetClass.newInstance();} catch (InstantiationException | IllegalAccessException e) {log.error("Failed to deserialize", e);throw new RuntimeException("Failed to deserialize");}Schema<T> schema = RuntimeSchema.getSchema(targetClass);ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);return instance;}/*** 序列化列表** @param objList* @return*/public static <T> byte[] serializeList(List<T> objList) {if (objList == null || objList.isEmpty()) {log.error("Failed to serializer, objList is empty");throw new RuntimeException("Failed to serializer");}@SuppressWarnings("unchecked") Schema<T> schema =(Schema<T>) RuntimeSchema.getSchema(objList.get(0).getClass());LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);byte[] protoStuff;ByteArrayOutputStream bos = null;try {bos = new ByteArrayOutputStream();ProtostuffIOUtil.writeListTo(bos, objList, schema, buffer);protoStuff = bos.toByteArray();} catch (Exception e) {log.error("Failed to serializer, obj list:{}", objList, e);throw new RuntimeException("Failed to serializer");} finally {buffer.clear();try {if (bos != null) {bos.close();}} catch (IOException e) {e.printStackTrace();}}return protoStuff;}/*** 反序列化列表** @param paramArrayOfByte* @param targetClass* @return*/public static <T> List<T> deserializeList(byte[] paramArrayOfByte, Class<T> targetClass) {if (paramArrayOfByte == null || paramArrayOfByte.length == 0) {log.error("Failed to deserialize, byte is empty");throw new RuntimeException("Failed to deserialize");}Schema<T> schema = RuntimeSchema.getSchema(targetClass);List<T> result;try {result = ProtostuffIOUtil.parseListFrom(new ByteArrayInputStream(paramArrayOfByte), schema);} catch (IOException e) {log.error("Failed to deserialize", e);throw new RuntimeException("Failed to deserialize");}return result;}}

3.RedisTemplate的工具类方法

@Component
public class RedisClient {private final RedisTemplate<String, String> redisTemplate;@Autowiredpublic RedisClient(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}/*** get cache** @param field* @param targetClass* @param <T>* @return*/public <T> T get(final String field, Class<T> targetClass) {byte[] result = redisTemplate.execute((RedisCallback<byte[]>) connection -> connection.get(field.getBytes()));if (result == null) {return null;}return ProtoStuffUtil.deserialize(result, targetClass);}/*** put cache** @param field* @param obj* @param <T>* @return*/public <T> void set(String field, T obj) {final byte[] value = ProtoStuffUtil.serialize(obj);redisTemplate.execute((RedisCallback<Void>) connection -> {connection.set(field.getBytes(), value);return null;});}/*** put cache with expire time** @param field* @param obj* @param expireTime 单位: s* @param <T>*/public <T> void setWithExpire(String field, T obj, final long expireTime) {final byte[] value = ProtoStuffUtil.serialize(obj);redisTemplate.execute((RedisCallback<Void>) connection -> {connection.setEx(field.getBytes(), expireTime, value);return null;});}/*** get list cache** @param field* @param targetClass* @param <T>* @return*/public <T> List<T> getList(final String field, Class<T> targetClass) {byte[] result = redisTemplate.execute((RedisCallback<byte[]>) connection -> connection.get(field.getBytes()));if (result == null) {return null;}return ProtoStuffUtil.deserializeList(result, targetClass);}/*** put list cache** @param field* @param objList* @param <T>* @return*/public <T> void setList(String field, List<T> objList) {final byte[] value = ProtoStuffUtil.serializeList(objList);redisTemplate.execute((RedisCallback<Void>) connection -> {connection.set(field.getBytes(), value);return null;});}/*** put list cache with expire time** @param field* @param objList* @param expireTime* @param <T>* @return*/public <T> void setListWithExpire(String field, List<T> objList, final long expireTime) {final byte[] value = ProtoStuffUtil.serializeList(objList);redisTemplate.execute((RedisCallback<Void>) connection -> {connection.setEx(field.getBytes(), expireTime, value);return null;});}/*** get h cache** @param key* @param field* @param targetClass* @param <T>* @return*/public <T> T hGet(final String key, final String field, Class<T> targetClass) {byte[] result = redisTemplate.execute((RedisCallback<byte[]>) connection -> connection.hGet(key.getBytes(), field.getBytes()));if (result == null) {return null;}return ProtoStuffUtil.deserialize(result, targetClass);}/*** put hash cache** @param key* @param field* @param obj* @param <T>* @return*/public <T> boolean hSet(String key, String field, T obj) {final byte[] value = ProtoStuffUtil.serialize(obj);return redisTemplate.execute((RedisCallback<Boolean>) connection -> connection.hSet(key.getBytes(), field.getBytes(), value));}/*** put hash cache** @param key* @param field* @param obj* @param <T>*/public <T> void hSetWithExpire(String key, String field, T obj, long expireTime) {final byte[] value = ProtoStuffUtil.serialize(obj);redisTemplate.execute((RedisCallback<Void>) connection -> {connection.hSet(key.getBytes(), field.getBytes(), value);connection.expire(key.getBytes(), expireTime);return null;});}/*** get list cache** @param key* @param field* @param targetClass* @param <T>* @return*/public <T> List<T> hGetList(final String key, final String field, Class<T> targetClass) {byte[] result = redisTemplate.execute((RedisCallback<byte[]>) connection -> connection.hGet(key.getBytes(), field.getBytes()));if (result == null) {return null;}return ProtoStuffUtil.deserializeList(result, targetClass);}/*** put list cache** @param key* @param field* @param objList* @param <T>* @return*/public <T> boolean hSetList(String key, String field, List<T> objList) {final byte[] value = ProtoStuffUtil.serializeList(objList);return redisTemplate.execute((RedisCallback<Boolean>) connection -> connection.hSet(key.getBytes(), field.getBytes(), value));}/*** get cache by keys** @param key* @param fields* @param targetClass* @param <T>* @return*/public <T> Map<String, T> hMGet(String key, Collection<String> fields, Class<T> targetClass) {List<byte[]> byteFields = fields.stream().map(String::getBytes).collect(Collectors.toList());byte[][] queryFields = new byte[byteFields.size()][];byteFields.toArray(queryFields);List<byte[]> cache = redisTemplate.execute((RedisCallback<List<byte[]>>) connection -> connection.hMGet(key.getBytes(), queryFields));Map<String, T> results = new HashMap<>(16);Iterator<String> it = fields.iterator();int index = 0;while (it.hasNext()) {String k = it.next();if (cache.get(index) == null) {index++;continue;}results.put(k, ProtoStuffUtil.deserialize(cache.get(index), targetClass));index++;}return results;}/*** set cache by keys** @param field* @param values* @param <T>*/public <T> void hMSet(String field, Map<String, T> values) {Map<byte[], byte[]> byteValues = new HashMap<>(16);for (Map.Entry<String, T> value : values.entrySet()) {byteValues.put(value.getKey().getBytes(), ProtoStuffUtil.serialize(value.getValue()));}redisTemplate.execute((RedisCallback<Void>) connection -> {connection.hMSet(field.getBytes(), byteValues);return null;});}/*** get caches in hash** @param key* @param targetClass* @param <T>* @return*/public <T> Map<String, T> hGetAll(String key, Class<T> targetClass) {Map<byte[], byte[]> records = redisTemplate.execute((RedisCallback<Map<byte[], byte[]>>) connection -> connection.hGetAll(key.getBytes()));Map<String, T> ret = new HashMap<>(16);for (Map.Entry<byte[], byte[]> record : records.entrySet()) {T obj = ProtoStuffUtil.deserialize(record.getValue(), targetClass);ret.put(new String(record.getKey()), obj);}return ret;}/*** list index** @param key* @param index* @param targetClass* @param <T>* @return*/public <T> T lIndex(String key, int index, Class<T> targetClass) {byte[] value =redisTemplate.execute((RedisCallback<byte[]>) connection -> connection.lIndex(key.getBytes(), index));return ProtoStuffUtil.deserialize(value, targetClass);}/*** list range** @param key* @param start* @param end* @param targetClass* @param <T>* @return*/public <T> List<T> lRange(String key, int start, int end, Class<T> targetClass) {List<byte[]> value = redisTemplate.execute((RedisCallback<List<byte[]>>) connection -> connection.lRange(key.getBytes(), start, end));return value.stream().map(record -> ProtoStuffUtil.deserialize(record, targetClass)).collect(Collectors.toList());}/*** list left push** @param key* @param obj* @param <T>*/public <T> void lPush(String key, T obj) {final byte[] value = ProtoStuffUtil.serialize(obj);redisTemplate.execute((RedisCallback<Long>) connection -> connection.lPush(key.getBytes(), value));}/*** list left push** @param key* @param objList* @param <T>*/public <T> void lPush(String key, List<T> objList) {List<byte[]> byteFields = objList.stream().map(ProtoStuffUtil::serialize).collect(Collectors.toList());byte[][] values = new byte[byteFields.size()][];redisTemplate.execute((RedisCallback<Long>) connection -> connection.lPush(key.getBytes(), values));}/*** 精确删除key** @param key*/public void deleteCache(String key) {redisTemplate.delete(key);}/*** 排行榜的存入** @param redisKey* @param immutablePair*/public void zAdd(String redisKey, ImmutablePair<String, BigDecimal> immutablePair) {final byte[] key = redisKey.getBytes();final byte[] value = immutablePair.getLeft().getBytes();redisTemplate.execute((RedisCallback<Boolean>) connection -> connection.zAdd(key, immutablePair.getRight().doubleValue(), value));}/*** 获取排行榜低->高排序** @param redisKey 要进行排序的类别* @param start* @param end* @return*/public List<ImmutablePair<String, BigDecimal>> zRangeWithScores(String redisKey, int start, int end) {Set<RedisZSetCommands.Tuple> items = redisTemplate.execute((RedisCallback<Set<RedisZSetCommands.Tuple>>) connection -> connection.zRangeWithScores(redisKey.getBytes(), start, end));return items.stream().map(record -> ImmutablePair.of(new String(record.getValue()), BigDecimal.valueOf(record.getScore()))).collect(Collectors.toList());}/*** 获取排行榜高->低排序** @param redisKey 要进行排序的类别* @param start* @param end* @return*/public List<ImmutablePair<String, BigDecimal>> zRevRangeWithScores(String redisKey, int start, int end) {Set<RedisZSetCommands.Tuple> items = redisTemplate.execute((RedisCallback<Set<RedisZSetCommands.Tuple>>) connection -> connection.zRevRangeWithScores(redisKey.getBytes(), start, end));return items.stream().map(record -> ImmutablePair.of(new String(record.getValue()), BigDecimal.valueOf(record.getScore()))).collect(Collectors.toList());}
}
  • 最推荐的一种序列化方式GenericJackson2JsonRedisSerializer,org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer 使用Jackson 实现JSON的序列化方式,Generic单词翻译过来表示:通用的意思,可以看出,是支持所有类。
@Bean@ConditionalOnMissingBean(name = "redisTemplate")public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);//String的序列化方式StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// 使用GenericJackson2JsonRedisSerializer 替换默认序列化(默认采用的是JDK序列化)GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();//key序列化方式采用String类型template.setKeySerializer(stringRedisSerializer);//value序列化方式采用jackson类型template.setValueSerializer(genericJackson2JsonRedisSerializer);//hash的key序列化方式也是采用String类型template.setHashKeySerializer(stringRedisSerializer);//hash的value也是采用jackson类型template.setHashValueSerializer(genericJackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}}

运行下边的测试类测试GenericJackson2JsonRedisSerializer,发现不管是字符串还是对象还是数组都很通用

@Test
void redisTemplateSerializeTest() {String redisTemplateStringKey = "redisTemplateStringKey";String redisTemplateUserObjectKey = "redisTemplateUserObjectKey";String redisTemplateUserArrayObjectKey = "redisTemplateUserArrayObjectKey";String redisTemplateJSONObjectKey = "redisTemplateJSONObjectKey";String redisTemplateJSONArrayKey = "redisTemplateJSONArrayKey";//序列化String类型和反序列化String类型redisTemplate.opsForValue().set(redisTemplateStringKey, "austin");String austin = (String) redisTemplate.opsForValue().get(redisTemplateStringKey);System.out.println("stringGet: " + austin);//序列化Object对象类型和反序列化Object对象类型 (User对象)User user = new User("123", "austin", 25);redisTemplate.opsForValue().set(redisTemplateUserObjectKey, user);User userGet = (User) redisTemplate.opsForValue().get(redisTemplateUserObjectKey);System.out.println("userGet: " + userGet);//序列化Object对象数组类型和反序列化Object对象数组类型 (User[]对象数组)User user1 = new User("1", "austin1", 25);User user2 = new User("2", "austin2", 25);User[] userArray = new User[]{user1, user2};redisTemplate.opsForValue().set(redisTemplateUserArrayObjectKey, userArray);User[] userArrayGet = (User[]) redisTemplate.opsForValue().get(redisTemplateUserArrayObjectKey);System.out.println("userArrayGet: " + userArrayGet);//序列化JSONObject对象类型和反序列化JSONObject对象类型JSONObject jsonObject = new JSONObject();jsonObject.put("id", "123");jsonObject.put("name", "austin");jsonObject.put("age", 25);redisTemplate.opsForValue().set(redisTemplateJSONObjectKey, jsonObject);JSONObject jsonObjectGet = (JSONObject) redisTemplate.opsForValue().get(redisTemplateJSONObjectKey);System.out.println("jsonObjectGet: " + jsonObjectGet);//序列化JSONArray对象类型和反序列化JSONArray对象类型JSONArray jsonArray = new JSONArray();JSONObject jsonObject1 = new JSONObject();jsonObject1.put("id", "1");jsonObject1.put("name", "austin1");jsonObject1.put("age", 25);JSONObject jsonObject2 = new JSONObject();jsonObject2.put("id", "1");jsonObject2.put("name", "austin2");jsonObject2.put("age", 25);jsonArray.add(jsonObject1);jsonArray.add(jsonObject2);redisTemplate.opsForValue().set(redisTemplateJSONArrayKey, jsonArray);JSONArray jsonArrayGet = (JSONArray) redisTemplate.opsForValue().get(redisTemplateJSONArrayKey);System.out.println("jsonArrayGet: " + jsonArrayGet);
}

key- value :

字符串类型
Key: redisTemplateStringKey
Value: "austin"


对象类型
Key: redisTemplateUserObjectKey
Value:
{
    "@class": "com.example.jedisserializefrombytestojson.User",
    "id": "123",
    "name": "austin",
    "age": 25
}
 
对象数组类型
Key: redisTemplateUserArrayObjectKey
Value: 
[
    "[Lcom.example.jedisserializefrombytestojson.User;",
    [
        {
            "@class": "com.example.jedisserializefrombytestojson.User",
            "id": "1",
            "name": "austin1",
            "age": 25
        },
        {
            "@class": "com.example.jedisserializefrombytestojson.User",
            "id": "2",
            "name": "austin2",
            "age": 25
        }
    ]
]
 

JSONObject类型
Key: redisTemplateJSONObjectKey
Value:
{
    "@class": "com.alibaba.fastjson.JSONObject",
    "name": "austin",
    "id": "123",
    "age": 25
}


JSONArray类型
Key: redisTemplateJSONArrayKey
Value: 
[
    "com.alibaba.fastjson.JSONArray",
    [
        {
            "@class": "com.alibaba.fastjson.JSONObject",
            "name": "austin1",
            "id": "1",
            "age": 25
        },
        {
            "@class": "com.alibaba.fastjson.JSONObject",
            "name": "austin2",
            "id": "1",
            "age": 25
        }
    ]
]

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

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

相关文章

useEffect和useMemo

每次点击》状态发生改变会执行Example()函数&#xff0c; useEffect会执行吗&#xff1f;只有数组里传了count才会执行&#xff0c;没有的话不会执行&#xff08;但页面中的state还是响应式的&#xff0c;只是不会执行useEffect里面的内容&#xff09;。 useEffect里所执行的…

深度学习框架:Pytorch与Keras的区别与使用方法

☁️主页 Nowl &#x1f525;专栏《机器学习实战》 《机器学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 文章目录 Pytorch与Keras介绍 Pytorch 模型定义 模型编译 模型训练 输入格式 完整代码 Keras 模型定义 模型编译 模型训练 输入格式 完整代…

渗透测试考核(靶机1)

信息收集 主机发现 nbtscan -r 172.16.17.0/24 发现在局域网内&#xff0c;有两台主机名字比较可疑&#xff0c;177和134&#xff0c;猜测其为目标主机&#xff0c;其余的应该是局域网内的其他用户&#xff0c;因为其主机名字比较显眼&#xff0c;有姓名的拼音和笔记本电脑的…

【Python】SqlmapAPI调用实现自动化SQL注入安全检测

文章目录 简单使用优化 应用案例&#xff1a;前期通过信息收集拿到大量的URL地址&#xff0c;这个时候可以配置sqlmapAP接口进行批量的SQL注入检测 &#xff08;SRC挖掘&#xff09; 查看sqlmapapi使用方法 python sqlmapapi.py -h启动sqlmapapi 的web服务&#xff1a; 任务流…

【论文笔记】SDCL: Self-Distillation Contrastive Learning for Chinese Spell Checking

文章目录 论文信息Abstract1. Introduction2. Methodology2.1 The Main Model2.2 Contrastive Loss2.3 Implementation Details(Hyperparameters) 3. Experiments代码实现个人总结值得借鉴的地方 论文信息 论文地址&#xff1a;https://arxiv.org/pdf/2210.17168.pdf Abstrac…

游戏APP接入哪些广告类型

当谈到游戏应用程序&#xff08;APP&#xff09;接入广告时&#xff0c;选择适合用户体验和盈利的广告类型至关重要。游戏开发者通常考虑以下几种广告类型&#xff1a; admaoyan猫眼聚合 横幅广告&#xff1a; 这些广告以横幅形式显示在游戏界面的顶部或底部。它们不会打断游戏…

idea doc 注释 插件及使用

开启rendered view https://blog.csdn.net/Leiyi_Ann/article/details/124145492 生成doc https://blog.csdn.net/qq_42581682/article/details/105018239 把注释加到类名旁边插件 https://blog.csdn.net/qq_30231473/article/details/128825306

解决QT信号在信号和槽连接前发出而导致槽函数未调用问题

1.使用QMetaObject::invokeMethod 当使用 QMetaObject::invokeMethod 将函数放入事件队列时&#xff0c;该函数会在适当时机被执行&#xff0c;然后被从事件队列中移除。 "适当时机" 指的是函数被安排在事件队列中&#xff0c;等待事件循环处理时机。这个时机取决于…

聚类分析例题 (多元统计分析期末复习)

例一 动态聚类&#xff0c;K-means法&#xff0c;随机选取凝聚点&#xff08;题目直接给出&#xff09; 已知5个样品的观测值为&#xff1a;1&#xff0c;4&#xff0c;5&#xff0c;7&#xff0c;11。试用K均值法分为两类(凝聚点分别取1&#xff0c;4与1&#xff0c;11) 解&…

找不到 sun.misc.BASE64Decoder ,sun.misc.BASE64Encoder 类

找不到 sun.misc.BASE64Decoder &#xff0c;sun.misc.BASE64Encoder 类 1. 现象 idea 引用报错 找不到对应的包 import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder;2. 原因 因为sun.misc.BASE64Decoder和sun.misc.BASE64Encoder是Java的内部API&#xff0c;通…

oracle java.sql.SQLException: Invalid column type: 1111

1.遇到的问题 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{propertyuuid, modeIN, javaTypeclass java.lang.String, jdbcTypenull, numericScalenull, r…

VR虚拟教育展厅,为教学领域开启创新之路

线上虚拟展厅是一项全新的展示技术&#xff0c;可以为参展者带来不一样的观展体验。传统的实体展览存在着空间限制、时间限制以及高昂的成本&#xff0c;因此对于教育领域来说&#xff0c;线上虚拟教育展厅的出现&#xff0c;可以对传统教育方式带来改革&#xff0c;凭借强大的…

An illegal reflective access operation has occurred问题记录

报错 2023-11-30T01:08:18.7440800 [ERROR] [system.err] WARNING: An illegal reflective access operation has occurred 2023-11-30T01:08:18.7450800 [ERROR] [system.err] WARNING: Illegal reflective access by com.intellij.ui.JreHiDpiUtil to method sun.java2d.Sun…

ORA-00837: Specified value of MEMORY_TARGET greater than MEMORY_MAX_TARGET

有个11g rac环境&#xff0c;停电维护后&#xff0c;orcl1正常启动了&#xff0c;orcl2启动报错如下 SQL*Plus: Release 11.2.0.4.0 Production on Wed Nov 29 14:04:21 2023 Copyright (c) 1982, 2013, Oracle. All rights reserved. Connected to an idle instance. SYS…

1091 Acute Stroke (三维搜索)

题目可能看起来很难的样子&#xff0c;但是看懂了其实挺简单的。&#xff08;众所周知&#xff0c;pat考察英文水平&#xff09; 题目意思大概是&#xff1a;给你一个L*M*N的01长方体&#xff0c;求全为1的连通块的总体积大小。&#xff08;连通块体积大于T才计算在内&#xf…

从0开始学习JavaScript--JavaScript 模板字符串的全面应用

JavaScript 模板字符串是 ES6 引入的一项强大特性&#xff0c;它提供了一种更优雅、更灵活的字符串拼接方式。在本文中&#xff0c;将深入探讨模板字符串的基本语法、高级用法以及在实际项目中的广泛应用&#xff0c;通过丰富的示例代码带你领略模板字符串的魅力。 模板字符串…

亚马逊云科技基于 Polygon 推出首款 Amazon Managed Blockchain Access,助 Web3 开发人员降低区块链节点运行成本

2023 年 11 月 26 日&#xff0c;亚马逊 (Amazon) 旗下 Amazon Web Services&#xff08;Amazon&#xff09;在其官方博客上宣布&#xff0c;Amazon Managed Blockchain (AMB) Access 已支持 Polygon Proof-of-Stake(POS) 网络&#xff0c;并将满足各种场景的需求&#xff0c;包…

vueRouter常用属性

vueRouter常用属性 basemodehashhistoryhistory模式下可能会遇到的问题及解决方案 routesprops配置(最佳方案) scrollBehavior base 基本的路由请求的路径 如果整个单页应用服务在 /app/ 下&#xff0c;然后 base 就应该设为 “/app/”,所有的请求都会在url之后加上/app/ new …

删除list中除最后一个之外所有的数据

1.你可以新建一个list List<Integer> listnew ArrayList<>();int i0;while (i<100){list.add(i);}List<Integer> subList list.subList(list.size()-1, list.size());System.out.println("原list大小--"list.size());System.out.println("…

el-table根据返回数据回显选择复选框

接口给你返回一个集合&#xff0c;然后如果这个集合里面的status2&#xff0c;就把这一行的复选框给选中 注意&#xff1a; 绑定的ref :row-key"getRowKeys" this.$refs.multiTableInst.toggleRowSelection(this.list[i], true); <el-table :data"list"…