SpringBoot项目整合Redis及遇到的问题
2018-05-27 本文已影响228人
作草分茶
1、Springboot整合redis所需的依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、redis相关配置bean。
新建redisconfig.java,继承自CachingConfigurerSupport。
- 配置redis key默认生成器。keyGenerator是默认的key生成器,这里用 包名+类名+方法名+所有参数生成key。
@Override
@Bean
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(".");
sb.append(method.getName());
for (Object obj : params) {
sb.append(".");
sb.append(obj.toString());
}
return sb.toString();
}
}
- 配置项目model的key的生成策略。用 包名+方法名+返回类名+model的Id。
@Bean
public KeyGenerator modelKeyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(".");
Class<?> clazz = method.getReturnType();
sb.append(clazz.getSimpleName());
sb.append(".");
try {
for (Object obj : params) {
if (obj instanceof Long) {
sb.append(obj.toString());
} else {
Class<?> superclass = obj.getClass().getSuperclass();
Field field = superclass.getDeclaredField("id");
if (field != null) {
field.setAccessible(true);
sb.append(field.get(obj).toString());
}
}
}
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
return sb.toString();
};
}
- 配置SpringBoot的缓存为RedisCacheManage。
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
Map<String, Long> map = new HashMap<>(2);
//token对应登录的账号,过期时间2小时
map.put(RedisKeys.TOKEN_ACCOUNT, 2L * 60 * 60);
//普通缓存,5分钟过期
map.put(RedisKeys.MODEL, 5L * 60);
cacheManager.setExpires(map);
return cacheManager;
}
- 配置RedisTemplate,后面通过代码操作redis需要用到。
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
//使用jdk自带的序列化
template.setValueSerializer(new JdkSerializationRedisSerializer());
return template;
}
3、在项目中使用Redis缓存。
- 使用java代码方式操作redis。
@Service
public class RedisHelper<T> implements IRedisHelper<T> {
private final RedisTemplate<String, Object> redisTemplate;
private final StringRedisTemplate stringRedisTemplate;
@Autowired
public RedisHelper(RedisTemplate<String, Object> redisTemplate, StringRedisTemplate stringRedisTemplate) {
this.redisTemplate = redisTemplate;
this.stringRedisTemplate = stringRedisTemplate;
}
@Override
@SuppressWarnings("unchecked")
public T getValue(String key) {
return (T) redisTemplate.opsForValue().get(key);
}
@Override
public void setValue(String key, T data) {
redisTemplate.opsForValue().set(key, data);
}
@Override
public String getString(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
@Override
public void setString(String key, String value) {
stringRedisTemplate.opsForValue().set(key,value);
}
}
- 注解方式操作redis。首先说下 @Cacheable、@CachePut和@CacheEvict的区别。
- @Cacheable:每次一执行该方法之前,都会在缓存中查找该key是否有所对应的缓存,如果有则在缓存中取出且不再进入该方法。如果没有则执行该方法,将返回值存到redis中。
- @CachePut:和@Cacheable不同,每次都会调用该方法,然后将返回值存到redis中。
- @CacheEvict:删除该key及所对应的value。
三个注解都有几个相同的属性。 - value:缓存名字。相当于分类,在CacheManage中可以配置缓存的过期时间。
- key:键的名字。可以根据业务自定义。
- keyGenerator:和key属性冲突,两者只能存在一个。根据所配置的keyGenerator生成key,如果key和keyGenerator都没有填,则按默认的keyGenerator生成key。
@Override
@CachePut(value = RedisKeys.TOKEN_ACCOUNT, key = "'token_account_'+#token")
public AccountEntity setIntoCacheByToken(String token, AccountEntity account) {
return account;
}
@Cacheable(value = RedisKeys.ROLE_RESOURCE_TREE)
public List<ResourceEntity> findResourceTreeByRoleId(Long roleId) {
RoleEntity role = roleService.findById(roleId);
return role.getResources();
}
4、开发过程中所遇到的坑。
- 使用@Cacheable和@CachePut注解方式时,注解所在的方法必须要有返回值,该返回值才是最后存到redis中的值。
- 使用注解方式时,两个方法不能相互嵌套,如果存在嵌套的话,则只有外层的方法生效。
- 注解方式和java代码方式灵活使用最好。最好是在一些不需要经常更新的数据或者从数据库中查询需要花费很长时间的情况下使用redis,不要为了使用缓存而用缓存,避免造成不必要的麻烦。