🏆 SpringBoot 集成Redis

一、总体概述

jedis-lettuce-RedisTemplate三者的联系

在 Spring Boot 项目中,通常使用 Spring Data Redis 来连接 Redis 缓存服务器。而 Spring Data Redis 依赖于 Jedis 或 Lettuce,默认情况下使用 Lettuce。具体来说,在 Spring Boot 1.x 版本中,RedisTemplate 的具体实现是 Jedis;而在 Spring Boot 2.x 版本中,RedisTemplate 的具体实现变成了 Lettuce。

Jedis是 Redis 官方推荐的面向 Java 的操作 Redis 的客户端,采用同步阻塞式 IO,使用线程池时是线程安全的。优点是简单、灵活、API 全面;缺点是高级功能需要自己封装,执行效率较低。

Lettuce 作为新式的 Redis 客户端,基于 Netty 采用异步非阻塞式 IO,是线程安全的。优点是提供了很多 Redis 高级功能,例如集群、哨兵、管道等;缺点是 API 抽象,学习成本高。

RedisTemplate 是 Spring Data Redis 中对 Jedis API 的高度封装,基于 Spring Boot 自动装配的原理,使得整合 Redis 时比较简单。优点是可以方便地更换 Redis 的 Java 客户端,并且比 Jedis 多了自动管理连接池的特性;缺点是执行效率较低。

二、开发环境搭建

1.新建springboot项目、导入pom文件

java 复制代码
<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>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <junit.version>4.12</junit.version>
    <log4j.version>1.2.17</log4j.version>
    <lombok.version>1.16.18</lombok.version>
    <swaager-ur.version>1.9.6</swaager-ur.version>
    <tk.mybatis.version>4.1.5</tk.mybatis.version>
</properties>

<dependencies>
    <!--guava Google 开源的 Guava 中自带的布隆过滤器-->
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>23.0</version>
    </dependency>
    <!--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>
    <!--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>
    <!--swagger2-->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>
    <!--Mysql数据库驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <!--SpringBoot集成druid连接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.10</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>
    <!--mybatis和springboot整合-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.0</version>
    </dependency>
    <!--hutool-->
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.2.3</version>
    </dependency>
    <!--persistence-->
    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>persistence-api</artifactId>
        <version>1.0.2</version>
    </dependency>
    <!--通用Mapper-->
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper</artifactId>
        <version>${tk.mybatis.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
    <!--通用基础配置junit/devtools/test/log4j/lombok/-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
    </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>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>swagger-bootstrap-ui</artifactId>
        <version>${swaager-ur.version}</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

2.修改application.properties文件

java 复制代码
server.port=8888
spring.application.name=redis7Study

# ========================logging=====================
logging.level.root=info
logging.level.com.atguigu.redis7=info
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
logging.file.name=D:/myLogs2024/redis7_study.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n

# ========================swagger=====================
spring.swagger2.enabled=true
spring.mvc.pathmatch.matching-strategy=ant_path_matcher

spring.redis.database=0
spring.redis.host=192.168.118.128
spring.redis.port=6379
spring.redis.password=123456
spring.redis.timeout=2000
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0

# ========================alibaba.druid=====================
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.118.128:3306/redisTest?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.druid.test-while-idle=false

# ========================mybatis===================
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.bottom.redis7.entities

三、集成Jedis

1.新建配置类JedisConfig

java 复制代码
@Configuration
public class JedisConfig {
    private Logger logger = LoggerFactory.getLogger(JedisConfig.class);

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

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Bean
    public JedisPool jedisPool() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
        logger.info("JedisPool连接成功:" + host + "\t" + port);
        return jedisPool;
    }
}

2.新建测试类JedisTest

java 复制代码
@SpringBootTest
public class JedisTest {
    @Autowired
    private JedisPool jedisPool;

    @Test
    public void listTest() {
        //在连接池中得到Jedis连接
        Jedis jedis = jedisPool.getResource();
        jedis.lpush("bottom", "1", "2", "3", "4", "5");
        jedis.lrange("bottom", 0, 1);
        jedis.lpop("bottom");
        String index = jedis.lindex("bottom", 2);
        System.out.println("index = " + index);
        long len = jedis.llen("bottom");
        System.out.println("len = " + len);
        jedis.close();
    }
}

四、集成lettuce

1.新建配置类LettuceConfig

java 复制代码
@Configuration
public class LettuceConfig {

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

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.password}")
    private String password;

    @Bean
    public StatefulRedisConnection<String, String> lettucePool() {
        // 1 使用构建器链式编程来builder我们RedisURI
        RedisURI uri = RedisURI.Builder
                .redis(host)
                .withPort(port)
                .withAuthentication("default", password)
                .build();
        //2 创建连接客户端
        RedisClient redisClient = RedisClient.create(uri);
        return redisClient.connect();
    }
}

