SpringBoot整合Redis

151 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

SpringBoot整合Redis

SpringBoot操作数据:spring-data jpa jdbc mongodb redis

SpringData是和SpringBoot齐名的项目

如果是SpringBoot2.0以上配置集群的话一定要使用lettuce.pool下面的属性

在SpringBoot2.x之后 jedis被替换成了lettuce

jedis和lettuce有什么区别呢?

jedis:
用作于2.0之前,底层采用的是直连的serve,多个线程操作的话是不安全的,如果想要避免这种情况,需要使用jedis的连接池来解决 更像BIO(阻塞)模式(dubbo)
lettuce:
底层采用netty(高性能的网络框架,异步请求),实例key在线程中进行共享,不存在线程不安全的情况,可以减少线程数据,性能更加的高 更像NIO模式
源码分析:
//原文:如果不存在bean才生效   也就是告诉我们可以自己定义一个RedisTemplate来替换这个默认的

@ConditionalOnSingleCandidate(RedisConnectionFactory.class)

public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {

    //默认的RedisTemplate 没有过多的设置,redis对象的保存都是需要序列化的,尤其是使用netty NIO这种异步的

    //两个泛型都是object类型,后面使用需要强制转换,我们期望的数据类型应该是<string,object>

    RedisTemplate<Object, Object> template = new RedisTemplate();

    template.setConnectionFactory(redisConnectionFactory);

    return template;

}



@Bean

@ConditionalOnMissingBean

@ConditionalOnSingleCandidate(RedisConnectionFactory.class)

public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {

    //由于string类型是redis最长使用的数据类型,所以单独提出来了一个方法(bean)

    StringRedisTemplate template = new StringRedisTemplate();

    template.setConnectionFactory(redisConnectionFactory);

    return template;

}
综上所述,我们整合测试一下
1.导入依赖(pom)


 <!--redis依赖-->

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>
2.配置连接(application.properties(yml))
 # SpringBoot所有的配置类,都有一个自动配置类 RedisAutoConfiguration

 # 自动配置类都会绑定一个properties配置文件  RedisProperties



 #配置redis的ip 如果是本机的话可以写localhost或者127.0.0.1 如果是远程的话就写远程的ip即可

spring.redis.host=localhost

 #配置redis的端口号 默认都是6379

spring.redis.port=6379

 #配置redis使用的数据库 注:redis共有16个数据库 默认使用第0个

spring.redis.database=2

 #配置redis的集群 ( 如果是SpringBoot2.0以上配置集群的话一定要使用lettuce.pool下面的属性 )

spring.redis.lettuce.pool
3.测试
package com.wyh;



import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.data.redis.connection.RedisConnection;

import org.springframework.data.redis.core.RedisTemplate;



@SpringBootTest

class SpringBootRedis01ApplicationTests {

    //注入RedisTemplate

 @Autowired

    private RedisTemplate redisTemplate;

    @Test

    void contextLoads() {

        //很多数据类型api命令是以OpsFor开头的,操作不同的数据类型,api用法和redis类似

 //redisTemplate.opsForSet();    //  集合

 //redisTemplate.opsForZSet();   //有序集合

 //redisTemplate.opsForList();   //list列表

 //redisTemplate.opsForHash();   //Hash哈希

 //redisTemplate.opsForValue();  //字符串

 //redisTemplate.opsForGeo();   //地理位置

 //redisTemplate.opsForHyperLogLog(); //基数统计

 //除了基本的操作,我们常用的方法都可以通过RedisTemplate操作,比如事务和基本的CRUD(增删改查)

 //redisTemplate.multi(); //事务

 //获取Redis连接

 //RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();

 // connection.flushDb(); //刷新数据库

 // connection.close(); //关闭数据库



 //设置字符串  尽量不要用中文(转义)

  redisTemplate.opsForValue().set( "name" , "wyh" );

        redisTemplate.opsForValue().set( "name1" , "魏一鹤" );

        //获取字符串

 System.out.println( redisTemplate.opsForValue().get( "name" ));

        System.out.println( redisTemplate.opsForValue().get( "name1" ));

    }



}

1 序列化配置

默认的序列化方式是JDK序列化,对字符串转义,我们可能会使用JSON来进行序列化,这时候我们就需要自己进行配置一个redisTemplate类了

2 自定义RedisTemplate(自带的不能存储中文和对象,需要我们进行更改)

例子1:创建user实体,name(中文存储到redis),age存储到redis,不进行序列化

user对象实体

package com.wyh.entity;



import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

import org.springframework.stereotype.Component;



import java.io.Serializable;



 /**

 *  @program:  SpringBoot-Redis-01

 *  @description:  User实体

 *  @author:  魏一鹤

 *  @createDate:  2021-11-18 23:30

 **/

@Data //自动get set生成(lombok依赖)

@Component //进行注入到spring工厂成为一个组件,方便我们使用

@AllArgsConstructor //生成有参构造函数(lombok依赖)

@NoArgsConstructor  //生成无参构造函数(lombok依赖)

 //目前我们的User实体是没有被序列化的

 //想要实现序列化只需在User后加implements Serializable(实现序列化接口)

public class User  {

    private String name;

    private int age;

}

测试方法



 //注入RedisTemplate

@Autowired

private RedisTemplate redisTemplate;

@Test //表示该方法是测试方法(junit依赖)

public  void setUser() throws JsonProcessingException {

    //真实的开发一般传递json来传递对象,而不是直接new出来对象

 User user = new User( "魏一鹤" , 22);

    //利用ObjectMapper把我们的User对象进行json格式化

 String jsonUser = new ObjectMapper().writeValueAsString(user);

    //把json格式化后的user对象以键值对应的方式存在redis中

  redisTemplate.opsForValue().set( "user" ,jsonUser);

    //通过key获取user对象

 System.out.println( redisTemplate.opsForValue().get( "user" ));

}

打印输出

{"name":"魏一鹤","age":22}

redis中查看中文乱码

127.0.0.1:6379> keys *

1) "\xac\xed\x00\x05t\x00\x04user" #中文乱码
例子2:创建user实体,name(中文存储到redis),age存储到redis,进行序列化

代码和上面类似,只不过传的对象从json变成实体,也就是没有经过json字符串转化直接传对象



@Test //表示该方法是测试方法(junit依赖)

public  void setUser() throws JsonProcessingException {

    //真实的开发一般传递json来传递对象,而不是直接new出来对象

 User user = new User( "魏一鹤" , 22);

    //利用ObjectMapper把我们的User对象进行json格式化

 // String jsonUser = new ObjectMapper().writeValueAsString(user);

 //把json格式化后的user对象以键值对应的方式存在redis中

 //直接存储对象,而不是存储json数据类型

  redisTemplate.opsForValue().set( "user" ,user); 

 //redisTemplate.opsForValue().set("user",jsonUser);

    //通过key获取user对象

 System.out.println( redisTemplate.opsForValue().get( "user" ));

}

此时会报错我们的实体User没有进行序列化

@Data *//自动get set生成(lombok依赖)*

@Component *//进行注入到spring工厂成为一个组件,方便我们使用*

@AllArgsConstructor *//生成有参构造函数(lombok依赖)*

@NoArgsConstructor *//生成无参构造函数(lombok依赖)*

*//想要实现序列化只需在User后加implements Serializable(实现序列化接口)*

*//目前企业中 我们所以的pojo(Java对象)都会进行序列化*

**public class** User **implements** Serializable {

**private** String **name**;

**private int age**;

}