需求:
1.系統需要加一個實時的報警列表,就是說如果用戶不處理報警就一直彈出右下角提示框.
思路:
1.這個需求在數據交互方面實現起來沒有什么難點,問題主要在實時性;
2.當時想到了兩個解決方案,第一個是類似聊天室功能實現的HTTP長連接,第二個就是在后台做數據的緩存,從減少數據庫的交互,來減輕頻繁造成負擔(ps:只是減輕.客戶端和服務端的ajax還是一直在跑);
3.后來,選擇了緩存的方式實現.因為,第一Spring已經幫我把緩存中很多重要的步驟完成了(我只需要在需要緩存的數據函數上加個注解和配置就可以),第二長連接會一直占有服務器的系統資源(特別是內存).對於我們這種服務器硬件的壓力會有隱患(並不是不行,而是我們的服務器采購的時候一般不會考慮這方面的性能).
環境:
1.spring-context.jar
2.spring-context-support.jar
過程:
1.定義Ehcache緩存配置文件用於指定緩存對象的一些屬性.比如失效時間等,其中name是spring的beanId.其他屬性在備注中有闡述.
<ehcache>
<!-- <diskStore path="d:\\temp\\cache" /> (企業版支持)-->
<!-- default cache -->
<defaultCache maxElementsInMemory="100000" eternal="false"
timeToLiveSeconds="36000" overflowToDisk="false" />
<!-- 緩存10個小時 -->
<cache name="queryEquWaring" maxElementsInMemory="100000" eternal="false"
timeToLiveSeconds="36000" overflowToDisk="false"/>
</ehcache>
<!--
defaultCache這些配置只會對在程序中通過CacheManager的addCache(String cacheName)方法添加的Cache起作用.
-->
<!--
cache元素中可以指定的屬性也有很多,但只有一個是必須的。那就是name屬性。
name:指定cache的名稱。
maxEntriesLocalDisk:指定允許在硬盤上存放元素的最大數量,0表示不限制。這個屬性我們也可以在運行期通過CacheConfiguration來更改。
maxEntriesLocalHeap:指定允許在內存中存放元素的最大數量,0表示不限制。這個屬性也可以在運行期動態修改。
maxEntriesInCache:指定緩存中允許存放元素的最大數量。這個屬性也可以在運行期動態修改。但是這個屬性只對Terracotta分布式緩存有用。
maxBytesLocalDisk:指定當前緩存能夠使用的硬盤的最大字節數,其值可以是數字加單位,單位可以是K、M或者G,不區分大小寫,如:30G。當在CacheManager級別指定了該屬性后,Cache級別也可以用百分比來表示,如:60%,表示最多使用CacheManager級別指定硬盤容量的60%。該屬性也可以在運行期指定。當指定了該屬性后會隱式的使當前Cache的overflowToDisk為true。
maxBytesLocalHeap:指定當前緩存能夠使用的堆內存的最大字節數,其值的設置規則跟maxBytesLocalDisk是一樣的。
maxBytesLocalOffHeap:指定當前Cache允許使用的非堆內存的最大字節數。當指定了該屬性后,會使當前Cache的overflowToOffHeap的值變為true,如果我們需要關閉overflowToOffHeap,那么我們需要顯示的指定overflowToOffHeap的值為false。
(企業版支持)overflowToDisk:boolean類型,默認為false。當內存里面的緩存已經達到預設的上限時是否允許將按驅除策略驅除的元素保存在硬盤上,默認是LRU(最近最少使用)。當指定為false的時候表示緩存信息不會保存到磁盤上,只會保存在內存中。該屬性現在已經廢棄,推薦使用cache元素的子元素persistence來代替,如:<persistence strategy=”localTempSwap”/>。
diskSpoolBufferSizeMB:當往磁盤上寫入緩存信息時緩沖區的大小,單位是MB,默認是30。
overflowToOffHeap:boolean類型,默認為false。表示是否允許Cache使用非堆內存進行存儲,非堆內存是不受Java GC影響的。該屬性只對企業版Ehcache有用。
copyOnRead:當指定該屬性為true時,我們在從Cache中讀數據時取到的是Cache中對應元素的一個copy副本,而不是對應的一個引用。默認為false。
copyOnWrite:當指定該屬性為true時,我們在往Cache中寫入數據時用的是原對象的一個copy副本,而不是對應的一個引用。默認為false。
timeToIdleSeconds:單位是秒,表示一個元素所允許閑置的最大時間,也就是說一個元素在不被請求的情況下允許在緩存中待的最大時間。默認是0,表示不限制。
timeToLiveSeconds:單位是秒,表示無論一個元素閑置與否,其允許在Cache中存在的最大時間。默認是0,表示不限制。
eternal:boolean類型,表示是否永恆,默認為false。如果設為true,將忽略timeToIdleSeconds和timeToLiveSeconds,Cache內的元素永遠都不會過期,也就不會因為元素的過期而被清除了。
diskExpiryThreadIntervalSeconds :單位是秒,表示多久檢查元素是否過期的線程多久運行一次,默認是120秒。
clearOnFlush:boolean類型。表示在調用Cache的flush方法時是否要清空MemoryStore。默認為true。
memoryStoreEvictionPolicy:當內存里面的元素數量或大小達到指定的限制后將采用的驅除策略。默認是LRU(最近最少使用),可選值還有LFU(最不常使用)和FIFO(先進先出)。
-->
2.在spring-cache.xml文件中,配置緩存管理bean.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bean="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- spring 注解緩存開啟 -->
<cache:annotation-driven />
<!--spring cache 采用 Ehcache實現 -->
<cache:annotation-driven cache-manager="cacheManager" />
<!-- cacheManagerFactory為由Spring生成的ehcache的cacheManager -->
<bean id="cacheManagerFactory"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:conf/ehcache.xml" />
</bean>
<!--Spring的cacheManager使用Ehcache的cacheManager -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="cacheManagerFactory" />
</bean>
<!-- 報警列表的緩存 -->
<bean id="queryEquWaring" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheName" value="queryEquWaring" />
<property name="cacheManager" ref="cacheManagerFactory" />
</bean>
<!-- 自定義的cache key生成器 -->
<bean id="customKeyGenerator" class="ths.jdp.core.cache.CustomKeyGenerator"/>
</beans>
3.在spring.xml中引入spring-cache.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bean="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<import resource="spring-core.xml" />
<import resource="spring-cache.xml" />
<import resource="datasource.xml" />
<import resource="spring-db.xml" />
<import resource="spring-mybatis.xml" />
<!--
<import resource="spring-job.xml" />
//-->
</beans>
4.在servise方法上添加注解,將方法的返回值加入緩存池
@Service
public class EquWaringService extends BaseService {
private final String sqlPackage = "ths.project.portal.equipment.mapper.equWarningMapper";
@Cacheable(value="queryEquWaring",keyGenerator="customKeyGenerator" condition="1==1")
public List<Map<String, Object>> queryEquWarning(Map<String, Object> form) {
return dao.list(form, sqlPackage+".queryEquWarning");
}
@CacheEvict(value="queryEquWaring",allEntries=true,beforeInvocation=true)
public int updateEquWaring(Map<String, Object> form){
return dao.update(form, sqlPackage+".updateEquWaring");
}
}
原理:
--springCache基於spring AOP 通過動態生成的 proxy 代理機制來對方法的調用進行切面實現緩存邏輯代碼的嵌入--
1.在spring-cache.xml文件中開啟springCache緩存機制;
2.在spring-cache.xml文件中設置緩存的實現類為org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
3.將我的value為queryEquWaring的緩存對象交給cacheManagerFactory來管理;
4.在service中通過@Cacheable標簽來定義方法,每次在外部類調用的時候,springCache會先去緩存池中取數據,如果沒有才會調用方法返回結果,並將返回值加載到緩存池中;
5.我們也可以通過使用@CacheEvict標簽來清空緩存;
總結:
1.PS:通過@Cacheable注解的緩存方法,如果在緩存池中找到數據.Spring就不會再調用的這個方法了.而是直接返回緩存中的數據.如果,我還需要執行這個方法那可以使用@
CachePut來注解方法;
2.PS:condition參數用來指定當前操作的條件,返回值應該是一個boolean.支持spEL表達式,CacheEvict中beforeInvocation參數是用於指定清空緩存的操作是在方法執行前,還是后.默認值是在后,我覺得還是在后好些,因為在后的話.這個方法報錯后.緩存是不清空的.當然看需求.
3.SpringCache只支持在類外部的方法調用才會保存和清空緩存,原因就是proxy會在this關鍵字下失效.
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">