在SpringBoot中使用Redis有两种方式,一种是使用Jredis,这是一个Client,得到实例后可以调用Redis的命令,使用上很简单明了,不过好像要自己处理下连接池
另一种是使用RedisTemplate,这个是被Spring封装了一次的,可以不关心连接池,在使用上又分为两种方式,一种是使用它封装的方法(类似于使用Jredis),另一种是使用注解方式
使用之前需要先添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
一、使用Jredis
使用Jredis需要先初始化连接池,然后从连接池中获取对象
JedisPool pool = new JedisPool("192.168.0.1",6379);
然后获取对象
Jedis jedis = jedisPool.getResource();
然后可以使用jedis调用Redis的命令
jedis.hset("hset","tem1","haha");
String str=jedis.get("string");
jedis封装了Redis的命令,命名和命令一致
二、使用RedisTeplate
使用RedisTeplate需要先创建一个他的配置类
在这里面主要求三个东西
第一个是CacheManager,在这里设置缓存的默认过期时间和某个缓存的过期时间(这个主要在使用注解方式时使用)
第二个是keyGenerator,这个是key生成规则,在这里写默认的(注解方式使用),也可以在写注解的时候定义
第三个是redisTemplate,这里谢了序列化方法,这里用的是json
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.payme.mbe.user.controller.UserController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... 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();
}
};
}
@SuppressWarnings("rawtypes")
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
//设置默认缓存过期时间
rcm.setDefaultExpiration(3600);//秒
rcm.setExpires(this.initExpiresMap());//设置某个缓存的过期时间
return rcm;
}
private Map<String, Long> initExpiresMap()
{
Map<String, Long> map= new HashMap<String, Long>();
map.put("users",100L);
return map;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
1、使用方法
写好上面那些之后,我们可以使用方法来操作Redis
先注入两个Template
@Autowired
private StringRedisTemplate stringRedisTemplate;//操作String型数据
@Autowired
private RedisTemplate redisTemplate;//操作其它类型数据
stringRedisTemplate.opsForValue().set("aaa", "111");//添加一个key为aaa,值为111的缓存
下面是一个插入对象的
UserEntity user=new UserEntity();//UserEntity需要implements Serializable
user.setUserid(11);
user.setUserName("admin");
//这两个是将User插入缓存,第二个自定义了过期时间
ValueOperations<String, UserEntity> operations=redisTemplate.opsForValue();
operations.set("com.neox", user);
operations.set("com.neo.f", user,10, TimeUnit.SECONDS);
//判断是否存在key
boolean exists=redisTemplate.hasKey("com.neo.f");
//操作List,方法名和命令名有些类似
redisTemplate.opsForList().rightPush("gllist","1");
redisTemplate.opsForList().rightPush("gllist","2");
String str = (String)redisTemplate.opsForList().leftPop("gllist");
long siz = redisTemplate.opsForList().size("testList");
//一次性在list中插入多个(List方式)
redisTemplate.opsForList().rightPushAll("testList",list);
使用这种方法的形式可以操作Redis,如果实现缓存逻辑,插入、取出、删除需要自己写,这样的方式和Jedris类似
2、使用注解
也可以使用注解的方式使用缓存,如果在一个GetInfo的方法上使用注解,方法会自动先去缓存找数据,找不到再执行方法体(去数据库找),获取后再加入缓存(如果使用上面的方式,这些逻辑要自己写)
有三个注解项
@Cacheable//这个注解放到Get方法上,实现先去缓存找数据,找不到执行方法体(数据库找数据),获取后插入到缓存
@CachePut//这个注解一般是放到更新语句上,实现的功能是更新缓存对应的值(但是注意更新这个直接把更新方法的返回值更新到缓存里,例如GetUser和UpdateUser,我们缓存的是UserInfo,但是如果UpdateUser的返回值是int,只表示成功失败,那这个注解会把UserInfo替换为int值,所以如果使用需要把函数返回值改为对象)
@CacheEvict//这个是删除对应的缓存,一般放到delete方法上(如果我们在所有修改的方法上都放这个也行,修改就删除,靠get更新缓存)
例如下面的几个方法
注解的两个参数value表示这类数据的缓存列表名称,例如上面配置了users的过期时间。key就是每个数据的缓存key值(下面方法中key定义的缓存key值最后会是"userentity1","userentity2"这样)
这个方法会先去缓存找数据,找不到执行方法获取数据,然后再插入缓存
@Cacheable(value = "users", key="'userentity'+#userID")
public UserEntity get(int userID) {
UserEntity u = userMapper.getOne(userID);//userRepository.get(userID);
if (u!=null)
{
logger.info("插入了- " + userID);
}
return u;
}
这个方法会删除缓存中对应key值得数据
@CacheEvict(value = "users", key="'userentity'+#userID")
public int delete(int userID) {
int result = userMapper.delete(userID); //userRepository.delete(userID);
return result;
}
更新方法我同样也做了删除数据
@CacheEvict(value = "users", key="'userentity'+#userEntity.userid")
public int update(UserEntity userEntity) {
int result = userMapper.update(userEntity);
return result;
}
到Redis里面数据会是这样
@Cacheable(value = "users", key="'userentity'+#userID")
public UserEntity get(int userID) {
UserEntity u = userMapper.getOne(userID);//userRepository.get(userID);
if (u!=null)
{
logger.info("CityServiceImpl.findCityById() : 插入了>> " + userID);
}
return u;
}