Spring boot uses spring cache to consolidate multi-level caches (Ehcache,redis)

Source: Internet
Author: User
Tags delete key redis valid
Spring boot Spring Cache implementation of multi-level cache, just according to their own ideas to achieve, if the reader has a better solution to the idea, welcome guidance
The spring cache implements multilevel caching in the following ways:
Add custom CacheManager, custom cache, implement multi-level cache operation in cache (addition and deletion)


The configuration class takes note of the red marked sections as follows:


Package com.zyc.zspringboot.config;
Import Com.zyc.zspringboot.cache.MyCacheManager;
Import Com.zyc.zspringboot.cache.MyCacheTemplate;
Import Com.zyc.zspringboot.cache.MyRedisCache;
Import org.springframework.boot.context.properties.ConfigurationProperties;
Import Org.springframework.cache.CacheManager;
Import org.springframework.cache.annotation.EnableCaching;
Import Org.springframework.cache.ehcache.EhCacheCacheManager;
Import Org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
Import Org.springframework.context.annotation.AdviceMode;
Import Org.springframework.context.annotation.Bean;
Import org.springframework.context.annotation.Configuration;
Import Org.springframework.context.annotation.Primary;
Import Org.springframework.core.io.ClassPathResource;
Import Org.springframework.core.io.Resource;
Import Org.springframework.data.redis.cache.RedisCacheManager;
Import Org.springframework.data.redis.connection.jedis.JedisConnectionFactory; Import Org.springframework.data.redis.Core.
Redistemplate;
Import Org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
Import Org.springframework.data.redis.serializer.RedisSerializer;
Import Org.springframework.data.redis.serializer.StringRedisSerializer;
Import Redis.clients.jedis.JedisPoolConfig;
Import java.util.ArrayList;

