《SpringBoot》中使用的Redis

2021年05月05日 阅读数:8
这篇文章主要向大家介绍《SpringBoot》中使用的Redis,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

Redis入门

Linux中安装Redisjava

redis的说明

Redis 是一个开源的,内存中的数据结构存储系统它能够用做数据库、缓存和消息中间件。 它支持多种类型的数据结构redis

1. Redis经常使用命令

string类型:

命令 说明 案例
set 添加key-value set username admin
get 根据key获取数据 get username
exists 判断key是否存在 exists name(返回1存在 0不存在)
del 删除redis中的key del key
Keys 用于查询符合条件的key keys 查询redis中所有的key,keys n?me 使用占位符获取数据 keys nam 获取nam开头的数据

Hash类型

命令 说明 案例
hset 为对象添加数据 hset key field value
hget 获取对象的属性值 hget key field
hexists 判断对象的属性是否存在 HEXISTS key field1表示存在 0表示不存在
hdel 删除hash中的属性 hdel user field

List类型

说明

Redis中的List集合是双端循环列表,分别能够从左右两个方向插入数据
List集合能够当作队列使用,也能够当作栈使用spring

队列:存入数据的方向和获取数据的方向相反

栈:存入数据的方向和获取数据的方向相同

命令 说明 案例
lpush 从队列的左边入队一个或多个元素 LPUSH key value
rpush 从队列的右边入队一个或多个元素 RPUSH key value
lpop 从队列的左端出队一个元素 LPOP key
rpop 从队列的右端出队一个元素 RPOP key

Redis事务命令

说明

说明:redis中操做能够添加事务的支持.一项任务能够由多个redis命令完成,若是有一个命令失败致使入库失败时.须要实现事务回滚.数据库

命令 说明 案例
multi 标记一个事务开始 127.0.0.1:6379> MULTI
exec 执行全部multi以后发的命令 127.0.0.1:6379> EXEC
discard 丢弃全部multi以后发的命令

Redis入门

导入jar包

         <!--spring整合redis -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
    </dependency>

客户端操做String类型

前提

建立一个Java类测试类json

配置redis服务

主要目的测试程序远程操做Redis是否有效
1.redis须要关闭IP绑定模式
2.redis关闭保护模式
3.redis最好开启后端运行

redis入门案例(1)

总体结构

 public void test01() throws InterruptedException {
    //1.测试连接
    Jedis jedis = new Jedis("192.168.126.129",6379);
    jedis.set("a", "动态获取redis中的数据");
    System.out.println(jedis.get("a"));

    //2.测试数据是否存在
    if(jedis.exists("a")){
        jedis.set("a", "修改数据");
    }else{
        jedis.set("a", "新增数据");
    }

    //3.删除redis
    jedis.del("a");

    //4.清空全部的数据
    jedis.flushDB();
    jedis.flushAll();

    //5.为数据添加超时时间
    jedis.set("b", "设定超时时间");
    jedis.expire("b", 10);
    Thread.sleep(2000);
    System.out.println(jedis.ttl("b"));
}

1 . 测试连接

Jedis jedis = new Jedis("192.168.126.129",6379);
jedis.set("a", "动态获取redis中的数据");
System.out.println(jedis.get("a"));
1 - Jedis是在springboot中使用redis的时候引入到包,他springboot中表明redis new一个Jedis的时候参数的方式来引入redis所在的ip地址和端口。
2 - set是 添加key和value
3 - get是 获取根据key获取value

2 . 测试数据是否存在

  if(jedis.exists("a")){
        jedis.set("a", "修改数据");
    }else{
        jedis.set("a", "新增数据");
    }
exists 是判断数据是否存在

判断 a 是否存在 若是存在的话a的value值改为<修改数据>,若是不存在的话a的value是<新增数据>segmentfault

3 . 删除redis

jedis.del("a");
del 表示删除

删除key 是 a 的数据后端

4 . 清空全部的数据

jedis.flushDB();
jedis.flushAll();
flushDB 清空单个数据库
flushAll 清空所有数据库

此方法很危险删除你的数据因此不建议使用缓存

5 . 为数据添加超时时间

jedis.set("b", "设定超时时间");
jedis.expire("b", 10);
Thread.sleep(2000);
System.out.println(jedis.ttl("b"));

redis入门案例(2)

原子性

什么是原子性?

一个事务是一个不可分割的最小工做单位,要么都成功要么都失败。springboot

原子操做是指你的一个业务逻辑必须是不可拆分的.好比你给别人转钱,你的帐号扣钱,别人的帐号
增长钱,这个业务逻辑就是原子性的,这个操做就是原子操做,要么都成功要么都失败。数据结构

Redis全部单个命令的执行都是原子性的。

总体结构

 public void test02(){
    Jedis jedis = new Jedis("192.168.126.129", 6379);
    jedis.set("c", "测试redis");
    //需求1: 若是数据不存在时,才会为数据赋值.
    jedis.setnx("d","测试setnx方法");
    System.out.println(jedis.get("d"));

    //需求2: 须要为数据添加超时时间,同时知足原子性的要求
    //为数据添加超时时间
    jedis.setex("s", 20, "为数据添加超时111");
    System.out.println("获取超时时间:"+jedis.ttl("s"));
}

需求1

若是数据不存在时,才会为数据赋值.

     jedis.setnx("d","测试setnx方法");
     System.out.println(jedis.get("d"));
setnx - 在指定的 key 不存在时,为 key 设置指定的值

若是d不存在的话才指定值

需求2

须要为数据添加超时时间,同时知足原子性的要求


jedis.setex("s", 20, "为数据添加超时111");
System.out.println("获取超时时间:"+jedis.ttl("s"));

