簡單聊聊Ehcache緩存

最近工做沒有那麼忙,有時間來寫寫東西。今年的系統分析師報名已經開始了,面對歷年的真題,真的難以入筆,因此忽然對將來充滿了擔心,仍是得抓緊時間學習技術。javascript

同事推了一篇軟文,看到了這個Ehcache,感受簡單又好用,因此在本身這邊也作個記錄。java

先來談談什麼是Ehcache緩存,咱們從實際場景出發,支撐一個系統最直接的東西就是數據庫,針對數據庫咱們最經常使用的操做就是查詢。反覆的查詢數據庫會致使數據庫壓力變大,傳統的數據庫查詢效率就不高(網絡、sql語句複雜),致使查詢體驗很差。尤爲當咱們查詢的語句仍是相似甚至重複的時候,這就是浪費資源了。那這個時候,緩存機制就變得頗有必要了。像咱們常用的實現緩存的方式大體有兩種,一種是NoSQL數據庫,好比Redis、MongoDB等,另外一種即是今天要提的緩存框架:Ehcache、Memcache等。web

引用官方的內容一句話定義:EhCache 是一個純Java的進程內緩存框架,具備快速、精幹等特色,是Hibernate中默認的CacheProvider。spring

下面就開始使用了:sql

整合Ehcache-優化性能-下降查詢數據庫的頻率
Spring集成Ehcache:
配置Ehcache緩存管理器(EhcacheManager),將其注入給Spring平臺緩存管理器(cachemanager),Spring平臺緩存管理器再注入給Spring緩存註解驅動。代碼中使用註解進行緩存。
 
Shiro集成Ehcache:
配置Ehcache緩存管理器(EhcacheManager),將其注入給Shiro緩存管理器(這裏是shiro整合ehcache的緩存管理器),最後將Shiro的緩存管理器注入給Shiro安全管理器
1.經過maven座標導入jar(ehcache和spring的context-support)
 
<ehcache.version>2.6.10</ehcache.version>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache-core</artifactId>
    <version>${ehcache.version}</version>
</dependency>
 
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
</dependency>
 
2.配置ApplicationContext.xml (Shiro整合ehcache)
 
 <!-- ehchace緩存管理器:ehcache緩存大對象 -->
<bean id="ehcacheManager"
	class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
	<!-- 注入緩存配置文件的位置 -->
	<property name="configLocation" value="classpath:ehcache.xml" />
</bean>
<!-- shiro緩存管理器:整合ehcache -->
<bean id="shrioCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
	<!-- 注入ehcache的緩存管理器 -->
	<property name="cacheManager" ref="ehcacheManager" />
</bean>
 
 
<!-- shiro安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	<!-- 注入 Realm鏈接安全數據 -->
	<property name="realm" ref="bosRealm"></property>
	<!-- 注入shiro的緩存管理器 -->
	<property name="cacheManager" ref="shiroCacheManager" />
</bean>
 
 
<!--經過配置的方式配置realm對象,這裏參考 -->
<!-- <bean id="bosRealm" class="cn.itcast.bos.auth.realm.BosRealm"> 注入緩存具體對象的名字,該名字在ehcache.xml中配置的 
	<property name="authenticationCacheName" value="BosShiroCache"/> </bean> -->
 
 
3.BosRealm中添加註解
 
@Component("bosRealm")
public class BosRealm extends AuthorizingRealm{
    //注入緩存名稱
    @Value("BosShiroCache")//注入緩存具體對象的名字,該名字在ehcache.xml中配置的
    public void setSuperAuthenticationCacheName(String authenticationCacheName){
        super.setAuthenticationCacheName(authenticationCacheName);
    }
}
 
4.配置ehcache.xml
 
<!-- 自定義緩存區域 -->
<cache name=" BosShiroCache " maxElementsInMemory="10000" eternal="false"
	timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000"
	diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
	<persistence strategy="localTempSwap" />
</cache>
 
默認的策略:
<!-- 硬盤緩存的臨時路徑 -->
<diskStore path="java.io.tmpdir" />
<!-- 默認的緩存區域的緩存策略 maxElementsInMemory:內存中最大容納的元素數量 eternal:對象是否永生,默認是false
	timeToIdleSeconds:發呆不用超過多長時間,over死掉 timeToLiveSeconds:活多久就死掉。 maxElementsOnDisk:硬盤上能存放多少元素 
	diskExpiryThreadIntervalSeconds:輪詢的時間,檢查的時間。 memoryStoreEvictionPolicy:若是緩存滿了怎麼辦?LRU,LFU,FIFO
	persistence strategy:若是內存滿了,溢出到硬盤 -->
<defaultCache maxElementsInMemory="10000" eternal="false"
	timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000"
	diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
	<persistence strategy="localTempSwap" />
</defaultCache>
 
 
動態菜單優化
減小無用數據查詢(減小SQL的發出)
 
問題:每次菜單生成的語句太多。生成了不少與功能權限菜單無關的語句,如角色等
解決:在Function的實體類中,使用@JSON(serialize=fase)
 
對每一個用戶菜單進行緩存
 
問題:每次刷新整個頁面都會從新生成菜單,都會從新查詢一次數據庫。
解決方案:使用緩存。具體:使用spring 整合ehcache的緩存
 
1.使用maven座標引入jar
略(上面已經引過了)
2.配置ApplicationContext.xml
 
xmlns:cache="http://www.springframework.org/schema/cache"
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
 
