> 文档中心 > Springboot+Redis优雅的实现分布式缓存附使用示例(redisTemplate及Annotation)(附源码下载)

Springboot+Redis优雅的实现分布式缓存附使用示例(redisTemplate及Annotation)(附源码下载)


Springboot-cli 开发脚手架系列

Springboot系列:Springboot+Redis优雅的实现分布式缓存(redisTemplate及Annotation)


文章目录

  • Springboot-cli 开发脚手架系列
  • 前言
    • 1. 环境
    • 2. 配置redisTemplate
    • 3. 编写实体,并实现序列化接口
    • 4. 测试手动存储
    • 5. 注解方式实现
    • 6. 源码分享

前言

致力于让开发者快速搭建基础环境并让应用跑起来,并提供使用示例供使用者参考,快速上手。
本博客项目源码地址:

  • 项目源码github地址
  • 项目源码国内gitee地址

1. 环境

  • 引入依赖pom.xml
      <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>  <dependency>     <groupId>org.springframework.session</groupId>     <artifactId>spring-session-data-redis</artifactId> </dependency>  <dependency>     <groupId>org.apache.commons</groupId>     <artifactId>commons-pool2</artifactId>     <version>2.10.0</version> </dependency>
  • application.yml
spring:  # redis 配置  redis:    database: 0    host: 127.0.0.1    port: 6379    #连接超时时间    timeout: 3000    password: 123456    #连接池配置    lettuce:      pool: max-active: 8 max-idle: 8 min-idle: 0 max-wait: -1

2. 配置redisTemplate

  • 编写RedisConfig.java配置,配置序列化方式
@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport {    /**     * RedisTemplate 默认使用 jdk 序列化,存在乱码等问题,将 value 的序列化方式换为 Jackson 后,value 中不再出现乱码。     */    @Bean    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); template.setKeySerializer(RedisSerializer.string()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setEnableTransactionSupport(true); return template;    }}
  • 封装RedisUtils.java
