概述

SpringBoot 整合 Redis 是使用 SpringData 实现的。

SpringData 是与 SpringBoot 齐名的顶级项目,整合了对常用数据库的模板型操作。

在 SpringBoot 2.x 之后,Jedis 被 Lettuce 替代了。

Jedis

采用的直连,多个线程操作的话,是不安全的。

如果想要避免不安全,就要使用 Jedis pool 连接池解决。

这样是有一些弊端的,比如线程数量太多了,Redis 服务就比较庞大,而且它是阻塞的。

Lettuce

底层采用 Netty,实例可以在多个线程中进行共享。

不存在线程不安全的情况,可以减少线程数量。

使用

导入依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

yaml 配置

spring:
redis:
host: 47.100.222.85
port: 6379
jedis:
pool:
max-active: 8
max-wait: -1ms
max-idle: 500
min-idle: 0
lettuce:
shutdown-timeout: 0ms

测试

@Resource
private RedisTemplate redisTemplate; @Test
void contextLoads() {
redisTemplate.opsForValue().set("myKey", "myValue");
System.out.println(redisTemplate.opsForValue().get("myKey"));
}

输出为:myValue,连接成功。

源码分析

RedisAutoConfiguration

@AutoConfiguration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
} @Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}
)
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 默认的 RedisTemplate 没有过多的设置,Redis 对象都是需要序列化的
// 两个泛型都是 Object 的类型,我们使用需要强制转换,很不方便,预期是 <String, Object>
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
} @Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
// 由于 String 是 Redis 最常使用的类型,所以说单独提出来了一个 Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
}

通过源码可以看出,SpringBoot 自动帮我们在容器中生成了一个 RedisTemplate 和一个 StringRedisTemplate。

但是,这个 RedisTemplate 的泛型是 <Object, Object>,写代码不方便,需要写好多类型转换的代码。

我们需要一个泛型为 <String, Object> 形式的 RedisTemplate。

并且,这个 RedisTemplate 没有设置数据存在 Redis 时,key 及 value 的序列化方式。

由 @ConditionalOnMissingBean 可以看出,如果 Spring 容器中有了自定义的 RedisTemplate 对象,自动配置的 RedisTemplate 不会实例化。

因此我们可以直接自己写个配置类,配置 RedisTemplate。

集成

Redis 配置类

import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter; /**
* Redis 配置类
*/
@Configuration
@EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport { @Value("${spring.redis.database}")
private int database; @Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置数据库
connectionFactory.setDatabase(database);
// 刷新配置
connectionFactory.afterPropertiesSet();
// 重置连接
connectionFactory.resetConnection();
// 设置连接
template.setConnectionFactory(connectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.activateDefaultTyping(
om.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
om.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
this.registerLocalDateTime(om);
serializer.setObjectMapper(om);
// key采用String的序列化方式
template.setKeySerializer(new StringRedisSerializer());
// value序列化方式采用jackson
template.setValueSerializer(serializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
// hash的value序列化方式采用jackson
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
// 添加对事务的支持
template.setEnableTransactionSupport(true);
return template;
} /**
* 处理时间类型
*
* @param objectMapper 待序列化对象
*/
private void registerLocalDateTime(ObjectMapper objectMapper) {
// 设置java.util.Date时间类的序列化以及反序列化的格式
objectMapper.setDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN)); JavaTimeModule timeModule = new JavaTimeModule();
// LocalDateTime
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
// LocalDate
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN);
timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter));
timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter));
// LocalTime
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN);
timeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter));
timeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter));
objectMapper.registerModule(timeModule); } }

直接用 RedisTemplate 操作 Redis,比较繁琐。

因此直接封装好一个 RedisUtils,这样写代码更方便点。

这个 RedisUtils 交给Spring容器实例化,使用时直接注解注入。

