一、前言
基于org.springframework.cache.CacheManager和org.springframework.cache.annotation.Cacheable代码和注解方式实现redis缓存使用,详情如下代码说明(完整代码示例下载)
二、代码说明
getUserBy方法 - 注解代码方式 、getUserById缓存cacheManager.getCache(CACHE_NAME).get(userId)代码方式
package com.meizhi.service;@b@@b@import cn.hutool.core.util.RandomUtil;@b@import com.meizhi.config.CacheManagerConfig;@b@import com.meizhi.mapper.UserMapper;@b@import com.meizhi.model.User;@b@import lombok.extern.slf4j.Slf4j;@b@import org.springframework.beans.factory.annotation.Autowired;@b@import org.springframework.cache.Cache;@b@import org.springframework.cache.CacheManager;@b@import org.springframework.cache.annotation.CacheConfig;@b@import org.springframework.cache.annotation.CacheEvict;@b@import org.springframework.cache.annotation.CachePut;@b@import org.springframework.cache.annotation.Cacheable;@b@import org.springframework.data.redis.core.RedisTemplate;@b@import org.springframework.stereotype.Service;@b@@b@@Service@b@@CacheConfig(cacheNames = "user")@b@@Slf4j@b@public class UserService {@b@@b@ @Autowired@b@ private UserMapper userMapper;@b@@b@ @Autowired@b@ private CacheManager cacheManager;@b@@b@ @Autowired@b@ private RedisTemplate<String, Object> redisTemplate;@b@@b@ // 简单来说这个 CACHE_NAME 的作用就是指当前的缓存操作的 key 的前缀都是 "user::"@b@ private static final String CACHE_NAME = CacheManagerConfig.USER_CACHE_NAME;@b@@b@@b@ @Cacheable(value = "getUserBy", key = "#user.userId", unless = "#result == null")@b@ public User getUserBy(User user) {@b@ log.info("getUserBy={}",user);@b@ try {@b@ // 真的去数据库中查询数据,查完以后存入缓存@b@ User userQuery = userMapper.selectById(user.getUserId());@b@ return userQuery;@b@ } catch (Exception e) {@b@ e.printStackTrace();@b@ return null;@b@ }@b@ }@b@@b@@b@ /**@b@ * 根据 id 查询用户详情的接口@b@ * 使用布隆过滤器防止缓存穿透@b@ * 使用加锁、限流解决缓存雪崩@b@ */@b@ public User getUserById(Integer userId) {@b@ // 从缓存中读取@b@ Cache.ValueWrapper valueWrapper = cacheManager.getCache(CACHE_NAME).get(userId);@b@ if (valueWrapper != null) {@b@ System.err.println("从缓存中得到数据");@b@ return (User) valueWrapper.get();@b@ }@b@@b@ try {@b@ // 真的去数据库中查询数据,查完以后存入缓存@b@ User user = userMapper.selectById(userId);@b@ if (user != null) {@b@ cacheManager.getCache(CACHE_NAME).put(userId, user);@b@ }@b@ return user;@b@ } catch (Exception e) {@b@ e.printStackTrace();@b@ return null;@b@ }@b@ }@b@@b@@b@ /**@b@ * 添加接口@b@ * 由于是使用 userId 作为 key ,但是 id 又是添加后才得到的,所以不能直接使用 @cachePut 注解@b@@b@ */@b@ public User userAdd() {@b@ User user = new User();@b@ user.setUsername("许强" + RandomUtil.randomInt(100));@b@ userMapper.insert(user);@b@@b@ redisTemplate.opsForValue().set("user::" + user.getUserId(), user);@b@@b@ return user;@b@ }@b@@b@@b@ /**@b@ * 更新接口@b@ * @CachePut 应用到写数据的方法上,如新增/修改方法,调用方法时会自动把该方法返回值放入缓存@b@ */@b@ @CachePut(key = "#user.userId")@b@ public User userUpdate(User user){@b@ userMapper.updateById(user);@b@ return user;@b@ }@b@@b@@b@@b@ /**@b@ * 删除用户@b@ * 删除的时候同时需要删除 redis 里的缓存数据@b@ * CacheEvict 注解的存在会使调用这个接口的时候删除 redis 里 key 为 user::userId 的数据@b@ * 由于配置了 @CacheConfig(cacheNames = "user") 所以 @CacheEvict(value = "user", key = "#userId") 不需要写 value 了@b@ */@b@ @CacheEvict(key = "#userId")@b@ public boolean userDelete(Integer userId) {@b@ int i = userMapper.deleteById(userId);@b@ return i == 1;@b@ }@b@@b@@b@@b@@b@}