Java项目实战 - Redis集成Spring

一般只会在生产环境使用集群,而开发环境使用Redis单机版,所以我们在整合项目的时候,单机版和集群版都要有。

Spring整合Redis

创建一个接口,再编写单机版和集群版的实现类,使用spring进行管理,在部署时,使用哪种Redis,就切换那种实现类。

实现

Interface:

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.izheyi.rest.redis;

public interface RedisUtils {
String set(String key, String value);
String get(String key);
Boolean exists(String key);
Long expire(String key, int seconds);
Long ttl(String key);
Long incr(String key);
Long hset(String key, String field, String value);
String hget(String key, String field);
Long hdel(String key, String... field);
}

单机版:

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
public class RedisPool implements RedisUtils {

@Autowired
private JedisPool jedisPool;

@Override
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String result = jedis.set(key, value);
jedis.close();
return result;
}

@Override
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
}

@Override
public Boolean exists(String key) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.exists(key);
jedis.close();
return result;
}

@Override
public Long expire(String key, int seconds) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.expire(key, seconds);
jedis.close();
return result;
}

@Override
public Long ttl(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.ttl(key);
jedis.close();
return result;
}

@Override
public Long incr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.incr(key);
jedis.close();
return result;
}

@Override
public Long hset(String key, String field, String value) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hset(key, field, value);
jedis.close();
return result;
}

@Override
public String hget(String key, String field) {
Jedis jedis = jedisPool.getResource();
String result = jedis.hget(key, field);
jedis.close();
return result;
}

@Override
public Long hdel(String key, String... field) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hdel(key, field);
jedis.close();
return result;
}

}

集群版:

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
public class RedisCluster implements RedisUtils {

@Autowired
private JedisCluster jedisCluster;

@Override
public String set(String key, String value) {
return jedisCluster.set(key, value);
}

@Override
public String get(String key) {
return jedisCluster.get(key);
}

@Override
public Boolean exists(String key) {
return jedisCluster.exists(key);
}

@Override
public Long expire(String key, int seconds) {
return jedisCluster.expire(key, seconds);
}

@Override
public Long ttl(String key) {
return jedisCluster.ttl(key);
}

@Override
public Long incr(String key) {
return jedisCluster.incr(key);
}

@Override
public Long hset(String key, String field, String value) {
return jedisCluster.hset(key, field, value);
}

@Override
public String hget(String key, String field) {
return jedisCluster.hget(key, field);
}

@Override
public Long hdel(String key, String... field) {
return jedisCluster.hdel(key, field);
}
}

applicationContext-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
<!-- 两种方案:使用jedis连接池(单机版)和jedis集群 -->
<!-- 一般生产环境使用集群,开发环境使用单机版 -->
<!-- 使用哪种,可以将另一种注释掉 -->

<!-- 单机版 -->
<!-- 配置jedis连接池 -->
<bean class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="${redis.host}" />
<constructor-arg name="port" value="${redis.port}" />
</bean>

<!-- 集群版 -->
<!-- 配置jedis集群 -->
<bean class="redis.clients.jedis.JedisCluster">
<constructor-arg name="nodes">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${cluster.host1}" />
<constructor-arg name="port" value="${cluster.port1}" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${cluster.host2}" />
<constructor-arg name="port" value="${cluster.port2}" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${cluster.host3}" />
<constructor-arg name="port" value="${cluster.port3}" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${cluster.host4}" />
<constructor-arg name="port" value="${cluster.port4}" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${cluster.host5}" />
<constructor-arg name="port" value="${cluster.port5}" />
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="${cluster.host6}" />
<constructor-arg name="port" value="${cluster.port6}" />
</bean>
</set>
</constructor-arg>
</bean>

添加到业务中

缓存的添加不能影响正常的业务逻辑。

以首页大广告位的展示为例。在请求的时候如果有缓存,就直接响应;如果没有,就从DB中读取,并写入到缓存中,再响应。
对获得大广告位的Service进行修改:

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
public List<TbContent> getContentList(long contentCategoryId) {
// 查询数据库之前,先查询缓存
try {
String json = redisUtils.hget(CONTENT_KEY, contentCategoryId + "");
// 判断是否命中缓存
if (StringUtils.isNotBlank(json)) {
// 把这个json转换成List集合
List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
return list;
}
} catch (Exception e) {
e.printStackTrace();
}

TbContentExample example = new TbContentExample();
Criteria criteria = example.createCriteria();
criteria.andCategoryIdEqualTo(contentCategoryId);

List<TbContent> result = contentMapper.selectByExample(example);

// 添加缓存,并且不能影响正常业务逻辑
try {
redisUtils.hset(CONTENT_KEY, contentCategoryId + "", JsonUtils.objectToJson(result));
} catch (Exception e) {
e.printStackTrace();
}
return result;
}

验证

刷新首页,检查redis缓存。

1
2
3
4
5
127.0.0.1:6379> hget CONTENT_KEY 89
(nil)
127.0.0.1:6379> hget CONTENT_KEY 89
"[{\"id\":33,\"categoryId\":89,\"title\":\"ad1\",\"subTitle\":\"ad1\",\"titleDesc\":\"ad1\",\"url\":\"http://google.com\",\"pic\":\"http://192.168.220.133/images/2018/07/18/c7ae33f0-1e56-451c-94b3-a7cc5dbd5101.jpg\",\"pic2\":\"http://192.168.220.133/images/2018/07/18/f7622208-d7df-4a95-b279-69e48c148fdf.jpg\",\"created\":1531905943000,\"updated\":1531905943000,\"content\":null},{\"id\":34,\"categoryId\":89,\"title\":\"ad2\",\"subTitle\":\"ad2\",\"titleDesc\":\"ad2\",\"url\":\"#\",\"pic\":\"http://192.168.220.133/images/2018/07/18/b83eae10-105e-4fa4-8b46-26f16114c11b.jpg\",\"pic2\":\"http://192.168.220.133/images/2018/07/18/7dec8ede-5fae-4e80-90cc-15a6a7781355.jpg\",\"created\":1531905966000,\"updated\":1531905966000,\"content\":null},{\"id\":35,\"categoryId\":89,\"title\":\"ad3\",\"subTitle\":\"ad3\",\"titleDesc\":\"ad3\",\"url\":\"ad3\",\"pic\":\"http://192.168.220.133/images/2018/07/18/7adf566c-2967-4e99-9265-283244d3379d.jpg\",\"pic2\":\"http://192.168.220.133/images/2018/07/18/2381bf63-2b89-40ad-858c-498ea01e5abf.jpg\",\"created\":1531905995000,\"updated\":1531905995000,\"content\":null}]"
127.0.0.1:6379>

唐胡璐 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
分享创造价值,您的支持将鼓励我继续前行!