Import java.util.List; /** * classname:redisconfig * * @author zyc-admin * @date January 23, 2018 * @Description: */@Configuration @EnableCachi Ng (mode = advicemode.proxy)//model property default proxy//Mode property, you can select the value Proxy and ASPECTJ. Proxy is used by default. When mode is proxy,//Only the cache method will take effect when it is called externally. This also means that if a cache method is called inside a pair//image, Springcache is not going to work. When mode is ASPECTJ, there will be no//this problem.
In addition, when using proxy, only the public method on the @cacheable will take effect.
If you want to use a method other than public, then change mode to ASPECTJ. @ConfigurationProperties (prefix = "Spring.redis")//Getter Setter method that uses @configurationproperties to implement attributes,// Prior to 1.5, the version needs to be activated using @enableconfigurationproperties on the startup class, and 1.5 directly on the configuration class using @component,// Since this class uses @configuration annotations to include @component it is not necessary to declare @component,//so that it can be used directly in other classes @Autowired directly into the class//extends Cachingconfigurersupport public class Redisconfig {private String hostName;

	private int port;

	private int timeOut; private int maxidle;//Maximum number of idle connections, default 8 private int maxwaitmillis;//The maximum number of milliseconds to wait for a connection when the private Boolean testonborrow;//gets the connection's 
	When checking validity, the default false private Boolean testwhileidle;//whether the idle check is valid, the default is False public String GetHostName () {return hostName;
	} public void SetHostName (String hostName) {this.hostname = HostName;
	} public int Getport () {return port;
	} public void Setport (int port) {this.port = port;
	} public int GetTimeout () {return timeOut;
	} public void SetTimeOut (int timeOut) {this.timeout = TimeOut;
	} public int Getmaxidle () {return maxidle;
	} public void Setmaxidle (int maxidle) {this.maxidle = Maxidle;
	} public int Getmaxwaitmillis () {return maxwaitmillis;
	} public void Setmaxwaitmillis (int maxwaitmillis) {this.maxwaitmillis = Maxwaitmillis; } public boolean Istestonborrow () {return testonborrow;
	The public void Settestonborrow (Boolean testonborrow) {this.testonborrow = Testonborrow;
	} public boolean Istestwhileidle () {return testwhileidle;
	The public void Settestwhileidle (Boolean testwhileidle) {this.testwhileidle = Testwhileidle; } @Bean ("Jedispoolconfig") public jedispoolconfig Jedispoolconfig () {jedispoolconfig jedispoolconfig = new JedisPoo
		Lconfig ();
		Jedispoolconfig.setmaxidle (Maxidle);
		Jedispoolconfig.setmaxwaitmillis (Maxwaitmillis);
		Jedispoolconfig.settestonborrow (TRUE);
		Jedispoolconfig.settestwhileidle (FALSE);
	return jedispoolconfig; } @Bean Public jedisconnectionfactory redisconnectionfactory (jedispoolconfig jedispoolconfig) {//If the cluster uses new Jedi
		Sconnectionfactory (New//Redisclusterconfiguration ()), cluster configuration in redisclusterconfiguration, here omit specific configuration
		Jedisconnectionfactory redisconnectionfactory = new Jedisconnectionfactory ();

		Redisconnectionfactory.setpoolconfig (Jedispoolconfig); redisconnectionfactory.seThostname (HostName);
		Redisconnectionfactory.setport (port);
		Redisconnectionfactory.settimeout (TimeOut);
	return redisconnectionfactory; }/** * Redistemplate configuration * * @param redisconnectionfactory * @return redistemplate */@Bean public Redistempl Ate<string, object> redistemplate (jedisconnectionfactory redisconnectionfactory) {RedisTemplate<String, Ob
		ject> redistemplate = new redistemplate<> ();
		Redistemplate.setconnectionfactory (redisconnectionfactory);
		redisserializer<string> Redisserializer = new Stringredisserializer ();
		Redistemplate.setkeyserializer (Redisserializer); jackson2jsonredisserializer<object> Jackson2jsonredisserializer = new//jackson2jsonredisserializer<
		Object> (//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);
		Jdkserializationredisserializer Jdkserializationredisserializer = new Jdkserializationredisserializer ();
		Redistemplate.setvalueserializer (Jdkserializationredisserializer);
	return redistemplate; /** * Redis Cache Manager * @param redistemplate * @return * * * @Bean public rediscachemanager Rediscachemanager (RedisT
		Emplate<string, object> redistemplate) {Rediscachemanager CacheManager = new Rediscachemanager (redisTemplate); Number of seconds before expiration. Defaults to Unlimited (0) cachemanager.setdefaultexpiration (120);
		Set Key-value timeout time list<string> cachenames = new arraylist<> ();
		Cachenames.add ("Myredis");
		Cachenames.add ("J2cacheredis");
		Cachemanager.setcachenames (Cachenames);
	return CacheManager; }/** * Spring cache Consolidation (Ehcache,redis) level two cache specific caches * @param rediscachemanager * @param redistemplate * @return * /@Bean Public MycacheteMplate mycachetemplate (Rediscachemanager rediscachemanager,redistemplate<string, Object> RedisTemplate) {
		Mycachetemplate mycachetemplate=new mycachetemplate ();
		Mycachetemplate.setrediscachemanager (Rediscachemanager);
		Mycachetemplate.setredistemplate (redistemplate);
		Mycachetemplate.setname ("J2cacheredis");
	return mycachetemplate; }/** * Custom Redis Cache * @param rediscachemanager * @param redistemplate * @return * * * @Bean public Myrediscache Myrediscache (Rediscachemanager rediscachemanager,redistemplate<string,object> RedisTemplate) {MyRedisCache
		Myrediscache=new Myrediscache ();
		Custom attribute configuration cache name Myrediscache.setname ("Myredis");
		Redis Cache Manager Myrediscache.setrediscachemanager (Rediscachemanager);
		Redistemplate instance myrediscache.setredistemplate (redistemplate);
	return myrediscache; }/** * Spring Cache Unified Cache Manager * @param mycachetemplate * @param myrediscache * @return * * * @Bean @Primary Pub Lic CacheManager CacheManager (mycachetemplate Mycachetemplate,myrediscache myrediscache) {Mycachemanager cachemanager=new mycachemanager ();
		Cachemanager.setmycachetemplate (mycachetemplate);
		Cachemanager.setmyrediscache (Myrediscache);
	return CacheManager; }//Integration Ehcache @Bean public Ehcachecachemanager Ehcachecachemanager () {Ehcachecachemanager Ehcachecachemanager
		  = New Ehcachecachemanager (Ehcachemanagerfactorybean (). GetObject ());
	 return ehcachecachemanager; } @Bean Public Ehcachemanagerfactorybean Ehcachemanagerfactorybean () {Ehcachemanagerfactorybean cacheManagerFacto
	 Rybean = new Ehcachemanagerfactorybean ();
	 Here for the time being borrow Shiro ehcache configuration file Resource r=new classpathresource ("Ehcache-shiro.xml");
	 Cachemanagerfactorybean.setconfiglocation (R);
	 Cachemanagerfactorybean.setshared (TRUE);
	 return Cachemanagerfactorybean;
 }

}

The Custom CacheManager is as follows:



Package Com.zyc.zspringboot.cache;

Import Org.springframework.cache.Cache;
Import Org.springframework.cache.CacheManager;
Import java.util.Collection;

/**
 * @author zyc-admin
 * @data 2018-03-20 10:12
 **/Public
class Mycachemanager implements CacheManager {

	private mycachetemplate mycachetemplate;

	Private Myrediscache Myrediscache;

	Public Myrediscache Getmyrediscache () {
		return myrediscache;
	}

	public void Setmyrediscache (Myrediscache myrediscache) {
		this.myrediscache = Myrediscache;
	}

	Public Mycachetemplate getmycachetemplate () {
		return mycachetemplate;
	}

	public void Setmycachetemplate (Mycachetemplate mycachetemplate) {
		this.mycachetemplate = mycachetemplate;
	}

	@Override public
	cache GetCache (String name) {
		//multilevel Cache implementation
		if (Name.equals ( Mycachetemplate.getname ())) {
			return mycachetemplate;
		}
		
		return null;
	}

	@Override public
	collection<string> getcachenames () {

		return null;
	}
}


Custom Cache implementations:


Package Com.zyc.zspringboot.cache;
Import Net.sf.ehcache.CacheManager;
Import net.sf.ehcache.Element;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory;
Import Org.springframework.cache.Cache;
Import Org.springframework.cache.support.SimpleValueWrapper;
Import org.springframework.data.redis.cache.RedisCacheElement;
Import Org.springframework.data.redis.cache.RedisCacheKey;
Import Org.springframework.data.redis.cache.RedisCacheManager;
Import Org.springframework.data.redis.core.RedisTemplate;

Import java.util.concurrent.Callable; /** * @author zyc-admin * @data 2018-03-19 17:15 **/public class Mycachetemplate implements Cache {private static

	Final Logger logger= Loggerfactory.getlogger (mycachetemplate.class);

	Private CacheManager Ehcachemanager;

	Private Rediscachemanager Rediscachemanager;

	Private redistemplate<string, object> redistemplate;
	Public CacheManager Getehcachemanager () {return ehcachemanager; } public void Setehcachemanager (CacheManager ehCacheManager) {This.ehcachemanager = Ehcachemanager;
	} public Rediscachemanager Getrediscachemanager () {return rediscachemanager;
	} public void Setrediscachemanager (Rediscachemanager rediscachemanager) {this.rediscachemanager = RedisCacheManager;
	} public redistemplate<string, Object> getredistemplate () {return redistemplate; } public void Setredistemplate (redistemplate<string, object> redistemplate) {this.redistemplate = RedisTemplate
	;

	} private String name;
	@Override public String GetName () {return name;
	}//Add the Set method yourself, implement the cache itself without this method public void SetName (String name) {this.name=name;
	} @Override Public Object Getnativecache () {return null;
		} @Override public Valuewrapper get (Object key) {Ehcachemanager=cachemanager.getcachemanager ("EC");
			if (ehcachemanager!=null) {Net.sf.ehcache.Cache Myehcache = Ehcachemanager.getcache (GetName ());
			Logger.info ("Fetch Data Ehcache library ===key:{}", key); if (Myehcache.get (key)!=null) {VaLuewrapper v=new Simplevaluewrapper (Myehcache.get (key). Getobjectvalue ());
			return v;
		}} Cache Myredis = Rediscachemanager.getcache (GetName ());
			if (myredis!=null) {logger.info ("Fetch Data Reids library ===key:{}", key); if (Myredis.get (key)!=null) {rediscacheelement vr=new rediscacheelement (new Rediscachekey (key), Myredis.get (key). Get
				());
			return VR;
	}} return null; } @Override Public <T> T get (Object key, class<t> type) {System.out.println (key+ "=======================
		"+type);
	return null;
	} @Override Public <T> T get (Object key, callable<t> valueloader) {return null;
		} @Override public void put (object key, Object value) {Ehcachemanager=cachemanager.getcachemanager ("EC");
			if (ehcachemanager!=null) {Net.sf.ehcache.Cache Myehcache = Ehcachemanager.getcache (GetName ());
			Element e=new Element (Key,value);
			Logger.info ("Insert Ehcache Library ===key:{},value:{}", Key,value);
		Myehcache.put (e); } Cache Myredis = Rediscachemanager.gEtcache (GetName ());
			if (myredis!=null) {logger.info ("Insert Reids Library ===key:{},value:{}", Key,value);
		Myredis.put (Key,value);

	} System.out.println ("Cha ru key" + key);
	} @Override Public Valuewrapper putifabsent (object key, object value) {return null;
		} @Override public void evict (Object key) {Cache Myredis = Rediscachemanager.getcache (GetName ());
			if (myredis!=null) {logger.info ("Delete reids library ===key:{}", key);
		Myredis.evict (key);
		} ehcachemanager=cachemanager.getcachemanager ("EC");
			if (ehcachemanager!=null) {Net.sf.ehcache.Cache Myehcache = Ehcachemanager.getcache (GetName ());
			Logger.info ("Delete ehcache library ===key:{}", key);
			if (Myehcache.iskeyincache (key)) {Myehcache.remove (key);
	}} System.out.println ("Delete key" + key);
		} @Override public void Clear () {Cache Myredis = Rediscachemanager.getcache (GetName ());
		Myredis.clear ();
		Ehcachemanager=cachemanager.getcachemanager ("EC"); if (ehcachemanager!=null) {Net.sf.ehcache.Cache Myehcache = ehCachemanager.getcache (GetName ());
		Myehcache.removeall (); }
	}
}


Using the spring cache annotations uses the following caches: (When this method is first called, the Put,get method of the custom cache is always printed 2 times to insert the data, 2 times to fetch the data, temporarily do not know what the reason, if any god knows, welcome comments pointing. )



@Cacheable (value = "J2cacheredis", key = "Role:id: ' + #id", unless = "#result = = null")
	//@Log (value = "Get data and Cache") Public
	Role getrole (String ID) {
		//TODO auto-generated method stub
		return roledao.getrole (ID);
	}


The application.properties configuration file is as follows



#redis------start-------
spring.redis.hostname=127.0.0.1
spring.redis.port=63791
spring.redis.timeout=1000
spring.redis.maxidle=10
spring.redis.maxwaitmillis=15000
Spring.redis.testonborrow=true
Spring.redis.testwhileidle=false


The Ecache-shiro.xml configuration file is as follows (Shiro is used for this project, so Ehcache uses the Shiro cache profile)


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

<diskStore path = "java.io.tmpdir" /> <!-cache storage directory (this directory is placed in the system's default cache directory), or "D: / cache" java.io.tmpdir->
    <defaultCache
            maxElementsInMemory = "10000"
            eternal = "false"
            timeToIdleSeconds = "120"
            timeToLiveSeconds = "120"
            overflowToDisk = "true"
            maxElementsOnDisk = "10000000"
            diskPersistent = "false"
            diskExpiryThreadIntervalSeconds = "120"
            memoryStoreEvictionPolicy = "LRU"
    />

    <!-->
    <cache name = "j2CacheRedis"
           maxElementsInMemory = "1000"
           eternal = "false"
           timeToIdleSeconds = "120"
           timeToLiveSeconds = "140"
           overflowToDisk = "false"
           memoryStoreEvictionPolicy = "LRU" />

    <!-
  name: the unique identifier of the cache
  maxElementsInMemory: the maximum number of cached objects in memory
  maxElementsOnDisk: the maximum number of cache objects in the disk, if 0 is infinite
  eternal: Whether the element is permanently valid. Once set, timeout will not work.
  overflowToDisk: configure this property, when the number of elements in memory reaches maxElementsInMemory, Ehcache will write the elements to disk
  timeToIdleSeconds: Set the allowed idle time of the Element before it expires. Only used when element is not permanently valid. Optional attribute. The default value is 0, which means the idle time is infinite.
  timeToLiveSeconds: Sets the time allowed for the element to expire before it expires. The maximum time is between the creation time and the expiration time. Only used when element is not permanently valid, the default is 0. That is, the element lifetime is infinite
  diskPersistent: Whether to cache virtual machine restart data
  diskExpiryThreadIntervalSeconds: the interval between disk failure threads running, the default is 120 seconds
  diskSpoolBufferSizeMB: This parameter sets the size of the buffer area of the DiskStore. The default is 30MB. Each cache should have its own buffer
   memoryStoreEvictionPolicy: When the maxElementsInMemory limit is reached, Ehcache will clear the memory according to the specified policy. The default policy is LRU (Least Recently Used). You can set it to FIFO (First In First Out) or LFU (Less Used)
  ->
</ ehcache> 
Problems encountered in the integration process:
1 failed while creating CacheManager bean
WORKAROUND: You may have multiple CacheManager configured, make sure that you do not have duplicate names, and add @Primary annotations on the custom CacheManager
Custom CacheManager to implement the CacheManager interface,
Be careful not to inherit the Org.springframework.cache.support.AbstractCacheManager class to implement your own CacheManager
2 Create Ehcachecachemanager failed
WORKAROUND: See if your ehcachecachemanager is in conflict with Shiro's Ehcache cache.
EhCache version 2.5, the JVM typically only has EhCache instances.
3 Method Cache invalidation for internal method calls with spring cache annotations
Workaround: Spring cache relies on AOP, using Aopcontext.currentproxy (). Your method,
You need to expose the proxy object to add annotations before using @EnableAspectJAutoProxy (exposeproxy=true,proxytargetclass=true)
Exposeproxy: Exposing proxy objects, Proxytargetclass forcing use of Cglib proxy

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.