调查问卷中或许每个单击动做都会引起大量的数据库访问,特别是在参与调查的过程当中,只是单击“上一页”或者“下一页”的按钮就会引起大量的查询,必须对这种问题进行优化才行。使用缓存策略进行查询缓存是下降数据库压力很是理想的方法,这里最起码可以有两种缓存方式:java
1.使用hibernate的二级缓存。spring
2.使用spring自带的缓存模块进行查询缓存。使用spring自带的缓存模块功能必需要知足一下条件:数据库
(1)spring版本必须至少在3.1或以上,这里使用了spring3.1express
(2)必需要使用第三方缓存厂商的缓存支持,这里使用ehcacheapache
这里使用spring自带的缓存模块进行查询缓存。缓存
[spring功能模块]app
spring-modules-cache.jar eclipse
[第三方缓存供应商] ide
backport-util-concurrent.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
ehcache-1.5.0.jar
jsr107cache-1.1.jar测试
1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
2 <diskStore path="java.io.tmpdir"/>
3 <defaultCache 4 maxElementsInMemory="10000"
5 eternal="false"
6 timeToIdleSeconds="120"
7 timeToLiveSeconds="120"
8 overflowToDisk="true"
9 maxElementsOnDisk="10000000"
10 diskPersistent="false"
11 diskExpiryThreadIntervalSeconds="120"
12 memoryStoreEvictionPolicy="LRU"
13 />
14 <!-- 自定义一个缓存策略 -->
15 <cache name="surveyCache"
16 maxElementsInMemory="10000"
17 eternal="false"
18 timeToIdleSeconds="120"
19 timeToLiveSeconds="120"
20 overflowToDisk="true"
21 maxElementsOnDisk="10000000"
22 diskPersistent="false"
23 diskExpiryThreadIntervalSeconds="120"
24 memoryStoreEvictionPolicy="LRU"
25 />
26 </ehcache>
上面配置中的属性意思都比较简单,很容易理解,不赘述。
首先,必须必须引入缓存的命名空间才行,因为eclipse中并无自带该命名空间相关信息,因此须要外部引入xsd约束,引入方式:
Window->preferences->XML->XML catalog->Add找到spring-cache-3.1.xsd文件添加进来便可,因为对应的location已经失效,因此建议使用本地文件协议file:///替代http协议。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/aop file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/cache file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema\cache/spring-cache-3.1.xsd http://www.springframework.org/schema/tx file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/context file:///D:\程序\java\Spring\spring-framework-4.2.1\spring-framework-4.2.1.RELEASE\schema/context/spring-context-2.5.xsd">
1 <!-- ehcacheManager工厂配置 -->
2 <bean id="ehcacheManager"
3 class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
4 <property name="configLocation" value="classpath:ehcache.xml"></property>
5 </bean>
1 <!-- ehcache管理器 -->
2 <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
3 <property name="cacheManager" ref="ehcacheManager"></property>
4 </bean>
<!-- Key生成器 ,先存档 -->
<bean id="surveyKeyGenerator" class="com.kdyzm.cache.SurveykeyGenerator" />
1 <!-- 定义缓存通知 -->
2 <cache:advice id="cacheAdvice" cache-manager="cacheManager"
3 key-generator="surveyKeyGenerator"><!-- 这里须要配置key生成器 -->
4 <cache:caching cache="surveyCache">
5 <!-- 设置缓存的方法 -->
6 <cache:cacheable method="get*" />
7 <cache:cacheable method="load" />
8 <cache:cacheable method="find*" />
9 <cache:cacheable method="is*" />
10
11 <!-- 设置须要清空缓存的方法 -->
12 <cache:cache-evict method="save*" all-entries="true" />
13 <cache:cache-evict method="update*" all-entries="true" />
14 <cache:cache-evict method="delete*" all-entries="true" />
15 <cache:cache-evict method="batch*" all-entries="true" />
16 <cache:cache-evict method="create*" all-entries="true" />
17 <cache:cache-evict method="new*" all-entries="true" />
18 </cache:caching>
19 </cache:advice>
为了将缓存通知首先启动,将其order属性配置为0(并非由于0才首先启动,只是相对于日志通知和事务通知来讲其order属性值最小)。
1 <aop:config>
2 <!-- 日志切入点 -->
3 <aop:pointcut 4 expression="(execution(* *..*Service.save*(..)) 5 or execution(* *..*Service.update*(..)) 6 or execution(* *..*Service.delete*(..)) 7 or execution(* *..*Service.batch*(..)) 8 or execution(* *..*Service.create*(..)) 9 or execution(* *..*Service.new*(..))) and !bean(logService)"
10 id="loggerPointcut" />
11 <aop:pointcut expression="execution(* *..*Service.*(..))"
12 id="txPointcut" />
13 <!-- 必须配置order属性,使用该属性能够改变配置的通知的加载顺序,order值越大,优先级越高 必须让事务的通知放到后面,让日志的通知先执行,这样才能在执行完成日志的通知后事务确保可以结束。 14 order值越小,优先级越高 为了解决事务没有结束的问题,必须同时修改解除绑定的时间 -->
15 <aop:advisor advice-ref="cacheAdvice" 16 pointcut="execution(* com.kdyzm.service.SurveyService.*(..)) or 17 execution(* com.kdyzm.service.PageService.*(..)) or 18 execution(* com.kdyzm.service.QuestionService.*(..)) or 19 execution(* com.kdyzm.service.AnswerService.*(..))" order="0" />
20 <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"
21 order="2" />
22 <aop:aspect id="loggerAspect" ref="logger" order="1">
23 <aop:around method="record" pointcut-ref="loggerPointcut" />
24 </aop:aspect>
25 </aop:config>
这里对调查相关的全部Service中的相关方法都进行了代理缓存。
配置文件中有一个key生成器的配置,该配置的做用就是根据当前执行的方法环境(方法名、参数列表、类名)计算出来惟一的标识符(key值),若是该标识符已经存在,则缓存管理器就会调用缓存中的数据不然就执行目标方法并将目标方法的查询结果缓存起来。
1 package com.kdyzm.cache; 2
3 import java.lang.reflect.Method; 4
5 import org.springframework.cache.interceptor.KeyGenerator; 6
7 /**
8 * 自定义key生成器 9 * @author kdyzm 10 * 11 */
12 public class SurveykeyGenerator implements KeyGenerator{ 13
14 //什么对象调用的什么方法,参数列表是什么
15 @Override 16 public Object generate(Object arg0, Method arg1, Object... arg2) { 17 String targetCode=arg0.getClass().getSimpleName()+"["+arg0.hashCode()+"]"; //arg0是类 18 String methodName=arg1.getName(); //arg1是方法 19 if(arg2!=null){ //arg2是参数列表 20 StringBuffer stringBuffer=new StringBuffer(); 21 stringBuffer.append("("); 22 for(int i=0;i<arg2.length;i++){ 23 stringBuffer.append(arg2[i].toString()); 24 stringBuffer.append(","); 25 } 26 stringBuffer.append(")"); 27 targetCode= targetCode+"."+methodName+stringBuffer.toString(); 28 System.out.println(targetCode); 29 return targetCode; 30 } 31 targetCode= targetCode+"."+methodName+"()"; 32 System.out.println(targetCode); 33 return targetCode; 34 } 35 }
清空控制台,从新单击一次“参与调查”超连接,再次查看后台,这时候就会发现没有SQL语句发出了(手要快,不要超过120秒,以前配置的ehcach.xml配置文件中声明了若是超过120s没用的话就会清空缓存,因此仍是会发出SQL查询语句)
这里须要建立多个调查页,在翻页的过程当中查看缓存的效果,这里个人调查1中一共有三页。