jedis操作起来始终不方便,所以我们这里采用springboot提供的data数据包 spring-boot-starter-data-redis,这个比起jedis更加方便,而且对key值和value值都做了序列化的处理
1:集成data-redis包(这里继续使用上个文章的项目)
相关版本依赖,这里建议不填写版本号,默认会获取springboot的版本号来进行拉取
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2:配置redis相关信息
redis:
url: 127.0.0.1
port: 6379
# redis如果设置了密码这里需要输入密码相关信息
# password: xxxx
3:书写redis 配置类;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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;
/**
* @Author hjq
*
* @Date 01/26/2019 14:21
*
* @Description //TODO
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
/**
* 生成key的策略
* @return
*/
@Override
@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();
}
};
}
/**
* 管理缓存
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheManager cacheManager = RedisCacheManager.create(factory);
return cacheManager;
}
/**
* RedisTemplate配置
*/
@Bean("template")
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;
}
}
3:书写测试方法
/**
* 测试 redis
* @return 测试数据
*/
@GetMapping("redisTest.do")
public String redisTest(){
//获取ValueOperations
ValueOperations<Serializable,Object> valueOperations = redisTemplate.opsForValue();
//进行存储操作
valueOperations.set("test","hello redis");
//获取刚刚存储的东西,返回给页面
return Objects.requireNonNull(valueOperations.get("test")).toString();
}
}
4:验证成功
使用redis.cli进行查看:
这里使用redis-cli取出数据为null的原因解释:因为Template中set值时会先调用序列化器将键和值都序列化为byte字节数组放入redis数据库中,在客户端除非get后的key为“test”使用同样的序列化器序列化后的值,否则取不到值。提出set源码方便理解;
final byte[] rawValue = this.rawValue(value);
this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.set(rawKey, rawValue);
return null;
}
}, true);
}
总结:
1:spring-data-redis可以通过及其简单的配置访问redis服务,对redis底层开发包(jedis,Jredis)进行了高度封装,让我们可以开箱即用;RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。
2: spring-data-redis针对jedis提供了如下功能:
连接池自动管理,提供了一个高度封装的“RedisTemplate”类
针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作
3:redis常用操作的工具类代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @Author hjq
*
* @Date 01/26/2019 14:23
*
* @Description //TODO redis的工具类
*/
@SuppressWarnings("unchecked")
public class RedisUtils {
@Autowired
public static RedisTemplate redisTemplate;
public RedisUtils(RedisTemplate redisTemplate) {
RedisUtils.redisTemplate = redisTemplate;
}
/**
* 写入缓存
* @param key
* @param value
* @return
*/
public static boolean set( final String key, Object value) {
return setObject(key, value, redisTemplate);
}
/**
* 写入缓存
* @param key
* @param value
* @return
*/
public static boolean set( final String key, Object value,RedisTemplate redisTemplate) {
return setObject(key, value, redisTemplate);
}
/**
* 写入缓存
* @param key
* @param value
* @param redisTemplate
* @return
*/
private static boolean setObject(String key, Object value, RedisTemplate redisTemplate) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 写入缓存设置时效时间
* @param key
* @param value
* @return
*/
public static boolean set(final String key, Object value, Long expireTime,RedisTemplate redisTemplate) {
return setWithTime(key, value, expireTime, redisTemplate);
}
/**
* 写入缓存设置时效时间
* @param key
* @param value
* @return
*/
private static boolean setWithTime(String key, Object value, Long expireTime, RedisTemplate redisTemplate) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 写入缓存设置时效时间
* @param key
* @param value
* @return
*/
public static boolean set(final String key, Object value, Long expireTime) {
return setWithTime(key, value, expireTime, redisTemplate);
}
/**
* 批量删除对应的value
* @param keys
*/
public static void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
}
/**
* 批量删除key
* @param pattern
*/
public static void removePattern(final String pattern) {
Set<Serializable> keys = redisTemplate.keys(pattern);
if (keys.size() > 0){
redisTemplate.delete(keys);
}
}
/**
* 删除对应的value
* @param key
*/
public static void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* 删除对应的value
* @param key
*/
public static void remove(final String key,RedisTemplate redisTemplate) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* 判断缓存中是否有对应的value
* @param key
* @return
*/
public static boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/**
* 读取缓存
* @param key
* @return
*/
public static Object get(final String key,RedisTemplate redisTemplate) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
/**
* 读取缓存
* @param key
* @return
*/
public static Object get(final String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
/**
* 哈希 添加
* @param key
* @param hashKey
* @param value
*/
public static void hmSet(String key, Object hashKey, Object value){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
hash.put(key,hashKey,value);
}
/**
* 哈希获取数据
* @param key
* @param hashKey
* @return
*/
public static Object hmGet(String key, Object hashKey){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
return hash.get(key,hashKey);
}
/**
* 列表添加
* @param k
* @param v
*/
public static void lPush(String k,Object v){
ListOperations<String, Object> list = redisTemplate.opsForList();
list.rightPush(k,v);
}
/**
* 列表获取
* @param k
* @param l
* @param l1
* @return
*/
public static List<Object> lRange(String k, long l, long l1){
ListOperations<String, Object> list = redisTemplate.opsForList();
return list.range(k,l,l1);
}
/**
* 集合添加
* @param key
* @param value
*/
public static void add(String key,Object value){
SetOperations<String, Object> set = redisTemplate.opsForSet();
set.add(key,value);
}
/**
* 集合获取
* @param key
* @return
*/
public static Set<Object> setMembers(String key){
SetOperations<String, Object> set = redisTemplate.opsForSet();
return set.members(key);
}
/**
* 有序集合添加
* @param key
* @param value
* @param scoure
*/
public static void zAdd(String key,Object value,double scoure){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.add(key,value,scoure);
}
/**
* 有序集合获取
* @param key
* @param scoure
* @param scoure1
* @return
*/
public static Set<Object> rangeByScore(String key,double scoure,double scoure1){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
return zset.rangeByScore(key, scoure, scoure1);
}
/**
* opsForList().range(key, start, end); 取范围值 redis里面的list下标从0开始
* 流程 拿到key 对应的list 取 0 到 5 和 mysql的limt 类似 注意下标即可
* 从redis list 里面的获取数据分页
* @param key redis list 对应的key
* @param start 开始下标
* @param end 介绍下标
* @return 返回list给前端
*/
public static List getListPage(String key, int start, int end){
return (List)redisTemplate.opsForList().range(key, start, end);
}
/**
* 使键值自增
* @param key
* @return
*/
public static Integer getIncrement(String key){
RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
Long increment = entityIdCounter.getAndIncrement();
return increment.intValue()+1;
}
}