1、實現目標
通過redis緩存數據。(目的不是加快查詢的速度,而是減少數據庫的負擔)
2、所需Jar包
注意: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(主從)
4、編碼實現
1)、配置的文件(properties)
將那些經常要變化的參數配置成獨立的propertis,方便以后的修改
redis.properties
1 redis.hostName=127.0.0.1 2 redis.port=6379 3 redis.timeout=15000 4 redis.usePool=true 5 6 redis.maxIdle=6 7 redis.minEvictableIdleTimeMillis=300000 8 redis.numTestsPerEvictionRun=3 9 redis.timeBetweenEvictionRunsMillis=60000
2)、spring-redis.xml
redis的相關參數配置設置。參數的值來自上面的properties文件
1 <beans xmlns="http://www.springframework.org/schema/beans" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"> 4 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> 5 <!-- <property name="maxIdle" value="6"></property> 6 <property name="minEvictableIdleTimeMillis" value="300000"></property> 7 <property name="numTestsPerEvictionRun" value="3"></property> 8 <property name="timeBetweenEvictionRunsMillis" value="60000"></property> --> 9 10 <property name="maxIdle" value="${redis.maxIdle}"></property> 11 <property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"></property> 12 <property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"></property> 13 <property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"></property> 14 </bean> 15 <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy"> 16 <property name="poolConfig" ref="jedisPoolConfig"></property> 17 <property name="hostName" value="${redis.hostName}"></property> 18 <property name="port" value="${redis.port}"></property> 19 <property name="timeout" value="${redis.timeout}"></property> 20 <property name="usePool" value="${redis.usePool}"></property> 21 </bean> 22 <bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> 23 <property name="connectionFactory" ref="jedisConnectionFactory"></property> 24 <property name="keySerializer"> 25 <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> 26 </property> 27 <property name="valueSerializer"> 28 <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> 29 </property> 30 </bean> 31 </beans>
3)、applicationContext.xml
spring的總配置文件,在里面假如一下的代碼
1 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 2 <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> 3 <property name="ignoreResourceNotFound" value="true" /> 4 <property name="locations"> 5 <list> 6 7 <value>classpath*:/META-INF/config/redis.properties</value> 8 </list> 9 </property> 10 </bean> 11 12 <import resource="spring-redis.xml" />
4)、web.xml
設置spring的總配置文件在項目啟動時加載
1 <context-param> 2 <param-name>contextConfigLocation</param-name> 3 <param-value>classpath*:/META-INF/applicationContext.xml</param-value><!-- --> 4 </context-param>
5)、redis緩存工具類
ValueOperations ——基本數據類型和實體類的緩存
ListOperations ——list的緩存
SetOperations ——set的緩存
HashOperations Map的緩存
1 import java.io.Serializable; 2 import java.util.ArrayList; 3 import java.util.HashMap; 4 import java.util.HashSet; 5 import java.util.Iterator; 6 import java.util.List; 7 import java.util.Map; 8 import java.util.Set; 9 10 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Qualifier; 12 import org.springframework.context.support.ClassPathXmlApplicationContext; 13 import org.springframework.data.redis.core.BoundSetOperations; 14 import org.springframework.data.redis.core.HashOperations; 15 import org.springframework.data.redis.core.ListOperations; 16 import org.springframework.data.redis.core.RedisTemplate; 17 import org.springframework.data.redis.core.SetOperations; 18 import org.springframework.data.redis.core.ValueOperations; 19 import org.springframework.stereotype.Service; 20 21 @Service 22 public class RedisCacheUtil<T> 23 { 24 25 @Autowired @Qualifier("jedisTemplate") 26 public RedisTemplate redisTemplate; 27 28 /** 29 * 緩存基本的對象,Integer、String、實體類等 30 * @param key 緩存的鍵值 31 * @param value 緩存的值 32 * @return 緩存的對象 33 */ 34 public <T> ValueOperations<String,T> setCacheObject(String key,T value) 35 { 36 37 ValueOperations<String,T> operation = redisTemplate.opsForValue(); 38 operation.set(key,value); 39 return operation; 40 } 41 42 /** 43 * 獲得緩存的基本對象。 44 * @param key 緩存鍵值 45 * @param operation 46 * @return 緩存鍵值對應的數據 47 */ 48 public <T> T getCacheObject(String key/*,ValueOperations<String,T> operation*/) 49 { 50 ValueOperations<String,T> operation = redisTemplate.opsForValue(); 51 return operation.get(key); 52 } 53 54 /** 55 * 緩存List數據 56 * @param key 緩存的鍵值 57 * @param dataList 待緩存的List數據 58 * @return 緩存的對象 59 */ 60 public <T> ListOperations<String, T> setCacheList(String key,List<T> dataList) 61 { 62 ListOperations listOperation = redisTemplate.opsForList(); 63 if(null != dataList) 64 { 65 int size = dataList.size(); 66 for(int i = 0; i < size ; i ++) 67 { 68 69 listOperation.rightPush(key,dataList.get(i)); 70 } 71 } 72 73 return listOperation; 74 } 75 76 /** 77 * 獲得緩存的list對象 78 * @param key 緩存的鍵值 79 * @return 緩存鍵值對應的數據 80 */ 81 public <T> List<T> getCacheList(String key) 82 { 83 List<T> dataList = new ArrayList<T>(); 84 ListOperations<String,T> listOperation = redisTemplate.opsForList(); 85 Long size = listOperation.size(key); 86 87 for(int i = 0 ; i < size ; i ++) 88 { 89 dataList.add((T) listOperation.leftPop(key)); 90 } 91 92 return dataList; 93 } 94 95 /** 96 * 緩存Set 97 * @param key 緩存鍵值 98 * @param dataSet 緩存的數據 99 * @return 緩存數據的對象 100 */ 101 public <T> BoundSetOperations<String,T> setCacheSet(String key,Set<T> dataSet) 102 { 103 BoundSetOperations<String,T> setOperation = redisTemplate.boundSetOps(key); 104 /*T[] t = (T[]) dataSet.toArray(); 105 setOperation.add(t);*/ 106 107 Iterator<T> it = dataSet.iterator(); 108 while(it.hasNext()) 109 { 110 setOperation.add(it.next()); 111 } 112 113 return setOperation; 114 } 115 116 /** 117 * 獲得緩存的set 118 * @param key 119 * @param operation 120 * @return 121 */ 122 public Set<T> getCacheSet(String key/*,BoundSetOperations<String,T> operation*/) 123 { 124 Set<T> dataSet = new HashSet<T>(); 125 BoundSetOperations<String,T> operation = redisTemplate.boundSetOps(key); 126 127 Long size = operation.size(); 128 for(int i = 0 ; i < size ; i++) 129 { 130 dataSet.add(operation.pop()); 131 } 132 return dataSet; 133 } 134 135 /** 136 * 緩存Map 137 * @param key 138 * @param dataMap 139 * @return 140 */ 141 public <T> HashOperations<String,String,T> setCacheMap(String key,Map<String,T> dataMap) 142 { 143 144 HashOperations hashOperations = redisTemplate.opsForHash(); 145 if(null != dataMap) 146 { 147 148 for (Map.Entry<String, T> entry : dataMap.entrySet()) { 149 150 /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); */ 151 hashOperations.put(key,entry.getKey(),entry.getValue()); 152 } 153 154 } 155 156 return hashOperations; 157 } 158 159 /** 160 * 獲得緩存的Map 161 * @param key 162 * @param hashOperation 163 * @return 164 */ 165 public <T> Map<String,T> getCacheMap(String key/*,HashOperations<String,String,T> hashOperation*/) 166 { 167 Map<String, T> map = redisTemplate.opsForHash().entries(key); 168 /*Map<String, T> map = hashOperation.entries(key);*/ 169 return map; 170 } 171 172 /** 173 * 緩存Map 174 * @param key 175 * @param dataMap 176 * @return 177 */ 178 public <T> HashOperations<String,Integer,T> setCacheIntegerMap(String key,Map<Integer,T> dataMap) 179 { 180 HashOperations hashOperations = redisTemplate.opsForHash(); 181 if(null != dataMap) 182 { 183 184 for (Map.Entry<Integer, T> entry : dataMap.entrySet()) { 185 186 /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); */ 187 hashOperations.put(key,entry.getKey(),entry.getValue()); 188 } 189 190 } 191 192 return hashOperations; 193 } 194 195 /** 196 * 獲得緩存的Map 197 * @param key 198 * @param hashOperation 199 * @return 200 */ 201 public <T> Map<Integer,T> getCacheIntegerMap(String key/*,HashOperations<String,String,T> hashOperation*/) 202 { 203 Map<Integer, T> map = redisTemplate.opsForHash().entries(key); 204 /*Map<String, T> map = hashOperation.entries(key);*/ 205 return map; 206 } 207 }
6)、測試
這里測試我是在項目啟動的時候到數據庫中查找出國家和城市的數據,進行緩存,之后將數據去出
6.1 項目啟動時緩存數據
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 @Autowired 2 private RedisCacheUtil<User> redisCache; 3 4 @RequestMapping("testGetCache") 5 public void testGetCache() 6 { 7 /*Map<String,Country> countryMap = redisCacheUtil1.getCacheMap("country"); 8 Map<String,City> cityMap = redisCacheUtil.getCacheMap("city");*/ 9 Map<Integer,Country> countryMap = redisCacheUtil1.getCacheIntegerMap("countryMap"); 10 Map<Integer,City> cityMap = redisCacheUtil.getCacheIntegerMap("cityMap"); 11 12 for(int key : countryMap.keySet()) 13 { 14 System.out.println("key = " + key + ",value=" + countryMap.get(key)); 15 } 16 17 System.out.println("------------city"); 18 for(int key : cityMap.keySet()) 19 { 20 System.out.println("key = " + key + ",value=" + cityMap.get(key)); 21 } 22 }
由於Spring在配置文件中配置的bean默認是單例的,所以只需要通過Autowired注入,即可得到原先的緩存類。
原文:http://www.cnblogs.com/0201zcr/p/4987561.html