🏆 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比较合适

相关推荐
鬼火儿2 小时前
SpringBoot】Spring Boot 项目的打包配置
java·后端
cr7xin2 小时前
缓存三大问题及解决方案
redis·后端·缓存
间彧3 小时前
Kubernetes的Pod与Docker Compose中的服务在概念上有何异同?
后端
间彧4 小时前
从开发到生产,如何将Docker Compose项目平滑迁移到Kubernetes?
后端
间彧4 小时前
如何结合CI/CD流水线自动选择正确的Docker Compose配置?
后端
间彧4 小时前
在多环境(开发、测试、生产)下,如何管理不同的Docker Compose配置?
后端
间彧4 小时前
如何为Docker Compose中的服务配置健康检查,确保服务真正可用?
后端
间彧4 小时前
Docker Compose和Kubernetes在编排服务时有哪些核心区别?
后端
间彧4 小时前
如何在实际项目中集成Arthas Tunnel Server实现Kubernetes集群的远程诊断?
后端
brzhang4 小时前
读懂 MiniMax Agent 的设计逻辑,然后我复刻了一个MiniMax Agent
前端·后端·架构