Redis 工具类

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnectionCommands;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; /**
* Redis 工具类
*/
@Component
public class RedisUtils { private static RedisTemplate<String, Object> redisTemplate; @Autowired
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
RedisUtils.redisTemplate = redisTemplate;
} /**
* 连接测试
*
* @return 测试结果
*/
public static String ping() {
return redisTemplate.execute(RedisConnectionCommands::ping);
} /**
* 切换数据库
*
* @param dbIndex 数据库编号(默认有16个数据库,编号在0-15之间)
*/
public static void select(int dbIndex) {
// 获取连接工厂
LettuceConnectionFactory connectionFactory = (LettuceConnectionFactory) redisTemplate.getConnectionFactory();
if (ObjUtil.isNull(connectionFactory)) {
return;
}
// 设置数据库
connectionFactory.setDatabase(dbIndex);
// 刷新配置
connectionFactory.afterPropertiesSet();
redisTemplate.setConnectionFactory(connectionFactory);
} /**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒),指定为-1代表永久有效
*/
public static boolean expire(String key, long time) {
return Boolean.TRUE.equals(redisTemplate.expire(key, time, TimeUnit.SECONDS));
} /**
* 根据key获取过期时间
*
* @param key 键
* @return 时间(秒)。-1:永久有效;-2:该键已过期或不存在
*/
public static long getExpire(String key) {
Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
return ObjUtil.isNull(expire) ? 0 : expire;
} /**
* 判断key是否存在
*
* @param key 键
* @return 结果
*/
public static boolean has(String key) {
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
} /**
* 删除缓存
*
* @param key 键,可以传一个或多个值
*/
public static void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollUtil.toList(key));
}
}
} /**
* 字符串缓存取值(不能获取token值,因为其自带加密,无法解析)
*
* @param key 键
* @return 值
*/
public static Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
} /**
* 字符串缓存设值
*
* @param key 键
* @param value 值
*/
public static void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
} /**
* 只有在 key 不存在时设置 key 的值
*
* @param key 键
* @param value 值
*/
public static void setIfAbsent(String key, String value) {
redisTemplate.opsForValue().setIfAbsent(key, value);
} /**
* 字符串缓存设值并设置生效时间
*
* @param key 键
* @param value 值
* @param time 时间(秒),time要大于0,如果time小于等于0,将设置无限期
*/
public static void set(String key, Object value, long time) {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
} /**
* 递增
*
* @param key 键
* @param num 要增加几
*/
public static long inc(String key, long num) {
Long increment = redisTemplate.opsForValue().increment(key, num);
return increment == null ? 0 : increment;
} /**
* 递减
*
* @param key 键
* @param num 要减少几
*/
public static long dec(String key, long num) {
Long decrement = redisTemplate.opsForValue().decrement(key, num);
return decrement == null ? 0 : decrement;
} /**
* 获取list缓存的内容
*
* @param key 键
* @return 列表
*/
public static List<Object> getList(String key) {
return redisTemplate.opsForList().range(key, 0, -1);
} /**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束。0到-1代表所有值
*/
public static List<Object> getList(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
} /**
* 获取list缓存的长度
*
* @param key 键
*/
public static long getListSize(String key) {
Long size = redisTemplate.opsForList().size(key);
return size == null ? 0 : size;
} /**
* 获取list中的值
*
* @param key 键
* @param index 索引index>=0时,0:表头,1:第二个元素,依次类推;<br>
* 索引index<0时,-1:表尾,-2:倒数第二个元素,依次类推
*/
public static Object getList(String key, long index) {
return redisTemplate.opsForList().index(key, index);
} /**
* 将list放入缓存
*
* @param key 键
* @param value 值
*/
public static void setList(String key, Object value) {
redisTemplate.opsForList().rightPush(key, value);
} /**
* 将list放入缓存并设置生效时间
*
* @param key 键
* @param value 值
* @param time 时间(秒)
*/
public static void setList(String key, Object value, long time) {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
} /**
* 将list放入列表缓存
*
* @param key 键
* @param value 值
*/
public static void setList(String key, List<Object> value) {
redisTemplate.opsForList().rightPushAll(key, value);
} /**
* 将list放入列表缓存并设置生效时间
*
* @param key 键
* @param value 值
* @param time 时间(秒)
*/
public static void setList(String key, List<Object> value, long time) {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
} /**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
*/
public static void setList(String key, long index, Object value) {
redisTemplate.opsForList().set(key, index, value);
} /**
* 移除n个值为value的
*
* @param key 键
* @param count 移除多少个
* @param value 值
*/
public static void delList(String key, long count, Object value) {
redisTemplate.opsForList().remove(key, count, value);
} /**
* 左弹出list缓存的内容
*
* @param key 键
*/
public static void popList(String key) {
redisTemplate.opsForList().leftPop(key);
} /**
* 根据key获取Set中的所有值
*
* @param key 键
*/
public static Set<Object> getSet(String key) {
return redisTemplate.opsForSet().members(key);
} /**
* 随机获取变量中的元素
*
* @param key 键
* @return value值
*/
public static Object randomSet(String key) {
return redisTemplate.opsForSet().randomMember(key);
} /**
* 获取set缓存的长度
*
* @param key 键
*/
public static long getSetSize(String key) {
Long size = redisTemplate.opsForSet().size(key);
return size == null ? 0 : size;
} /**
* 将数据放入set缓存
*
* @param key 键
* @param values 值,可以是多个
*/
public static void setSet(String key, Object... values) {
redisTemplate.opsForSet().add(key, values);
} /**
* 将set数据放入缓存并设置生效时间
*
* @param key 键
* @param time 时间(秒)
* @param values 值,可以是多个
*/
public static void setSetTime(String key, long time, Object... values) {
redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
} /**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return 结果
*/
public static boolean hasSet(String key, Object value) {
return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, value)); } /**
* 移除值为value的
*
* @param key 键
* @param values 值,可以是多个
*/
public static void delSet(String key, Object... values) {
redisTemplate.opsForSet().remove(key, values);
} /**
* 添加元素,有序集合是按照元素的score值由小到大排列
*
* @param key 键
* @param value 对象名称
* @param score 数据值
*/
public static void setZset(String key, TypedTuple<Object> value, double score) {
redisTemplate.opsForZSet().add(key, value, score);
} /**
* 添加元素,向集合中插入多个元素
*
* @param key 键
* @param values set集合
*/
public static void setZset(String key, Set<TypedTuple<Object>> values) {
redisTemplate.opsForZSet().add(key, values);
} /*
* 获取元素集合,从小到大排序
* @param key
* @param start 开始位置
* @param end 结束位置, -1查询所有
* @return 元素集合
*/
public static Set<Object> getZset(String key, long start, long end) {
return redisTemplate.opsForZSet().range(key, start, end);
} /**
* 从集合中删除指定元素
*
* @param key 键
* @param values 值
*/
public static void delZset(String key, Object... values) {
redisTemplate.opsForZSet().remove(key, values);
} /**
* 增加元素的score值,并返回增加后的值
*
* @param key 键
* @param value 值
* @param num 增加多少score值
* @return 增加后的score值
*/
public static double incScoreZset(String key, String value, double num) {
Double result = redisTemplate.opsForZSet().incrementScore(key, value, num);
return ObjUtil.isNull(result) ? 0 : result;
} /**
* 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列
*
* @param key 键
* @param value 值
* @return 0表示第一位
*/
public static long rankZset(String key, Object value) {
Long result = redisTemplate.opsForZSet().rank(key, value);
return ObjUtil.isNull(result) ? 0 : result;
} /**
* 获取集合大小
*
* @param key 键
* @return 集合大小
*/
public static long getZsetSize(String key) {
Long result = redisTemplate.opsForZSet().size(key);
return ObjUtil.isNull(result) ? 0 : result;
} /**
* 获取键对应的所有值
*
* @param key 键
* @return 对应的多个键值
*/
public static Map<Object, Object> getHash(String key) {
return redisTemplate.opsForHash().entries(key);
} /**
* 根据键和项取值
*
* @param key 键
* @param item 项
*/
public static Object getHash(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
} /**
* 设值
*
* @param key 键
* @param map 对应多个键值
*/
public static void setHash(String key, Map<String, Object> map) {
redisTemplate.opsForHash().putAll(key, map);
} /**
* 设值
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
*/
public static void setHash(String key, Map<String, Object> map, long time) {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
} /**
* 向一张hash表中放入数据,如果不存在则创建
*
* @param key 键
* @param item 项
* @param value 值
*/
public static void setHash(String key, String item, Object value) {
redisTemplate.opsForHash().put(key, item, value);
} /**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
*/
public static void setHash(String key, String item, Object value, long time) {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
} /**
* 判断hash表中是否有该项的值
*
* @param key 键,不能为null
* @param item 项,不能为null
* @return 结果
*/
public static boolean hasHash(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
} /**
* 删除hash表中的值
*
* @param key 键,不能为null
* @param item 项,可以是多个,不能为null
*/
public static void delHash(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
} /**
* hash递增,如果不存在,就会创建一个,并把新增后的值返回
*
* @param key 键
* @param item 项
* @param num 要增加几(大于0)
*/
public static double incHash(String key, String item, double num) {
return redisTemplate.opsForHash().increment(key, item, num);
} /**
* hash递减
*
* @param key 键
* @param item 项
* @param num 要减少几(小于0)
*/
public static double decHash(String key, String item, double num) {
return redisTemplate.opsForHash().increment(key, item, -num);
} }

