在這裏就不作spring框架詳細描述,只對用的做解釋,有什麼問題歡迎來信。
這裏增長spring-data-redis
和jedis
必需要jar包。java
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.3.4.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.5.2</version> </dependency>
在spring的配置文件applicationContext.xml里加入下面的redis的配置信息。程序員
<!-- redis配置 --> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="300" /> <property name="maxTotal" value="600" /> <property name="maxWaitMillis" value="1000" /> <property name="testOnBorrow" value="true" /> </bean> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="192.168.31.4" p:port="6379" p:password="" p:pool-config-ref="poolConfig"/> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="connectionFactory" /> </bean>
這裏配置redis的一些信息,固然也能夠用配置文件來配置redis
redis.host=192.168.31.4 redis.port=6379 redis.pass= redis.maxIdle=50 redis.maxActive=50 redis.maxWait=50 redis.testOnBorrow=true redis.timeout=1000
接下來在配置文件中配置要緩存的對象值,以下:spring
<cache:annotation-driven/> <!-- 緩存管理器 --> <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> <property name="caches"> <set> <bean class="com.hejia.alauda.redis.SystemRedisCache"> <property name="redisTemplate" ref="redisTemplate" /> <property name="name" value="default" /> <property name="timeout" value="600" /><!-- 10分鐘後過時 --> </bean> <bean class="com.hejia.alauda.redis.SystemRedisCache"> <property name="redisTemplate" ref="redisTemplate" /> <property name="name" value="orderServiceImpl.selectInterests" /> <property name="timeout" value="600" /> </bean> <bean class="com.hejia.alauda.redis.SystemRedisCache"> <property name="redisTemplate" ref="redisTemplate" /> <property name="name" value="orderServiceImpl.selectInterestsList" /> <property name="timeout" value="600" /> </bean> </set> </property> </bean>
這裏面配置的orderServiceImpl.selectInterests 和 orderServiceImpl.selectInterestsList 分別是redis緩存的名稱,下面代碼會說到數據庫
這裏增長配置文件中實現的SystemRedisCache ,這裏主要對redis的業務的操做方法。數組
import com.hejia.alauda.utils.SerializableUtil; import org.springframework.cache.Cache; import org.springframework.cache.support.SimpleValueWrapper; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.util.StringUtils; /** * info:redis緩存配置類 * Created by shang on 2016/11/9. */ public class SystemRedisCache implements Cache { /** * Redis */ private RedisTemplate<String, Object> redisTemplate; /** * 緩存名稱 */ private String name; /** * 超時時間 */ private long timeout; /* * (non-Javadoc) * @see org.springframework.cache.Cache#getName() */ @Override public String getName() { return this.name; } /* * (non-Javadoc) * @see org.springframework.cache.Cache#getNativeCache() */ @Override public Object getNativeCache() { // TODO Auto-generated method stub return this.redisTemplate; } /* * (non-Javadoc) * @see org.springframework.cache.Cache#get(java.lang.Object) */ @Override public ValueWrapper get(Object key) { if (StringUtils.isEmpty(key)) { return null; } else { final String finalKey; if (key instanceof String) { finalKey = (String) key; } else { finalKey = key.toString(); } Object object = null; object = redisTemplate.execute(new RedisCallback<Object>() { public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] key = finalKey.getBytes(); byte[] value = connection.get(key); if (value == null) { return null; } return SerializableUtil.unserialize(value); } }); return (object != null ? new SimpleValueWrapper(object) : null); } } /* * (non-Javadoc) * @see org.springframework.cache.Cache#get(java.lang.Object, java.lang.Class) */ @SuppressWarnings("unchecked") @Override public <T> T get(Object key, Class<T> type) { if (StringUtils.isEmpty(key) || null == type) { return null; } else { final String finalKey; final Class<T> finalType = type; if (key instanceof String) { finalKey = (String) key; } else { finalKey = key.toString(); } final Object object = redisTemplate.execute(new RedisCallback<Object>() { public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] key = finalKey.getBytes(); byte[] value = connection.get(key); if (value == null) { return null; } return SerializableUtil.unserialize(value); } }); if (finalType != null && finalType.isInstance(object) && null != object) { return (T) object; } else { return null; } } } /* * (non-Javadoc) * @see org.springframework.cache.Cache#put(java.lang.Object, java.lang.Object) */ @Override public void put(final Object key, final Object value) { if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { return; } else { final String finalKey; if (key instanceof String) { finalKey = (String) key; } else { finalKey = key.toString(); } if (!StringUtils.isEmpty(finalKey)) { final Object finalValue = value; redisTemplate.execute(new RedisCallback<Boolean>() { @Override public Boolean doInRedis(RedisConnection connection) { connection.set(finalKey.getBytes(), SerializableUtil.serialize(finalValue)); // 設置超時間 connection.expire(finalKey.getBytes(), timeout); return true; } }); } } } /* * 根據Key 刪除緩存 */ @Override public void evict(Object key) { if (null != key) { final String finalKey; if (key instanceof String) { finalKey = (String) key; } else { finalKey = key.toString(); } if (!StringUtils.isEmpty(finalKey)) { redisTemplate.execute(new RedisCallback<Long>() { public Long doInRedis(RedisConnection connection) throws DataAccessException { return connection.del(finalKey.getBytes()); } }); } } } /* * 清楚系統緩存 */ @Override public void clear() { // TODO Auto-generated method stub // redisTemplate.execute(new RedisCallback<String>() { // public String doInRedis(RedisConnection connection) throws DataAccessException { // connection.flushDb(); // return "ok"; // } // }); } public RedisTemplate<String, Object> getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } public void setName(String name) { this.name = name; } public long getTimeout() { return timeout; } public void setTimeout(long timeout) { this.timeout = timeout; } }
這裏附帶一個工具類的代碼,主要對開發中object和list對象的序列化和反序列化。 由於redis不知object和泛型,全部在將對象存入redis時,須要將緩存的數據序列化。緩存
import java.io.*; import java.util.ArrayList; import java.util.List; /** * info:序列化工具類 * Created by shang on 2016/11/9. */ public class SerializableUtil { /** * 序列化 * * @param object * @return */ public static byte[] serialize(Object object) { if (object == null) { return null; } ObjectOutputStream oos = null; ByteArrayOutputStream baos = null; byte[] bytes = null; try { // 序列化 baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(object); bytes = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { close(oos); close(baos); } return bytes; } /** * 反序列化 * * @param bytes * @return */ public static Object unserialize(byte[] bytes) { if (bytes == null) { return null; } ByteArrayInputStream bais = null; ObjectInputStream ois = null; try { // 反序列化 bais = new ByteArrayInputStream(bytes); ois = new ObjectInputStream(bais); return ois.readObject(); } catch (Exception e) { e.printStackTrace(); } finally { close(bais); close(ois); } return null; } /** * 序列化 list 集合 * * @param list * @return */ public static byte[] serializeList(List<?> list) { if (list==null||list.size()==0) { return null; } ObjectOutputStream oos = null; ByteArrayOutputStream baos = null; byte[] bytes = null; try { baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); for (Object obj : list) { oos.writeObject(obj); } bytes = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { close(oos); close(baos); } return bytes; } /** * 反序列化 list 集合 */ public static List<?> unserializeList(byte[] bytes) { if (bytes == null) { return null; } List<Object> list = new ArrayList<Object>(); ByteArrayInputStream bais = null; ObjectInputStream ois = null; try { // 反序列化 bais = new ByteArrayInputStream(bytes); ois = new ObjectInputStream(bais); while (bais.available() > 0) { Object obj = (Object) ois.readObject(); if (obj == null) { break; } list.add(obj); } } catch (Exception e) { e.printStackTrace(); } finally { close(bais); close(ois); } return list; } /** * 關閉io流對象 * * @param closeable */ public static void close(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (Exception e) { e.printStackTrace(); } } } }
對指定的service方法作緩存,使用方法以下:app
@Cacheable(value = "orderServiceImpl.selectInterests",key = "'selectInterests_'+#params.get('user_id')+'_'+#params.get('type')+'_'+#pager.pageNumber")//增長redis緩存 @Override public Pager<Interest> selectInterests(Map<String, Object> params, Pager<Interest> pager) { System.out.println("select selectInterests class ...."); pager.setList(interestMapper.findInterestListV3(params, pager)); pager.setTotalCount(interestMapper.findCountInterestListV3(params)); return pager; } @Cacheable(value = "orderServiceImpl.selectInterestsList",key = "'selectInterestsList_'+#params.get('user_id')+'_'+#params.get('type')+'_'+#params.get('valueDate')")//增長redis緩存 @Override public List<Map<String, Object>> selectInterestsList(Map<String, Object> params) { System.out.println("select ---selectInterestsList class"); return interestMapper.selectInterestsListV3(params); }
這上面的兩個方法就是spring配置文件裏配置的兩個緩存,我這裏主要是對查詢的分頁作緩存。 上面的方法只是添加緩存,並10分鐘後過時。這裏的key是在redis所對應的標識,若是要查詢出來可使用key值來查詢。框架
若是你須要對緩存進行修改和刪除,這須要使用@CachePut
和 @CacheEvict
。使用方法以下less
- @CacheConfig:主要用於配置該類中會用到的一些共用的緩存配置。在這裏@CacheConfig(cacheNames = "users"):配置了該數據訪問對象中返回的內容將存儲於名爲users的緩存對象中,咱們也能夠不使用該註解,直接經過@Cacheable本身配置緩存集的名字來定義。 - @Cacheable:配置了findByName函數的返回值將被加入緩存。同時在查詢時,會先從緩存中獲取,若不存在纔再發起對數據庫的訪問。該註解主要有下面幾個參數: - value、cacheNames:兩個等同的參數(cacheNames爲Spring 4新增,做爲value的別名),用於指定緩存存儲的集合名。因爲Spring 4中新增了@CacheConfig,所以在Spring 3中本來必須有的value屬性,也成爲非必需項了 - key:緩存對象存儲在Map集合中的key值,非必需,缺省按照函數的全部參數組合做爲key值,若本身配置需使用SpEL表達式,好比:@Cacheable(key = "#p0"):使用函數第一個參數做爲緩存的key值,更多關於SpEL表達式的詳細內容可參考官方文檔 - condition:緩存對象的條件,非必需,也需使用SpEL表達式,只有知足表達式條件的內容纔會被緩存,好比:@Cacheable(key = "#p0", condition = "#p0.length() < 3"),表示只有當第一個參數的長度小於3的時候纔會被緩存,若作此配置上面的AAA用戶就不會被緩存,讀者可自行實驗嘗試。 - unless:另一個緩存條件參數,非必需,需使用SpEL表達式。它不一樣於condition參數的地方在於它的判斷時機,該條件是在函數被調用以後才作判斷的,因此它能夠經過對result進行判斷。 - keyGenerator:用於指定key生成器,非必需。若須要指定一個自定義的key生成器,咱們須要去實現org.springframework.cache.interceptor.KeyGenerator接口,並使用該參數來指定。須要注意的是:該參數與key是互斥的 - cacheManager:用於指定使用哪一個緩存管理器,非必需。只有當有多個時才須要使用 - cacheResolver:用於指定使用那個緩存解析器,非必需。需經過org.springframework.cache.interceptor.CacheResolver接口來實現本身的緩存解析器,並用該參數指定。 除了這裏用到的兩個註解以外,還有下面幾個核心註解: - @CachePut:配置於函數上,可以根據參數定義條件來進行緩存,它與@Cacheable不一樣的是,它每次都會真是調用函數,因此主要用於數據新增和修改操做上。它的參數與@Cacheable相似,具體功能可參考上面對@Cacheable參數的解析 - @CacheEvict:配置於函數上,一般用在刪除方法上,用來從緩存中移除相應數據。除了同@Cacheable同樣的參數以外,它還有下面兩個參數: - allEntries:非必需,默認爲false。當爲true時,會移除全部數據 - beforeInvocation:非必需,默認爲false,會在調用方法以後移除數據。當爲true時,會在調用方法以前移除數據。
上面這些就是使用spring cache對redis作緩存的用法。若是在你的項目裏須要能夠試試一番,這裏沒有使用Ecache緩存是由於項目使用分佈式部署,若是是本地緩存就不行了,因此使用redis作緩存,統一存取。
有什麼問題歡迎給我來信或留言!