2.新建测试类LettuceTest

java 复制代码
@SpringBootTest
public class LettuceTest {

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String password;

    @Autowired
    private LettuceConfig lettuceConfig;

    @Test
    public void listTest() {
        StatefulRedisConnection<String, String> connect = lettuceConfig.lettucePool();
        //3 通过conn创建操作的lettuce
        RedisCommands<String, String> lettuce = connect.sync();
        lettuce.lpush("bottom", "1", "2", "3", "4", "5");
        lettuce.lrange("bottom", 0, 1);
        lettuce.lpop("bottom");
        String index = lettuce.lindex("bottom", 2);
        System.out.println("index = " + index);
        long len = lettuce.llen("bottom");
        System.out.println("len = " + len);
        //关闭连接
        connect.close();
    }
}

五、集成RedisTemplate

1.新建配置类RedisConfig

解决中文乱码问题

java 复制代码
@Configuration
public class RedisConfig
{
    /**
     * redis序列化的工具配置类
     * this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法
     * this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法
     * this.redisTemplate.opsForSet(); //提供了操作set的所有方法
     * this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法
     * this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法
     * @param lettuceConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
    {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();

        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        //设置key序列化方式string
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

2.新建配置类SwaggerConfig

提供api接口测试

java 复制代码
@Configuration
@EnableSwagger2
public class SwaggerConfig
{
    @Value("${spring.swagger2.enabled}")
    private Boolean enabled;

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(enabled)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.bottom.redis7"))
                .paths(PathSelectors.any())
                .build();
    }
    public ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("springboot利用swagger2构建api接口文档 "+"\t"+ DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDateTime.now()))
                .description("springboot+redis整合")
                .version("1.0")
                .termsOfServiceUrl("https://www.baidu.com/")
                .build();
    }
}

3.新建一个接口StringService

java 复制代码
@Service
@Slf4j
public class StringService {

    public static final String ORDER_KEY = "bottom:";
    @Resource
    private RedisTemplate redisTemplate;

    public String addBottom()
    {
        redisTemplate.opsForValue().set(ORDER_KEY,"helloRedisTemplate");

        log.info("***key:{}",ORDER_KEY);
        return  (String) redisTemplate.opsForValue().get(ORDER_KEY);
    }
}

4.新建一个类StringController

Java 复制代码
@RestController
@Slf4j
@Api(tags = "测试String类型")
public class StringController {

    @Resource
    private StringService stringService;

    @ApiOperation("测试string类型")
    @RequestMapping(value = "/bottom/add",method = RequestMethod.POST)
    public String addOrder()
    {
        return stringService.addBottom();
    }
}

5.把刚才的JedisConfig.java注释掉

6.输入swagger测试地址:http://localhost:8888/doc.html

六、总结

本文主要介绍了jedis-lettuce-RedisTemplate三者的联系、jedis是官方提供的连接redis工具,但是它每一次连接都要打开一个新的连接池,这在高并发的情况下对redis的io是非常不利的。

因此出现了jedis的升级版lettuce,如果使用Lettuce这个客户端连接Redis服务器的时候,就不会出现上面的情况,Lettuce底层使用的是Netty当有多个线程都需要连接Redis服务器的时候,可以保证只创建一个Lettuce连接,使所有的线程共享这一个Letuce连接,这样可以减少创建关闭一个Lettuce连接时候的开销;而且这种方式也是线程安全的,不会出现一个线程通过Lettuce更改Redis服务器中的数据之后而影响另一个线程的情况;

RedisTemplate则是整合了jedis和lettuce,因此我们在实际开发的时候选择 RedisTemplate比较合适

相关推荐
Java4ye2 小时前
Netty 是如何解析 Redis RESP 协议的——请求篇
后端
刘铸纬9 小时前
Golang中defer和return顺序
开发语言·后端·golang
多多*10 小时前
每天一道面试题之浅浅讲一下java5中的自动装箱和自动拆箱
java·开发语言·spring boot·后端·spring
江湖十年10 小时前
Go 语言中的结构体内存对齐你了解吗?
后端·go
cjay_fighting10 小时前
redis7新特性、源码解析
数据库·redis·分布式
passion更好11 小时前
IT专业入门,高考假期预习指南
java·前端·人工智能·后端·python·机器学习·高考
谦宇11 小时前
Nest 接入消息队列 RabbitMQ
前端·后端·nestjs
破晓的历程12 小时前
Spring Boot的无缝衔接:深入解析与实践
数据库·spring boot·后端
肖哥弹架构12 小时前
解释器模式(Interpreter Pattern):电商平台优惠规则解析实战案例分析
前端·后端·程序员
长河13 小时前
Jackson使用详解
java·开发语言·后端