参考

https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0

版本

6.2.6

Redis 19 SpringBoot集成的更多相关文章

  1. 【redis】-- springboot集成redis及使用

    springboot自动配置的redis并不是特别好用,所以需要我们使用原生的jedis, 1.添加依赖 2.在application文件中配置 # Redis服务器地址 redis.host= # ...

  2. springboot集成redis(mybatis、分布式session)

    安装Redis请参考:<CentOS快速安装Redis> 一.springboot集成redis并实现DB与缓存同步 1.添加redis及数据库相关依赖(pom.xml) <depe ...

  3. 【springBoot】springBoot集成redis的key,value序列化的相关问题

    使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...

  4. SpringBoot集成redis的key,value序列化的相关问题

    使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...

  5. Windows环境下springboot集成redis的安装与使用

    一,redis安装 首先我们需要下载Windows版本的redis压缩包地址如下: https://github.com/MicrosoftArchive/redis/releases 连接打开后如下 ...

  6. springBoot集成Redis遇到的坑(择库)源码分析为什么择库失败

    提示: springboot提供了一套链接redis的api,也就是个jar包,用到的连接类叫做LettuceConnectionConfiguration,所以我们引入pom时是这样的 <de ...

  7. Springboot集成mybatis(mysql),mail,mongodb,cassandra,scheduler,redis,kafka,shiro,websocket

    https://blog.csdn.net/a123demi/article/details/78234023  : Springboot集成mybatis(mysql),mail,mongodb,c ...

  8. SpringBoot | 集成Redis

    Windows下安装: https://github.com/MicrosoftArchive/redis/releases zip下就解包到自定义目录下,msi就跟着步骤安装 进入安装目录下运行命令 ...

  9. springboot集成redis使用redis作为session报错ClassNotFoundException类RememberMeServices

    springboot 集成redis使用redis作为缓存,会报错的问题. 错误信息: java.lang.IllegalStateException: Error processing condit ...

  10. 基于Springboot集成security、oauth2实现认证鉴权、资源管理

    1.Oauth2简介 OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAu ...

