第三章 Redis 客户端的使用 Java版【Redis入门教程】

image

Redis入门教程目录【Redis入门教程目录】

Redis客户端

我们知道Redis是C语言开发的,如果想用别的语言操作Redis,那就需要用到别的语言的客户端。我们前面介绍过Redis的其中一个特性就是客户端多,几乎所有语言都有Redis的客户端,比如Java语言的JedisPython语言的redis-pyPHP语言的PredisGo语言的Redigo等等。这些客户端也都是遵循了Redis给的协议,然后按照协议去开发出对应语言的客户端。如Redis官方提供的redis-cli客户端其实就是一个Shell客户端
image

Jedis的使用

本篇我就讲Java语言的客户端Jedis,使用其他语言的读者可以阅读相关客户端的文档。要使用Jedis,首先确保我们已经添加了Jedis的依赖,这里我使用Maven配置

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.1</version>
</dependency>

Jedis的直连

1
2
3
4
5
6
7
8
9
10
import redis.clients.jedis.Jedis;

public class RedisJava {
public static void main(String[] args) {
//连接本地的 Redis 服务
Jedis jedis = new Jedis("127.0.0.1",6379);
jedis.set("name", "redis");
System.out.println("redis 存储的字符串为: "+ jedis.get("name"));
}
}

运行以上Java程序,输出

1
redis 存储的字符串为: redis

Jedis的连接池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import redis.clients.jedis.Jedis;

public class RedisPool {
public static void main(String[] args) {
//初始化连接池
JedisPoolConfig config=new JedisPoolConfig();
JedisPool jedisPool=new JedisPool(config,"127.0.0.1",6379);

Jedis jedis=null;
try{
jedis=jedisPool.getResource(); // 获取连接
jedis.set("name", "redis"); // 设置值
String value=jedis.get("name"); // 获取值
System.out.println(value);
}catch(Exception e){
e.printStackTrace();
}finally{
if(jedis!=null){
jedis.close();
}
if(jedisPool!=null){
jedisPool.close();
}
}
}
}

运行以上Java程序,输出

1
redis

Spring-data-redis的使用

前面我们使用了Jedis实现对Redis的操作,这里再介绍使用基于Spring的Spring-data-redis操作Redis,Spring就不用我过多介绍了,相信学Java的都认识它。
Jedis与Spring-data-redis的区别和关系:

  • Jedis:Jedis是Redis的Java客户端,通过它可以对Redis进行操作,与之功能相似的还包括Lettuce等。
  • Spring-data-redis:Spring-data-redis对Redis的操作依赖Jedis或Lettuce,实际上是对Jedis、Lettuce这些客户端的封装,提供一套与客户端无关的api供应用使用,从而你在从一个redis客户端切换为另一个客户端,不需要修改业务代码。

添加依赖

在使用Spring-data-redis前首先确保我们已经添加了相关依赖,这里我使用Maven配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.3.RELEASE</version>
<scope>test</scope>
</dependency>

<!--MySQL连接驱动-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>

<!-- Redis客户端jedis依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.0</version>
</dependency>

<!-- spring-data-redis依赖 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.5.0.RELEASE</version>
</dependency>

Spring和Spring-data-redis整合

通过XML配置文件将Spring-data-redis连接池Redis模板注入到Spring容器中。Redis模板有2个,分别是RedisTemplateStringRedisTemplate,这两个模板的区别是采用的序列化策略不一样,前者采用的是Java原生的序列化后者采用的是String序列化。模板的好处是为Redis的交互提供了高级抽象,用户无需关注Redis的连接管理、序列化等问题,把更多注意力放在业务上。
redis.properties:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ip地址
redis.host.ip=192.168.174.129
#端口号
redis.port=6379
#如果有密码
redis.password=
#客户端超时时间单位是毫秒 默认是2000
redis.timeout=3000

#最大空闲数
redis.maxIdle=6
#连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal
#redis.maxActive=600maxIdle
#控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性
redis.maxTotal=20
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=3000
#连接的最小空闲时间 默认1800000毫秒(30分钟)
redis.minEvictableIdleTimeMillis=300000
#每次释放连接的最大数目,默认3
redis.numTestsPerEvictionRun=4
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
redis.timeBetweenEvictionRunsMillis=30000

