文章开始之前先抛出一个问题:Jedis、Lettuce、Redisson以及RedisTemplate几者之间有什么区别,又有什么联系?
如果你心中已经很清晰的有了答案,那么本文你可以很轻松的阅读过去!
如果你感觉能说出来但是又有点说不太清楚的样子,又或者上面的问题你暂时还没有答案,我相信这篇文章能给你一点点的帮助!
文章目录
一、Jedis、Lettuce、Redisson以及RedisTemplate介绍
(一)Jedis、Lettuce、Redisson介绍
1、背景
Redis是个非关系型数据库,其提供了丰富的API,上一文我写到了怎么在linux服务器上安装部署redis,并简单操作了一些原生的lAPI命令操作。
就像数据库Mysql,我们可以使用命令行去对数据库进行增删改查操作,我们在程序中要想去操作数据库的话,总不至于每个人每次都写一套发送http请求去给数据库进行操作吧,所以后来就有了jdbc这个东西,极大的方便了我们去连接mysql(也可以连接orecal)。
同样的道理,那么我们平常在开发中经常需要去连接Redis,于是就有人给我们提供了一些个工具去连接Redis,就是上面提到的那几个兄弟,只不过各有优劣,适应不同的场合。
2、概念:
Jedis:是Redis的Java实现客户端,提供了比较全面的Redis命令的支持,其命令基本与原生的命令行操作redis保持一致。
Lettuce:高级Redis客户端,线程安全同步,异步和响应使用以及一些高级特性;其实日常开发中我们主动使用的不多,但是后文要讲述的RedisTemplate,springboot2以后底层使用是这位老兄。
Redisson:实现了分布式和可扩展的Java数据结构。
3、各自优点:
Jedis:比较全面的提供了Redis的操作特性
Lettuce:主要在一些分布式缓存框架上使用比较多,以及同步异步
Redisson:促使使用者对Redis的关注分离,提供很多分布式相关操作服务,例如:分布式锁
(二)RedisTemplate介绍
我相信到这里,Jedis、Lettuce、Redisson是什么,大家伙应该清楚了。那么RedisTemplate又是什么呢?且慢慢继续往下看。
Jedis、Lettuce都可以操作Redis,他们操作Redis的API又不太相同,这样对于开发人员来说,学习成本就增加了,所以Spring爸爸SpringDataRedis中对JedisApi的高度封装了一个RedisTemplate,给我们屏蔽掉了底层的实现,这样我们只需要学习RedisTemplate的相关API,这样是不是就算是减少了开发人员的学习成本。那来源码中验证一下是不是这样呢!
最终可以发现RedisTemplate 其实还是使用Jedis或者Lettuce去操作哦Redis,关于RedisTemplate 我们先介绍这么多,项目中使用真香。
下面我们就开始直接冲代码了,代码我都在工程里测试过,亲测有效。
二、Java操作redis
(一)Jedis连接Redis
1、创建一个maven工程,并在pom.xml中引进依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.0</version>
</dependency>
2、具体代码实现如下,Jedis只是简单的举了一个操作string数据类型的例子,jedis的api跟redis原生的基本保持一次,可以参考上一篇进行一些练习
package com.xiaoma.javaope;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisConnectRedis {
public static void main(String[] args) {
Jedis jedis = JedisUtil.getJedis();
// 在redis中创建一个string 变量名字是hero,值是caocao
jedis.set("hero", "caocao");
// 取出变量名为hero的值
String hero = jedis.get("hero");
System.out.println(hero);
jedis.close();
}
}
class JedisUtil {
private static final JedisPool jedisPool;
static {
//设置基本属性
JedisPoolConfig poolConfig = new JedisPoolConfig();
//最大连接数
poolConfig.setMaxTotal(20);
//最大空闲数
poolConfig.setMaxIdle(5);
jedisPool = new JedisPool(poolConfig,
"127.0.0.1", 6379, 2000, "pass");
}
public static Jedis getJedis() {
return jedisPool.getResource();
}
public static void releaseJedis(Jedis jedis) {
jedis.close();
}
}
(二) Lettuce连接Redis
1、创建一个maven工程,并在pom.xml中引进依赖
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
2、具体代码实现如下,这里只是简单的介绍了一下Lettuce操作string和map数据类型,其他的数据类型包括Lettuce的高级特性,后面会再写一篇文章介绍
public static void main(String[] args) {
RedisURI uri = RedisURI.Builder.redis("127.0.0.1")
.withPort(6379).withPassword("pass").build();
RedisClient client = RedisClient.create(uri);
// connection, 线程安全的长连接,连接丢失时会自动重连,直到调用 close 关闭连接。
StatefulRedisConnection<String, String> connection = client.connect();
RedisStringCommands<String, String> command = connection.sync();
//1、操作字符串String
command.set("曹操", "曹孟德");
String value = command.get("曹操");
System.out.println(value);
//2、操作map
Map<String, String> hero = new HashMap<>(16);
hero.put("曹操", "主公");
hero.put("许褚", "保镖");
hero.put("夏侯渊", "武将");
command.mset(hero);
List<KeyValue<String, String>> mget = command.mget("曹操", "许褚");
for (KeyValue<String, String> key : mget) {
System.out.println(key.getKey() + "_" + key.getValue());
}
// 关闭资源
connection.close();
client.shutdown();
}
(三)Redisson 操作Redis
1、创建一个maven工程,并在pom.xml中引进依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.3.2</version>
</dependency>
2、具体代码实现如下,Redisson的API就有比较大的改变,我们这边先介绍一下基本数据类型,分布式锁等应用后续文章中会继续进行介绍
package com.xiaoma.javaope;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
public class RedissonOperateRedis {
public static void main(String[] args) {
RedissonClient redissonClient = RedissonConfig.getRedissonClient();
// 1、操作string类型数据
RBucket<String> stringKey = redissonClient.getBucket("tom");
stringKey.set("28");
String value = stringKey.get();
System.out.println(value);
// 2、操作map类型的数据
RMap<String, String> heroMap = redissonClient.getMap("heroMap");
heroMap.put("zhangliao", "wujiang");
heroMap.put("xunyu", "moushi");
RMap<String, String> afterMaps = redissonClient.getMap("heroMap");
System.out.println(afterMaps.get("zhangliao"));
//3、操作set集合
RSet<Object> myset = redissonClient.getSet("myset");
//4、操作List
RList<Object> testList = redissonClient.getList("testList");
//5、操作Zset
RSortedSet<Object> zsetTest = redissonClient.getSortedSet("zsetTest");
}
}
class RedissonConfig {
public static RedissonClient getRedissonClient() {
Config config = new Config();
// 使用单机Redis服务
config.useSingleServer().setAddress("127.0.0.1:6379");
config.useSingleServer().setPassword("pass");
// 创建Redisson客户端
RedissonClient redisson = Redisson.create(config);
return redisson;
}
}
上面一个模块我们基本把三种客户端操作Redis都进行进行简单的介绍了,我相信大家应该都有一定的了解了。
下文Spring 整合Redis、SpringBoot整合Redis我就不再一 一用上面的三种实现方式去写了,基本工作中都是使用RedisTemplate,所以下文就使用RedisTemplate来操作了。
三、Spring 整合Redis
上文又提到RedisTemplate,RedisTemplate只是Spring帮助我们封装的一个模板,屏蔽了我们底层Jedis和Lettuce,所以我后面的介绍都是基于RedisTemplate来操作Redis。如果你想直接用spring直接整合jedis、Lettuce、Redisson当然也是可以的。
1、新建一个maven工程,其工程目录如下图所示
2、pom.xml 引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
3、编辑 redis.properties
redis.host=127.0.0.1
redis.port=6379
redis.password=password
redis.maxTotal=10
redis.maxIdle=5
redis.maxWaitMillis=2000
redis.testOnBorrow=true
redis.timeout=0
4、编辑redisbean.xml,spring的容器启动会加载这个文件,进行bean的初始化
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd ">
<bean id="annotationPropertyConfigurerRedis"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="1" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>classpath:redis.properties</value>
</list>
</property>
</bean>
<!-- redis数据源 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!--最大空闲数 -->
<property name="maxIdle" value="${redis.maxIdle}" />
<!--最大空连接数 -->
<property name="maxTotal" value="${redis.maxTotal}" />
<!--最大等待时间 -->
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<!--返回连接时,检测连接是否成功 -->
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!--redis连接池 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<!--redis地址 -->
<property name="hostName" value="${redis.host}" />
<!--端口号和密码 -->
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.password}" />
<!--超时时间-->
<property name="timeout" value="${redis.timeout}" />
<!--连接池引用 -->
<property name="poolConfig" ref="poolConfig" />
<!--是否使用连接池 -->
<property name="usePool" value="true"/>
</bean>
<!-- 将redisTemplate交给spring托管 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
</bean>
</beans>
5、编辑启动类,启动spring容器,并且从容器中取出RedisTemplate操作redis
package com.xiaoma.redis;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.List;
import java.util.Set;
public class SpringOperateRedis {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("redisbean.xml");
RedisTemplate redisTemplate = (RedisTemplate) context.getBean("redisTemplate");
//1、操作string数据类型
System.out.println("1、操作string数据类型");
redisTemplate.opsForValue().set("三国", "罗贯中");
System.out.println( redisTemplate.opsForValue().get("三国"));
//2、操作map数据类型
System.out.println("2、操作map数据类型");
redisTemplate.opsForHash().put("蜀国","刘备","主公");
redisTemplate.opsForHash().put("蜀国","诸葛亮","军师");
System.out.println(redisTemplate.opsForHash().get("蜀国", "刘备"));
//3、操作list数据类型
System.out.println("3、操作list数据类型");
redisTemplate.opsForList().leftPush("三大战役","官渡之战");
redisTemplate.opsForList().leftPushAll("三大战役","赤壁之战","夷陵之战");
List list = redisTemplate.opsForList().range("三大战役", 0, 2);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("4、操作set数据类型");
//4、操作set数据类型
redisTemplate.opsForSet().add("三个国家","魏国","蜀国","吴国","魏国");
Set country = redisTemplate.opsForSet().members("三个国家");
for (Object object :country) {
System.out.println(object);
}
//5、操作zset数据类型
System.out.println("5、操作zset数据类型");
redisTemplate.opsForZSet().add("武将排行榜","吕布",100);
redisTemplate.opsForZSet().add("武将排行榜","关羽",98);
redisTemplate.opsForZSet().add("武将排行榜","邢道荣",58);
//取出武力值在20-99的英雄,从小到大排序
Set sort = redisTemplate.opsForZSet().rangeByScore("武将排行榜", 20, 99);
for (Object object :sort) {
System.out.print(object);
}
}
}
注:介于篇幅,每种数据类型都只是操作几个API,熟能生巧,大家一定要强加练习哟!
四、SpringBoot整合redis
1、新建一个springBoot工程
2、引入pom依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3、application配置
spring:
redis:
port: 6379
database: 0
host: 127.0.0.1
password: password
jedis:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0
timeout: 5000ms
4、RedisConfig配置类
package com.example.springbootoperedis.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
5、测试类
@SpringBootTest
class SpringbootOpeRedisApplicationTests {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Test
public void RedisTemplateTest() {
System.out.println(redisTemplate);
redisTemplate.opsForValue().set("刘备", "刘皇叔");
System.out.println(redisTemplate.opsForValue().get("刘备"));
}
}
至此 Java操作Redis、Spring整合Redis及SpringBoot整合Redis这里都有就介绍的差不多了,这一篇只要侧重于使用,以上代码都亲测有效。
由于文章的篇幅,关于Lettuce的高级特性以及RedisTemplate的序列化方式、以及本文目前操作的都是单机版的Redis,工作中一般需要操作的是集群模式等一些平时开发中需要重点关注的问题,暂时还没有介绍到,后续的文章中将会继续写到。
如果这篇【文章】有帮助到你,希望可以给博主点个赞👍,创作不易。后面我还会继续更新Redis集群的搭建、Redis的面试题等文章,我们一起继续学习Redis的相关知识吧。