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(" _________ 缓存数据 ________ "); 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注入,即可得到原先的缓存类。