SpringBoot 操作 Redis 数据


简介




Redis 是一个开源的NoSQL数据库,基于内存的键值存储,速度快。Redis




5种主要数据类型:



字符串类型    string散列类型      hash列表类型      list集合类型      set有序集合类型  zset


Redis优缺点




直接基于内存读写,不用Redis直接用MySQL,先不说查询性能耗时,一个是直达一个是通过媒介,显而易见,Redis 速度很快 。不过Redis ,仅适用于键值对,并不能替代MySQL,虽然其有持久化,但是也可能会崩溃,损失几秒的数据




项目环境




项目工具环境:



IDE工具,这里是 Jetbrains IDEAMavenJDK1.8Redis 服务器


源码环境地址




https://github.com/Gleans/SpringBootLearn/tree/master/springboot-redis
后面的基于这个项目来操作




定义 RedisTemplate




RedisConfig.java




import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
        jedisConnectionFactory.setPassword("ekko1234");
        return jedisConnectionFactory;
    }

    @Bean
    public RedisTemplate redisTemplate() {
        final RedisTemplate redisTemplate = new RedisTemplate<>();
        RedisSerializer stringSerializer = new StringRedisSerializer();
        RedisSerializer jsonString = new GenericToStringSerializer<>(Object.class);
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(jsonString);
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(jsonString);return redisTemplate;
    }
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
        jedisConnectionFactory.setPassword("ekko1234");
        return jedisConnectionFactory;
    }

    @Bean
    public RedisTemplate redisTemplate() {
        final RedisTemplate redisTemplate = new RedisTemplate<>();
        RedisSerializer stringSerializer = new StringRedisSerializer();
        RedisSerializer jsonString = new GenericToStringSerializer<>(Object.class);
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(jsonString);
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(jsonString);return redisTemplate;
    }
}




操作 Redis 初体验




Spring Boot 的开箱即用的特点



集成 Redis 也是显而易见
在test环境新建测试类 TestRedis.java




import lombok.extern.slf4j.Slf4j;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

//根据测试方法名字搞定执行顺序
@Slf4j
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestRedis {

    private RedisTemplate redisTemplate;@Autowiredpublic void setRedisTemplate(RedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;
    }// 做下面的操作
}
import lombok.extern.slf4j.Slf4j;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

//根据测试方法名字搞定执行顺序
@Slf4j
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TestRedis {

    private RedisTemplate redisTemplate;@Autowiredpublic void setRedisTemplate(RedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;
    }// 做下面的操作
}




操作字符串




在测试类中操作字符串:




@Test
    public void operateStr(){
        // 存入 key为username  value 为 admin
        redisTemplate.opsForValue().set("username","admin");
        // 获取 key为username
        String username = (String) redisTemplate.opsForValue().get("username");
        System.out.println(username);
    }

    @Test
    public void operateStr(){
        // 存入 key为username  value 为 admin
        redisTemplate.opsForValue().set("username","admin");
        // 获取 key为username
        String username = (String) redisTemplate.opsForValue().get("username");
        System.out.println(username);
    }




执行过后发现存在redis中的数据:

电商类目redis缓存 redis缓存工具类_电商类目redis缓存




操作集合




opsForList()




@Test
    public void operateList() {
        List userList = new ArrayList<>();
        userList.add("张三");
        userList.add("李四");//循环向userlist左添加值
        userList.forEach(value -> redisTemplate.opsForList().leftPush("userlist", value));//向userlist右添加值
        redisTemplate.opsForList().rightPush("userlist", "麻子");
        log.info("删除前:userlist->{}", redisTemplate.opsForList().range("userlist", 0, 10));/*
          三个参数:
          - key redis中存 key值
          - count 从左或是从右删除,正左负右
          - value 就是需要从list移除的值
          */
        redisTemplate.opsForList().remove("userlist", 0, "麻子");
        log.info("删除后:userlist->{}", redisTemplate.opsForList().range("userlist", 0, 10));
    }
    @Test
    public void operateList() {
        List userList = new ArrayList<>();
        userList.add("张三");
        userList.add("李四");//循环向userlist左添加值
        userList.forEach(value -> redisTemplate.opsForList().leftPush("userlist", value));//向userlist右添加值
        redisTemplate.opsForList().rightPush("userlist", "麻子");
        log.info("删除前:userlist->{}", redisTemplate.opsForList().range("userlist", 0, 10));/*
          三个参数:
          - key redis中存 key值
          - count 从左或是从右删除,正左负右
          - value 就是需要从list移除的值
          */
        redisTemplate.opsForList().remove("userlist", 0, "麻子");
        log.info("删除后:userlist->{}", redisTemplate.opsForList().range("userlist", 0, 10));
    }




