搭建网站用什么软件,wordpress菜单图标美化,做企业官网用什么开发,西安建设厅网站作为开发者#xff0c;相信大家都知道 Redis 的重要性。Redis 是使用 C 语言开发的一个高性能键值对数据库#xff0c;是互联网技术领域使用最为广泛的存储中间件#xff0c;它是「Remote Dictionary Service」的首字母缩写#xff0c;也就是「远程字典服务」。 Redis 以超…作为开发者相信大家都知道 Redis 的重要性。Redis 是使用 C 语言开发的一个高性能键值对数据库是互联网技术领域使用最为广泛的存储中间件它是「Remote Dictionary Service」的首字母缩写也就是「远程字典服务」。 Redis 以超高的性能、完美的文档、简洁的源码著称国内外很多大型互联网公司都在用比如说阿里、腾讯、GitHub、Stack Overflow 等等。当然了中小型公司也都在用。 安装 Redis
Redis 的官网提供了各种平台的安装包Linux、macOS、Windows 的都有。 官方地址https://redis.io/docs/install/ 完成安装后执行 redis-server 就可以启动 Redis 服务了。 顺带安装一下 Redis 客户端工具推荐 GitHub 星标 20k 的 AnotherRedisDesktopManager一款 更快、更好、更稳定的Redis桌面(GUI)管理客户端支持 Windows、macOS 和 Linux性能出众可以轻松加载海量键值。 https://github.com/qishibo/AnotherRedisDesktopManager 安装完成后链接 Redis 服务 Redis 数据类型 Redis支持五种数据类型string字符串hash哈希list列表set集合及zset(sorted set有序集合)。 Redis 教程Redis 字符串(String)_redis教程 Spring Boot 整合 Redis 第一步在 pom.xml 文件中添加 Redis 的 starter。 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId
/dependency
第二步在 application.yml 文件中添加 Redis 的配置信息
spring:redis:host: xxx.xxx.99.232 # Redis服务器地址database: 0 # Redis数据库索引默认为0port: 6379 # Redis服务器连接端口password: xxx # Redis服务器连接密码默认为空
第三步在测试类中添加以下代码。
SpringBootTest
class CodingmoreRedisApplicationTests {Resourceprivate RedisTemplate redisTemplate;Resourceprivate StringRedisTemplate stringRedisTemplate;Testpublic void testRedis() {// 添加redisTemplate.opsForValue().set(name,欧尼甲);// 查询System.out.println(redisTemplate.opsForValue().get(name));// 删除redisTemplate.delete(name);// 更新redisTemplate.opsForValue().set(name,哈哈好傻);// 查询System.out.println(redisTemplate.opsForValue().get(name));// 添加stringRedisTemplate.opsForValue().set(name,欧尼甲);// 查询System.out.println(stringRedisTemplate.opsForValue().get(name));// 删除stringRedisTemplate.delete(name);// 更新stringRedisTemplate.opsForValue().set(name,哈哈好傻);// 查询System.out.println(stringRedisTemplate.opsForValue().get(name));}}
RedisTemplate 和 StringRedisTemplate 都是 Spring Data Redis 提供的模板类可以对 Redis 进行操作后者针对键值对都是 String 类型的数据前者可以是任何类型的对象。 RedisTemplate 和 StringRedisTemplate 除了提供 opsForValue 方法来操作字符串之外还提供了以下方法 opsForList操作 listopsForSet操作 setopsForZSet操作有序 setopsForHash操作 hash
运行测试类后可以在控制台看到相关信息。
也可以通过 AnotherRedisDesktopManager 客户端查看 Redis 数据库中的数据 编程喵整合 Redis 编程喵是一个 Spring Boot Vue 的前后端分离项目要整合 Redis 的话最好的方式是使用 Spring Cache仅仅通过 Cacheable、CachePut、CacheEvict、EnableCaching 等注解就可以轻松使用 Redis 做缓存了 1EnableCaching 开启缓存功能。 2Cacheable 调用方法前去缓存中找找到就返回找不到就执行方法并将返回值放到缓存中。 3CachePut 方法调用前不会去缓存中找无论如何都会执行方法执行完将返回值放到缓存中。 4CacheEvict 清理缓存中的一个或多个记录。 Spring Cache 是 Spring 提供的一套完整的缓存解决方案虽然它本身没有提供缓存的实现但它提供的一整套接口、规范、配置、注解等可以让我们无缝衔接 Redis、Ehcache 等缓存实现。 Spring Cache 的注解前面提到的四个会在调用方法之后去缓存方法返回的最终结果或者在方法调用之前拿缓存中的结果当然还有删除缓存中的结果。 这些读写操作不用我们手动再去写代码实现了直接交给 Spring Cache 来打理就 OK 了是不是非常贴心
第一步在 pom.xml 文件中追加 Redis 的 starter。 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId
/dependency
第二步在 application.yml 文件中添加 Redis 链接配置。 spring:redis:host: 118.xx.xx.xxx # Redis服务器地址database: 0 # Redis数据库索引默认为0port: 6379 # Redis服务器连接端口password: xx # Redis服务器连接密码默认为空timeout: 1000ms # 连接超时时间毫秒 第三步新增 RedisConfig.java 类通过 RedisTemplate 设置 JSON 格式的序列化器这样的话存储到 Redis 里的数据将是有类型的 JSON 数据例如 EnableCaching
Configuration
public class RedisConfig extends CachingConfigurerSupport {Beanpublic RedisTemplateString, Object redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplateString, Object redisTemplate new RedisTemplate();redisTemplate.setConnectionFactory(redisConnectionFactory);// 通过 Jackson 组件进行序列化RedisSerializerObject serializer redisSerializer();// key 和 value// 一般来说 redis-key采用字符串序列化// redis-value采用json序列化 json的体积小可读性高不需要实现serializer接口。redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(serializer);redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(serializer);redisTemplate.afterPropertiesSet();return redisTemplate;}Beanpublic RedisSerializerObject redisSerializer() {//创建JSON序列化器Jackson2JsonRedisSerializerObject serializer new Jackson2JsonRedisSerializer(Object.class);ObjectMapper objectMapper new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// https://www.cnblogs.com/shanheyongmu/p/15157378.html// objectMapper.enableDefaultTyping()被弃用objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.WRAPPER_ARRAY);serializer.setObjectMapper(objectMapper);return serializer;}} 通过 RedisCacheConfiguration 设置超时时间来避免产生很多不必要的缓存数据。 Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {RedisCacheWriter redisCacheWriter RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);//设置Redis缓存有效期为1天RedisCacheConfiguration redisCacheConfiguration RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1));return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
第四步在标签更新接口中添加 CachePut 注解也就是说方法执行前不会去缓存中找但方法执行完会将返回值放入缓存中。
Controller
Api(tags 标签)
RequestMapping(/postTag)
public class PostTagController {Autowiredprivate IPostTagService postTagService;Autowiredprivate IPostTagRelationService postTagRelationService;RequestMapping(value /update, method RequestMethod.POST)ResponseBodyApiOperation(修改标签)CachePut(value codingmore, key codingmore:postags:#postAddTagParam.postTagId)public ResultObjectString update(Valid PostTagParam postAddTagParam) {if (postAddTagParam.getPostTagId() null) {return ResultObject.failed(标签id不能为空);}PostTag postTag postTagService.getById(postAddTagParam.getPostTagId());if (postTag null) {return ResultObject.failed(标签不存在);}QueryWrapperPostTag queryWrapper new QueryWrapper();queryWrapper.eq(description, postAddTagParam.getDescription());int count postTagService.count(queryWrapper);if (count 0) {return ResultObject.failed(标签名称已存在);}BeanUtils.copyProperties(postAddTagParam, postTag);return ResultObject.success(postTagService.updateById(postTag) ? 修改成功 : 修改失败);}
}
注意看 CachePut 注解这行代码
CachePut(value codingmore, key codingmore:postags:#postAddTagParam.postTagId)
value缓存名称也就是缓存的命名空间value 这里应该换成 namespace 更好一点key用于在命名空间中缓存的 key 值可以使用 SpEL 表达式比如说 codingmore:postags:#postAddTagParam.postTagId还有两个属性 unless 和 condition 暂时没用到分别表示条件符合则不缓存条件符合则缓存。
第五步启动服务器端启动客户端修改标签进行测试 使用 Redis 连接池 Redis 是基于内存的数据库本来是为了提高程序性能的但如果不使用 Redis 连接池的话建立连接、断开连接就需要消耗大量的时间。 用了连接池就可以实现在客户端建立多个连接需要的时候从连接池拿用完了再放回去这样就节省了连接建立、断开的时间。 要使用连接池我们得先了解 Redis 的客户端常用的有两种Jedis 和 Lettuce。 JedisSpring Boot 1.5.x 版本时默认的 Redis 客户端实现上是直接连接 Redis Server如果在多线程环境下是非线程安全的这时候要使用连接池为每个 jedis 实例增加物理连接LettuceSpring Boot 2.x 版本后默认的 Redis 客户端基于 Netty 实现连接实例可以在多个线程间并发访问一个连接实例不够的情况下也可以按需要增加连接实例。 它俩在 GitHub 上都挺受欢迎的大家可以按需选用。 我这里把两种客户端的情况都演示一下方便小伙伴们参考。 1Lettuce 第一步修改 application-dev.yml添加 Lettuce 连接池配置pool 节点。 spring:redis:lettuce:pool:max-active: 8 # 连接池最大连接数max-idle: 8 # 连接池最大空闲连接数min-idle: 0 # 连接池最小空闲连接数max-wait: -1ms # 连接池最大阻塞等待时间负值表示没有限制 第二步在 pom.xml 文件中添加 commons-pool2 依赖否则会在启动的时候报 ClassNotFoundException 的错。这是因为 Spring Boot 2.x 里默认没启用连接池。
Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoolConfigat java.net.URLClassLoader.findClass(URLClassLoader.java:381)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)at java.lang.ClassLoader.loadClass(ClassLoader.java:357)... 153 common frames omitted 添加 commons-pool2 依赖
dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-pool2/artifactIdversion2.6.2/versiontypejar/typescopecompile/scope
/dependency 重新启动服务在 RedisConfig 类的 redisTemplate 方法里对 redisTemplate 打上断点debug 模式下可以看到连接池的配置信息redisConnectionFactory→clientConfiguration→poolConfig。如下图所示。 如果在 application-dev.yml 文件中没有添加 Lettuce 连接池配置的话是不会看到 2Jedis 第一步在 pom.xml 文件中添加 Jedis 依赖去除 Lettuce 默认依赖。
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactIdexclusionsexclusiongroupIdio.lettuce/groupIdartifactIdlettuce-core/artifactId/exclusion/exclusions
/dependencydependencygroupIdredis.clients/groupIdartifactIdjedis/artifactId
/dependency 第二步修改 application-dev.yml添加 Jedis 连接池配置。 spring:redis:jedis:pool:max-active: 8 # 连接池最大连接数max-idle: 8 # 连接池最大空闲连接数min-idle: 0 # 连接池最小空闲连接数max-wait: -1ms # 连接池最大阻塞等待时间负值表示没有限制 启动服务后观察 redisTemplate 的 clientConfiguration 节点可以看到它的值已经变成 DefaultJedisClientConfiguration 对象了。 当然了也可以不配置 Jedis 客户端的连接池走默认的连接池配置。因为 Jedis 客户端默认增加了连接池的依赖包在 pom.xml 文件中点开 Jedis 客户端依赖可以查看到。 自由操作 Redis Spring Cache 虽然提供了操作 Redis 的便捷方法比如我们前面演示的 CachePut 注解但注解提供的操作非常有限比如说它只能保存返回值到缓存中而返回值并不一定是我们想要保存的结果。 与其保存这个返回给客户端的 JSON 信息我们更想保存的是更新后的标签。那该怎么自由地操作 Redis 呢 第一步增加 RedisService 接口
package com.codingmore.service;import java.util.List;
import java.util.Map;
import java.util.Set;/*** redis操作Service*/
public interface IRedisService {/*** 保存属性*/void set(String key, Object value, long time);/*** 保存属性*/void set(String key, Object value);/*** 获取属性*/Object get(String key);/*** 删除属性*/Boolean del(String key);/*** 批量删除属性*/Long del(ListString keys);/*** 设置过期时间*/Boolean expire(String key, long time);/*** 获取过期时间*/Long getExpire(String key);/*** 判断是否有该属性*/Boolean hasKey(String key);/*** 按delta递增*/Long incr(String key, long delta);/*** 按delta递减*/Long decr(String key, long delta);/*** 获取Hash结构中的属性*/Object hGet(String key, String hashKey);/*** 向Hash结构中放入一个属性*/Boolean hSet(String key, String hashKey, Object value, long time);/*** 向Hash结构中放入一个属性*/void hSet(String key, String hashKey, Object value);/*** 直接获取整个Hash结构*/MapObject, Object hGetAll(String key);/*** 直接设置整个Hash结构*/Boolean hSetAll(String key, MapString, Object map, long time);/*** 直接设置整个Hash结构*/void hSetAll(String key, MapString, Object map);/*** 删除Hash结构中的属性*/void hDel(String key, Object... hashKey);/*** 判断Hash结构中是否有该属性*/Boolean hHasKey(String key, String hashKey);/*** Hash结构中属性递增*/Long hIncr(String key, String hashKey, Long delta);/*** Hash结构中属性递减*/Long hDecr(String key, String hashKey, Long delta);/*** 获取Set结构*/SetObject sMembers(String key);/*** 向Set结构中添加属性*/Long sAdd(String key, Object... values);/*** 向Set结构中添加属性*/Long sAdd(String key, long time, Object... values);/*** 是否为Set中的属性*/Boolean sIsMember(String key, Object value);/*** 获取Set结构的长度*/Long sSize(String key);/*** 删除Set结构中的属性*/Long sRemove(String key, Object... values);/*** 获取List结构中的属性*/ListObject lRange(String key, long start, long end);/*** 获取List结构的长度*/Long lSize(String key);/*** 根据索引获取List中的属性*/Object lIndex(String key, long index);/*** 向List结构中添加属性*/Long lPush(String key, Object value);/*** 向List结构中添加属性*/Long lPush(String key, Object value, long time);/*** 向List结构中批量添加属性*/Long lPushAll(String key, Object... values);/*** 向List结构中批量添加属性*/Long lPushAll(String key, Long time, Object... values);/*** 从List结构中移除属性*/Long lRemove(String key, long count, Object value);/*** 获取数量* param keyPrefix* return*/int countKey(String keyPrefix);
} 第二步增加 RedisServiceImpl 实现类 package com.codingmore.service.impl;import com.codingmore.service.IRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;/*** redis操作实现类*/
Service
public class RedisServiceImpl implements IRedisService {Autowiredprivate RedisTemplateString, Object redisTemplate;Overridepublic void set(String key, Object value, long time) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);}Overridepublic void set(String key, Object value) {redisTemplate.opsForValue().set(key, value);}Overridepublic Object get(String key) {return redisTemplate.opsForValue().get(key);}Overridepublic Boolean del(String key) {return redisTemplate.delete(key);}Overridepublic Long del(ListString keys) {return redisTemplate.delete(keys);}Overridepublic Boolean expire(String key, long time) {return redisTemplate.expire(key, time, TimeUnit.SECONDS);}Overridepublic Long getExpire(String key) {return redisTemplate.getExpire(key, TimeUnit.SECONDS);}Overridepublic Boolean hasKey(String key) {return redisTemplate.hasKey(key);}Overridepublic Long incr(String key, long delta) {return redisTemplate.opsForValue().increment(key, delta);}Overridepublic Long decr(String key, long delta) {return redisTemplate.opsForValue().increment(key, -delta);}Overridepublic Object hGet(String key, String hashKey) {return redisTemplate.opsForHash().get(key, hashKey);}Overridepublic Boolean hSet(String key, String hashKey, Object value, long time) {redisTemplate.opsForHash().put(key, hashKey, value);return expire(key, time);}Overridepublic void hSet(String key, String hashKey, Object value) {redisTemplate.opsForHash().put(key, hashKey, value);}Overridepublic MapObject, Object hGetAll(String key) {return redisTemplate.opsForHash().entries(key);}Overridepublic Boolean hSetAll(String key, MapString, Object map, long time) {redisTemplate.opsForHash().putAll(key, map);return expire(key, time);}Overridepublic void hSetAll(String key, MapString, Object map) {redisTemplate.opsForHash().putAll(key, map);}Overridepublic void hDel(String key, Object... hashKey) {redisTemplate.opsForHash().delete(key, hashKey);}Overridepublic Boolean hHasKey(String key, String hashKey) {return redisTemplate.opsForHash().hasKey(key, hashKey);}Overridepublic Long hIncr(String key, String hashKey, Long delta) {return redisTemplate.opsForHash().increment(key, hashKey, delta);}Overridepublic Long hDecr(String key, String hashKey, Long delta) {return redisTemplate.opsForHash().increment(key, hashKey, -delta);}Overridepublic SetObject sMembers(String key) {return redisTemplate.opsForSet().members(key);}Overridepublic Long sAdd(String key, Object... values) {return redisTemplate.opsForSet().add(key, values);}Overridepublic Long sAdd(String key, long time, Object... values) {Long count redisTemplate.opsForSet().add(key, values);expire(key, time);return count;}Overridepublic Boolean sIsMember(String key, Object value) {return redisTemplate.opsForSet().isMember(key, value);}Overridepublic Long sSize(String key) {return redisTemplate.opsForSet().size(key);}Overridepublic Long sRemove(String key, Object... values) {return redisTemplate.opsForSet().remove(key, values);}Overridepublic ListObject lRange(String key, long start, long end) {return redisTemplate.opsForList().range(key, start, end);}Overridepublic Long lSize(String key) {return redisTemplate.opsForList().size(key);}Overridepublic Object lIndex(String key, long index) {return redisTemplate.opsForList().index(key, index);}Overridepublic Long lPush(String key, Object value) {return redisTemplate.opsForList().rightPush(key, value);}Overridepublic Long lPush(String key, Object value, long time) {Long index redisTemplate.opsForList().rightPush(key, value);expire(key, time);return index;}Overridepublic Long lPushAll(String key, Object... values) {return redisTemplate.opsForList().rightPushAll(key, values);}Overridepublic Long lPushAll(String key, Long time, Object... values) {Long count redisTemplate.opsForList().rightPushAll(key, values);expire(key, time);return count;}Overridepublic Long lRemove(String key, long count, Object value) {return redisTemplate.opsForList().remove(key, count, value);}Overridepublic int countKey(String keyPrefix) {return redisTemplate.keys(keyPrefix).size();}
}第三步在标签 PostTagController 中增加 Redis 测试用接口 simpleTest Controller
Api(tags 标签)
RequestMapping(/postTag)
public class PostTagController {Autowiredprivate IPostTagService postTagService;Autowiredprivate IPostTagRelationService postTagRelationService;Autowiredprivate RedisService redisService;RequestMapping(value /simpleTest, method RequestMethod.POST)ResponseBodyApiOperation(修改标签/Redis 测试用)public ResultObjectPostTag simpleTest(Valid PostTagParam postAddTagParam) {if (postAddTagParam.getPostTagId() null) {return ResultObject.failed(标签id不能为空);}PostTag postTag postTagService.getById(postAddTagParam.getPostTagId());if (postTag null) {return ResultObject.failed(标签不存在);}QueryWrapperPostTag queryWrapper new QueryWrapper();queryWrapper.eq(description, postAddTagParam.getDescription());int count postTagService.count(queryWrapper);if (count 0) {return ResultObject.failed(标签名称已存在);}BeanUtils.copyProperties(postAddTagParam, postTag);boolean successFlag postTagService.updateById(postTag);String key redis:simple: postTag.getPostTagId();redisService.set(key, postTag);PostTag cachePostTag (PostTag) redisService.get(key);return ResultObject.success(cachePostTag);}}
第四步重启服务使用 Knife4j 测试该接口