/** * Redis工具类 */@Component@Slf4jpublic class RedisUtils {    @Resource    private RedisTemplate<String, Object> rt;    private static RedisTemplate<String, Object> redisTemplate;    @PostConstruct    public void init() { // bean赋值给静态变量 redisTemplate = rt;    }    /**     * 存储     *     * @param cacheKey     缓存key     * @param value   值     * @param timeout 超时时间 秒     */    public static void save(String cacheKey, Object value, long timeout) { redisTemplate.opsForValue().set(cacheKey, value, timeout, TimeUnit.SECONDS);    }    public static void save(String cacheKey, Object value) { save(cacheKey, value, -1);    }    /**     * 获取     *     * @param cacheKey 缓存key     * @param c   返回值类型     * @return c类型的对象     */    public static <T> T get(String cacheKey, Class<T> c) { Object o = redisTemplate.opsForValue().get(cacheKey); return JSON.parseObject(JSON.toJSONString(o), c);    }    /**     * 缓存是否存在     *     * @param cacheKey 缓存key     * @return true 存在     */    public static boolean hasKey(String cacheKey) { return Boolean.TRUE.equals(redisTemplate.hasKey(cacheKey));    }    /**     * 添加到set集合     *     * @param cacheKey 缓存key     * @param value  值 一个或多个     */    public static void addForSet(String cacheKey, Object... value) { redisTemplate.opsForSet().add(cacheKey, value);    }    /**     * 获取set集合     *     * @param cacheKey 缓存     * @param c      返回值类型     * @return c类型的set集合     */    public static <T> Set<T> getForSet(String cacheKey, Class<T> c) { Set<Object> set = redisTemplate.boundSetOps(cacheKey).members(); if (Objects.isNull(set)) {     return null; } return set.stream().map(o -> JSON.parseObject(JSON.toJSONString(o), c)).collect(Collectors.toSet());    }    /**     * 设置过期时间     *     * @param cacheKey    缓存 key     * @param timeout 过期时间(秒)     */    public static void expire(String cacheKey, long timeout) { redisTemplate.expire(cacheKey, timeout, TimeUnit.MINUTES);    }    /**     * 删除指定缓存     *     * @param cacheKey 缓存key     */    public static Boolean delete(String cacheKey) { return redisTemplate.delete(cacheKey);    }    /**     * 指定元素删除     *     * @param cacheKey  缓存     * @param objKey 集合元素     */    public static void remove(String cacheKey,String objKey) { redisTemplate.boundSetOps(cacheKey).remove(objKey);    }}

3. 编写实体,并实现序列化接口

  • User.java
@Data@Accessors(chain = true)public class User implements Serializable {    private static final long serialVersionUID = 1L;    /**     * 用户id     */    private Long userId;    /**     * 用户名     */    private String username;    /**     * 性别     */    private String sex;    /**     * 备注     */    private String remark;}
  • 注意:实体一定要加上序列化
    Springboot+Redis优雅的实现分布式缓存附使用示例(redisTemplate及Annotation)(附源码下载)

4. 测试手动存储

  • 编写测试接口
@RestController@RequiredArgsConstructorpublic class IndexController {    /**     * 手动设置缓存     */    @GetMapping("/set")    public String set() { RedisUtils.save("key", new User().setUserId(999L).setSex("男").setUsername("王小锤"), 6000); return "设置成功 !";    }    /**     * 手动获取缓存     */    @GetMapping("/get")    public User get() { return RedisUtils.get("key", User.class);    }}
  • 启动项目浏览器输入ip+端口+/set 添加缓存
    Springboot+Redis优雅的实现分布式缓存附使用示例(redisTemplate及Annotation)(附源码下载)

  • ip+端口+/get 获取缓存
    Springboot+Redis优雅的实现分布式缓存附使用示例(redisTemplate及Annotation)(附源码下载)

5. 注解方式实现

  • 在前面配置RedisConfig.java中加入如下配置
   /**     * 此处重写·springboot注解方式·缓存的Key生成规则     * key=包+方法名+参数     */    @Override    @Bean    public KeyGenerator keyGenerator() { return (target, method, params) -> {     StringBuilder sb = new StringBuilder();     sb.append(target.getClass().getName());     sb.append(method.getName());     for (Object obj : params) {  sb.append(Objects.nonNull(obj) ? obj.toString() : "null");     }     System.out.println(sb);     return sb.toString(); };    }    /**     * 此处重写·springboot注解方式·缓存的序列化方式及有效时间     * key=包+方法名+参数     */    @Bean    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()  // 将::改写为一个:  .computePrefixWith(cacheName -> cacheName + ":")  // 设置缓存有效期24小时  .entryTtl(Duration.ofHours(24))  // 禁止空值  .disableCachingNullValues()  // 设置序列化规则  .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(connectionFactory)  .cacheDefaults(cacheConfiguration)  .build();    }
  • 编写service 接口层
  • IUserService.java
public interface IUserService {    /**     * 缓存测试     *     * @param id 用户id 随便输入     * @return 用户数据     */    User getUser(Long id);    /**     * 删除缓存测试     *     * @param id 用户id 随便输入     */    void delUser(Long id);}
  • 编写实现类UserServiceImpl.java,模拟数据库存储
  • 在我们需要用缓存的方法上添加@Cacheable(value = "user-key")
  • 需要刷新缓存的地方添加@CacheEvict(value = "user-key", allEntries = true)
@Service@Slf4jpublic class UserServiceImpl implements IUserService {    @Override    @Cacheable(value = "user-key")    public User getUser(Long id) { return this.getUserInfo(id);    }    @Override    @CacheEvict(value = "user-key", allEntries = true)    public void delUser(Long id) { this.delUserInfo(id);    }    public void delUserInfo(Long id) { log.info("删除{}用户数据执行了!!", id);    }    /**     * 模拟数据库查询     */    private User getUserInfo(Long id) { log.info("获取用户数据执行了!!"); return new User().setUserId(id).setUsername("王小锤").setSex("男").setRemark("注解方式aop实现缓存");    }}
  • 效果
    观察控制台我们可以发现,当我们查询的id一样时,只有第一次会触发getUserInfo方法,之后就会走缓存进行获取,只有当id不一样时,才会从新去调用getUserInfo方法。
    Springboot+Redis优雅的实现分布式缓存附使用示例(redisTemplate及Annotation)(附源码下载)

6. 源码分享

本项目已收录

  • Springboot-cli开发脚手架,集合各种常用框架使用案例,完善的文档,致力于让开发者快速搭建基础环境并让应用跑起来,并提供丰富的使用示例供使用者参考,快速上手。
  • 项目源码github地址
  • 项目源码国内gitee地址

Springboot+Redis优雅的实现分布式缓存附使用示例(redisTemplate及Annotation)(附源码下载) 创作打卡挑战赛 Springboot+Redis优雅的实现分布式缓存附使用示例(redisTemplate及Annotation)(附源码下载) 赢取流量/现金/CSDN周边激励大奖