一、总体概述
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比较合适