詳解spring boot集成ehcache 2.x 用于hibernate二級(jí)緩存
本文將介紹如何在spring boot中集成ehcache作為hibernate的二級(jí)緩存。各個(gè)框架版本如下
- spring boot:1.4.3.RELEASE
- spring framework: 4.3.5.RELEASE
- hibernate:5.0.1.Final(spring-boot-starter-data-jpa默認(rèn)依賴)
- ehcache:2.10.3
項(xiàng)目依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <exclusions> <exclusion> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.3</version> </dependency>
Ehcache簡(jiǎn)介
ehcache是一個(gè)純Java的緩存框架,既可以當(dāng)做一個(gè)通用緩存使用,也可以作為將其作為hibernate的二級(jí)緩存使用。緩存數(shù)據(jù)可選擇如下三種存儲(chǔ)方案
- MemoryStore – On-heap memory used to hold cache elements. This tier is subject to Java garbage collection.
- OffHeapStore – Provides overflow capacity to the MemoryStore. Limited in size only by available RAM. Not subject to Java garbage collection (GC). Available only with Terracotta BigMemory products.
- DiskStore – Backs up in-memory cache elements and provides overflow capacity to the other tiers.
hibernate二級(jí)緩存配置
hibernate的二級(jí)緩存支持entity和query層面的緩存,org.hibernate.cache.spi.RegionFactory各類可插拔的緩存提供商與hibernate的集成。
# 打開(kāi)hibernate統(tǒng)計(jì)信息 spring.jpa.properties.hibernate.generate_statistics=true # 打開(kāi)二級(jí)緩存 spring.jpa.properties.hibernate.cache.use_second_level_cache=true # 打開(kāi)查詢緩存 spring.jpa.properties.hibernate.cache.use_query_cache=true # 指定緩存provider spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory # 配置shared-cache-mode spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE
關(guān)于hibernate緩存相關(guān)的所有配置可參考hibernate5.0官方文檔#緩存
ehcache配置文件
ehcache 2.x配置文件樣板參考官方網(wǎng)站提供的ehcache.xml。本例中使用的配置文件如下所示
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true"> <diskStore path="user.dir/cache"/> <transactionManagerLookup class="net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup" properties="jndiName=java:/TransactionManager" propertySeparator=";"/> <cacheManagerEventListenerFactory class="com.yangyi.base.ehcache.CustomerCacheManagerEventListenerFactory" properties=""/> <defaultCache maxEntriesLocalHeap="0" eternal="false" timeToIdleSeconds="1200" timeToLiveSeconds="1200"> <!--<terracotta/>--> </defaultCache> <cache name="entityCache" maxEntriesLocalHeap="1000" maxEntriesLocalDisk="10000" eternal="false" diskSpoolBufferSizeMB="20" timeToIdleSeconds="10" timeToLiveSeconds="20" memoryStoreEvictionPolicy="LFU" transactionalMode="off"> <persistence strategy="localTempSwap"/> <cacheEventListenerFactory class="com.yangyi.base.ehcache.CustomerCacheEventListenerFactory" /> </cache> <cache name="org.hibernate.cache.internal.StandardQueryCache" maxEntriesLocalHeap="5" eternal="false" timeToLiveSeconds="120"> <persistence strategy="localTempSwap" /> <cacheEventListenerFactory class="com.yangyi.base.ehcache.CustomerCacheEventListenerFactory" /> </cache> <cache name="org.hibernate.cache.spi.UpdateTimestampsCache" maxEntriesLocalHeap="5000" eternal="true"> <persistence strategy="localTempSwap" /> <cacheEventListenerFactory class="com.yangyi.base.ehcache.CustomerCacheEventListenerFactory" /> </cache> </ehcache>
ehcache事件監(jiān)聽(tīng)
在ehcache中,有兩大類事件,一是cacheManager相關(guān)的事件,如cache的init/added等;二是cahche相關(guān)的事件,如cache put/expire等。在ehcache中,默認(rèn)沒(méi)有這兩類事件的監(jiān)聽(tīng)器,需要自主實(shí)現(xiàn)監(jiān)聽(tīng)器以及監(jiān)聽(tīng)器工廠類,然后配置到ehcache.xml中,方可生效。
上述ehcache.xml配置中,給自定義cache都配置了cacheEventListenerFactory,用于監(jiān)聽(tīng)緩存事件。同時(shí)也配置了cacheManager Factory實(shí)現(xiàn)類。具體實(shí)現(xiàn)代碼如下
CacheManagerEventListener簡(jiǎn)單實(shí)現(xiàn)
package com.yangyi.base.ehcache; import net.sf.ehcache.CacheException; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Status; import net.sf.ehcache.event.CacheManagerEventListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ehcache customer cacheManagerEventListener * Created by yangjinfeng on 2017/1/5. */ public class CustomerCacheManagerEventListener implements CacheManagerEventListener { private Logger logger = LoggerFactory.getLogger(getClass()); private final CacheManager cacheManager; public CustomerCacheManagerEventListener(CacheManager cacheManager) { this.cacheManager = cacheManager; } @Override public void init() throws CacheException { logger.info("init ehcache..."); } @Override public Status getStatus() { return null; } @Override public void dispose() throws CacheException { logger.info("ehcache dispose..."); } @Override public void notifyCacheAdded(String s) { logger.info("cacheAdded... {}", s); logger.info(cacheManager.getCache(s).toString()); } @Override public void notifyCacheRemoved(String s) { } }
CacheManagerEventListenerFactory的簡(jiǎn)單實(shí)現(xiàn)
package com.yangyi.base.ehcache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.event.CacheManagerEventListener; import net.sf.ehcache.event.CacheManagerEventListenerFactory; import java.util.Properties; /** * Created by yangjinfeng on 2017/1/5. */ public class CustomerCacheManagerEventListenerFactory extends CacheManagerEventListenerFactory { @Override public CacheManagerEventListener createCacheManagerEventListener(CacheManager cacheManager, Properties properties) { return new CustomerCacheManagerEventListener(cacheManager); } }
CacheEventListener的簡(jiǎn)單實(shí)現(xiàn)
package com.yangyi.base.ehcache; import net.sf.ehcache.CacheException; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; import net.sf.ehcache.event.CacheEventListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Created by yangjinfeng on 2017/1/5. */ public class CustomerCacheEventListener implements CacheEventListener { private Logger logger = LoggerFactory.getLogger(getClass()); @Override public void notifyElementRemoved(Ehcache ehcache, Element element) throws CacheException { logger.info("cache removed. key = {}, value = {}", element.getObjectKey(), element.getObjectValue()); } @Override public void notifyElementPut(Ehcache ehcache, Element element) throws CacheException { logger.info("cache put. key = {}, value = {}", element.getObjectKey(), element.getObjectValue()); } @Override public void notifyElementUpdated(Ehcache ehcache, Element element) throws CacheException { logger.info("cache updated. key = {}, value = {}", element.getObjectKey(), element.getObjectValue()); } @Override public void notifyElementExpired(Ehcache ehcache, Element element) { logger.info("cache expired. key = {}, value = {}", element.getObjectKey(), element.getObjectValue()); } @Override public void notifyElementEvicted(Ehcache ehcache, Element element) { logger.info("cache evicted. key = {}, value = {}", element.getObjectKey(), element.getObjectValue()); } @Override public void notifyRemoveAll(Ehcache ehcache) { logger.info("all elements removed. cache name = {}", ehcache.getName()); } @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } @Override public void dispose() { logger.info("cache dispose."); } }
CacheEventListenerFactory的簡(jiǎn)單實(shí)現(xiàn)
package com.yangyi.base.ehcache; import net.sf.ehcache.event.CacheEventListener; import net.sf.ehcache.event.CacheEventListenerFactory; import java.util.Properties; /** * Created by yangjinfeng on 2017/1/5. */ public class CustomerCacheEventListenerFactory extends CacheEventListenerFactory { @Override public CacheEventListener createCacheEventListener(Properties properties) { return new CustomerCacheEventListener(); } }
完成上述事件監(jiān)聽(tīng)器的實(shí)現(xiàn)和配置后,我們可以啟動(dòng)應(yīng)用,查看下相應(yīng)事件監(jiān)聽(tīng)器中輸出的log,以驗(yàn)證是否生效
2017-01-07 10:27:07.810 INFO 4264 --- [ main] com.yangyi.Application : Starting Application on yangjinfeng-pc with PID 4264 (E:\JavaWorkSpace\spring-boot-ehcache3-hibernate5-jcache\target\classes started by yangjinfeng in E:\JavaWorkSpace\spring-boot-ehcache3-hibernate5-jcache) 2017-01-07 10:27:07.810 INFO 4264 --- [ main] com.yangyi.Application : No active profile set, falling back to default profiles: default 2017-01-07 10:27:07.865 INFO 4264 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2ef3eef9: startup date [Sat Jan 07 10:27:07 CST 2017]; root of context hierarchy 2017-01-07 10:27:09.155 INFO 4264 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [class org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$6eb4eae9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-07 10:27:09.191 INFO 4264 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cache.annotation.ProxyCachingConfiguration' of type [class org.springframework.cache.annotation.ProxyCachingConfiguration$$EnhancerBySpringCGLIB$$b7c72107] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-07 10:27:09.206 INFO 4264 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration' of type [class org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration$$EnhancerBySpringCGLIB$$ac3ae5ab] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-07 10:27:09.285 INFO 4264 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.cache-org.springframework.boot.autoconfigure.cache.CacheProperties' of type [class org.springframework.boot.autoconfigure.cache.CacheProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-07 10:27:09.291 INFO 4264 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.cache.CacheManagerCustomizers' of type [class org.springframework.boot.autoconfigure.cache.CacheManagerCustomizers] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-07 10:27:09.293 INFO 4264 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration' of type [class org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration$$EnhancerBySpringCGLIB$$46d9b2a9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-07 10:27:09.418 INFO 4264 --- [ main] .y.b.e.CustomerCacheManagerEventListener : init ehcache... 2017-01-07 10:27:09.487 INFO 4264 --- [ main] .y.b.e.CustomerCacheManagerEventListener : cacheAdded... org.hibernate.cache.spi.UpdateTimestampsCache 2017-01-07 10:27:09.487 INFO 4264 --- [ main] .y.b.e.CustomerCacheManagerEventListener : [ name = org.hibernate.cache.spi.UpdateTimestampsCache status = STATUS_ALIVE eternal = true overflowToDisk = true maxEntriesLocalHeap = 5000 maxEntriesLocalDisk = 0 memoryStoreEvictionPolicy = LRU timeToLiveSeconds = 0 timeToIdleSeconds = 0 persistence = LOCALTEMPSWAP diskExpiryThreadIntervalSeconds = 120 cacheEventListeners: com.yangyi.base.ehcache.CustomerCacheEventListener ; orderedCacheEventListeners: maxBytesLocalHeap = 0 overflowToOffHeap = false maxBytesLocalOffHeap = 0 maxBytesLocalDisk = 0 pinned = false ] 2017-01-07 10:27:09.487 INFO 4264 --- [ main] .y.b.e.CustomerCacheManagerEventListener : cacheAdded... org.hibernate.cache.internal.StandardQueryCache 2017-01-07 10:27:09.487 INFO 4264 --- [ main] .y.b.e.CustomerCacheManagerEventListener : [ name = org.hibernate.cache.internal.StandardQueryCache status = STATUS_ALIVE eternal = false overflowToDisk = true maxEntriesLocalHeap = 5 maxEntriesLocalDisk = 0 memoryStoreEvictionPolicy = LRU timeToLiveSeconds = 120 timeToIdleSeconds = 0 persistence = LOCALTEMPSWAP diskExpiryThreadIntervalSeconds = 120 cacheEventListeners: com.yangyi.base.ehcache.CustomerCacheEventListener ; orderedCacheEventListeners: maxBytesLocalHeap = 0 overflowToOffHeap = false maxBytesLocalOffHeap = 0 maxBytesLocalDisk = 0 pinned = false ] 2017-01-07 10:27:09.503 INFO 4264 --- [ main] .y.b.e.CustomerCacheManagerEventListener : cacheAdded... entityCache 2017-01-07 10:27:09.503 INFO 4264 --- [ main] .y.b.e.CustomerCacheManagerEventListener : [ name = entityCache status = STATUS_ALIVE eternal = false overflowToDisk = true maxEntriesLocalHeap = 1000 maxEntriesLocalDisk = 10000 memoryStoreEvictionPolicy = LFU timeToLiveSeconds = 20 timeToIdleSeconds = 10 persistence = LOCALTEMPSWAP diskExpiryThreadIntervalSeconds = 120 cacheEventListeners: com.yangyi.base.ehcache.CustomerCacheEventListener ; orderedCacheEventListeners: maxBytesLocalHeap = 0 overflowToOffHeap = false maxBytesLocalOffHeap = 0 maxBytesLocalDisk = 0 pinned = false ] 2017-01-07 10:27:09.503 INFO 4264 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'ehCacheCacheManager' of type [class net.sf.ehcache.CacheManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-07 10:27:09.503 INFO 4264 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'cacheManager' of type [class org.springframework.cache.ehcache.EhCacheCacheManager] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-07 10:27:09.503 INFO 4264 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'cacheAutoConfigurationValidator' of type [class org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration$CacheManagerValidator] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2017-01-07 10:27:09.829 INFO 4264 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2017-01-07 10:27:09.839 INFO 4264 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat 2017-01-07 10:27:09.839 INFO 4264 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.6 2017-01-07 10:27:09.924 INFO 4264 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2017-01-07 10:27:09.924 INFO 4264 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2061 ms 2017-01-07 10:32:41.876 INFO 4264 --- [nio-8080-exec-1] c.y.b.e.CustomerCacheEventListener : cache put. key = com.yangyi.entity.User#1, value = org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy$Item@1c13194d 2017-01-07 10:32:41.877 INFO 4264 --- [nio-8080-exec-1] c.y.b.e.CustomerCacheEventListener : cache put. key = com.yangyi.entity.Authority#1, value = org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy$Item@2accc177 2017-01-07 10:32:41.878 INFO 4264 --- [nio-8080-exec-1] c.y.b.e.CustomerCacheEventListener : cache put. key = com.yangyi.entity.Authority#2, value = org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy$Item@2b3b9c7e 2017-01-07 10:32:41.879 INFO 4264 --- [nio-8080-exec-1] c.y.b.e.CustomerCacheEventListener : cache put. key = com.yangyi.entity.Authority#3, value = org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy$Item@4c31e58c
注解方式使用二級(jí)緩存
要使用entity cache,需要在entity上配上相應(yīng)的注解方可生效。javax.persistence.Cacheable注解標(biāo)記該entity使用二級(jí)緩存,org.hibernate.annotations.Cache注解指定緩存策略,以及存放到哪個(gè)緩存區(qū)域。
有關(guān)緩存策略詳細(xì)信息可參考hibernate5.0官方文檔#緩存
package com.yangyi.entity; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import javax.persistence.Cacheable; import javax.persistence.Entity; import javax.persistence.JoinTable; @Entity @Table(name = "users") @Cacheable @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "entityCache") public class User implements Serializable { }
最后,我們需要在spring boot應(yīng)用層面打開(kāi)cache功能,使用org.springframework.cache.annotation.EnableCaching注解
package com.yangyi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
完整代碼
完整代碼示例見(jiàn)github
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
EasyExcel自定義下拉注解的三種實(shí)現(xiàn)方式總結(jié)
使用EasyExcel設(shè)置下拉數(shù)據(jù)時(shí),每次都要?jiǎng)?chuàng)建一個(gè)SheetWriteHandler組件確實(shí)比較繁瑣,為了優(yōu)化這個(gè)過(guò)程,我們可以通過(guò)自定義注解來(lái)簡(jiǎn)化操作,下面就來(lái)看看具體實(shí)現(xiàn)方法吧2024-10-10eclipse中maven的pom.xml文件中增加依賴的方法
日 在Maven項(xiàng)目中,可以使用pom.xml文件來(lái)添加依賴包,本文主要介紹了eclipse中maven的pom.xml文件中增加依賴的方法,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12基于java swing實(shí)現(xiàn)答題系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了基于java swing實(shí)現(xiàn)答題系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01springboot前后端分離集成CAS單點(diǎn)登錄(統(tǒng)一認(rèn)證)
單點(diǎn)登錄是一種身份認(rèn)證和授權(quán)技術(shù),允許用戶在多個(gè)應(yīng)用系統(tǒng)中使用同一套用戶名和密碼進(jìn)行登錄,本文主要介紹了springboot前后端分離集成CAS單點(diǎn)登錄,具有一定的參考價(jià)值,感興趣的可以了解一下2024-09-09java8實(shí)現(xiàn)list集合中按照某一個(gè)值相加求和,平均值等操作代碼
這篇文章主要介紹了java8實(shí)現(xiàn)list集合中按照某一個(gè)值相加求和,平均值等操作代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08基于selenium-java封裝chrome、firefox、phantomjs實(shí)現(xiàn)爬蟲(chóng)
這篇文章主要介紹了基于selenium-java封裝chrome、firefox、phantomjs實(shí)現(xiàn)爬蟲(chóng),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2020-10-10基于Java設(shè)計(jì)一個(gè)高并發(fā)的秒殺系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了如何基于Java設(shè)計(jì)一個(gè)高并發(fā)的秒殺系統(tǒng),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下2023-10-10Spring Boot+Nginx實(shí)現(xiàn)大文件下載功能
相信很多小伙伴,在日常開(kāi)放中都會(huì)遇到大文件下載的情況,大文件下載方式也有很多,比如非常流行的分片下載、斷點(diǎn)下載;當(dāng)然也可以結(jié)合Nginx來(lái)實(shí)現(xiàn)大文件下載,在中小項(xiàng)目非常適合使用,這篇文章主要介紹了Spring Boot結(jié)合Nginx實(shí)現(xiàn)大文件下載,需要的朋友可以參考下2024-05-05