这里写自定义目录标题
- 一、引入依赖
- 二、修改启动类和配置文件
- 三、添加配置类
- 四、缓存示例
一、引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><optional>true</optional></dependency>
二、修改启动类和配置文件
@EnableCaching
public class WebApplication extends SpringBootServletInitializer
spring:cache:type: redisredis:# Redis数据库索引(默认为0)database: 0# Redis服务器地址host: 127.0.0.1# Redis服务器连接端口port: 6379# Redis服务器连接密码(默认为空)password:# 连接超时时间(毫秒)timeout: 1000
三、添加配置类
package com.ffcs.config;import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** @author 天真热* @create 2022-09-24 13:37* @desc**/
@Configuration
public class RedisConfiguration {// ${cache} 获取配置文件的配置信息 #{}是spring表达式,获取Bean对象的属性
// @Value("#{${cache}}")
// private Map<String, Long> ttlParams;/*** @param redisConnectionFactory* @功能描述 redis作为缓存时配置缓存管理器CacheManager,主要配置序列化方式、自定义* <p>* 注意:配置缓存管理器CacheManager有两种方式:* 方式1:通过RedisCacheConfiguration.defaultCacheConfig()获取到默认的RedisCacheConfiguration对象,* 修改RedisCacheConfiguration对象的序列化方式等参数【这里就采用的这种方式】* 方式2:通过继承CachingConfigurerSupport类自定义缓存管理器,覆写各方法,参考:* https://blog.csdn.net/echizao1839/article/details/102660649* <p>* 切记:在缓存配置类中配置以后,yaml配置文件中关于缓存的redis配置就不会生效,如果需要相关配置需要通过@value去读取*/@Beanpublic CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();redisCacheConfiguration = redisCacheConfiguration// 设置key采用String的序列化方式.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer.UTF_8))//设置value序列化方式采用jackson方式序列化.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer()))//全局配置缓存过期时间【可以不配置】//.entryTtl(Duration.ofMinutes(30L))//当value为null时不进行缓存.disableCachingNullValues();//专门指定某些缓存空间的配置,如过期时间【主要这里的key为缓存空间名称】
// Map<String, RedisCacheConfiguration> map = new HashMap<>();
// Set<Map.Entry<String, Long>> entries = ttlParams.entrySet();
// for (Map.Entry<String, Long> entry : entries) {
// //指定特定缓存空间对应的过期时间
// map.put("user", redisCacheConfiguration.entryTtl(Duration.ofSeconds(40)));
// map.put(entry.getKey(), redisCacheConfiguration.entryTtl(Duration.ofSeconds(entry.getValue())));
// }return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(redisCacheConfiguration) //默认配置
// .withInitialCacheConfigurations(map) //某些缓存空间的特定配置.build();}/*** 自定义缓存的redis的KeyGenerator【key生成策略】* 注意: 该方法只是声明了key的生成策略,需在@Cacheable注解中通过keyGenerator属性指定具体的key生成策略* 可以根据业务情况,配置多个生成策略* 如: @Cacheable(value = "key", keyGenerator = "cacheKeyGenerator")*/@Beanpublic KeyGenerator keyGenerator() {/*** target: 类* method: 方法* params: 方法参数*/return (target, method, params) -> {//获取代理对象的最终目标对象StringBuilder sb = new StringBuilder();sb.append(target.getClass().getSimpleName()).append(":");sb.append(method.getName()).append(":");//调用SimpleKey的key生成器Object key = SimpleKeyGenerator.generateKey(params);return sb.append(key);};}/*** @param redisConnectionFactory:配置不同的客户端,这里注入的redis连接工厂不同: JedisConnectionFactory、LettuceConnectionFactory* @功能描述 :配置Redis序列化,原因如下:* (1) StringRedisTemplate的序列化方式为字符串序列化,* RedisTemplate的序列化方式默为jdk序列化(实现Serializable接口)* (2) RedisTemplate的jdk序列化方式在Redis的客户端中为乱码,不方便查看,* 因此一般修改RedisTemplate的序列化为方式为JSON方式【建议使用GenericJackson2JsonRedisSerializer】*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = serializer();RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();// key采用String的序列化方式redisTemplate.setKeySerializer(StringRedisSerializer.UTF_8);// value序列化方式采用jacksonredisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);// hash的key也采用String的序列化方式redisTemplate.setHashKeySerializer(StringRedisSerializer.UTF_8);//hash的value序列化方式采用jacksonredisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);redisTemplate.setConnectionFactory(redisConnectionFactory);return redisTemplate;}/*** 此方法不能用@Ben注解,避免替换Spring容器中的同类型对象*/public GenericJackson2JsonRedisSerializer serializer() {return new GenericJackson2JsonRedisSerializer();}
}
四、缓存示例
-
简单测试
package com.ffcs.test.redis;import com.ffcs.test.mysql.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.text.SimpleDateFormat; import java.util.Date;/*** @author 天真热* @create 2024-02-19 19:42* @desc**/ @RestController @RequestMapping("/redis") public class RedisController {@AutowiredRedisService redisService;@RequestMapping("/test")public String test() {return redisService.getdata();} }
package com.ffcs.test.redis;import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.text.SimpleDateFormat; import java.util.Date;/*** @author 天真热* @create 2024-02-19 19:42* @desc**/ @Service public class RedisService {@Cacheable(value = "space", key = "'key'", sync = true)public String getdata() {SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sf.format(new Date());}}
-
新增缓存:只要在方法上备注了@Cacheable注解,每次调用,都会判断缓存中是否已经存在相应的数据,如果存在,则直接取出。如果不存在,则查询相关数据存入缓存,然后返回。
@Cacheable(value = "space", key = "key", sync = true), condition = "#id>1000")1)value:指定缓存的名称。可以根据业务来区分,使用自定义的业务名。//不设置则使用默认的缓存 2)key:指定缓存中的键。即一个缓存中,可以存在不同的键值,一般可以使用业务参数进行区分。//不设置则自动根据参数进行设置键 3)sync:用于指定是否使用异步模式来执行方法。如果设置为true,则方法的执行将在一个新的线程中进行,不会阻塞当前线程。//不设置默认为false 4)condition:根据条件判断是否生成缓存。//不设置则无条件过滤
-
更新缓存:只要在方法上备注了@CachePut注解,每次调用后,都会查询相关数据更新缓存,然后返回。一般修改了缓存值后,及时查数据时调用
@CachePut(value = "space", key = "'cache'") public Map updateCache() {}
-
删除缓存:只要在方法上备注了@CacheEvict注解,每次调用后,都会删除数据缓存。一般修改了缓存值后,不查数据时调用
-
升级用法之使用多个缓存:@Cacheable(value = {“space1”, “space2”})
-
升级用法之自定义缓存变量键
1)根据参数列表获取相关的键变量
@Cacheable(value = "space", key = "#id")public Map addCacheById(int id) {}#id 为参数列表名称为id的参数值
@Cacheable(value = "space", key = "#m.get('id')")public Map addCacheByMap(Map m) {}#map.get('id') 为参数列表名称为m的map集合,里面的id属性的值
2)根据方法对象获取相关的键变量
@Cacheable(value = "space", key = "#root.methodName+#root.args[0]+#root.method.name")1. #root表示当前方法对象 2. #root.methodName表示当前方法名称 3. #root.args[0]表示当前方法的第一个参数
-
升级用法之自定义缓存条件:参数用法如升级用法之自定义缓存变量键
-
升级用法之自定义缓存条件unless
@Cacheable(value = "space", key = "#id", unless = "#result==null") public Map addCacheByIdAndUnless(int id) {}我们正常的缓存,一般是在进入方法后,执行业务逻辑前,就进行判断是否需要使用缓存。如果需要在执行业务逻辑后在判断是否使用缓存,则可以使用上述的unless属性。
-
升级用法之自定义模板
@Cacheable(keyGenerator = "keyGenerator") public String addCacheByGenerator(int id) {}我们可以自己自定义模板。然后所有的缓存方法,都可以指定模板进行生成缓存和缓存键。可参考com.ffcs.biyiict.config.RedisConfiguration.keyGenerator
-
升级用法之删除多个缓存键
@Caching(evict = {@CacheEvict(value = {"space"}, key = "'1500'"),@CacheEvict(value = {"space"}, key = "'addCacheByMethod15addCacheByMethod'") }) public String delMuchCache() {}
-
升级用法之删除某个缓存及底下所有键
@CacheEvict(value = {"space"}, allEntries = true) public void delAllCacheOfValue() {}
-
升级用法之同时新增、修改、删除多个自定义缓存
@Caching(cacheable = {@Cacheable(value = "t1", key = "#id"), @Cacheable(value = "t2", key = "#id")},put = {@CachePut(value = "t3", key = "#id"), @CachePut(value = "t4", key = "#id")},evict = {@CacheEvict(value = "t5", key = "#id"), @CacheEvict(value = "t6", key = "#id")}) public String cacheMuchOperator(int id) {}