1、實現目標
通過redis緩存數據。(目的不是加快查詢的速度,而是減少數據庫的負擔)
2、所需jar包
注意:jdies和commons-pool兩個jar的版本是有對應關系的,注意引入jar包是要配對使用,否則將會報錯。因為commons-pooljar的目錄根據版本的變化,目錄結構會變。前面的版本是org.apache.pool,而后面的版本是org.apache.pool2...
style="background-color: #0098dd; color: white; font-size: 17px; font-weight: bold;"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
|
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
|
<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
|
<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
|
<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
|
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
|
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
|
@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實現數據緩存的方法,希望對大家的學習有所幫助。