redis使用

Redis的使用

一、Redis下载

redis的使用很简单,首先需要下载redis,在本机上或者是在远程服务器上下载均可,推荐使用docker的方式下载redis镜像。

二、spring boot环境配置

首先创建一个web项目,方便测试

maven配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

application.properties配置

//Redis数据库索引(默认为0)  
spring.redis.database=0  
//Redis服务器地址  
spring.redis.host=192.168.0.24  
//Redis服务器连接端口  
spring.redis.port=6379  
//Redis服务器连接密码(默认为空)  
spring.redis.password=  
//连接池最大连接数(使用负值表示没有限制)  
spring.redis.pool.max-active=200  
//连接池最大阻塞等待时间(使用负值表示没有限制)  
spring.redis.pool.max-wait=-1  
//连接池中的最大空闲连接  
spring.redis.pool.max-idle=10 
//连接池中的最小空闲连接  
spring.redis.pool.min-idle=0  
//连接超时时间(毫秒)  
spring.redis.timeout=1000 
我们只需要配置spring.redis.host和spring.redis.port即可使用,由于他们的默认值分别是localhost和6379,所以如果我们把redis下载到了本地,则什么都不用配置就可以直接使用redis。

三、RedisTemplate与StringRedisTemplate

StringRedisTemplate使用的是StringRedisSerializer来序列化String。

RedisTemplate使用的是JdkSerializationRedisSerializer来序列化对象。

StringRedisTemplate指定的范型是String,因此不能用来存储对象,当存入对象的时候会报错,而RedisTemplate可以存入对象,但是它是以二进制的方式进行存储的,如果不经过序列化,存入的数据完全没有可读性,如果要让数据有可读性,需要我们自己设置序列化的方式。

在实际开发中,大多数情况都是用StringRedisTemplate来操作,如果需要存入对象,先把对象转成jsonString,再存入redis中,使用的时候再转成需要的对象。

在有特定的需求,需要在redis中存入对象的时候,我们一般不用自带的RedisTemplate,因为
默认的这个类挺不好用的,它的范型是<Object, Object>的,因此每次都要写类型转换的代码。所以我们一般自定义一个RedisTemplate,范型是<String, Object>,并设置key和value的序列化方式,综合情况下考虑,key一般使用String的序列化方式,value一般使用jackson的序列化方式。

/**
 * create by bafan 2019/04/24
 * redis配置类
 */
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(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);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

}

Redis工具类

在开发中,一般会自己写工具类来封装RedisTemplate,这里只写了StringRedisTemplate的工具类,RedisTemplate的工具类与之类似。

@Component
public class RedisStringUtils {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**-------------------------------基础----------------------------------------*/

    /**
     * 指定缓存失效时间
     * @param key
     * @param time 时间(秒)
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if(time > 0) {
                return stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取缓存失效时间
     * @param key
     * @return
     */
    public long getExpire(String key) {
        return stringRedisTemplate.getExpire(key);
    }

    /**
     * 判断key是否存在
     * @param key
     * @return
     */
    public boolean hasKey(String key) {
        try {
            return stringRedisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     * @param key
     */
    public void del(String... key) {
        if(key != null && key.length > 0) {
            if(key.length == 1) {
                stringRedisTemplate.delete(key[0]);
            } else {
                stringRedisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    /**-------------------------------String----------------------------------------*/

    /**
     * 获取value
     * @param key
     * @return
     */
    public Object get(String key) {
        return key == null ? null : stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 缓存放入
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key, String value) {
        try {
            stringRedisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 缓存放入并设置过期时间
     * @param key
     * @param value
     * @param time
     * @return
     */
    public boolean set(String key, String value, long time) {
        try {
            stringRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     * @param key
     * @param delta
     * @return
     */
    public long incr(String key, long delta) {
        if(delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     * @param key
     * @param delta
     * @return
     */
    public long decr(String key, long delta) {
        if(delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return stringRedisTemplate.opsForValue().increment(key, -delta);
    }

}

测试

public class RedisTest {

    @Autowired
    private RedisStringUtils redisStringUtils;

    private User user = new User();

    @Before
    public void before() {
        user.setName("八幡");
        user.setAge(24);
    }

    /**
     * 测试普通字符串
     */
    @Test
    public void test1() {
        redisStringUtils.set("bafan1", "1");
        redisStringUtils.set("bafan2", "hello", 60);
        String bafan1 = (String)redisStringUtils.get("bafan1");
        String bafan2 = (String)redisStringUtils.get("bafan2");
        System.out.println(bafan1 + "..." + bafan2);
        boolean b1 = redisStringUtils.hasKey("bafan1");
        boolean b2 = redisStringUtils.hasKey("bafan3");
        System.out.println(b1 + "..." + b2);
        long expire1 = redisStringUtils.getExpire("bafan1");
        long expire2 = redisStringUtils.getExpire("bafan2");
        System.out.println(expire1 + "..." + expire2);
        redisStringUtils.incr("bafan1", 3l);
        //如果不是数字incr会报错
        //redisStringUtils.incr("bafan2", 3l);
        String bafan3 = (String)redisStringUtils.get("bafan1");
        String bafan4 = (String)redisStringUtils.get("bafan2");
        System.out.println(bafan3 + "..." + bafan4);
        redisStringUtils.decr("bafan1", 2l);
        String bafan5 = (String)redisStringUtils.get("bafan1");
        String bafan6 = (String)redisStringUtils.get("bafan2");
        System.out.println(bafan5 + "..." + bafan6);
        redisStringUtils.expire("bafan1", 100);
        long expire3 = redisStringUtils.getExpire("bafan1");
        System.out.println(expire3);
    }

    /**
     * 测试DTO类
     */
    @Test
    public void test2() {
        redisStringUtils.set("bafan3", JSON.toJSONString(user));
        Object o = redisStringUtils.get("bafan3");
        User user = JSON.parseObject(o.toString(), User.class);
        System.out.println(user.getName() + "..." + user.getAge());
    }

    /**
     * 测试Map
     */
    @Test
    public void test3() {
        Map<String, String> map = new HashMap<>();
        map.put("bafan1", "1");
        map.put("bafan2", "2");
        redisStringUtils.set("bafan4", JSON.toJSONString(map));
        Object o = redisStringUtils.get("bafan4");
        Map<String, String> map1 = JSON.parseObject(o.toString(), Map.class);
        System.out.println(map1);
    }

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容