服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 详解redis与spring的整合(使用缓存)

详解redis与spring的整合(使用缓存)

2020-09-03 13:52奋斗,坚持 Java教程

本篇文章主要介绍了redis与spring的整合(使用缓存),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

1、实现目标

通过redis缓存数据。(目的不是加快查询的速度,而是减少数据库的负担)  

2、所需jar包

详解redis与spring的整合(使用缓存)

注意:jdies和commons-pool两个jar的版本是有对应关系的,注意引入jar包是要配对使用,否则将会报错。因为commons-pooljar的目录根据版本的变化,目录结构会变。前面的版本是org.apache.pool,而后面的版本是org.apache.pool2...

3、redis简介

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)

3、编码实现

1)、配置的文件(properties)

将那些经常要变化的参数配置成独立的propertis,方便以后的修改redis.properties

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
redis.hostName=127.0.0.1
 
redis.port=6379
 
redis.timeout=15000
 
redis.usePool=true
 
redis.maxIdle=6
 
redis.minEvictableIdleTimeMillis=300000
 
redis.numTestsPerEvictionRun=3
 
redis.timeBetweenEvictionRunsMillis=60000

2)、spring-redis.xml

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
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
<beans xmlns="http://www.springframework.org/schema/beans"
 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
 
 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
 
 <!-- <property name="maxIdle" value="6"></property>
 
 <property name="minEvictableIdleTimeMillis" value="300000"></property>
 
 <property name="numTestsPerEvictionRun" value="3"></property>
 
 <property name="timeBetweenEvictionRunsMillis" value="60000"></property> -->
 <property name="maxIdle" value="${redis.maxIdle}"></property>
 
 <property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"></property>
 
 <property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"></property>
 
 <property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"></property>
 
 </bean>
 
 <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
 
 <property name="poolConfig" ref="jedisPoolConfig"></property>
 
 <property name="hostName" value="${redis.hostName}"></property>
 
 <property name="port" value="${redis.port}"></property>
 
 <property name="timeout" value="${redis.timeout}"></property>
 
 <property name="usePool" value="${redis.usePool}"></property>
 
 </bean>
 
 <bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
 
 <property name="connectionFactory" ref="jedisConnectionFactory"></property>
 
 <property name="keySerializer">
 
 <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
 
 </property>
 
 <property name="valueSerializer">
 
 <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
 
 </property>
 
 </bean>
 
</beans>

 3)、applicationContext.xml

spring的总配置文件,在里面假如一下的代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 
 <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
 
 <property name="ignoreResourceNotFound" value="true" />
 
 <property name="locations">
 
 <list>
 <value>classpath*:/META-INF/config/redis.properties</value>
 
 </list>
 
 </property>
 
 </bean>
<import resource="spring-redis.xml" />

4)web.xml

设置spring的总配置文件在项目启动时加载

?
1
2
3
4
5
6
7
<context-param>
 
 <param-name>contextConfigLocation</param-name>
 
 <param-value>classpath*:/META-INF/applicationContext.xml</param-value><!-- -->
 
</context-param>

5)、redis缓存工具类

ValueOperations  ——基本数据类型和实体类的缓存

ListOperations     ——list的缓存

SetOperations    ——set的缓存

HashOperations  Map的缓存

?
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
import java.io.Serializable;
 
import java.util.ArrayList;
 
import java.util.HashMap;
 
import java.util.HashSet;
 
import java.util.Iterator;
 
import java.util.List;
 
import java.util.Map;
 
import java.util.Set;
 
import org.springframework.beans.factory.annotation.Autowired;
 
import org.springframework.beans.factory.annotation.Qualifier;
 
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import org.springframework.data.redis.core.BoundSetOperations;
 
import org.springframework.data.redis.core.HashOperations;
 
import org.springframework.data.redis.core.ListOperations;
 
import org.springframework.data.redis.core.RedisTemplate;
 
import org.springframework.data.redis.core.SetOperations;
 
import org.springframework.data.redis.core.ValueOperations;
 
import org.springframework.stereotype.Service;
 
@Service
 
public class RedisCacheUtil<T>
 
{
 
 @Autowired @Qualifier("jedisTemplate")
 
 public RedisTemplate redisTemplate;
 /**
 
 * 缓存基本的对象,Integer、String、实体类等
 
 * @param key 缓存的键值
 
 * @param value 缓存的值
 
 * @return 缓存的对象
 
 */
 
