【加精】Spring全家桶系列–SpringBoot入门Redis

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 【加精】Spring全家桶系列–SpringBoot入门Redis

//本文作者:cuifuan

//本文将收录到菜单栏:《Spring全家桶》专栏中

 

首先,Redis是什么?

Redis是一个开源的,基于内存的键值数据存储,用作数据库,缓存和消息代理。在实现方面,Key-Value存储代表NoSQL空间中最大和最老的成员之一。Redis支持数据结构,如字符串,散列,列表,集和带范围查询的有序集。
 
在spring data redis的框架,可以很容易地编写,通过提供一个抽象的数据存储使用Redis的键值存储的Spring应用程序。 非关系型数据库,基于内存,存取数据的速度不是关系型数据库所能比拟的 redis是键值对(key-value)的数据库

有5中主要数据类型:

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

redis缓存为啥速度快

这么说吧,别人问你什么是“redis”,如果你知道,你可以直接吧啦吧啦一大堆,其实这个时候你的大脑就类似redis缓存,别人问的“redis”就是key,你说出来的结果就是value,而你如果不知道,你就去上网查,然后再告诉别人,这就类似于查询数据库了,你查了再告诉别人当然慢了!
你把脑袋里的东西写进笔记就类似redis持久化保存了;
你过了两个月把这玩意忘了,就是redis的定期删除了;
引自:https://blog.csdn.net/angleflyyy/article/details/81627785

准备工作

项目工具环境:
    - IDEA 2018.2 - Gradle 4+ - JDK1.8以上 - redis服务器

你把脑袋里的东西写进笔记就类似redis持久化保存了;

引自:https://blog.csdn.net/angleflyyy/article/details/81627785

设置Redis服务器

redis下载地址:https://redis.io/download

如果你的电脑是Mac:

1
brew install redis

brew install redis

然后运行redis服务器

12345678910111213141516171819202122232425
cuifuandeMacBook-Pro:~ cuifuan$ redis-server25336:C 29 Nov 2018 14:53:42.490 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo25336:C 29 Nov 2018 14:53:42.490 # Redis version=5.0.2, bits=64, commit=00000000, modified=0, pid=25336, just started25336:C 29 Nov 2018 14:53:42.490 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf25336:M 29 Nov 2018 14:53:42.491 * Increased maximum number of open files to 10032 (it was originally set to 256).                _._                                                             _.-``__ ''-._                                                   _.-``    `.  `_.  ''-._           Redis 5.0.2 (00000000/0) 64 bit  .-`` .-```.  ```\/    _.,_ ''-._                                    (    '      ,       .-`  | `,    )     Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379 |    `-._   `._    /     _.-'    |     PID: 25336  `-._    `-._  `-./  _.-'    _.-'                                    |`-._`-._    `-.__.-'    _.-'_.-'|                                   |    `-._`-._        _.-'_.-'    |           http://redis.io          `-._    `-._`-.__.-'_.-'    _.-'                                    |`-._`-._    `-.__.-'    _.-'_.-'|                                   |    `-._`-._        _.-'_.-'    |                                    `-._    `-._`-.__.-'_.-'    _.-'                                         `-._    `-.__.-'    _.-'                                                 `-._        _.-'                                                         `-.__.-'                                                25336:M 29 Nov 2018 14:53:42.492 # Server initialized25336:M 29 Nov 2018 14:53:42.492 * Ready to accept connections

cuifuandeMacBook-Pro:~ cuifuan$ redis-server
25336:C 29 Nov 2018 14:53:42.490 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
25336:C 29 Nov 2018 14:53:42.490 # Redis version=5.0.2, bits=64, commit=00000000, modified=0, pid=25336, just started
25336:C 29 Nov 2018 14:53:42.490 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
25336:M 29 Nov 2018 14:53:42.491 * Increased maximum number of open files to 10032 (it was originally set to 256).
.
.-``_ ‘’-._
.-`` . . ‘’-._ Redis 5.0.2 (00000000/0) 64 bit
.- .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.-.|’ _.-'| Port: 6379 | -._ ._ / _.-' | PID: 25336 -._ -._ -./ _.-‘ _.-‘
|`-.
-._ -..-‘ .-‘.-‘|
| -._-.
.-‘.-‘ | http://redis.io
-._ -. -.__.-'_.-' _.-' |-. -._ -._.-‘ .-‘.-‘|
| -._-.
.-‘.-‘ |
-._ -. -.__.-'_.-' _.-' -. -.__.-' _.-' -.
_.-‘
`-.__.-‘

25336:M 29 Nov 2018 14:53:42.492 # Server initialized
25336:M 29 Nov 2018 14:53:42.492 * Ready to accept connections

初始化项目

现在去Spring开始界面初始化一个项目

