在 Spring + SpringMVC + MyBatis (SSM) 架構中引入 Ehcache 作為二級快取,能顯著降低資料庫壓力。本文詳細記錄從 Maven 依賴、Ehcache 配置、Spring 整合、MyBatis Mapper 配置到 Shiro 共享 CacheManager 的完整步驟。
<dependencies>
<!-- MyBatis-Ehcache 整合包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Ehcache 核心 (注意:2.x 與 3.x API 差異大,此處用 2.x 相容 mybatis-ehcache) -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.6</version>
</dependency>
<!-- Spring 對 Ehcache 的支援 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
注意:mybatis-ehcache 目前僅相容 Ehcache 2.x,若專案已用 3.x 需另行適配或改用 Caffeine/Redis。
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://ehcache.org/ehcache.xsd"
updateCheck="false">
<!-- 磁盤存儲路徑 -->
<diskStore path="java.io.tmpdir" />
<!-- 預設快取策略 -->
<defaultCache
eternal="false"
maxElementsInMemory="1000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU" />
<!-- 自訂快取:供 MyBatis 使用 -->
<cache name="testCache"
eternal="false"
maxElementsInMemory="100"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="300"
memoryStoreEvictionPolicy="LRU" />
</ehcache>
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml" />
</bean>
<!-- MyBatis & Shiro 共享同一個 CacheManager 實例 -->
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml" />
<property name="shared" value="true" /> <!-- 必須!否則 Shiro 會建立獨立實例導致快取不一致 -->
</bean>
<!-- Shiro 的 CacheManager 包裝 -->
<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManager" ref="ehCacheManager" />
</bean>
在對應的 XxxMapper.xml 中加入:
<cache type="org.mybatis.caches.ehcache.LoggingEhcache">
<property name="timeToIdleSeconds" value="3600"/>
<property name="timeToLiveSeconds" value="3600"/>
<property name="maxEntriesLocalHeap" value="1000"/>
<property name="maxEntriesLocalDisk" value="10000000"/>
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
LoggingEhcache:會輸出快取命中/未命中日誌,方便調試。org.mybatis.caches.ehcache.EhcacheCache (無日誌)。<select> 開啟快取 (useCache="true")。<select id="selectByName" resultMap="BaseResultMap" parameterType="String" useCache="false">
SELECT * FROM user WHERE name = #{name}
</select>
mybatis-ehcache 鎖定 Ehcache 2.x,勿誤引 3.x。Serializable。完成上述配置後,重啟應用觀察日誌,若出現 Cache Hit 字樣即表示生效。合理使用二級快取能大幅提升 SSM 應用的讀取效能,但務必根據業務特性設定適當的過期策略與容量上限。