标签:
推荐一个程序员的论坛网站:http://ourcoders.com/home/
以下内容使用到的技术有:Redis缓存、SpringMVC、Maven。项目中使用了redis缓存,目的是在业务场景中,提高SQL的查询效率,做出性能优化。先看pom.xml的配置文件中,Jedis是Redis的Java客户端,Jedis基本实现了Redis的所有功能。在使用的时候,我们创建一个Jedis对象,通过操作Jedis来操作Redis,实现我们的业务场景需求。项目中使用了Maven来托管,先看Jedis在pom文件中的配置如下:
1 <!-- Redis --> 2 <dependency> 3 <groupId>redis.clients</groupId> 4 <artifactId>jedis</artifactId> 5 <version>2.7.0</version> 6 </dependency> 7 8 <dependency> 9 <groupId>org.springframework.data</groupId> 10 <artifactId>spring-data-redis</artifactId> 11 <version>1.5.0.RELEASE</version> 12 </dependency>
我们的pom.xml配置文件中共有两部分,上述配置会导入jedis-2.7.0.jar包和spring-data-redis.jar包。我们再看配置文件app-context-cache.xml,其中配置了ip地址,端口号,以及数据库的访问密码。这部分配置利用了maven编译时,会扫描相应的配置文件动态加载,如maven会根据:dev.properties、pre.properties、production.properties;开发、测试、生产生成相应的配置文件:详情如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 7 <!-- redis --> 8 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> 9 <property name="maxTotal" value="100" /> 10 <property name="maxIdle" value="20" /> 11 <property name="timeBetweenEvictionRunsMillis" value="30000" /> 12 <property name="minEvictableIdleTimeMillis" value="30000" /> 13 <property name="testOnBorrow" value="true" /> 14 </bean> 15 <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy"> 16 <property name="poolConfig" ref="jedisPoolConfig" /> 17 <property name="hostName"> 18 <value>${redis.address}</value> 19 </property> 20 <property name="port"> 21 <value>${redis.port}</value> 22 </property> 23 <property name="password"> 24 <value>${redis.password}</value> 25 </property> 26 <property name="timeout" value="15000"></property> 27 <property name="usePool" value="true"></property> 28 </bean> 29 <bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> 30 <property name="connectionFactory" ref="jedisConnectionFactory"></property> 31 <property name="keySerializer"> 32 <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> 33 </property> 34 <property name="valueSerializer"> 35 <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> 36 </property> 37 </bean> 38 39 <bean id="cacheService" class="xx.xx.xx.xx.CacheService" /> 40 41 </beans>
其中<bean id="cacheService" class="xx.xx.xx.xx.CacheService" />指定了缓存类所在的package包中。再来看具体的CacheService的使用。
1 /** 2 * 缓存操作 3 */ 4 public class CacheService { 5 6 protected Logger logger = LoggerFactory.getLogger(getClass()); 7 8 @Autowired 9 private RedisTemplate<String, Object> redisTemplate; 10 11 /* 12 * 缓存最大过期时间-一个月 13 */ 14 public static final int EXPIRE_TIME_MAX = 30 * 24 * 3600; 15 16 /* 17 * 缓存过期时间-半天 18 */ 19 public static final int EXPIRE_TIME_HALFDAY = 12 * 3600; 20 21 /* 22 * 缓存过期时间-整天 23 */ 24 public static final int EXPIRE_TIME_ONEDAY = 24 * 3600; 25 26 /****************************** 27 ********* 缓存操作 *********** 28 ******************************/ 29 30 /** 31 * 设置缓存 32 * 33 * @param key 34 * @param value 35 */ 36 public void putCache(String key, Object value) { 37 try { 38 redisTemplate.opsForValue().set(key, value); 39 } catch (Exception e) { 40 logger.error("PUT cache exception [key=" + key + ", value=" + value + "].", e); 41 } 42 } 43 44 /** 45 * 设置缓存,并设定缓存时长(秒) 46 * 47 * @param key 48 * @param value 49 * @param expire 50 */ 51 public void putCache(String key, Object value, int expire) { 52 try { 53 54 redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS); 55 } catch (Exception e) { 56 logger.error("PUT cache exception [key=" + key + ", value=" + value + ", expire=" + expire + "].", e); 57 } 58 } 59 60 /** 61 * 获取缓存数据 62 * 63 * @param key 64 * @return 65 */ 66 public Object getCache(String key) { 67 try { 68 69 return redisTemplate.opsForValue().get(key); 70 } catch (Exception e) { 71 logger.error("GET cache exception [key=" + key + "].", e); 72 } 73 return null; 74 } 75 76 /** 77 * 删除缓存 78 * 79 * @param key 80 */ 81 public void removeCache(String key) { 82 try { 83 84 redisTemplate.delete(key); 85 86 } catch (Exception e) { 87 logger.error("Remove cache exception [key=" + key + "].", e); 88 } 89 } 90 91 /****************************** 92 ********* 队列操作 *********** 93 ******************************/ 94 95 /** 96 * 队列缓存设置 97 * 98 * @param key 99 * @param value 100 */ 101 public void putQueue(String key, Object value) { 102 try { 103 104 redisTemplate.opsForList().leftPush(key, value); 105 106 } catch (Exception e) { 107 logger.error("PUT Queue cache exception [key=" + key + ", value=" + value + "].", e); 108 } 109 } 110 111 /** 112 * 获取队列缓存 113 * 114 * @param key 115 * @return 116 */ 117 public Object getQueue(String key) { 118 try { 119 120 return redisTemplate.opsForList().rightPop(key); 121 122 } catch (Exception e) { 123 logger.error("GET Queue cache exception [key=" + key + "].", e); 124 return null; 125 } 126 } 127 128 /****************************** 129 ********* 栈操作 *********** 130 ******************************/ 131 public void putStack(String key, Object value) { 132 try { 133 redisTemplate.opsForList().leftPush(key, value); 134 } catch (Exception e) { 135 logger.error("PUT Stack cache exception [key=" + key + ", value=" + value + "].", e); 136 } 137 } 138 139 public Object getStack(String key) { 140 try { 141 return redisTemplate.opsForList().leftPop(key); 142 143 } catch (Exception e) { 144 logger.error("GET Stack cache exception [key=" + key + "].", e); 145 return null; 146 } 147 } 148 149 public int length(String key) { 150 151 try { 152 return redisTemplate.opsForList().size(key).intValue(); 153 } catch (Exception e) { 154 logger.error("GET cache length exception [key=" + key + "].", e); 155 return 0; 156 } 157 } 158 159 public void expire(String key, long timeout, TimeUnit unit) { 160 try { 161 redisTemplate.expire(key, timeout, unit); 162 } catch (Exception e) { 163 logger.error("SET expire time exception [key=" + key + "].", e); 164 } 165 } 166 167 /****************************** 168 ********* hash操作 *********** 169 ******************************/ 170 /** 171 * hash put all 172 * 173 * @param key 174 * @param map 175 * @date 2015年10月12日 176 */ 177 public void hputs(String key, HashMap<? extends Object, ? extends Object> map) { 178 try { 179 redisTemplate.opsForHash().putAll(key, map); 180 } catch (Exception e) { 181 logger.error("PUT All Hash exception [key=" + key + "].", e); 182 } 183 } 184 185 /** 186 * hash put 187 * 188 * @param key 189 * @param hashKey 190 * @param value 191 * @date 2015年10月12日 192 */ 193 public void hput(String key, Object hashKey, Object value) { 194 try { 195 redisTemplate.opsForHash().put(key, hashKey, value); 196 } catch (Exception e) { 197 logger.error("PUT Hash length exception [key=" + key + "].", e); 198 } 199 } 200 201 /** 202 * hash get 203 * 204 * @param key 205 * @param hashKey 206 * @return 207 * @date 2015年10月12日 208 */ 209 public Object hget(String key, Object hashKey) { 210 try { 211 return redisTemplate.opsForHash().get(key, hashKey); 212 } catch (Exception e) { 213 logger.error("GET Hash exception [key=" + key + "].", e); 214 return null; 215 } 216 } 217 218 /** 219 * hash remove 220 * 221 * @param key 222 * @param hashKey 223 * @date 2015年10月12日 224 */ 225 public void hrem(String key, Object hashKey) { 226 try { 227 redisTemplate.opsForHash().delete(key, hashKey); 228 } catch (Exception e) { 229 logger.error("DELETE Hash exception [key=" + key + "].", e); 230 } 231 } 232 233 /** 234 * hash size 235 * 236 * @param key 237 * @return 238 * @date 2015年10月12日 239 */ 240 public long hsize(String key) { 241 try { 242 return redisTemplate.opsForHash().size(key); 243 } catch (Exception e) { 244 logger.error("GET Hash size exception [key=" + key + "].", e); 245 return 0; 246 } 247 } 248 249 /** 250 * hash keys 251 * 252 * @param key 253 * @return 254 * @date 2015年10月12日 255 */ 256 public Set<?> hkeys(String key) { 257 try { 258 return redisTemplate.opsForHash().keys(key); 259 } catch (Exception e) { 260 logger.error("GET Hash size exception [key=" + key + "].", e); 261 return null; 262 } 263 } 264 265 /** 266 * 取出Map 267 */ 268 public Map<Object,Object> hMap(String key){ 269 try { 270 return redisTemplate.opsForHash().entries(key); 271 } catch (Exception e) { 272 logger.error("GET Map size exception [key=" + key + "].", e); 273 return null; 274 } 275 } 276 277 278 /************************************************************ 279 **********************zset 操作***************************** 280 ************************************************************/ 281 /** 282 *往Zset插入数据 283 */ 284 public void zsetPut(String key,Object hashKey,Double score){ 285 try{ 286 redisTemplate.opsForZSet().add(key, hashKey, score); 287 }catch(Exception e){ 288 logger.error("PUT Zset exception [key=" + key + "].", e); 289 } 290 } 291 292 /** 293 * 查询Zset,按照开始结束score 294 */ 295 public Set<?> zsetGet(String key,Double arg0,Double arg1){ 296 try{ 297 return redisTemplate.opsForZSet().rangeByScore(key, arg0, arg1); 298 }catch(Exception e){ 299 logger.error("GET Zset exception [key=" + key + "].", e); 300 return null; 301 } 302 } 303 304 /** 305 * 模糊查询 306 */ 307 public Set<String> fuzzyQuery(String pattern){ 308 try{ 309 return redisTemplate.keys(pattern); 310 }catch(Exception e){ 311 logger.error("GET fuzzyQuery exception [key=" + pattern + "].", e); 312 return null; 313 } 314 } 315 316 public RedisTemplate<String, Object> getRedisTemplate() { 317 return redisTemplate; 318 } 319 320 public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { 321 this.redisTemplate = redisTemplate; 322 } 323 }
我们使用快捷键:ctrl+o迅速浏览一下CacheService.java类文件中的方法:
其中有如下的方法:用于设置缓存。
1 /** 2 * 设置缓存 3 * 4 * @param key 5 * @param value 6 */ 7 public void putCache(String key, Object value) { 8 try { 9 redisTemplate.opsForValue().set(key, value); 10 } catch (Exception e) { 11 logger.error("PUT cache exception [key=" + key + ", value=" + value + "].", e); 12 } 13 }
做好了上述配置,再来看看我们项目中是如何使用他们的。
1 public TradingArea findById(Integer id) { 2 if (id == null) 3 return null; 4 TradingArea ta = tradingAreaMapper.selectByPrimaryKey(id); 5 if (ta == null || ta.getIsActive() == (byte) 0) { 6 return null; 7 } 8 return ta; 9 } 10 11 12 /** 13 * @Description: 缓存数据查询 14 */ 15 @Cache(expire = CacheService.EXPIRE_TIME_HALFDAY) 16 public TradingArea getTradingArea(Integer id){ 17 return findById(id); 18 }
根据主键ID查找对应的对象,我们写了两个方法,其中第一个方法,是针对该对象的增删改查,所以必须要用到实时数据,不能使用缓存。第二个方法,很显然,上方添加了缓存注解,通过设置缓存的有效时间,我们凡是做为关联表来查询的时候,都可以使用缓存来提示效率。那么问题的核心来了,我们上方添加了一个有效时间的注解,项目中是怎么实现来帮助我们取缓存的呢?先看缓存的定义文件
1 @Target(ElementType.METHOD) 2 @Retention(RetentionPolicy.RUNTIME) 3 public @interface Cache { 4 boolean notCacheNull() default false; 5 int expire() default CacheService.EXPIRE_TIME_ONEDAY ; 6 boolean requireNew() default false; 7 }
当上述注解加在方法上的时候,会被一个拦截器拦截,拦截器拦截到之后,就会执行我们想要让缓存来做的:有就取出,没有就查SQL,同时拷贝一份在缓存中。下述是拦截器的配置文件,如下:
1 <bean id="businessMethodInterceptor" class="com.XX.XX.interceptor.BusinessMethodInterceptor"> 2 <property name="needRoutingDatasource" value="false" /> 3 </bean>
我们来看一下拦截器,拦截了缓存注解之后,有哪些操作,代码如下:
1 /** 2 * 缓存处理 3 */ 4 if (thisMethod.isAnnotationPresent(Cache.class)) { 5 Cache annotation = thisMethod.getAnnotation(Cache.class); 6 Class<?> returnType = thisMethod.getReturnType(); 7 if (returnType != null && !"void".equals(returnType.getName())) { 8 Object cache = null; 9 try { 10 CacheKey key = new CacheKey(thisMethod.getDeclaringClass(), thisMethod, invocation.getArguments()); 11 if(!annotation.requireNew()){ 12 cache = cacheService.getCache(key.toString()); 14 } 15 if (cache == null) { 16 cache = invocation.proceed(); 17 try { 18 cacheService.putCache(key.toString(), cache, annotation.expire()); 19 } catch (Exception e) { 20 logger.error("Cache Annotation process PUT CACHE exception.", e); 21 } 23 } 24 return cache; 25 } catch (Exception e) { 26 logger.error("Cache Annotation process exception.", e); 27 } 28 } 29 } 30 return invocation.proceed();
标签:
原文地址:http://www.cnblogs.com/RunForLove/p/4903734.html