<!-- 配置Spring的緩存管理器 -->
<bean id="springCacheManagerSpring" class="org.springframework.cache.ehcache.EhCacheCacheManager">
	<!-- 注入ehcache的管理器 - -->
	<property name="cacheManager" ref="ehCacheManager" />
</bean>
 
<!-- 配置緩存的註解驅動,它會自動到spring的bean中尋找緩存相關注解,並使其有效 -->
<cache:annotation-driven cache-manager="springCacheManagerSpring" />
 
3.編寫ehcache.xml,添加一個新的緩存區域,如MenuSpringCache
 
4.在方法上添加註解
提示:spring的緩存管理器默認的key是方法名+參數,若是參數是個對象,那麼會發生每次緩存的key都不同,雖然數據的同樣的。所以這種狀況下,須要手動指定key
 
/**
 * 獲取用戶權限
 */
@Override
//value:緩存區域,緩存的東西往哪放
//緩存的的key的生成策略
//1.沒有參數,key='0'
//2.有1個參數,那麼key是對象自己,通常是對象地址
//3.有多個參數,那麼key是多個對象的hash值
@Cacheable(value="SpringCache",key="#user.id")
public List<Function> findFunctionByUser(User user) {
 
如添加權限,要清除緩存
 
/**
 * 添加功能
 */
@Override
//清除ehcache的某區域的全部對象
@CacheEvict(value="SpringCache",allEntries=true)
public void save(Function function) {
 
 
Hibernate中使用ehcache
 
1.導入 jar 包:ehcache-1.5.0.jar/ commons-logging.jar/ backport-util-concurrent.jar
2.開啓二級緩存(我要使用二級緩存)
3.肯定二級緩存提供商(我要使用哪一個二級緩存)
4.肯定須要緩存內容
1>配置須要緩存的類
2>配置須要緩存的集合
5.配置 ehcache 自定義配置文件
 
<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-ehcache</artifactId>
	<version>5.0.7.Final</version>
</dependency>
 
在 hibernate.cfg.xml 配置緩存,或者交由spring管理,在sessionFactory中配置
 
開啓二級緩存
 
<!-- 開啓二級緩存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
 
肯定緩存提供商
 
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
 
肯定緩存內容
 
<!-- 類緩存 -->
<!-- 指定二級緩存類 ,以及併發訪問策略 -->
<class-cache usage="read-write" class="cn.aric.domain.User"/>
<!-- 集合緩存 -->
<collection-cache usage="read-write" collection="cn.aric.doain.Customer.orderSet"/>
 
 
ehcache 配置文件
 
文件名:ehcache.xml
參考官方文件配置
 
<ehcache>
	<diskStore path="f:cache" />
	<defaultCache maxElementsInMemory="10000"
		eternal="false"
		timeToIdleSeconds="120"
		timeToLiveSeconds="120"
		overflowToDisk="true" />
	<cache name="hibernateCache"
		maxElementsInMemory="10000"
		eternal="false"
		timeToIdleSeconds="300"
		timeToLiveSeconds="600"
		overflowToDisk="true" />
</ehcache>
 
測試
 
//測試二級緩存是否配置成功
@Test
public void test(){
    Configuration configuration = new Configuration().configure();
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    //獲取session1
    Session session1 = sessionFactory.openSession();
    Transaction tx = session1.beginTransaction();
    User user1 = session1.get(User.class, 10L);
    System.out.println(user1.getUser_code());
    tx.commit();
    session1.close();
 
    //獲取session2
    Session session2 = sessionFactory.openSession();
    Transaction tx2 = session2.beginTransaction();
    User user2 = session2.get(User.class, 10L);
    System.out.println(user2.getUser_code());
    tx2.commit();
    session2.close();
}
 
查詢緩存
 
查詢緩存默認不使用。須要手動開啓
查詢緩存:將 HQL 語句與 查詢結果進行綁定。經過 HQL 相同語句能夠緩存內容。
默認狀況 Query 對象只將查詢結果存放在一級和二級緩存,不從一級或二級緩存獲取。
查詢緩存就是讓 Query 能夠從二級緩存得到內容。
 
<!-- 開啓查詢緩存 -->
<property name="hibernate.cache.use_query_cache">true</property>
 
 
@Test
public void demo(){
    // 查詢緩存
    Session s1 = factory.openSession();
    s1.beginTransaction();
    //1 query查詢
    Query q1 = s1.createQuery("from Customer");
    //設置查詢緩存爲true
    q1.setCacheable(true);
    List<Customer> a1 = q1.list();
    for (Customer c1 : a1) {
        System.out.println(c1);
    }
 
    //2 cid =1 -- 一級緩存得到
    Customer customer = (Customer) s1.get(Customer.class, 1);
    System.out.println(customer);
    s1.getTransaction().commit();
    s1.close();
    System.out.println("----------");
 
    Session s2 = factory.openSession();
    s2.beginTransaction();
    //2 cid =1 -- 二級緩存得到
    Customer customer2 = (Customer) s2.get(Customer.class, 1);
    System.out.println(customer2);
 
    //3 query查詢
    Query q2 = s2.createQuery("from Customer");
    q2.setCacheable(true);
    List<Customer> a2 = q2.list();
    for (Customer c2 : a2) {
        System.out.println(c2);
    }
    s2.getTransaction().commit();
    s2.close();
}
相關文章
相關標籤/搜索