<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
关于 SpringBoot
中配置 Redis
,本文不在赘述,请看:SpringBoot2.0.X配置Redis,本文配置也是在这个上面进行改造的。
1、启用缓存,在 Application
上添加 @EnableCaching
注解。
/*
* 启用缓存功能
* */
@EnableCaching
public class BuildingApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(BuildingApplication.class);
SpringApplication.run(BuildingApplication.class, args);
}
}
2、使 RedisConfig
继承 CachingConfigurerSupport
,重写 keyGenerator
方法,并缓存配置管理器
。
RedisConfig.java
/**
* Redis配置
*
* 创建人:leigq
* 创建时间:2018-11-08 10:11
*
* 修改人:
* 修改时间:
* 修改备注:
*
*/
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
/**
* 自定义缓存key的生成策略。默认的生成策略是看不懂的(乱码内容) 通过Spring 的依赖注入特性进行自定义的配置注入并且此类是一个配置类可以更多程度的自定义配置
*
* 配置参考:https://www.cnblogs.com/taiyonghai/p/9454764.html
*
* 使用参考:
*
*
*/
@Bean(name = "redisCacheKeyGenerator")
@Primary
@Override
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(obj.toString());
}
return sb.toString();
};
}
/**
* 缓存配置管理器
*/
@Bean(name = "redisCacheManager")
@Primary
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 以锁写入的方式创建RedisCacheWriter对象
RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(redisConnectionFactory);
/*
设置CacheManager的Value序列化方式为Jackson2JsonRedisSerialize,
RedisCacheConfiguration默认就是使用
StringRedisSerializer序列化key,
JdkSerializationRedisSerializer序列化value,
*/
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
objMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objMapper);
RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer);
// 创建默认缓存配置对象
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
return new RedisCacheManager(writer, config);
}
}
完整配置如下:
package com.blog.www.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Redis配置
*
* 创建人:leigq
* 创建时间:2018-11-08 10:11
*
* 修改人:
* 修改时间:
* 修改备注:
*
*/
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
/**
* 使用 JacksonConfig 中的 objMapper,兼容 java8 时间
*
* @see JacksonConfig#getObjMapper()
*/
private final ObjectMapper objMapper;
public RedisConfig(@Qualifier(value = "objMapper") ObjectMapper objMapper) {
this.objMapper = objMapper;
}
/**
* 自定义缓存key的生成策略。默认的生成策略是看不懂的(乱码内容) 通过Spring 的依赖注入特性进行自定义的配置注入并且此类是一个配置类可以更多程度的自定义配置
*
* 配置参考:https://www.cnblogs.com/taiyonghai/p/9454764.html
*
* 使用参考:
*
*
*/
@Bean(name = "redisCacheKeyGenerator")
@Primary
@Override
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(obj.toString());
}
return sb.toString();
};
}
/**
* 缓存配置管理器
*/
@Bean(name = "redisCacheManager")
@Primary
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 以锁写入的方式创建RedisCacheWriter对象
RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(redisConnectionFactory);
/*
设置CacheManager的Value序列化方式为Jackson2JsonRedisSerialize,
RedisCacheConfiguration默认就是使用
StringRedisSerializer序列化key,
JdkSerializationRedisSerializer序列化value,
*/
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
objMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objMapper);
RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer);
// 创建默认缓存配置对象
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
return new RedisCacheManager(writer, config);
}
/**
* redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类, 生产环境不建议这样
*
* 参考:https://blog.csdn.net/m0_37893932/article/details/78259288
*
创建人: leigq
*
创建时间: 2018-11-08 10:12
*
*
* @param redisConnectionFactory redis连接工厂
* @return RedisTemplate
*/
@Bean(value = "redisTemp")
@Primary
public RedisTemplate<Object, Object> getRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
objMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objMapper);
// 以下代码为将 RedisTemplate 的 Value 序列化方式由 JdkSerializationRedisSerializer更换为 Jackson2JsonRedisSerializer
// 此种序列化方式结果清晰、容易阅读、存储字节少、速度快,所以推荐更换
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// 设置 key 的序列化规则
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
// 是否启用事务
// redisTemplate.setEnableTransactionSupport(true);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
写个简单的根据用户id查询用户信息,使用 @Cacheable
注解来缓存,cacheNames
为缓存名称(必填),cacheManager
、keyGenerator
用我们刚才在 RedisConfig.java
中配置的。
// 确实可以缓存, @Cache* 注解使用详解:http://blog.didispace.com/springbootcache1/
@Cacheable(cacheNames = {"users"}, cacheManager = "redisCacheManager", keyGenerator = "redisCacheKeyGenerator")
public User getUser(Long id) {
return userMapper.selectByPrimaryKey(id);
}
package com.blog.www;
import com.blog.www.base.BaseApplicationTests;
import com.blog.www.domain.entity.User;
import com.blog.www.service.UserService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
/**
* Redis 缓存测试
*
* 创建人:leigq
* 创建时间:2018-12-08 14:48
*
* 修改人:
* 修改时间:
* 修改备注:
*
*/
public class RedisCacheTest extends BaseApplicationTests {
@Autowired
private CacheManager cacheManager;
@Autowired
private UserService userService;
/**
* 用户缓存测试
*/
@Test
public void cacheUserTest() {
// 可根据cacheManager查看具体使用哪种缓存
log.warn(cacheManager.getCache("user").getName());
User user1 = userService.getUser(1L);
User user2 = userService.getUser(1L);
User user3 = userService.getUser(1L);
log.warn("user1 is [{}]", user1);
log.warn("user2 is [{}]", user2);
log.warn("user3 is [{}]", user3);
}
}
BaseApplicationTests.java
package com.blog.www.base;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 测试基类,其他类继承此类
*
* @author :leigq
* @date :2019/8/13 17:17
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public abstract class BaseApplicationTests {
protected Logger log = LoggerFactory.getLogger(this.getClass());
private Long time;
@Before
public void setUp() {
this.time = System.currentTimeMillis();
log.info("==> 测试开始执行 <==");
}
@After
public void tearDown() {
log.info("==> 测试执行完成,耗时:{} ms <==", System.currentTimeMillis() - this.time);
}
}
测试结果如下:
我的项目是使用 MyBatis
并且打开了SQL执行日志打印,可以看到,第一次查询打印了SQL,第2、3次的时候没打印,说明第2、3次直接走的缓存。
注解使用详解:http://blog.didispace.com/springbootcache1/