1. Overview
This article describes how spring boot uses Redis for caching, how to customize the Redis cache (such as key expiration), and how spring boot initializes redis cache. Use specific code to introduce annotations such as @cacheable, @CacheEvict, @CachePut, @CacheConfig, and their properties. 2. Spring Boot integration Redis 2.1. Application.properties
Configuration Application.properties, contains the following information: Specify the type of cache Redis Server information please do not configure the Spring.cache.cache-names value, after which
# # Cache
# Spring.cache.cache-names=book1,book2
spring.cache.type=redis
# Redis (redisproperties)
Spring.redis.database=0
spring.redis.host=192.168.188.7
spring.redis.password=
spring.redis.port= 6379
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=100
Spring.redis.pool.max-wait=-1
2.2. Configure startup Classes@EnableCaching: Start the cache reconfiguration Rediscachemanager, using the new configured values
@SpringBootApplication
@EnableCaching//Start cache public
class Cacheapplication {
private static final Logger Log = Loggerfactory.getlogger (Cacheapplication.class);
public static void Main (string[] args) {
log.info ("Start cacheapplication ...");
Springapplication.run (Cacheapplication.class, args);
}
/**
* Reconfigure Rediscachemanager
* @param rd
/@Autowired public
void Configrediscachemanger ( Rediscachemanager Rd) {
rd.setdefaultexpiration (100L);
}
}
After the above configuration, the Redis cache management object has been generated. The following is a brief description of how spring boot initializes the Redis cache. 2.3. Spring boot How to initialize Redis cache
Cache management Interface Org.springframework.cache.cachemanager,spring boot is the management of caching through this class. Redis the implementation class corresponding to this interface is Org.springframework.data.redis.cache.RedisCacheManager. The following describes how this class is generated.
First, after we configure the Application.properties spring.redis.* property @enablecaching, Spring executes the redisautoconfiguration, Initializing Redistemplate and Stringredistemplate
@Configuration @ConditionalOnClass ({jedisconnection.class, Redisoperations.class, jedis.class}) @ Enableconfigurationproperties (redisproperties.class) public class Redisautoconfiguration {/** * Standard Redis
Configuration. * * @Configuration protected static class Redisconfiguration {... @Bean @ConditionalOnMissingBean (name = "Redis Template ") public Redistemplate<object, object> redistemplate (redisconnectionfactory REDISCONNECTIONFAC Tory) throws Unknownhostexception {redistemplate<object, object> template = new REDISTEMPLATE&L
T;object, object> ();
Template.setconnectionfactory (redisconnectionfactory);
return template;
@Bean @ConditionalOnMissingBean (stringredistemplate.class) public stringredistemplate stringredistemplate ( Redisconnectionfactory redisconnectionfactory) throws Unknownhostexception {Stringredistempla
Te template = new stringredistemplate (); Template.setconnectionfactory (redisconnectionfactory);
return template;
}
}
}
The
Then rediscacheconfiguration generates Rediscachemanager after the Redistemplate injection method generated by redisautoconfiguration.
@Configuration @AutoConfigureAfter (Redisautoconfiguration.class) @ConditionalOnBean (Redistemplate.class) @
Conditionalonmissingbean (Cachemanager.class) @Conditional (Cachecondition.class) class Rediscacheconfiguration {
Private final cacheproperties cacheproperties;
Private final cachemanagercustomizers Customizerinvoker; Rediscacheconfiguration (cacheproperties cacheproperties, cachemanagercustomizers customizerInvoker) {This
. cacheproperties = cacheproperties;
This.customizerinvoker = Customizerinvoker; @Bean public Rediscachemanager CacheManager (Redistemplate<object, object> redistemplate) {RedisC
Achemanager CacheManager = new Rediscachemanager (redistemplate);
Cachemanager.setuseprefix (TRUE);
list<string> cachenames = This.cacheProperties.getCacheNames ();
if (!cachenames.isempty ()) {cachemanager.setcachenames (cachenames); Return This.customizerInvoker.customIze (CacheManager);
}
}
Based on the above analysis, we know that spring has helped us build a Rediscachemanager and configured it.
Finally, we can configure this Rediscachemanager two times, only to list the validity period of the configuration key.
/**
* Reconfigure Rediscachemanager
* @param rd
/@Autowired public
void Configrediscachemanger ( Rediscachemanager Rd) {
rd.setdefaultexpiration (100L);
}
Attention:
Please do not configure in Applicaion.properties: Spring.cache.cache-names=book1,book2, otherwise our new configuration will not function on the cache of these configurations. This is because rediscacheconfiguration initializes the Rediscachemanager and immediately invokes the Rediscacheconfiguration's initialization cache. At this point, Configrediscachemanger has not yet implemented this method, so that our configuration cannot be restarted. Conversely, if not configured, then the cache will be created, using our configuration. 3. Use of spring cache annotations
The previous section describes how to configure caching, which describes how to use caching. 3.1 Auxiliary Classes
Auxiliary classes to be used below
Book:
public class Book implements Serializable {
private static final long serialversionuid = 2629983876059197650L;
Private String ID;
private String name; Title
Private Integer Price//Prices
Private Date Update//Public book
(string ID, string name, integer value, Date update) {
super ();
This.id = ID;
this.name = name;
This.price = Price;
this.update = update;
}
Set/get
}
Bookqry: Encapsulation Request Class
public class Bookqry {
private String ID;
private String name; Title
//Set/get
Abstractservice
Abstract class: Initializes the Repositorybook value and simulates the database data. Both Bookservice and BookService2 inherit this class
Public abstract class Abstractservice {
protected static map<string, book> Repositorybook = new hashmap<> ();
Public Abstractservice () {
super ();
}
@PostConstruct public
void init () {
//1 The book
Book1 = new book ("1", "Name_1", One, New Date ());
Repositorybook.put (Book1.getid (), Book1);
2 book
book2 = new book ("2", "name_2", One, New Date ());
Repositorybook.put (Book2.getid (), book2);
3 book
book3 = new book ("3", "Name_3", One, New Date ());
Repositorybook.put (Book3.getid (), BOOK3);
4 book
book4 = new book ("4", "Name_4", One, New Date ());
Repositorybook.put (Book4.getid (), BOOK4);
}
3.2. @Cacheable
The meaning of a @Cacheable property Cachenames: Specifies the cached name key: Defines the key value that is composed, and if not defined, computes a key value with all parameters. You can use the spring El expression
/** * Cachenames Set Cached value * Key: Specifies the cached key, which refers to the parameter ID value. Key can use the SPEL expression * @param ID * @return/@Cacheable (cachenames= "Book1", key= "#id") Public book Query
Bookcacheable (String ID) {logger.info ("querybookcacheable,id={}", id);
return Repositorybook.get (ID); /** * This uses another cache storage cache * * @param ID * @return/@Cacheable (cachenames= "Book2", key= "#i
D ") Public book querybookcacheable_2 (String ID) {logger.info (" querybookcacheable_2,id={} ", id);
return Repositorybook.get (ID); /** * Cached Key can also specify the object's member variable * @param qry * @return/@Cacheable (cachenames= "Book1", key= "#qry . ID ") Public book Querybookcacheablebybookqry (Bookqry qry) {logger.info (" querybookcacheablebybookqry,qry={} ", q
RY);
String id = qry.getid ();
Assert.notnull (ID, "ID can ' t be null!");
String name = Qry.getname ();
Book book = null;
if (ID!= null) { Book = Repositorybook.get (ID); if (book!= null &&!) (
Name!= null && book.getname (). Equals (name)) {book = null;
} return book; }
Keygenerator: Defines the class that the key generates and cannot exist simultaneously with the key
/**
* Above we use the default keygenerator, corresponding to spring simplekeygenerator
* If your use is complex, we can also customize the mykeygenerator generated key
* Key and Keygenerator are mutually exclusive, and if both are made the exception
* The key and keygenerator parameters are mutually exclusive and an operation specifying both to the exception.
* *
@param ID
* @return
/@Cacheable (cachenames= "Book3", keygenerator= "Mykeygenerator") Public book
Querybookcacheableusemykeygenerator (String id) {
logger.info (" querybookcacheableusemykeygenerator,id={} ", id);
return Repositorybook.get (ID);
}
The build class for the custom cache key is implemented as follows:
@Component public
class Mykeygenerator implements Keygenerator {
@Override
public object generate (object target, Method method, Object ... params) {
System.out.println ("Custom cache, using the first parameter as the cache key.") params = "+ arrays.tostring (params));
Just for testing, it's not possible to write return
Params[0] + "0";
}
}
Sync: If you set sync=true:a. If there is no data in the cache and multiple threads access the method at the same time, only one method executes to the method, and other methods need to wait; B. If there is already data in the cache, multiple threads can retrieve data from the cache at the same time
/***
* If you set sync=true,
* If there is no data in the cache and multiple threads access the method at the same time, then only one method executes to the method, and the other methods need to wait
* If there is already data in the cache, Multiple threads can get data from the cache at the same time
* @param ID
* @return
/@Cacheable (cachenames= "Book3", sync=true)
public Book Querybookcacheablewithsync (String id) {
logger.info ("Begin ... querybookcacheablebybookqry,id={}", id);
try {
Thread.Sleep (1000 * 2);
} catch (Interruptedexception e) {
}
logger.info ("End ...). querybookcacheablebybookqry,id={} ", id);
return Repositorybook.get (ID);
}
Condition and unless cache only for specific conditions:
Condition: The condition value is true before the method is executed, and the data unless is cached: After the method is executed, the unless is judged, and if the value is true, the data conditon and unless can be used at the same time. Then only the records that satisfy both are cached at this time
/**
* Condition cache:
* Only meet the condition request can be cached, if not meet the criteria, the method is not @cacheable annotations like the method
* The following is only ID < 3 to cache
*
* *
@Cacheable (cachenames= "book11", condition= "T (Java.lang.Integer). parseint (#id) < 3") public
Book Querybookcacheablewithcondition (String id) {
logger.info ("querybookcacheablebybookqry,id={}", id);
return Repositorybook.get (ID);
}
/**
* Condition cache:
* cache for records that do not meet unless
* "unless expressions" are evaluated after the method has been Ed
* as follows: Only cache records that do not meet the return ' T (Java.lang.Integer). parseint (#result. ID) <3 ' *
@param ID
* @return
* *
@Cacheable (cachenames= "book22", unless = "T (java.lang.Integer). parseint (#result. Id) <3")
Public book querybookcacheablewithunless (String id) {
logger.info ("querybookcacheablebybookqry,id={}", id);
return Repositorybook.get (ID);
}
3.3. @CacheEvict
Delete Cache Allentries = true: Empty all values in the cache Book1 Allentries = false: Default value, just delete key's corresponding value
/**
* allentries = true: Empty all caches in Book1
/@CacheEvict (cachenames= "Book1", allentries=true)
public void Clearbook1all () {
logger.info ("ClearAll");
}
/**
* Book1 remove
/@CacheEvict (cachenames= "Book1", key= "#id") public
void on records that meet key conditions from the cache Updatebook (string ID, string name) {
logger.info ("Updatebook");
Book book = Repositorybook.get (ID);
if (book!= null) {
book.setname (name);
Book.setupdate (New Date ());
}
3.4. @CachePut
Each execution executes a method, regardless of whether there is a value in the cache, and the value in the replacement cache of the new return value is used. This differs from @cacheable: @Cacheable If the cache does not have a value, executes the method and caches the data, and if the cache has a value, gets the value from the cache
@CachePut (cachenames= "Book1", key= "#id") Public book
Querybookcacheput (String id) {
logger.info (" querybookcacheput,id={} ", id);
return Repositorybook.get (ID);
}
3.5. @CacheConfig
@CacheConfig: Class-level annotations: If we define cachenames in this note, all methods in this class @Cacheable cachenames defaults to this value. Of course @cacheable can also redefine the value of Cachenames
@Component
@CacheConfig (cachenames= "Booksall") public
class BookService2 extends Abstractservice {
private static final Logger Logger = Loggerfactory.getlogger (bookservice2.class);
/**
* The @cacheable of this method does not define Cachenames, then use the value in the annotation @cacheconfig on the class cachenames
* @param ID
* @return
@Cacheable (key= "#id") Public book
querybookcacheable (String id) {
logger.info ("querybookcacheable,id={}") ID);
return Repositorybook.get (ID);
}
/**
* The @cacheable of this method has a defined cachenames, the value in the class annotation @cacheconfig is overwritten with this value cachenames
*
@param ID
* @return
*
/@Cacheable (cachenames= "Books_custom", key= "#id") Public book
QueryBookCacheable2 (String ID) {
logger.info ("querybookcacheable2,id={}", id);
return Repositorybook.get (ID);
}
4. Test
4.1. Prepare Redis
Can be installed through the Docker Redis, very convenient. Docker usage See Docker installation and common commands 4.2. Test class
If you want to verify each of these methods, you can download the project and execute the test class cachetest. This is not a demo because it's simpler. 5. Code
Detailed code for this article github