 public <T> ValueOperations<String,T> setCacheObject(String key,T value)
 
 {
 
 ValueOperations<String,T> operation = redisTemplate.opsForValue();
 
 operation.set(key,value);
 
 return operation;
 
 }
 /**
 
 * 获得缓存的基本对象。
 
 * @param key 缓存键值
 
 * @param operation
 
 * @return 缓存键值对应的数据
 
 */
 
 public <T> T getCacheObject(String key/*,ValueOperations<String,T> operation*/)
 
 {
 
 ValueOperations<String,T> operation = redisTemplate.opsForValue();
 
 return operation.get(key);
 
 }
 
 /**
 
 * 缓存List数据
 
 * @param key 缓存的键值
 
 * @param dataList 待缓存的List数据
 
 * @return 缓存的对象
 
 */
 
 public <T> ListOperations<String, T> setCacheList(String key,List<T> dataList)
 
 {
 
 ListOperations listOperation = redisTemplate.opsForList();
 
 if(null != dataList)
 
 {
 
 int size = dataList.size();
 
 for(int i = 0; i < size ; i ++)
 
 {
 
  
 
 listOperation.rightPush(key,dataList.get(i));
 
 }
 
 }
 return listOperation;
 
 }
 
 /**
 
 * 获得缓存的list对象
 
 * @param key 缓存的键值
 
 * @return 缓存键值对应的数据
 
 */
 
 public <T> List<T> getCacheList(String key)
 
 {
 
 List<T> dataList = new ArrayList<T>();
 
 ListOperations<String,T> listOperation = redisTemplate.opsForList();
 
 Long size = listOperation.size(key);
 
 
 
 for(int i = 0 ; i < size ; i ++)
 
 {
 
 dataList.add((T) listOperation.leftPop(key));
 
 }
 
 
 
 return dataList;
 
 }
 
 /**
 
 * 缓存Set
 
 * @param key 缓存键值
 
 * @param dataSet 缓存的数据
 
 * @return 缓存数据的对象
 
 */
 
 public <T> BoundSetOperations<String,T> setCacheSet(String key,Set<T> dataSet)
 
 {
 
 BoundSetOperations<String,T> setOperation = redisTemplate.boundSetOps(key);
 
 /*T[] t = (T[]) dataSet.toArray();
 
 setOperation.add(t);*/
 
 Iterator<T> it = dataSet.iterator();
 
 while(it.hasNext())
 
 {
 
 setOperation.add(it.next());
 
 }
 
 
 
 return setOperation;
 
 }
 
 /**
 
 * 获得缓存的set
 
 * @param key
 
 * @param operation
 
 * @return
 
 */
 
 public Set<T> getCacheSet(String key/*,BoundSetOperations<String,T> operation*/)
 
 {
 
 Set<T> dataSet = new HashSet<T>();
 
 BoundSetOperations<String,T> operation = redisTemplate.boundSetOps(key);
 
 
 
 Long size = operation.size();
 
 for(int i = 0 ; i < size ; i++)
 
 {
 
 dataSet.add(operation.pop());
 
 }
 
 return dataSet;
 
 }
 /**
 
 * 缓存Map
 
 * @param key
 
 * @param dataMap
 
 * @return
 
 */
 
 public <T> HashOperations<String,String,T> setCacheMap(String key,Map<String,T> dataMap)
 
 {
 
 HashOperations hashOperations = redisTemplate.opsForHash();
 
 if(null != dataMap)
 
 {
 
 for (Map.Entry<String, T> entry : dataMap.entrySet()) {
 /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); */
 
 hashOperations.put(key,entry.getKey(),entry.getValue());
 
 }
 }
 
 return hashOperations;
 
 }
 
 /**
 
 * 获得缓存的Map
 
 * @param key
 
 * @param hashOperation
 
 * @return
 
 */
 
 public <T> Map<String,T> getCacheMap(String key/*,HashOperations<String,String,T> hashOperation*/)
 
 {
 
 Map<String, T> map = redisTemplate.opsForHash().entries(key);
 
 /*Map<String, T> map = hashOperation.entries(key);*/
 
 return map;
 
 }
 
 
 
 /**
 
 * 缓存Map
 
 * @param key
 
 * @param dataMap
 
 * @return
 
 */
 
 public <T> HashOperations<String,Integer,T> setCacheIntegerMap(String key,Map<Integer,T> dataMap)
 
 {
 HashOperations hashOperations = redisTemplate.opsForHash();
 if(null != dataMap)
 {
 for (Map.Entry<Integer, T> entry : dataMap.entrySet()) {
 /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); */
 
 hashOperations.put(key,entry.getKey(),entry.getValue());
 
 }
 }
 return hashOperations;
 }
 /**
 
 * 获得缓存的Map
 
 * @param key
 
 * @param hashOperation
 
 * @return
 
 */
 
 public <T> Map<Integer,T> getCacheIntegerMap(String key/*,HashOperations<String,String,T> hashOperation*/)
 
 {
 
 Map<Integer, T> map = redisTemplate.opsForHash().entries(key);
 
 /*Map<String, T> map = hashOperation.entries(key);*/
 
 return map;
 
 }
 
}

 6)、测试

