1. 程式人生 > >Spring新增對快取的支援

Spring新增對快取的支援

快取可以可以儲存經常使用到的資訊,如果這些資訊儲存在資料庫中,經常對資料庫的讀取會嚴重影響應用的效能,所以將這些資訊儲存在快取中,取出來就可以立即使用。

1、啟用spring對快取的支援

Spring對快取的支援有兩種方式:

1)註解驅動快取

2)XML申明的快取

使用Spring最通用的方法就是在方法上新增@Cacheable和@CacheEvict註解。本人更喜歡使用XML與註解混合使用的方式開發。

2、使用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:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"
>
<!-- 啟用快取註解開關 --> <cache:annotation-driven cache-manager="cacheManager"/> <!-- 啟用註解 --> <context:component-scan base-package="com.zjp" /> <context:annotation-config/> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
>
<property name="configLocation" value="classpath:ehcache.xml"/> </bean> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehcache"/> </bean> </beans>

在spring配置檔案中聲明瞭使用ehcache快取管理器以及對應的ehcache.xml檔案定義的快取。
對應的ehcache.xml檔案

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

  <!-- 磁碟快取位置 -->
  <diskStore path="java.io.tmpdir/ehcache"/>

  <!-- 預設快取 -->
  <defaultCache
          maxEntriesLocalHeap="10000"
          eternal="false"
          timeToIdleSeconds="120"
          timeToLiveSeconds="120"
          maxEntriesLocalDisk="10000000"
          diskExpiryThreadIntervalSeconds="120"
          memoryStoreEvictionPolicy="LRU">
    <persistence strategy="localTempSwap"/>
  </defaultCache>

  <cache name="userCache"
         maxElementsInMemory="1000"
         eternal="false"
         timeToIdleSeconds="3"
         timeToLiveSeconds="3"
         maxEntriesLocalDisk="10000000"
         overflowToDisk="false"
         memoryStoreEvictionPolicy="LRU"/>
  <cache name="users"
         maxElementsInMemory="1000"
         eternal="false"
         timeToIdleSeconds="3"
         timeToLiveSeconds="3"
         maxEntriesLocalDisk="10000000"
         overflowToDisk="false"
         memoryStoreEvictionPolicy="LRU"/>
</ehcache>

其中定義了兩個快取,分別為userCache和users。

3、為對應的方法添加註解支援快取

為對應的方法新增上註解就可以實現對快取的控制,常用的註解如下:

註解 作用
@Cacheable 新增快取之前檢查快取中是否存在,存在就不呼叫,否則呼叫
@CachePut 不管快取是否存在都呼叫方法
@CacheEvict 刪除一條或者多條快取
@Caching 分組的註解,可以同時應用多個快取註解

1)新增快取

@Cacheable和@CachePut註解都可以填充快取,但是它們的工作方差異。
@Cacheable首先在快取中查詢條目,如果找到了匹配的條目,那麼就不會對方法進行
了。如果沒有找到匹配的條目,方法會被呼叫並且返回值要放到快取之中。而@Cache
不會在快取中檢查匹配的值,目標方法總是會被呼叫,並將返回值新增到快取之中。
a、自定義快取key
@Cacheable和@CachePut都有一個名為key屬性,這個屬效能夠替換預設的key,它是通過
一個SpEL表示式計算得到的。任意的SpEL表示式都是可行的,但是更常見的場景是所定義的
表示式與儲存在快取中的值有關,據此計算得到key。

 @CachePut(value = "users", key = "#user.getId()")
    public void updateUser(User user) {
        userDao.updateUser(user);
    }

b、條件化快取
@Cacheable和@CachePut提供了兩個屬性用以實現條件化快取:unless和condition,
這兩個屬性都接受一個SpEL表示式。如果unless屬性的SpEL表示式計算結果為true,那麼
快取方法返回的資料就不會放到快取中。與之類似,如果condition屬性的SpEL表示式計算
結果為false,那麼對於這個方法快取就會被禁用掉。

 @Cacheable(value = "users", condition = "#user.getId() <= 2")// 當id>2的時候禁用快取
    public User findUserInLimit(User user) {
        return userDao.findUserById(user.getId());
    }

2)快取的移除

使用@CacheEvict 就可以移除快取中對應的資料。
對於快取操作的UserService如下:

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    @Cacheable({"users"})
    public User findUser(User user) {
        System.out.println("userDao--"+userDao);
        User findUserById = userDao.findUserById(user.getId());//資料庫
        System.out.println("user---"+findUserById);
        return userDao.findUserById(user.getId());//資料庫
    }

    @Cacheable(value = "users", condition = "#user.getId() <= 2")// 當id>2的時候禁用快取
    public User findUserInLimit(User user) {
        return userDao.findUserById(user.getId());
    }

    @CachePut(value = "users", key = "#user.getId()")
    public void updateUser(User user) {
        userDao.updateUser(user);
    }

    @CacheEvict(value = "users")
    public void removeUser(User user) {
        userDao.removeUserById(user.getId());
    }

    @CacheEvict(value = "users", allEntries = true)
    public void clear() {
        userDao.removeAllUser();
    }
}   

同時新增上其他的


public interface UserDao {

    /**
     * 刪除所有使用者
     */
    public void removeAllUser();
    /**
     * 根據Id查詢使用者
     * @param id
     * @return
     */
    public User findUserById(long id);
    /**
     * 更新使用者
     * @param user
     */
    public void updateUser(User user);
    /**
     * 根據Id刪除使用者
     * @param id
     */
    public void removeUserById(long id);

}
package com.zjp.service.impl;

import org.springframework.stereotype.Service;

import com.zjp.domain.User;
import com.zjp.service.UserDao;

@Service
public class UserDaoImpl implements UserDao{

    public void removeAllUser() {
        // TODO Auto-generated method stub

    }

    public User findUserById(long id) {
        User user = new User();
        user.setId(123424);
        user.setPassword("ahfakjbnfjk");
        user.setUsername("lisi");
        return user;
    }

    public void updateUser(User user) {
        // TODO Auto-generated method stub

    }

    public void removeUserById(long id) {
        // TODO Auto-generated method stub

    }

}