Caching can be said to be a very effective and simple way to speed up service response. In the caching field, there are many well-known frameworks, such as EhCache, Guava, HazelCast, etc. As a key-value database, Redis has also become a popular data caching tool due to its feature.
In the traditional way, the cache processing code is very bloated.
For example: We need to add a query function to the cache function, which requires roughly three steps.
1. Before the function is executed, we need to check whether there is data in the cache. If it exists, return the cached data.
2. If it does not exist, it needs to be queried in the database data.
3. Finally, store the data in the cache. When this function is called next time, you can use the cached data directly to reduce the pressure on the database.
So how much code is required to implement the above three steps? Here is an example:
The red part in the above picture is all template code, but the code that is really related to this function only accounts for 1/5. For all functions that need to implement cache functions, bloated template code is required. It is an extremely inelegant solution.
So how can we get the bloated code back to the freshest time?
Isn't AOP the best solution to this template-style code? Fortunately, we no longer need to implement the sections by ourselves. SpringCache has provided us with a good section. We only need to make simple configurations to return to the original one, like the following:
You only need to add annotation. You don’t even need to change the original code. Are you eager to try it?
There are only three steps to configure SpringCache:
Step 1: Add relevant dependencies:
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.0.RELEASE</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.3.2</version></dependency>
Step 2: Configure SpringCache, Redis connection and other information
applicationContext-redis.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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/mvc" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.2.xsd"> <!-- Configuration file loading--> <context:property-placeholder location="classpath:*.properties"/><cache:annotation-driven cache-manager="cacheManager"/> <!-- redis connection pool--> <bean id="poolConfig"> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxWaitMillis" value="${redis.maxWait}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean> <!-- Connection Factory--> <bean id="JedisConnectionFactory" p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/> <!-- redis template--> <bean id="redisTemplate"> <property name="connectionFactory" ref="JedisConnectionFactory" /> </bean> <bean id="cacheManager"> <property name="caches"> <set> <!-- You can configure multiple redis here --> <bean> <property name="redisTemplate" ref="redisTemplate" /> <property name="name" value="content"/> <!-- The name corresponding to the name should be used in the annotation of the class or method --> </bean> </set> </property> </bean> </beans>redis.properties file:
# Redis settings # server IP redis.host=192.168.100.55 # server port redis.port=6379 # server pass redis.pass=# use dbIndex redis.database=0 #max idel instance of jedisredis.maxIdle=300 #if wait too long ,throw JedisConnectionExceptionredis.maxWait=3000 #if true,it will validate before borrow jedis instance,what you get instance is all usefulredis.testOnBorrow=true
The third step is to write the Cache interface implementation class
Spring only provides an abstract interface for cache, and calls functions through interfaces. There is no specific implementation class, so we need to implement specific operations ourselves.
In the above configuration, we can see that each implementation class will inject a redisTemplate instance, and we can operate redis through redisTemplate
package com.cky.rest.utils;import java.io.Serializable;import org.apache.commons.lang3.SerializationUtils;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;public class RedisCache implements Cache { private RedisTemplate<String, Object> redisTemplate; private String name; @Override public void clear() { System.out.println("---------------"); redisTemplate.execute(new RedisCallback<String>() { @Override public String doInRedis(RedisConnection connection) throws DataAccessException { connection.flushDb(); return "ok"; } }); } @Override public void evict(Object key) { System.out.println("-----------------"); final String keyf=key.toString(); redisTemplate.execute(new RedisCallback<Long>() { @Override public Long doInRedis(RedisConnection connection) throws DataAccessException { return connection.del(keyf.getBytes()); } }); } @Override public ValueWrapper get(Object key) { System.out.println("-----------------------"+key.toString()); final String keyf = key.toString(); Object object = null; object = redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] key = keyf.getBytes(); byte[] value = connection.get(key); if (value == null) { System.out.println("----------------------"); return null; } return SerializationUtils.deserialize(value); } }); ValueWrapper obj=(object != null ? new SimpleValueWrapper(object) : null); System.out.println("-------------------------------------"+obj); return obj; } @Override public void put(Object key, Object value) { System.out.println("-----------------------"); System.out.println("key----:"+key); System.out.println("key----:"+value); final String keyString = key.toString(); final Object value = value; final long liveTime = 86400; redisTemplate.execute(new RedisCallback<Long>() { @Override public Long doInRedis(RedisConnection connection) throws DataAccessException { byte[] keyb = keyString.getBytes(); byte[] valueb = SerializationUtils.serialize((Serializable) value); connection.set(keyb, valueb); if (liveTime > 0) { connection.expire(keyb, liveTime); } return 1L; } }); } @Override public <T> T get(Object arg0, Class<T> arg1) { // TODO Auto-generated method stub return null; } @Override public String getName() { return this.name; } @Override public Object getNativeCache() { return this.redisTemplate; } @Override public ValueWrapper putIfAbsent(Object arg0, Object arg1) { // TODO Auto-generated method stub return null; } 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; }}There have been two errors during the configuration process:
1.Xxxx.ClassNotFoundException Finally, I found that the jar download is incomplete. Just delete the corresponding jar package folder of the maven local repository and download it again.
2.Xxxx.MethodNotFoundException This situation is the wrong version, just change to the version in the first step.
Use of common annotations in SpringCache:
@Cacheable annotation
The most commonly used annotation will cache the return value of the annotated method. How it works is: first look up in the cache, if no method is executed and the result is cached, and then the data is returned. The cache name of this annotation must be specified and corresponds to the name value of a cache in caches in cacheManager. Can be specified using value or cacheNames.
If no key attribute is specified, spring will use the default primary key generator to generate primary keys. You can also customize the primary key, and SpEL expressions can be used in the key. as follows:
@Cacheable(cacheNames=”content”,key=”#user.userId”) Public User getUser(User user){ xxxxx }You can use the condition attribute to add conditions to the cache, as follows:
@Cacheable(cacheNames=”content”,key=”#user.userId”,condition=”#user.age<40”)Public User getUser(User user){xxxxx}@CachePut annotation
Execute the method first, and then put the return value back into the cache. Can be used as cached updates.
@CacheEvict annotation
This annotation is responsible for explicitly removing data from the cache. Usually, the cached data has an expiration date and the data will also be removed when it expires.
This annotation has two additional attributes:
Whether allEntries removes all cache entries.
beforeInvocation: Complete the removal operation before or after the method is called. true/false
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.