随机推荐

  1. DataGear 制作自定义柱状图条目颜色的数据可视化看板

    DataGear 看板提供了dg-chart-options图表选项配置功能,可自定义样式.位置.显示内容等图表选项,其中的processUpdateOptions回调函数配置项,可以在图表更新数据前 ...

  2. 【Azure 应用服务】应用代码中需要使用客户端证书访问服务接口,部署在应用服务后报错不能找到证书(Cannot find the X.509 certificate)

    问题描述 在应用中,需要访问另一个服务接口,这个接口需要使用客户端证书进行认证.在代码中使用 System.Security.Cryptography.X509Certificates 加载Windo ...

  3. 【Azure Function】开启Azure Function输出详细Debug日志 ( --verbose)

    When func.exe is run from VS, it suggests "For detailed output, run func with --verbose flag.&q ...

  4. 【Azure 存储服务】关于Storage Account Queue使用的几个问题

    1) 在消费Storage Queue中的数据的时候,如何只过滤出 Subject 为"message/{messageid}"这种,去掉subject为"informa ...

  5. C++11新特性的一些用法举例②

    /** C++11 * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝构造函数 拷贝赋值重载 取地址重载 const 取地址重载 最后重要的是前4个,后两个用处不大.默认 ...

  6. 使用go语言开发自动化API测试工具

    前言 上一篇文章说到我还开发了一个独立的自动测试工具,可以根据 OpenAPI 的文档来测试,并且在测试完成后输出测试报告,报告内容包括每个接口是否测试通过和响应时间等. 这个工具我使用了 go 语言 ...

  7. Zabbix6.0使用教程 (一)—zabbix新增功能介绍2

    上一篇我们已经介绍了部分zabbix6.0的新增功能,这期我们将继续为家详细介绍下余下的zabbix6.0新增功能,大家可以往下看. 六.监控项 6.1 自动类型选择 监控项配置表单会自动建议匹配的信 ...

  8. [VueJsDev] 快速入门 - vscode 自动格式化

    [VueJsDev] 目录列表 https://www.cnblogs.com/pengchenggang/p/17037320.html vscode 自动格式化(vue) ::: details ...

  9. CRC常用参数模型及C#代码实现

    目录 参数模型 算法实现 CRC-32 CRC-32/MPEG-2 表生成算法 参考资料 本文源码 参数模型 CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中 ...

  10. 基于Python的 如何检查字符串输入是否为数字

    一 概念 这种有很多常用的方法,这里只介绍一种常用的方法是使用正则表达式来匹配数字的模式.通过定义一个匹配数字的正则表达式,然后使用re模块中的search()方法来进行匹配. 二 例子: 下面是一个 ...