spring-redis.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!--加载配置文件-->
<bean:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"/>

<!--redis连接池配置-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!--最大空闲数 -->
<property name="maxIdle" value="${redis.maxIdle}" />
<!--连接池的最大数据库连接数 -->
<property name="maxTotal" value="${redis.maxTotal}" />
<!--最大建立连接等待时间 -->
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<!--逐出连接的最小空闲时间 默认1800000毫秒(30分钟) -->
<property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}" />
<!--每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3 -->
<property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}" />
<!--逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1 -->
<property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}" />
</bean>

<!--redis连接工厂-->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<!--连接池配置-->
<property name="poolConfig" ref="jedisPoolConfig"></property>
<!--redis地址-->
<property name="hostName" value="${redis.host.ip}"></property>
<!--redis密码-->
<!--<property name="password" value="${redis.password}"></property>-->
<!--redis端口-->
<property name="port" value="${redis.port}"></property>
<!--超时时间 毫秒-->
<property name="timeout" value="${redis.timeout}"></property>
</bean>

<!-- 注入redis操作模板为Bean 自动装配-->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<!-- 指定redis中key-value的序列化方式(此处省略) -->
</bean>

<!-- 注入redis操作模板为Bean 自动装配-->
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
</bean>

SpringSpring-data-redis整合完成之后,一般为了方便使用模板,我们会将模板进一步封装成自己的Dao工具类,这里我仅封装几个操作,如下
RedisDaoImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@Repository
public class RedisDaoImpl implements RedisDao {
@Autowired
StringRedisTemplate stringRedisTemplate;

public void setString(Object redisKey, Object redisValue) {
ValueOperations valueOperations = stringRedisTemplate.opsForValue();
valueOperations.set(redisKey, redisValue);

}

public Object getString(Object redisKey) {
ValueOperations valueOperations = stringRedisTemplate.opsForValue();
return valueOperations.get(redisKey);
}

/**
* @description: 通过redisKey 批量(map)设置redisValue(hash)
* @param: [redisKey, redisValue]
* @return: void
* @author: Xue 8
* @date: 2019/2/14
*/
public void setHashAll(Object redisKey, Map<String,Object> redisValue){
HashOperations hashOperations = stringRedisTemplate.opsForHash();
hashOperations.putAll(redisKey, redisValue);
}

/**
* @description: 通过redisKey、hashKey、hashValue设置单个redisValue(hash)
* @param: [redisKey, hashKey, hashValue]
* @return: void
* @author: Xue 8
* @date: 2019/2/14
*/
public void setHash(Object redisKey, Object hashKey, Object hashValue){
HashOperations hashOperations = stringRedisTemplate.opsForHash();
hashOperations.put(redisKey, hashKey, hashValue);
}

/**
* @description: 通过redisValue、hashKey获取hashValue
* @param: [redisKey, hashKey]
* @return: java.lang.Object
* @author: Xue 8
* @date: 2019/2/14
*/
public Object getHashValue(Object redisKey, Object hashKey){
HashOperations hashOperations = stringRedisTemplate.opsForHash();
return hashOperations.get(redisKey, hashKey);
}

/**
* @description: 通过redisKey获取hash
* @param: [redisKey]
* @return: java.util.Map<java.lang.String,java.lang.Object>
* @author: Xue 8
* @date: 2019/2/14
*/
public Map<String,Object> getHash(Object redisKey){
HashOperations hashOperations = stringRedisTemplate.opsForHash();
return hashOperations.entries(redisKey);
}

/**
* @description: 通过redisKey设置redisValue(List)
* @param: [redisKey, redisValue]
* @return: void
* @author: Xue 8
* @date: 2019/2/14
*/
public void setList(Object redisKey, List<Object> redisValue){
ListOperations listOperations = stringRedisTemplate.opsForList();
listOperations.leftPushAll(redisKey, redisValue);
}

}

之后在需要操作到Redis的地方,直接调用RedisDaoImpl即可。