調查問卷中或許每個單擊動做都會引起大量的數據庫訪問,特別是在參與調查的過程當中,只是單擊「上一頁」或者「下一頁」的按鈕就會引起大量的查詢,必須對這種問題進行優化才行。使用緩存策略進行查詢緩存是下降數據庫壓力很是理想的方法,這裏最起碼可以有兩種緩存方式: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中一共有三頁。