Spring全家桶系列--SpringBoot入门Redis

这里选择的是Gradle,选择完成点击Generate Projrct生成项目,这个时候会自动下载一个压缩包给你,解压过后导入,导入IDEA教程:http://note.youdao.com/noteshare?id=74e2d65e2d22cd684c3fdd6695b3ecdf

Gradle 依赖管理

让我们在build.gradle中为我们正在构建的示例应用程序声明必要的依赖项

12345678910111213141516171819202122232425262728293031
buildscript {    repositories {        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }    }    dependencies {        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.0.RELEASE")    }} apply plugin: 'java-library'apply plugin: 'org.springframework.boot'apply plugin: 'io.spring.dependency-management' group = 'com.example'version = '0.0.1-SNAPSHOT'sourceCompatibility = 1.8 repositories {    maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }} dependencies {    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'    implementation 'org.springframework.boot:spring-boot-starter-data-redis'    implementation 'org.springframework.boot:spring-boot-starter-web'    implementation 'mysql:mysql-connector-java'    implementation 'org.projectlombok:lombok'    implementation 'org.apache.commons:commons-pool2:2.4.2'    implementation 'com.alibaba:fastjson:1.2.51'    testImplementation 'org.springframework.boot:spring-boot-starter-test'}

buildscript {
repositories {
maven { url ‘http://maven.aliyun.com/nexus/content/groups/public/' }
}
dependencies {
classpath(“org.springframework.boot:spring-boot-gradle-plugin:2.1.0.RELEASE”)
}
}

apply plugin: ‘java-library’
apply plugin: ‘org.springframework.boot’
apply plugin: ‘io.spring.dependency-management’

group = ‘com.example’
version = ‘0.0.1-SNAPSHOT’
sourceCompatibility = 1.8

repositories {
maven { url ‘http://maven.aliyun.com/nexus/content/groups/public/' }
}

dependencies {
implementation ‘org.springframework.boot:spring-boot-starter-data-jpa’
implementation ‘org.springframework.boot:spring-boot-starter-data-redis’
implementation ‘org.springframework.boot:spring-boot-starter-web’
implementation ‘mysql:mysql-connector-java’
implementation ‘org.projectlombok:lombok’
implementation ‘org.apache.commons:commons-pool2:2.4.2’
implementation ‘com.alibaba:fastjson:1.2.51’
testImplementation ‘org.springframework.boot:spring-boot-starter-test’
}

开始使用

凭借着SpringBoot的开箱即用的特点,集成Redis也不例外

  • redisTemplate.opsForValue();//操作字符串
  • redisTemplate.opsForHash();//操作hash
  • redisTemplate.opsForList();//操作list
  • redisTemplate.opsForSet();//操作set
  • redisTemplate.opsForZSet();//操作有序set

 

Spring全家桶系列--SpringBoot入门Redis

在Spring的测试类中开始使用:

1
redisTemplate.opsForValue().set("username","test");

redisTemplate.opsForValue().set(“username”,”test”);

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

Spring全家桶系列--SpringBoot入门Redis

是乱的,是因为在set后redis会序列化key和value,所以我们要在config中重写一下redisTemplate

src/main/java/com/example/springbootredisdemo/config/RedisConfig.java

123456789101112131415161718192021222324252627282930313233
package com.example.springbootredisdemo.config; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;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; @Configurationpublic class RedisConfig {     private final RedisTemplate redisTemplate;     @Autowired    public RedisConfig(RedisTemplate redisTemplate) {        this.redisTemplate = redisTemplate;    }     @Bean    @SuppressWarnings("unchecked")    public RedisTemplateString, Object redisTemplate() {        RedisSerializerString stringSerializer = new StringRedisSerializer();        RedisSerializerObject jsonString = new GenericToStringSerializer(Object.class);        redisTemplate.setKeySerializer(stringSerializer);        redisTemplate.setValueSerializer(jsonString);        redisTemplate.setHashKeySerializer(stringSerializer);        redisTemplate.setHashValueSerializer(jsonString);        return redisTemplate;    } }

package com.example.springbootredisdemo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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 {


private final RedisTemplate redisTemplate;

@Autowired
public RedisConfig(RedisTemplate redisTemplate) {
    this.redisTemplate = redisTemplate;
}

@Bean
@SuppressWarnings("unchecked")
public RedisTemplateString, Object redisTemplate() {
    RedisSerializerString stringSerializer = new StringRedisSerializer();
    RedisSerializerObject jsonString = new GenericToStringSerializer(Object.class);
    redisTemplate.setKeySerializer(stringSerializer);
    redisTemplate.setValueSerializer(jsonString);
    redisTemplate.setHashKeySerializer(stringSerializer);
    redisTemplate.setHashValueSerializer(jsonString);
    return redisTemplate;
}

}

再去执行一下刚刚的方法

Spring全家桶系列--SpringBoot入门Redis

经过自定义的序列化之后可以了,没有乱码了

opsForList()添加操作
123456789101112
@Test    public void CsetListRedis(){        ListString trap = new ArrayList();        trap.add("张三");        trap.add("张无忌");        trap.add("新垣结衣");        //循环向userlist左添加值        trap.forEach(value-redisTemplate.opsForList().leftPush("userlist",value));        //向userlist右添加值        redisTemplate.opsForList().rightPush("userlist","rightValue");        log.info("userlist-{}",redisTemplate.opsForList().range("userlist",0,10));    }

@Test
public void CsetListRedis(){
ListString trap = new ArrayList();
trap.add(“张三”);
trap.add(“张无忌”);
trap.add(“新垣结衣”);
//循环向userlist左添加值
trap.forEach(value-redisTemplate.opsForList().leftPush(“userlist”,value));
//向userlist右添加值
redisTemplate.opsForList().rightPush(“userlist”,”rightValue”);
log.info(“userlist-{}”,redisTemplate.opsForList().range(“userlist”,0,10));
}

  • Spring全家桶系列--SpringBoot入门Redis
    opsForList()删除操作
    1234
    @Test    public void DlistRedisRemove(){        redisTemplate.opsForList().remove("userlist",0,"张无忌");    }

    @Test
    public void DlistRedisRemove(){
    redisTemplate.opsForList().remove(“userlist”,0,”张无忌”);
    }

    Spring全家桶系列--SpringBoot入门Redis

    通过源码看这里有三个参数:

  • key 对应的是redis中存的key值
  • count 正数就是从左边开始删除 负数是从右面 例如-1就从右删除第一个值为value的,0代表删除全部值为value的
  • value 就是需要从list移除的值
  • opsForSet()添加操作

    利用了set值的不可重复

    12345678910111213
    @Test    public void CsetRedis(){        ListString 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"));    }

    @Test
    public void CsetRedis(){
    ListString 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”));
    }

    结果

    Spring全家桶系列--SpringBoot入门Redis

    符合了Set集合的无序和不可重复性

    opsForSet()的删除操作

    这个删除操作就比较容易了,直接根据set的key值,后面参数写其需要删除的value就可以

     

    1234
    @Test    public void EsetRedisRemove(){        redisTemplate.opsForSet().remove("userSet","张无忌");    }

    @Test
    public void EsetRedisRemove(){
    redisTemplate.opsForSet().remove(“userSet”,”张无忌”);
    }

    opsForHash()操作

     

    12345678910111213
    //opsForHash()操作    @Test    public void FhashRedisAdd(){        //添加        redisTemplate.opsForHash().put("user","phone",10086);        redisTemplate.opsForHash().put("user","address","Shanghai");        redisTemplate.opsForHash().put("user","del","mubaba");        redisTemplate.opsForHash().put("user","dada","达达");        //修改        redisTemplate.opsForHash().put("user","address","Beijing");        //删除        redisTemplate.opsForHash().delete("user","del","dada");    }

    //opsForHash()操作
    @Test
    public void FhashRedisAdd(){
    //添加
    redisTemplate.opsForHash().put(“user”,”phone”,10086);
    redisTemplate.opsForHash().put(“user”,”address”,”Shanghai”);
    redisTemplate.opsForHash().put(“user”,”del”,”mubaba”);
    redisTemplate.opsForHash().put(“user”,”dada”,”达达”);
    //修改
    redisTemplate.opsForHash().put(“user”,”address”,”Beijing”);
    //删除
    redisTemplate.opsForHash().delete(“user”,”del”,”dada”);
    }

     

    结果

    Spring全家桶系列--SpringBoot入门Redis
    测试类SpringbootRedisDemoApplicationTests

    src/test/java/com/example/springbootredisdemo/SpringbootRedisDemoApplicationTests.java

    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
    package com.example.springbootredisdemo; import com.example.springbootredisdemo.service.NovelService;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.SpringRunner; import java.util.ArrayList;import java.util.List; //根据测试方法名字搞定执行顺序@FixMethodOrder(MethodSorters.NAME_ASCENDING)@RunWith(SpringRunner.class)@SpringBootTest@Slf4jpublic class SpringbootRedisDemoApplicationTests {     @Autowired    private NovelService novelService;     @Autowired    private RedisTemplateString,Object redisTemplate;     private final static String KEY = "username";    private final static String VALUE = "test";      @Test    public void AstringRedis(){        redisTemplate.opsForValue().set(KEY,VALUE);        log.info("string set存储:{}-{}",KEY,VALUE);        redisTemplate.opsForValue().get(KEY);        log.info("string 根据{}取出{}",KEY,VALUE);    }     @Test    public void BlistRedis(){        ListString trap = new ArrayList();        trap.add("张三");        trap.add("张三");        trap.add("张无忌");        trap.add("新垣结衣");        //循环向userlist左添加值        trap.forEach(value-redisTemplate.opsForList().leftPush("userlist",value));//        redisTemplate.opsForList().leftPushAll("userlist",trap);        //向userlist右添加值        redisTemplate.opsForList().rightPush("userlist","rightValue");        //取出userlist的值        log.info("userlist-{}",redisTemplate.opsForList().range("userlist",0,10));    }     @Test    public void CsetRedis(){        ListString 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"));    }     @Test    public void DlistRedisRemove(){        redisTemplate.opsForList().remove("userlist",0,"张无忌");    }      @Test    public void EsetRedisRemove(){        redisTemplate.opsForSet().remove("userSet","张无忌");    }     //opsForHash()操作    @Test    public void FhashRedisAdd(){        //添加        redisTemplate.opsForHash().put("user","phone",10086);        redisTemplate.opsForHash().put("user","address","Shanghai");        redisTemplate.opsForHash().put("user","del","mubaba");        redisTemplate.opsForHash().put("user","dada","达达");        //修改        redisTemplate.opsForHash().put("user","address","Beijing");        //删除        redisTemplate.opsForHash().delete("user","del","dada");    }}

    package com.example.springbootredisdemo;

    import com.example.springbootredisdemo.service.NovelService;
    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.SpringRunner;

    import java.util.ArrayList;
    import java.util.List;

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

    
    @Autowired
    private NovelService novelService;
    
    @Autowired
    private RedisTemplateString,Object redisTemplate;
    
    private final static String KEY = "username";
    private final static String VALUE = "test";
    
    
    @Test
    public void AstringRedis(){
        redisTemplate.opsForValue().set(KEY,VALUE);
        log.info("string set存储:{}-{}",KEY,VALUE);
        redisTemplate.opsForValue().get(KEY);
        log.info("string 根据{}取出{}",KEY,VALUE);
    }
    
    @Test
    public void BlistRedis(){
        ListString trap = new ArrayList();
        trap.add("张三");
        trap.add("张三");
        trap.add("张无忌");
        trap.add("新垣结衣");
        //循环向userlist左添加值
        trap.forEach(value-redisTemplate.opsForList().leftPush("userlist",value));
    

    // redisTemplate.opsForList().leftPushAll(“userlist”,trap);
    //向userlist右添加值
    redisTemplate.opsForList().rightPush(“userlist”,”rightValue”);
    //取出userlist的值
    log.info(“userlist-{}”,redisTemplate.opsForList().range(“userlist”,0,10));
    }

    
    @Test
    public void CsetRedis(){
        ListString 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"));
    }
    
    @Test
    public void DlistRedisRemove(){
        redisTemplate.opsForList().remove("userlist",0,"张无忌");
    }
    
    
    @Test
    public void EsetRedisRemove(){
        redisTemplate.opsForSet().remove("userSet","张无忌");
    }
    
    //opsForHash()操作
    @Test
    public void FhashRedisAdd(){
        //添加
        redisTemplate.opsForHash().put("user","phone",10086);
        redisTemplate.opsForHash().put("user","address","Shanghai");
        redisTemplate.opsForHash().put("user","del","mubaba");
        redisTemplate.opsForHash().put("user","dada","达达");
        //修改
        redisTemplate.opsForHash().put("user","address","Beijing");
        //删除
        redisTemplate.opsForHash().delete("user","del","dada");
    }
    

    }

    小知识

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

    日志注解@Slf4j是为了让日志书写更方便

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

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

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

    码云代码地址

    https://gitee.com/cuifuan/SpringBoot

    点击图片加入Spring交流群

    ↓↓↓

    看完本文有收获?请转发分享给更多人

    Spring全家桶系列--SpringBoot入门Redis

     

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> 【加精】Spring全家桶系列–SpringBoot入门Redis


     上一篇
    springboot配置文件种类 springboot配置文件种类
    文件类型的区分 xxx.propertis 格式简单,但是只支持键值对 spring.mvc.view.prefix=/static xxx.yml 如果需要表达列表,最好使用YAML格式YAML是一个类似 X
    2021-04-05
    下一篇 
    【加精】Spring Cloud Config 规范 【加精】Spring Cloud Config 规范
    本文作者:得少 Spring Cloud Config 规范首先Spring Cloud 是基于 Spring 来扩展的,Spring 本身就提供当创建一个Bean时可从Environment 中将一些属性值通过@Value的形式注入到
    2021-04-05