Redis基础篇学习笔记五:springBoot整合redis

由于springboot在业内的使用占比非常大,所以我们不仅仅要学redis的命令,更多使用的是redis与springboot的整合。那接下来,就一起学习关于springboot整合redis的内容吧。

学习redis,需要类比MySql。使用java连接MySql时,我们使用了JDBC,,同理,连接redis时,我们也需要这样的一个连接代理,因此,出现了Jedis。
但由于Jedis对线程并不安全,于是出现了Lettuce(翻译:生菜),后来,spring为了整合redis,推出了RedisTemplate,当然,这是对lettuce的封装和加强。本次介绍就依次介绍这三个以及它们的使用(重点是RedisTemplate,因为以后大多使用这个作为连接redis的连接器)。

在进行操作之前,大家要确保redis服务是开启的。

 redis-cli -a 123321 -p 6379 --raw

-a: redis密码 -p: 端口 --raw: 表示支持中文显示(当redis存入中文不显示乱码)

1:Jedis

jedis client是Redis官网推荐的一个面向java客户端,库文件实现了对各类API进行封装调用。
五步法建项目:

(1)建module
这里我们可以选择直接建立springboot项目,然后勾选一个web的start,版本使用2.6.10。
或者建立一个maven项目,后续在pom添加对应的依赖。
如果对建项目不熟,可以先学springboot的教材(推荐黑马程序员的教学)
(2)改pom
因为这是对Jedis的使用,所以需要添加Jedis的依赖,后续为了方便,我们还添加了lombok的依赖以及junit的依赖。

	<parent>
        <!--        父项目依赖-->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.10</version>
        <relativePath/>
    </parent>

    <!--    版本控制-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
    </properties>


    <dependencies>
        <!--        springboot通用模块-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        jedis依赖-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.3.1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
    </dependencies>

这里建议直接复制,不容易出错。

(3)写YML
因为使用的Jedis,所以简单配置一下port和application.name。

server:
  port: 8080

spring:
  application:
    name: redis7

(4)主启动类
如果建立项目是使用springboot的话,主启动类会自动生产,如果建立maven的话,建一个自己的包以及主启动类,包结构如下:
Redis基础篇学习笔记五:springBoot整合redis_第1张图片
config,service,controller,domo包里面没有类,整个结构只有主启动类。

package com.itludehu.redis;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisApplication.class);
    }
}

(5)业务类
最后,我们就可以进行jedis的业务测试了,为了方便,不再新建一个测试类,而是再demo包里面新建一个类RedisDemo:


public class RedisDemo {

    //使用原生的jedis来进行连接redis
    public static void main(String[] args) {

        //1,指定端口,ip获得连接redis的连接
        Jedis jedis = new Jedis("192.168.190.128", 6379);

        //2,指定访问器的密码
        jedis.auth("123321");

        //3.获得jedis客户端 和jdbc一样,访问redis
        System.out.println(jedis.ping());

        //keys的操作
        Set<String> keys = jedis.keys("*");
        System.out.println(keys);

        //string的操作
        jedis.set("k3","hello-Jedis7");

        //list
        jedis.lpush("list","11","22","33");
        List<String> list = jedis.lrange("list", 0, -1);
        for(String element : list){
            System.out.println(element);
        }

    }
}

可以将主方法运行起来并得到结果。
通过上面,可以得到,使用Jedis步骤:1,new 一个Jedis并连接好ip和端口(这里放入你们自己的ip),并使用方法auth()指定密码。2,使用jedis对redis的命令进行操作,这里的操作值redis的命令,上面仅仅写了几个命令的接口,各位可以参照其他命令的接口并运行起来。

2:Lettuce

上面的jedis以及可以对redis数据库进行操作了,但是有一个很大的问题,每当业务需要连接redis时候,都需要new一个Jedis,造成线程不安全,,当很多客户端需要连接redis的时候,这样会产生很多对象,浪费内存并且会是服务器宕机。
对比于MySql,解决这样的问题就是使用一个数据源DataSource来解决,所以redis中出现了Lettuce(生菜)。

lettuce是一个redis的Java驱动包。
优势:lettuce底层使用的Netty,当有很多个线程都需要连接redis服务器的时候,可以保证只创建一个lettuce连接,使所有的线程都共享这一个连接,这样减少了很大的开销;并且线程之间是安全的。
因为要使用到Lettuce,那需要在pow中添加对应的依赖

<!--        lettcue的依赖-->
        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>6.2.1.RELEASE</version>
        </dependency>

在代码中的demo包中新建一个类LettuceDemo:

public class LettuceDemo {

