依赖
缓存依赖
<!-- 缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
配置类
package chang.redis.config;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
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;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* @author chang
*/
@EnableCaching
@Configuration
public class RedisCachingConfig {
/**
* @param redisConnectionFactory
* @功能描述 redis作为缓存时配置缓存管理器CacheManager,主要配置序列化方式、自定义
*
* 注意:配置缓存管理器CacheManager有两种方式:
* 方式1:通过RedisCacheConfiguration.defaultCacheConfig()获取到默认的RedisCacheConfiguration对象,修改RedisCacheConfiguration对象的序列化方式等参数【这里就采用的这种方式】
* 方式2:通过继承CachingConfigurerSupport类自定义缓存管理器,覆写各方法,参考:
*
* 切记:在缓存配置类中配置以后,yaml配置文件中关于缓存的redis配置就不会生效,如果需要相关配置需要通过@value去读取
*/
@Bean
public 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()))
//当value为null时不进行缓存
.disableCachingNullValues()
// 配置缓存空间名称的前缀
.prefixCacheNameWith("demo:")
//全局配置缓存过期时间【可以不配置】
.entryTtl(Duration.ofMinutes(30L));
//专门指定某些缓存空间的配置,如果过期时间【主要这里的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")
*/
@Bean
public 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);
};
}
/**
* 此方法不能用@Ben注解,避免替换Spring容器中的同类型对象
*/
public GenericJackson2JsonRedisSerializer serializer() {
return new GenericJackson2JsonRedisSerializer();
}
}
使用
具体怎么使用可以自行百度
例如:
package chang.web.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author chang
* @Date 2022/5/29 22:22
*/
@RestController
@RequestMapping("/cache")
public class CacheRedisController {
private static final Logger logger= LoggerFactory.getLogger(CacheRedisController.class);
@GetMapping("/t1")
public String t1(){
logger.info("执行Controller。");
return cacheTest("a");
}
@Cacheable(cacheNames = "hello")
public String cacheTest(String user_id){
logger.info("缓存执行了。");
return "缓存执行了。";
}
}
注意,坑
其实上面的代码缓存是没有生效的,原理和事务失效一样,没有被AOP代理,事务是无法生效的
正确演示
package chang.web.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author chang
* @Date 2022/5/29 22:22
*/
@RestController
@RequestMapping("/cache")
public class CacheRedisController {
private static final Logger logger= LoggerFactory.getLogger(CacheRedisController.class);
@GetMapping("/t1")
public String t1(){
logger.info("执行Controller。");
// AOP 代理
CacheRedisController cacheRedisController = (CacheRedisController)AopContext.currentProxy();
return cacheRedisController.cacheTest("a");
}
@Cacheable(cacheNames = "hello")
public String cacheTest(String user_id){
logger.info("缓存执行了。");
return "缓存执行了。";
}
}
不过这么写的话,需要引入AOP依赖,在启动类上加注解
或者你可以直接使用自动注入去使用方法就行了
// 注解
@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class SpringbootReadApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootReadApplication.class, args);
}
}
<!-- 使用 AopContext -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>