本文主要是key value的形式。
這裏我先說下序列化吧
GenericToStringSerializer:使用Spring轉換服務進行序列化(能夠用來專門轉化存放Double等類型,我下面的工具類有介紹);java
JacksonJsonRedisSerializer:使用Jackson 1,將對象序列化爲JSON;git
Jackson2JsonRedisSerializer:使用Jackson 2,將對象序列化爲JSON;github
JdkSerializationRedisSerializer:使用Java序列化;web
StringRedisSerializer:序列化String類型的key和value。其實是String和byte數組之間的轉換,那麼Key只能是String類型的,不能爲Long,Integer,不然會報錯拋異常。redis
StringSerializer就是經過String.getBytes()來實現的,並且在Redis中,全部存儲的值都是字符串類型的。因此這種方法保存後,經過Redis-cli控制檯,是能夠清楚的查看到咱們保存了什麼key,value是什麼。它只能對String類型進行序列化spring
JdkSerializationRedisSerializer,這個序列化方法是Idk提供的,要求要被序列化的類繼承自Serializeable接口,而後經過Jdk對象序列化的方法保存,這個序列化保存的對象,即便是個String類型的,在redis控制檯,也是看不出來的,仍是相似於 亂碼的東西。由於它保存了一些對象的類型什麼的額外信息。除非中間再加上一些objectmappr就能夠看到內容了,以下數據庫
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
redisTemplate.setConnectionFactory(factory);
//key序列化方式,StringXX是轉爲String,JacksonXX是將對象轉爲json。
// 須要注意這裏Key使用了StringRedisSerializer,那麼Key只能是String類型的,不能爲Long,Integer,不然會報錯拋異常。
// 就是假如PostRepository裏定義的@Cacheable(key="0")的話就會報錯,由於這樣做爲key的是int型,key必須爲String。
//因此在沒有本身定義key生成策略的時候,能夠不配置,我就沒有配置
RedisSerializer<String> redisSerializer = new StringRedisSerializer();//Long類型不能夠會出現異常信息;
redisTemplate.setKeySerializer(redisSerializer);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
return redisTemplate;
}
我公司的項目中既有Ehcache 又有Redis,因此這裏都會講解
ehcache直接在jvm虛擬機中緩存,速度快,效率高;可是緩存共享麻煩,集羣分佈式應用不方便。express
redis是經過socket訪問到緩存服務,效率比ecache低,比數據庫要快不少,處理集羣和分佈式緩存方便,有成熟的方案。json
若是是單個應用或者對緩存訪問要求很高的應用,用ehcache。
若是是大型系統,存在緩存共享、分佈式部署、緩存內容很大的,建議用redis。數組
補充下:ehcache也有緩存共享方案,不過是經過RMI或者Jgroup多播方式進行廣播緩存通知更新,緩存共享複雜,維護不方便;簡單的共享能夠,可是涉及到緩存恢復,大數據緩存,則不合適
@ImportResource(value = "classpath:applicationContext.xml")
@SpringBootApplication
public class SinoredisSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SinoredisSpringbootApplication.class, args);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<description>spring configuration</description>
<import resource="applicationContext-redis.xml"/>
</beans>
########################################################
###REDIS (RedisProperties) redis ######################################################## hlj.redis.host-name=127.0.0.1 hlj.redis.password= hlj.redis.max-total=64 hlj.redis.max-idle=30 hlj.redis.port=6379 hlj.redis.pool.max-wait=-1
這裏能夠看到我使用了自定義的key 和value的序列化方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" >
<property name="maxTotal" value="${hlj.redis.max-total}"/>
<property name="maxIdle" value="${hlj.redis.max-idle}"/>
<property name="maxWaitMillis" value="${hlj.redis.pool.max-wait}"/>
</bean>
<bean id="jedisFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
<property name="password" value="${hlj.redis.password}"/>
<property name="hostName" value="${hlj.redis.host-name}"/>
<property name="port" value="${hlj.redis.port}"/>
<property name="usePool" value="true"/>
<property name="poolConfig" ref="jedisPoolConfig"/>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" scope="prototype">
<property name="connectionFactory" ref="jedisFactory"/>
<property name="keySerializer">
<bean class="com.hlj.redis.cache.CustomStringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="com.hlj.redis.cache.CustomJSONStringRedisSerializer"/>
</property>
</bean>
</beans>
package com.hlj.config.serializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.util.Assert;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
/** * 類名稱:CustomStringRedisSerializer * 類描述:定製String 序列轉換 * 建立人:qingxu * 修改人: * 修改時間:2016/3/2 15:04 * 修改備註: * * @version 1.0.0 */
public class CustomStringRedisSerializer implements RedisSerializer<Object> {
private final Charset charset;
public CustomStringRedisSerializer() {
this(Charset.forName("UTF8"));
}
public CustomStringRedisSerializer(Charset charset) {
Assert.notNull(charset);
this.charset = charset;
}
public String deserialize(byte[] bytes) {
return bytes == null?null:new String(bytes, this.charset);
}
public byte[] serialize(Object string) {
if(string == null ) {
return null;
}
if(string instanceof Long){
return String.valueOf(string).getBytes(this.charset);
}
if(string instanceof Integer){
return String.valueOf(string).getBytes(this.charset);
}
if(string instanceof BigDecimal){
return ((BigDecimal)string).toString().getBytes(this.charset);
}
if(string instanceof BigInteger){
return ((BigInteger)string).toString().getBytes(this.charset);
}
if(string instanceof Double){
return ((Double)string).toString().getBytes(this.charset);
}
if(string instanceof Float){
return ((Float)string).toString().getBytes(this.charset);
}
return ((String)string).getBytes(this.charset);
}
}
package com.hlj.config.serializer;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/** * 類名稱:CustomJSONStringRedisSerializer * 類描述:轉換對象爲json字符串 * 建立人:qingxu * 修改人: * 修改時間:2016/3/2 15:04 * 修改備註: * * @version 1.0.0 */
public class CustomJSONStringRedisSerializer implements RedisSerializer<Object> {
public static final String EMPTY_JSON = "{}";
public static final byte[] EMPTY_ARRAY = new byte[0];
private final ObjectMapper mapper;
/** * Creates {@link CustomJSONStringRedisSerializer} and configures {@link ObjectMapper} for default typing. */
public CustomJSONStringRedisSerializer() {
this((String) null);
}
/** * Creates {@link CustomJSONStringRedisSerializer} and configures {@link ObjectMapper} for default typing using the * given {@literal name}. In case of an {@literal empty} or {@literal null} String the default * {@link JsonTypeInfo.Id#CLASS} will be used. * * @param classPropertyTypeName Name of the JSON property holding type information. Can be {@literal null}. */
public CustomJSONStringRedisSerializer(String classPropertyTypeName) {
this(new RedisObjectMapper());
if (StringUtils.hasText(classPropertyTypeName)) {
mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, classPropertyTypeName);
} else {
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
}
}
/** * Setting a custom-configured {@link ObjectMapper} is one way to take further control of the JSON serialization * process. For example, an extended {@link} can be configured that provides custom serializers for * specific types. * * @param mapper must not be {@literal null}. */
public CustomJSONStringRedisSerializer(ObjectMapper mapper) {
Assert.notNull(mapper, "ObjectMapper must not be null!");
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
this.mapper = mapper;
}
/* * (non-Javadoc) * @see org.springframework.data.redis.serializer.RedisSerializer#serialize(java.lang.Object) */
@Override
public byte[] serialize(Object source) throws SerializationException {
if (source == null) {
return EMPTY_ARRAY;
}
try {
return mapper.writeValueAsBytes(source);
} catch (JsonProcessingException e) {
throw new SerializationException("Could not write JSON: " + e.getMessage(), e);
}
}
/* * (non-Javadoc) * @see org.springframework.data.redis.serializer.RedisSerializer#deserialize(byte[]) */
@Override
public Object deserialize(byte[] source) throws SerializationException {
return deserialize(source, Object.class);
}
/** * @param source can be {@literal null}. * @param type must not be {@literal null}. * @return {@literal null} for empty source. * @throws SerializationException */
public <T> T deserialize(byte[] source, Class<T> type) throws SerializationException {
Assert.notNull(type,
"Deserialization type must not be null! Pleaes provide Object.class to make use of Jackson2 default typing.");
if (source == null || source.length == 0) {
return null;
}
try {
return mapper.readValue(source, type);
} catch (Exception ex) {
throw new SerializationException("Could not read JSON: " + ex.getMessage(), ex);
}
}
}
1.3.四、若是使用上面序列化的話,那麼redis庫總能夠看到是class或者是請他的java數據類型,下圖是後期的答案,這裏只是簡單的介紹
一、這個工具類,在描述的時候,就說道,分不清Long和Integer,Double和Float。因此咱們通常只用來存放對象
二、本類中能夠看到有兩個服務類ValueOperations
和RedisOperations
,可是實際上是同一個類只不過名字不一樣。只是其做用的範圍表面上意思不同,第一個是用來存取數據,第二個用來操做參數數據的
package com.hlj.redis.redisTool;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/** * 類描述: * 操做redis 對象數據的工具類 * 提供存取數字外對象的存取,數字類型使用RedisLongData/RedisIntegerData進行操做 * 這個類分不清Long和Integer,Float和Double。也沒法進行原子操做 * 建立人: j.sh * 建立時間: 2016/3/1 * version:1.0.0 */
@Component
public class RedisObjectData {
@Resource(name="redisTemplate")
private ValueOperations<String, Object> valueOperations;
@Resource(name = "redisTemplate")
private RedisOperations<String,Object> operations;
/** * 根據key獲取數據 * @param key * @return */
public Object getData(String key) {
return valueOperations.get(key);
}
/** * 設置數據 * @param key * @param object */
public void setData(String key,Object object) {
valueOperations.set(key,object);
}
/** * 根據key 刪除對應的數據 * @param key */
public void delete(String key) {
operations.delete(key);
}
}
package com.hlj.controller;
import com.hlj.Format.ResponseBean;
import com.hlj.bean.Person;
import com.hlj.redis.redisTool.RedisLongData;
import com.hlj.redis.redisTool.RedisObjectData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.List;
@Controller
public class RedisObjectDataController {
@Autowired
private RedisObjectData redisObjectData;
/** * 添加緩存對象 */
@RequestMapping("/setRedisObjectData")
public @ResponseBody ResponseBean setRedisObjectData(Long id){
try {
Person person = new Person();
person.setName("HealerJean");
person.setPwd("123456");
person.setId(id);
redisObjectData.setData("person", person);
return ResponseBean.buildSuccess();
}catch (Exception e){
return ResponseBean.buildFailure(e.getMessage());
}
}
/** * 根據key獲取緩存對象 * @return */
@RequestMapping("/getRedisObjectData")
public @ResponseBody ResponseBean getRedisObjectData(String key){
try {
Person person = (Person) redisObjectData.getData(key);
return ResponseBean.buildSuccess(person);
}catch (Exception e){
return ResponseBean.buildFailure(e.getMessage());
}
}
服務器啓動:
1.一、瀏覽器打開輸入 http://localhost:8080/setRedisObjectData?id=1
1.二、查看redis中的數據,發現已經有數據了數據了
2.一、對數據進行讀取,瀏覽器中打開http://localhost:8080/getRedisObjectData?key=person
2.二、上述讀取數據成功
/** * 根據key刪除緩存對象 * @return */
@RequestMapping("/delRedisObjectData")
public @ResponseBody ResponseBean delRedisObjectData(String key){
try {
redisObjectData.delete(key);
return ResponseBean.buildSuccess();
}catch (Exception e){
return ResponseBean.buildFailure(e.getMessage());
}
}
1.一、瀏覽器中打開 http://localhost:8080/delRedisObjectData?key=person
1.二、查看redis庫,刪除成功
/** * 添加List緩存對象 * @param id * @return */
@RequestMapping("/setListRedisObjectData")
public @ResponseBody ResponseBean setListRedisObjectData(Long id){
try {
List<Person> persons = new ArrayList<>();
Person person1= new Person(id,"HealerJean"+id,"password"+id);
Person person2 = new Person(id+1,"HuangLiang"+id,"HuangLiang"+id);
persons.add(person1);
persons.add(person2);
redisObjectData.setData("persons", persons);
return ResponseBean.buildSuccess();
}catch (Exception e){
return ResponseBean.buildFailure(e.getMessage());
}
}
/** * 根據key獲取緩存List對象 * @return */
@RequestMapping("/getListRedisObjectData")
public @ResponseBody ResponseBean getListRedisObjectData(String key){
try {
List<Person> persons = (List<Person>) redisObjectData.getData(key);
return ResponseBean.buildSuccess(persons);
}catch (Exception e){
return ResponseBean.buildFailure(e.getMessage());
}
}
1.一、瀏覽器中打開http://localhost:8080/setListRedisObjectData?id=1
1.二、查看redis庫,有數據
2.一、根據key值獲取list對象,瀏覽器中打開http://localhost:8080/getListRedisObjectData?key=persons
2.二、成功,下面要測試,清除下redis庫
fulshdb
/** * 添加Long類型緩存對象,這是個錯誤的演示,僅供測試 * @param id * @return */
@RequestMapping("/set")
public @ResponseBody ResponseBean set(Long id){
try {
redisObjectData.setData("id", id);
return ResponseBean.buildSuccess();
}catch (Exception e){
return ResponseBean.buildFailure(e.getMessage());
}
}
/** * 根據key獲取Long,這是個錯誤的演示,僅供測試 * @return */
@RequestMapping("/get")
public @ResponseBody ResponseBean get(String key){
try {
Long id = (Long) redisObjectData.getData("id");
return ResponseBean.buildSuccess(id);
}catch (Exception e){
return ResponseBean.buildFailure(e.getMessage());
}
}
1.一、瀏覽器中打開http://localhost:8080/set?id=1
1.二、查看redis庫
2.一、根據key值獲取,這個時候 就會報錯了,朋友們,提示Integer不能轉化爲long
package com.hlj.redis.redisTool;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
/** * 類描述: * redis操做Long類型數據的工具類 * 提供Long類型原子操做 * 默認一天過時,其餘過時時間調用setExpire * 建立人: j.sh * 建立時間: 2016/3/1 * version:1.0.0 */
@Component
public class RedisLongData implements InitializingBean {
@Resource(name="redisTemplate")
private ValueOperations<String, Long> valueOperations;
@Resource(name="redisTemplate")
private RedisTemplate<String,Long> redisTemplate;
@Override
public void afterPropertiesSet() throws Exception {
redisTemplate.setValueSerializer(new GenericToStringSerializer<Long>(Long.class));
valueOperations = redisTemplate.opsForValue();
}
/** * 根據key 刪除 * @param key */
public void delete(String key) {
redisTemplate.delete(key);
}
/** * 進行數值的增長 * @param key * @param value * @return */
public Long increase(String key,long value){
Long result = valueOperations.increment(key,value);
this.setExpire(key,1L,TimeUnit.DAYS);
return result;
}
/** * 進行數值的增長 * @param key * @return */
public Long increase(String key){
return increase(key,1);
}
/** * 進行數值的遞減 * @param key * @param value * @return */
public Long decrease(String key,long value){
Long result = valueOperations.increment(key,0-value);
this.setExpire(key,1L,TimeUnit.DAYS);
return result;
}
/** * 進行數值的遞減 * @param key * @return */
public Long decrease(String key){
return decrease(key,1);
}
/** * 根據key獲取 * @param key * @return */
public Long get(String key) {
return valueOperations.get(key);
}
/** * 設置 * @param key * @param value */
public void set(String key,Long value) {
valueOperations.set(key,value);
this.setExpire(key,1L,TimeUnit.DAYS);
}
/** * 過時時間,默認單位秒 * @param key * @param time */
public void setExpire(String key,Long time){
redisTemplate.expire(key,time, TimeUnit.SECONDS);
}
/** * 過時時間 * @param key * @param time * @param timeUnit */
public void setExpire(String key,Long time,TimeUnit timeUnit){
redisTemplate.expire(key,time,timeUnit);
}
}
package com.hlj.controller;
import com.hlj.Format.ResponseBean;
import com.hlj.redis.redisTool.RedisLongData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class RedisLongDataController {
@Autowired
private RedisLongData redisLongData;
/** * 添加Long類型的緩存數據 */
@RequestMapping("/setRedisLongData")
public @ResponseBody ResponseBean setRedisLongData(Long id){
try {
redisLongData.set("long",id);
return ResponseBean.buildSuccess();
}catch (Exception e){
return ResponseBean.buildFailure(e.getMessage());
}
}
/** * 獲取Long類型的緩存數據 */
@RequestMapping("/getRedisLongData")
public @ResponseBody ResponseBean getRedisLongData(String key){
try {
Long id = redisLongData.get(key);
return ResponseBean.buildSuccess(id);
}catch (Exception e){
return ResponseBean.buildFailure(e.getMessage());
}
}
}
那麼關於它的使用,我先說明,這裏是要使用註解的,並且是很是完美的註解
<!-- 包含支持UI模版(Velocity,FreeMarker,JasperReports), 郵件服務, 腳本服務(JRuby), 緩存Cache(EHCache), 任務計劃Scheduling(uartz)。 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- 集成ehcache須要的依賴-->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
以前學習的時候,這個配置文件中藥寫入value的緩存策略,可是我作了一個自定義的緩存管理器,直接在Java類中配置常量就能夠了,很是小巧和方便
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
~ indicated by the @author tags or express copyright attribution
~ statements applied by the authors. All third-party contributions are
~ distributed under license by Red Hat Middleware LLC.
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, write to:
~ Free Software Foundation, Inc.
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
<ehcache updateCheck="false">
<!-- Sets the path to the directory where cache .data files are created.
If the path is a Java System Property it is replaced by
its value in the running VM.
The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
<!--<diskStore path="c:\dev\cache"/>-->
<!--
name:Cache的惟一標識
maxElementsInMemory:內存中最大緩存對象數
maxElementsOnDisk:磁盤中最大緩存對象數,如果0表示無窮大
eternal:Element是否永久有效,一但設置了,timeout將不起做用
overflowToDisk:配置此屬性,當內存中Element數量達到maxElementsInMemory時,Ehcache將會Element寫到磁盤中
timeToIdleSeconds:設置Element在失效前的容許閒置時間。僅當element不是永久有效時使用,可選屬性,默認值是0,也就是可閒置時間無窮大
timeToLiveSeconds:設置Element在失效前容許存活時間。最大時間介於建立時間和失效時間之間。僅當element不是永久有效時使用,默認是0.,也就是element存活時間無窮大
diskPersistent:是否緩存虛擬機重啓期數據
diskExpiryThreadIntervalSeconds:磁盤失效線程運行時間間隔,默認是120秒
diskSpoolBufferSizeMB:這個參數設置DiskStore(磁盤緩存)的緩存區大小。默認是30MB。每一個Cache都應該有本身的一個緩衝區
memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理內存。默認策略是LRU(最近最少使用)。你能夠設置爲FIFO(先進先出)或是LFU(較少使用)
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="600"
timeToLiveSeconds="600"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
diskSpoolBufferSizeMB="64"
memoryStoreEvictionPolicy="LRU"
/>
<!--中間能夠包含其餘的緩存key-->
</ehcache>
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd " >
<description>spring configuration</description>
<import resource="applicationContext-redis.xml"/>
<!-- 自定義Ehcache緩存,根據java類加入更多的key 支持註解緩存 -->
<cache:annotation-driven/>
<bean id="cacheManager" class="com.hlj.Ehcache.config.CustomEhCacheManager">
<property name="cacheManager" ref="ehcacheManager"/>
</bean>
<bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
<property name="shared" value="true"/>
</bean>
</beans>
package com.hlj.Ehcache.config;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.config.CacheConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.ehcache.EhCacheCache;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import java.lang.reflect.Field;
import java.util.*;
/** * 類描述:繼承 EhCacheCacheManager * @Description 初始化緩存。加載@CacheConstants中緩存定義及緩存自定義過時時間 * @Date 2018/3/21 下午2:46. */
public class CustomEhCacheManager extends EhCacheCacheManager {
private static String CACHE_PREFIX = "CACHE_";
private static String EXPIRE_PREFIX = "EXPIRE_";
private static Logger logger = LoggerFactory.getLogger(CustomEhCacheManager.class);
private static List<String> cacheNames = new ArrayList<>();
private static Map<String,Long> expires = new HashMap<>();
@Override
public void afterPropertiesSet() {
try {
Class clazz = CacheConstants.class;
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
if (field.getName().startsWith(CACHE_PREFIX)){
cacheNames.add(field.get(clazz).toString());
} else if (field.getName().startsWith(EXPIRE_PREFIX)){
expires.put(
clazz.getField(field.getName().replace(EXPIRE_PREFIX,"")).get(clazz).toString(),
Long.parseLong(field.get(clazz).toString())
);
}
}
} catch (Exception e) {
logger.error(e.getMessage(),e);
throw new RuntimeException("init cache failure!",e);
}
super.afterPropertiesSet();
}
@Override
protected Collection<Cache> loadCaches() {
LinkedHashSet<Cache> caches = new LinkedHashSet<Cache>(cacheNames.size());
for(String name:cacheNames){
Ehcache exist = this.getCacheManager().addCacheIfAbsent(name);
if(exist != null){
Cache cache = new EhCacheCache(exist);
Ehcache ehcache = (Ehcache) cache.getNativeCache();
CacheConfiguration configuration = ehcache.getCacheConfiguration();
Long time = expires.get(name);
configuration.setTimeToIdleSeconds(time);
configuration.setTimeToLiveSeconds(time);
caches.add(cache);
}
}
return caches;
}
}
package com.hlj.Ehcache.config;
/** * 類名稱:CacheConstants * 類描述:緩存常量類 * 建立人:HealerJean * 須要初始化的緩存定義名稱須要以CACHE_爲前綴。如:CACHE_XXX * 若是須要增長自定義過時時間,則增長過時時間變量定義EXPIRE_爲前綴的緩存過時時間.如:EXPIRE_CACHE_XXX * 如不設置自定義過時時間即默認spring cache中設置過時時間 * * @version 1.0.0 */
public class CacheConstants {
//公共緩存,1分鐘過時時間
public static final String CACHE_PUBLIC_PERSON = "cache.public.person";
public static final Long EXPIRE_CACHE_PUBLIC_PERSON = 60L;
public static final String CACHE_PUBLIC = "cache.public";
public static final Long EXPIRE_CACHE_PUBLIC = 60L;
public static final String CACHE_PUBLIC_TEN_MINUTE = "cache.public.ten.minute";
public static final Long EXPIRE_CACHE_PUBLIC_TEN_MINUTE = 10 * 60L;
}
package com.hlj.Ehcache.controller;
import com.hlj.Ehcache.service.EhcacheService;
import com.hlj.bean.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/** * @Description * @Author HealerJean * @Date 2018/3/21 下午1:58. */
@Controller
public class EhCacheController {
@Autowired
private EhcacheService ehcacheService;
@GetMapping("save")
public @ResponseBody Person save(Long id) {
Person person = new Person(id,"EhcacheHealerJean","123465");
return ehcacheService.save(person);
}
@GetMapping("findById")
public @ResponseBody Person findById(Long id) {
return ehcacheService.findById(id);
}
@GetMapping("update")
public @ResponseBody Person update(Person person) {
return ehcacheService.update(person);
}
@GetMapping("delete")
public @ResponseBody String delete(Long id) {
ehcacheService.delete(id);
return "刪除成功";
}
@GetMapping("listPerson")
public@ResponseBody List<Person> listPerson() {
return ehcacheService.listPerson();
}
}
package com.hlj.Ehcache.service.impl;
import com.hlj.Ehcache.config.CacheConstants;
import com.hlj.Ehcache.service.EhcacheService;
import com.hlj.bean.Person;
import com.hlj.repository.PersonRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/** * @Description * @Author HealerJean * @Date 2018/3/21 下午1:59. */
@Service
public class EhcacheServiceImpl implements EhcacheService{
@Autowired
private PersonRepository personRepository;
//這裏的單引號不能少,不然會報錯,被識別是一個對象;
public static final String CACHE_KEY = "'person'";
/** * value屬性表示使用哪一個緩存策略,緩存策略在ehcache.xml,如今存放在下面的實體類中,在啓動的時候自動加載了 * 也叫緩存存放位置名稱,不能爲空 */
public static final String DEMO_CACHE_NAME = CacheConstants.CACHE_PUBLIC_PERSON;
/** * 保存數據,防止是更新的操做,因此將以前緩存的刪除,事實上,我也並無很成功的實現它,後來明白啦,哈,原來是list集合緩存的時候,添加要刪除的哦 * @param Person */
@CacheEvict(value=DEMO_CACHE_NAME,key=CACHE_KEY)
public Person save(Person Person){
return personRepository.save(Person);
}
/** * 查詢數據. * @param id * @return */
@Cacheable(value=DEMO_CACHE_NAME ,key="'Person_'+#id")
public Person findById(Long id){
return personRepository.findOne(id);
}
/** * 修改數據. * 在支持Spring Cache的環境下,與@Cacheable不一樣的是使用@CachePut標註的方法在執行前不會去檢查緩存中是否存在以前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的緩存中。 @CachePut也能夠標註在類上和方法上。使用@CachePut時咱們能夠指定的屬性跟@Cacheable是同樣的。 */
@CachePut(value = DEMO_CACHE_NAME,key = "'Person_'+#person.getId()")
public Person update(Person person) {
Person Person = personRepository.findOne(person.getId());
Person.setName(person.getName());
Person.setPwd(person.getPwd());
return Person;
}
/** * 刪除數據. * @param id */
@CacheEvict(value = DEMO_CACHE_NAME,key = "'Person_'+#id")//這是清除緩存.
public void delete(Long id){
personRepository.delete(id);
}
@Cacheable(value=DEMO_CACHE_NAME ,key=CACHE_KEY)
public List<Person> listPerson() {
return personRepository.findAll();
}
}
若是滿意,請打賞博主任意金額,感興趣的請下方留言吧。可與博主自由討論哦
支付包 | 微信 | 微信公衆號 |
---|---|---|