    public static void main(String[] args) {

        //1.使用构建器链式编程构建Builder出lettuce
        RedisURI url = RedisURI.builder()
                .redis("192.168.190.128")
                .withPort(6379)
                .withAuthentication("default", "123321")
                .build();

        //2,创建连接客户端
        RedisClient redisClient = RedisClient.create(url);
        StatefulRedisConnection conn = redisClient.connect();

        //3.创建操作的command,使用conn
        RedisCommands commands = conn.sync();

        //-----------业务逻辑---------------
        //key
        List keys = commands.keys("*");
        System.out.println("***************"+keys);

        //String
        commands.set("k5","hello-lettuce");
        Object k5 = commands.get("k5");
        System.out.println("***************"+k5);

        //list

        //4.各种关闭释放资源
        conn.close();;
        redisClient.shutdown();

    }
}

在进行业务逻辑后,记得关闭相应的资源:conn.close(); redisClient.shutdown();
运行代码也可以得到相应的结果,同样,这里仅仅写了几个命令接口,其他需要自己动手操作。

3:RedisTemplate

RedisTemplate是spring整合redis的常用的连接器。

spring优点就是整合其他技术,然后将这些技术放入Ioc的容器中,让spring进行管理,这样大大简化了我们的开发。
使用RedisTemplate,我们要先添加相应的依赖坐标,包括:spring和redis的整合启动坐标,commons-pool2的坐标。

<!--        springboot整合redis依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

添加好依赖后,就可以修改yml文件中的配置。

server:
  port: 8080

spring:
  application:
    name: redis7
  redis:
    database: 0
    password: 123321
    host: 192.168.190.128
    port: 6379
    lettuce:   #连接器
      pool:
        max-active: 8
        max-wait: -1ms
        max-idle: 8
        min-idle: 0

!!!配置中的连接参数记得修改成你们自己的。
因为redisTemplate是对lettuce的封装加强,所有连接器使用的还是lettoce。
database: 0 表示连接的是redis的第一个库(redis一共有16个库)
password: 密码
host: 主机ip
port: 端口

接下来就是业务类的编写了。
之前添加了web的依赖,就在service和controller包下新建对应的OrderService和OrderController:
Redis基础篇学习笔记五:springBoot整合redis_第2张图片
代码如下:
Service层

@Service
public class OrderService {


    public static final String ORDER_KEY = "order:";

    @Resource
    private RedisTemplate redisTemplate;


    public void addOrder(){
        int keyID = ThreadLocalRandom.current().nextInt(1000)+1;
        String serialNo = UUID.randomUUID().toString();

        String key = ORDER_KEY + keyID;
        String value = "京东订单" + serialNo;
        //存入redis
        redisTemplate.opsForValue().set(key,value);
        System.out.println("***Key: "+ key);
        System.out.println("***value: {}"+value);
    }

    public String getOrderById(Integer keyID){
        return (String) redisTemplate.opsForValue().get(ORDER_KEY + keyID);

    }

}

里面注入了RedisTemplate,并创建了两个方法:addOrder和getOrderByID。
在里面,直接调用redisTemplate.opsForValue.set(key,value)就是对redis进行set key value的命令。
redisTemplate有几种opsFor.*:
opsForValue: 表示对String类型进行操作。
opsForList: 表示对List类型进行操作。
opsForHash:表示对hash类型进行操作。
opsForSet:表示对set进行操作。
opsForZSet:表示对zSet操作。

controller层:

@RestController
public class OrderController {


    @Resource
    private OrderService orderService;
    
    @GetMapping(value = "/order/add")
    public void addOrder(){
        orderService.addOrder();
    }
    
    @RequestMapping(value = "/order/{keyID}",method = RequestMethod.GET)
    public String getOrderByID(@PathVariable  Integer keyID){
        return orderService.getOrderById(keyID);
    }
}

上面定义了两个请求,一个是添加Order,一个是根据ID获取Oder。

启动主程序后,我们打开第一个请求,存入一个Order。
但奇怪的是,获取请求并没有获取到,于是我们去redis数据库进行查询。
输入指令: keys *
可以看到一个很奇怪的东西:

数据库出现了乱码,使用的redisTemplate存入的数据有一个不知道的前缀,根据源码,发现是spring对存入的数据进行了序列化的默认序列化,导致前面出现了乱码,但我们本身不希望有乱码的出现,于是需要我们手动配置一个序列化的工具给redisTemplate。
在config包中新建一个RedisConfig类,并注解配置类@Configuration:

@Configuration
public class RedisConfig {


    //解决redis的序列化问题:
    @Bean
    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        //注入lettuce工厂
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        //设置key的序列化方式String
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());


        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        return redisTemplate;
    }
}

这样序列化的方式就解决了。
运行发现后,redis数据没有了前缀。
当然,可以使用另外一种方法,也是就使用RedisTemplate的子类StringRedisTemplate来进行redis的连接,它本身就已经初始化了序列化类,所有在存入数据时并不会产生乱码前缀。
@Resource
private StringRedisTemplate stringRedisTemplate;
至此,springboot整合redis的基础就结束了。
后续会发布关于当使用redisTemplate来对对象(引用类型)进行存储到redis的一些步骤和会出现的问题!

你可能感兴趣的:(redis,redis,spring,boot,学习)