这里测试我是在项目启动的时候到数据库中查找出国家和城市的数据,进行缓存,之后将数据去除。

6.1  项目启动时缓存数据

?
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
86
87
88
89
90
91
92
93
import java.util.HashMap;
 
import java.util.List;
 
import java.util.Map;
 
import org.apache.log4j.Logger;
 
import org.springframework.beans.factory.annotation.Autowired;
 
import org.springframework.context.ApplicationListener;
 
import org.springframework.context.event.ContextRefreshedEvent;
 
import org.springframework.stereotype.Service;
 
import com.test.model.City;
 
import com.test.model.Country;
 
import com.zcr.test.User;
 
/*
 
 * 监听器,用于项目启动的时候初始化信息
 
 */
 
@Service
 
public class StartAddCacheListener implements ApplicationListener<ContextRefreshedEvent>
 
{
 
 //日志
 
 private final Logger log= Logger.getLogger(StartAddCacheListener.class);
 @Autowired
 
 private RedisCacheUtil<Object> redisCache;
 @Autowired
 
 private BrandStoreService brandStoreService;
 
 @Override
 
 public void onApplicationEvent(ContextRefreshedEvent event)
 
 {
 
 //spring 启动的时候缓存城市和国家等信息
 
 if(event.getApplicationContext().getDisplayName().equals("Root WebApplicationContext"))
 
 {
 
 System.out.println("\n\n\n_________\n\n缓存数据 \n\n ________\n\n\n\n");
 
 List<City> cityList = brandStoreService.selectAllCityMessage();
 
 List<Country> countryList = brandStoreService.selectAllCountryMessage();
 
 Map<Integer,City> cityMap = new HashMap<Integer,City>();
 
 Map<Integer,Country> countryMap = new HashMap<Integer, Country>();
 
 int cityListSize = cityList.size();
 
 int countryListSize = countryList.size();
 
 for(int i = 0 ; i < cityListSize ; i ++ )
 
 {
 
 cityMap.put(cityList.get(i).getCity_id(), cityList.get(i));
 
 }
 for(int i = 0 ; i < countryListSize ; i ++ )
 
 {
 
 countryMap.put(countryList.get(i).getCountry_id(), countryList.get(i));
 
 }
 
 redisCache.setCacheIntegerMap("cityMap", cityMap);
 
 redisCache.setCacheIntegerMap("countryMap", countryMap);
 
 }
 }
 
}

 6.2  获取缓存数据

?
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
@Autowired
 
private RedisCacheUtil<User> redisCache;
 
@RequestMapping("testGetCache")
 
public void testGetCache()
 
{
 
 /*Map<String,Country> countryMap = redisCacheUtil1.getCacheMap("country");
 
 Map<String,City> cityMap = redisCacheUtil.getCacheMap("city");*/
 
 Map<Integer,Country> countryMap = redisCacheUtil1.getCacheIntegerMap("countryMap");
 
 Map<Integer,City> cityMap = redisCacheUtil.getCacheIntegerMap("cityMap");
 for(int key : countryMap.keySet())
 
 {
 
 System.out.println("key = " + key + ",value=" + countryMap.get(key));
 
 }
 
 System.out.println("------------city");
 
 for(int key : cityMap.keySet())
 
 {
 
 System.out.println("key = " + key + ",value=" + cityMap.get(key));
 
 }
}

由于Spring在配置文件中配置的bean默认是单例的,所以只需要通过Autowired注入,即可得到原先的缓存类。

以上就是spring+redis实现数据缓存的方法,希望对大家的学习有所帮助。也希望大家多多支持服务器之家。

原文链接:http://www.cnblogs.com/holdouts/articles/5811118.html

延伸 · 阅读

精彩推荐