输出:




删除前:userlist->[李四, 张三, 麻子]
删除后:userlist->[李四, 张三]

删除前:userlist->[李四, 张三, 麻子]
删除后:userlist->[李四, 张三]




操作不可重复集合




opsForSet()




@Test
    public void operateSet(){
        List trap = new ArrayList<>();
        trap.add("工具人");
        trap.add("工具人");
        trap.add("工具人");
        trap.add("四块五的妞");
        trap.add("十元妹子");
        System.out.print(trap.toString());//循环向userlist左添加值
        trap.forEach(value->redisTemplate.opsForSet().add("userSet",value));
        log.info("删除前:userSet->{}",redisTemplate.opsForSet().members("userSet"));// 直接根据set的key值删除
        redisTemplate.opsForSet().remove("userSet","工具人");
        log.info("删除后:userSet->{}",redisTemplate.opsForSet().members("userSet"));
    }
    @Test
    public void operateSet(){
        List trap = new ArrayList<>();
        trap.add("工具人");
        trap.add("工具人");
        trap.add("工具人");
        trap.add("四块五的妞");
        trap.add("十元妹子");
        System.out.print(trap.toString());//循环向userlist左添加值
        trap.forEach(value->redisTemplate.opsForSet().add("userSet",value));
        log.info("删除前:userSet->{}",redisTemplate.opsForSet().members("userSet"));// 直接根据set的key值删除
        redisTemplate.opsForSet().remove("userSet","工具人");
        log.info("删除后:userSet->{}",redisTemplate.opsForSet().members("userSet"));
    }




输出:




删除前:userSet->[工具人, 工具人, 工具人, 四块五的妞, 十元妹子]
删除后:userSet->[四块五的妞, 十元妹子]

删除前:userSet->[工具人, 工具人, 工具人, 四块五的妞, 十元妹子]
删除后:userSet->[四块五的妞, 十元妹子]




哈希操作




opsForHash()  相当于在操作实体类




@Test
    public void operateHash(){
        //添加
        redisTemplate.opsForHash().put("user","username","ekko");
        redisTemplate.opsForHash().put("user","address","Shanghai");
        redisTemplate.opsForHash().put("user","passwd","1234");
        //修改
        redisTemplate.opsForHash().put("user","address","Beijing");
        //删除
        redisTemplate.opsForHash().delete("user","passwd");
    }

    @Test
    public void operateHash(){
        //添加
        redisTemplate.opsForHash().put("user","username","ekko");
        redisTemplate.opsForHash().put("user","address","Shanghai");
        redisTemplate.opsForHash().put("user","passwd","1234");
        //修改
        redisTemplate.opsForHash().put("user","address","Beijing");
        //删除
        redisTemplate.opsForHash().delete("user","passwd");
    }




结果:

电商类目redis缓存 redis缓存工具类_redis_02




总结



数据量大且不长变的还是用缓存接收数据来回操作使用 Redis,持久化时再入库做好缓存击穿的准备利用好 Redis 可以很大程度的减少 MySQL 的压力Redis 常用的操作基本满足需求


小知识

方法名字前加ABCD...是为了让方法有执行顺序
根据测试方法名字搞定执行顺序,在方法上加注解@FixMethodOrder(MethodSorters.NAME_ASCENDING)日志注解@Slf4j是为了让日志书写更方便

//之前写日志  
 log.info("输出a"+index+"b");
 //现在
 log.info("输出a{}b",index);

多个参数可以用多个{},总之,喜欢哪个用哪个,谢谢!