注: 本篇博客 SpringBoot 版本为 2.1.5.RELEASE,SpringBoot1.0 版本有些配置不适用
一, SpringBoot 配置 Redis
1.1 pom 引入 spring-boot-starter-data-Redis 包
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-Redis</artifactId>
- </dependency>
1.2 properties 配置文件配置 Redis 信息
默认连接本地 6379 端口的 Redis 服务, 一般需要修改配置, 例如:
- # Redis 数据库索引 (默认为 0)
- spring.Redis.database=0
- # Redis 服务器地址
- spring.Redis.host=127.0.0.1
- # Redis 服务器连接端口
- spring.Redis.port=6379
- # Redis 服务器连接密码 (默认为空)
- spring.Redis.password=
- # 连接池最大连接数 (使用负值表示没有限制)
- spring.Redis.jedis.pool.max-active=20
- # 连接池最大阻塞等待时间 (使用负值表示没有限制)
- spring.Redis.jedis.pool.max-wait=-1
- # 连接池中的最大空闲连接
- spring.Redis.jedis.pool.max-idle=10
- # 连接池中的最小空闲连接
- spring.Redis.jedis.pool.min-idle=0
- # 连接超时时间 (毫秒)
- spring.Redis.timeout=1000
二, RedisTemplate<K,V > 类的配置
Spring 封装了 RedisTemplate<K,V > 对象来操作 Redis.
2.1 Spring 对 RedisTemplate<K,V > 类的默认配置 (了解即可)
Spring 在 org.springframework.boot.autoconfigure.data.Redis.RedisAutoConfiguration 类下配置的两个 RedisTemplate 的 Bean.
(1) RedisTemplate<Object, Object>
这个 Bean 使用 JdkSerializationRedisSerializer 进行序列化, 即 key, value 需要实现 Serializable 接口, Redis 数据格式比较难懂, 例如
(2) StringRedisTemplate, 即 RedisTemplate<String, String>
key 和 value 都是 String. 当需要存储实体类时, 需要先转为 String, 再存入 Redis. 一般转为 JSON 格式的字符串, 所以使用 StringRedisTemplate, 需要手动将实体类转为 JSON 格式. 如
- ValueOperations<String, String> valueTemplate = stringTemplate.opsForValue();
- Gson gson = new Gson();
- valueTemplate.set("StringKey1", "hello spring boot redis, String Redis");
- String value = valueTemplate.get("StringKey1");
- System.out.println(value);
- valueTemplate.set("StringKey2", gson.toJson(new Person("theName", 11)));
- Person person = gson.fromJson(valueTemplate.get("StringKey2"), Person.class);
- System.out.println(person);
2.2 配置一个 RedisTemplate<String,Object > 的 Bean
Spring 配置的两个 RedisTemplate 都不太方便使用, 所以可以配置一个 RedisTemplate<String,Object> 的 Bean,key 使用 String 即可 (包括 Redis Hash 的 key),value 存取 Redis 时默认使用 JSON 格式转换. 如下
- @Bean(name = "template")
- public RedisTemplate<String, Object> template(RedisConnectionFactory factory) {
- // 创建 RedisTemplate<String, Object > 对象
- RedisTemplate<String, Object> template = new RedisTemplate<>();
- // 配置连接工厂
- template.setConnectionFactory(factory);
- // 定义 Jackson2JsonRedisSerializer 序列化对象
- Jackson2JsonRedisSerializer<Object> jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class);
- ObjectMapper om = new ObjectMapper();
- // 指定要序列化的域, field,get 和 set, 以及修饰符范围, ANY 是都有包括 private 和 public
- om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
- // 指定序列化输入的类型, 类必须是非 final 修饰的, final 修饰的类, 比如 String,Integer 等会报异常
- om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
- jacksonSeial.setObjectMapper(om);
- StringRedisSerializer stringSerial = new StringRedisSerializer();
- // Redis key 序列化方式使用 stringSerial
- template.setKeySerializer(stringSerial);
- // Redis value 序列化方式使用 jackson
- template.setValueSerializer(jacksonSeial);
- // Redis hash key 序列化方式使用 stringSerial
- template.setHashKeySerializer(stringSerial);
- // Redis hash value 序列化方式使用 jackson
- template.setHashValueSerializer(jacksonSeial);
- template.afterPropertiesSet();
- return template;
- }
所以可以这样使用
- @Autowired
- private RedisTemplate<String, Object> template;
- public void test002() {
- ValueOperations<String, Object> redisString = template.opsForValue();
- // SET key value: 设置指定 key 的值
- redisString.set("strKey1", "hello spring boot redis");
- // GET key: 获取指定 key 的值
- String value = (String) redisString.get("strKey1");
- System.out.println(value);
- redisString.set("strKey2", new User("ID10086", "theName", 11));
- User user = (User) redisString.get("strKey2");
- System.out.println(user);
- }
2.3 配置 Redis operations 的 Bean
RedisTemplate<K,V > 类以下方法, 返回值分别对应操作 Redis 的 String,List,Set,Hash 等, 可以将这些 operations 注入到 Spring 中, 方便使用
- /**
- * Redis string
- */
- @Bean
- public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
- return redisTemplate.opsForValue();
- }
- /**
- * Redis hash
- */
- @Bean
- public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
- return redisTemplate.opsForHash();
- }
- /**
- * Redis list
- */
- @Bean
- public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
- return redisTemplate.opsForList();
- }
- /**
- * Redis set
- */
- @Bean
- public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
- return redisTemplate.opsForSet();
- }
- /**
- * Redis zset
- */
- @Bean
- public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
- return redisTemplate.opsForZSet();
- }
三, RedisTemplate 类的 API 使用
RedisTemplate 是 Spring 封装的类, 它的 API 基本上对应了 Redis 的命令, 下面列举了一小部分的使用, 更多的请查看 Javadoc.
- @Autowired
- private HashOperations<String, String, Object> redisHash;// Redis Hash
- @Test
- public void test003() {
- Map<String, Object> map = new HashMap<>();
- map.put("id", "10010");
- map.put("name", "redis_name");
- map.put("amount", 12.34D);
- map.put("age", 11);
- redisHash.putAll("hashKey", map);
- // HGET key field 获取存储在哈希表中指定字段的值
- String name = (String) redisHash.get("hashKey", "name");
- System.out.println(name);
- // HGET key field
- Double amount = (Double) redisHash.get("hashKey", "amount");
- System.out.println(amount);
- // HGETALL key 获取在哈希表中指定 key 的所有字段和值
- Map<String, Object> map2 = redisHash.entries("hashKey");
- System.out.println(map2);
- // HKEYS key 获取在哈希表中指定 key 的所有字段
- Set<String> keySet = redisHash.keys("hashKey");
- System.out.println(keySet);
- // HVALS key 获取在哈希表中指定 key 的所有值
- List<Object> valueList = redisHash.values("hashKey");
- System.out.println(valueList);
- }
四, 使用 Redis 缓存数据库数据
Redis 有很多使用场景, 一个 demo 就是缓存数据库的数据. Redis 作为一个内存数据库, 存取数据的速度比传统的数据库快得多. 使用 Redis 缓存数据库数据, 可以减轻系统对数据库的访问压力, 及加快查询效率等好处. 下面讲解如何使用 SpringBoot + Redis 来缓存数据库数据 (这里数据库使用 MySQL).
4.1 配置 Redis 作为 Spring 的缓存管理
Spring 支持多种缓存技术: RedisCacheManager,EhCacheCacheManager,GuavaCacheManager 等, 使用之前需要配置一个 CacheManager 的 Bean. 配置好之后使用三个注解来缓存数据:@Cacheable,@CachePut 和 @CacheEvict. 这三个注解可以加 Service 层或 Dao 层的类名上或方法上 (建议加在 Service 层的方法上), 加上类上表示所有方法支持该注解的缓存; 三注解需要指定 Key, 以返回值作为 value 操作缓存服务. 所以, 如果加在 Dao 层, 当新增 1 行数据时, 返回数字 1, 会将 1 缓存到 Redis, 而不是缓存新增的数据.
RedisCacheManager 的配置如下:
- /**
- * <p>SpringBoot 配置 Redis 作为默认缓存工具 </p>
- * <p>SpringBoot 2.0 以上版本的配置 </p>
- */
- @Bean
- public CacheManager cacheManager(RedisTemplate<String, Object> template) {
- RedisCacheConfiguration defaultCacheConfiguration =
- RedisCacheConfiguration
- .defaultCacheConfig()
- // 设置 key 为 String
- .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getStringSerializer()))
- // 设置 value 为自动转 JSON 的 Object
- .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getValueSerializer()))
- // 不缓存 null
- .disableCachingNullValues()
- // 缓存数据保存 1 小时
- .entryTtl(Duration.ofHours(1));
- RedisCacheManager redisCacheManager =
- RedisCacheManagerBuilder
- // Redis 连接工厂
- .fromConnectionFactory(template.getConnectionFactory())
- // 缓存配置
- .cacheDefaults(defaultCacheConfiguration)
- // 配置同步修改或删除 put/evict
- .transactionAware()
- .build();
- return redisCacheManager;
- }
4.2 @Cacheabl,@CachePut,@CacheEvict 的使用
- package com.GitHub.Redis;
- import com.GitHub.mybatis.domain.User;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cache.annotation.CacheConfig;
- import org.springframework.cache.annotation.CacheEvict;
- import org.springframework.cache.annotation.CachePut;
- import org.springframework.cache.annotation.Cacheable;
- import org.springframework.stereotype.Service;
- import java.util.List;
- /**
- * 指定默认缓存区
- * 缓存区: key 的前缀, 与指定的 key 构成 Redis 的 key, 如 user::10001
- */
- @CacheConfig(cacheNames = "user")
- @Service
- public class RedisCacheUserService {
- @Autowired
- private UserDao dao;
- /**
- * @Cacheable 缓存有数据时, 从缓存获取; 没有数据时, 执行方法, 并将返回值保存到缓存中
- * @Cacheable 一般在查询中使用
- * 1) cacheNames 指定缓存区, 没有配置使用 @CacheConfig 指定的缓存区
- * 2) key 指定缓存区的 key
- * 3) 注解的值使用 SpEL 表达式
- * eq ==
- * lt < * le <=
- * gt>
- * ge>=
- */
- @Cacheable(cacheNames = "user", key = "#id")
- public User selectUserById(String id) {
- return dao.selectUserById(id);
- }
- @Cacheable(key="'list'")
- public List<User> selectUser() {
- return dao.selectUser();
- }
- /**
- * condition 满足条件缓存数据
- */
- @Cacheable(key = "#id", condition = "#number ge 20") //>= 20
- public User selectUserByIdWithCondition(String id, int number) {
- return dao.selectUserById(id);
- }
- /**
- * unless 满足条件时否决缓存数据
- */
- @Cacheable(key = "#id", unless = "#number lt 20") // < 20
- public User selectUserByIdWithUnless(String id, int number) {
- return dao.selectUserById(id);
- }
- /**
- * @CachePut 一定会执行方法, 并将返回值保存到缓存中
- * @CachePut 一般在新增和修改中使用
- */
- @CachePut(key = "#user.id")
- public User insertUser(User user) {
- dao.insertUser(user);
- return user;
- }
- @CachePut(key = "#user.id", condition = "#user.age ge 20")
- public User insertUserWithCondition(User user) {
- dao.insertUser(user);
- return user;
- }
- @CachePut(key = "#user.id")
- public User updateUser(User user) {
- dao.updateUser(user);
- return user;
- }
- /**
- * 根据 key 删除缓存区中的数据
- */
- @CacheEvict(key = "#id")
- public void deleteUserById(String id) {
- dao.deleteUserById(id);
- }
- /**
- * allEntries = true : 删除整个缓存区的所有值, 此时指定的 key 无效
- * beforeInvocation = true : 默认 false, 表示调用方法之后删除缓存数据; true 时, 在调用之前删除缓存数据 (如方法出现异常)
- */
- @CacheEvict(key = "#id", allEntries = true)
- public void deleteUserByIdAndCleanCache(String id) {
- dao.deleteUserById(id);
- }
- }
五, 项目地址
项目 GitHub 地址, 里面的测试类均有对上面涉及的内容进行测试. 喜欢的帮忙点个 Star
https://github.com/caizhaokai/spring-boot-demo
来源: http://www.bubuko.com/infodetail-3095880.html