setex - 指定的key设置值及其过时时间。若是key已经存在, setex 命令将会替换旧的值

需求3

若是数据存在才修改,而且为数据添加超时时间,知足原子性要求

SetParams:
    XX: 数据存在时赋值.
    NX: 数据不存在时赋值
    EX: 添加超时时间单位秒
    PX: 添加超时时间单位毫秒

使用Redis中的setparams

 public void test03(){
    Jedis jedis = new Jedis("192.168.126.129", 6379);
    jedis.flushAll();
    
    SetParams setParams = new SetParams();
    setParams.xx().ex(20);
    jedis.set("a", "测试方法",setParams);
    System.out.println(jedis.get("a"));
}
flushAll - 清空所有数据库(Redis)
xx().ex(20) - 分别为 xx() 数据存在时,ex(20) 超时20毫秒

关于List集合说明

关于队列应用场景

秒杀场景: 立刻过年了, 店铺周年店庆 1部苹果12proMax 12000 1元秒杀? 提早预付活动费 10块… 若是秒杀不成功 则7日内退还?
image.png

入门案例测试

队列:存入数据的方向和获取数据的方向相反

@Test
public void testList(){
    Jedis jedis = new Jedis("192.168.126.129",6379);
    jedis.lpush("list", "1","2","3");
    System.out.println(jedis.rpop("list")); //队列
}
lpush - 从列队的左边入队 一个或者多个元素
rpop - 从队列的右端出队一个元素

SpringBoot整合Redis

1 . 编辑properties配置文件

redis是公共的,建议配置放到公共的目录中

image.png
建立一个properties配置文件里面写redis的节点

2 . 编辑配置类

须要建立redis的一个配置类,配置类也放到公共的目录中

@Configuration  //表示一个配置类  通常会与@Bean的注解联用
@PropertySource("classpath:/redis.properties") //导入配置文件
public class RedisConfig {

@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private Integer port;

@Bean   //将方法的返回值结果,交给spring容器进行管理.
public Jedis jedis(){

    return new Jedis(host, port);
    }
}
@Configuration - 当前的类是配置类
@PropertySource - 导入配置文件
@bean - 把结果交给spring管理

3 . 测试redis的案例

在test中测试咱们的配置

image.png

@SpringBootTest //目的:动态获取spring容器中的数据
public class TestRedis {
    @Autowired
 private Jedis jedis;
    @Test
 public void testRedis(){
        jedis.set("jedis", "spring测试");
        System.out.println(jedis.get("jedis"));
    }
}

image.png
运行时出现这样表示成功

JSON转化工具API

测试1

    @Test
    public void test01() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        //将对象转化为JSON 调用的是对象的get方法获取属性/属性的值
        Sysprod sysprod = new Sysprod();
        sysprod.setId(1000).setTitle("对象与json转化").setProd_name("prodname").setPrice(1000).setProd_id(1000);
        String json = objectMapper.writeValueAsString(sysprod);
        System.out.println(json);
        //将JSON串转化为对象 调用的是对象的set方法为对象属性赋值
        Sysprod sysprod1 = objectMapper.readValue(json, Sysprod.class);
        System.out.println(sysprod1.getTitle());
    }
objectMapper - 将java对象与json格式相互转化的类
writeValuesAsString - 方法就能够把对角转化成json字符串(get方法)
readValue - 方法就能够把对角转化成json字符串(set方法)

把数据的get和set方式都要转换json类型,获取和赋值都转成json

sysprod 是 pojo对象

测试2

 @Test
public void test02() throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    //将对象转化为JSON  调用的是对象的get方法获取属性/属性的值
    ItemDesc itemDesc = new ItemDesc();
    itemDesc.setItemId(1000L).setItemDesc("对象与json转化").setCreated(new Date()).setUpdated(new Date());
    ItemDesc itemDesc2 = new ItemDesc();
    itemDesc2.setItemId(2000L).setItemDesc("对象与json转化2").setCreated(new Date()).setUpdated(new Date());

    List<ItemDesc> list2 = new ArrayList<>();
    list2.add(itemDesc);
    list2.add(itemDesc2);

    String json = objectMapper.writeValueAsString(list2);
    System.out.println(json);

    //将JSON串转化为对象 调用的是对象的set方法为对象属性赋值
    List list3 = objectMapper.readValue(json,list2.getClass());
    System.out.println(list3);
    }
}

若是有两个pojo对象那么把两个pojo对象包装给list集合

封装工具API

该工具类,主要的功能实现对象与JSON串的互相转化.

  • 1.对象转化为JSON
  • 2.JSON转化为对象
    public class ObjectMapperUtil {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    //1.对象转化为JSON
    public static String toJSON(Object object){
        try {
            return MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    //2.JSON转化为对象 要求用户传递什么类型就返回什么对象??
    public static <T> T toObj(String json,Class<T> target){

        try {
            return MAPPER.readValue(json, target);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
            }
        }
    }
第一步:new 一个 objectMapper类,(静态的和常量)修饰符
第二步:对象转化为JSON(返回string类型),把异常不要抛出去并且调用
第三步:JSON转化对象 要求用户传什么类型就返回给对象

工具类的功能:

咱们发出的数据转化成json格式到客户端,用户传来的json数据到服务端就转化对象

利用缓存实现查询

说明:若是页面的数据每次都数据库里查询的话这样的效率并不高,可使用redis缓存来提高效率

流程:

  • 1.用户第一次查询先查询缓存
  • 2.缓存中没有数据(这就是第一次查询),查询数据库. 将数据库记录保存到缓存中便可.
  • 3.缓存中有记录. 直接经过缓存获取数据以后返回便可.