SpringBoot special study Part26: Spring Cache Redis integration and implement caching new version SpringBoot 2.x custom CacheManager

Spring Cache is used by default ConcurrentMapCacheManager manager
created is ConcurrentMapCache cache data is then stored in the ConcurrentMap

The actual use of the cache middleware will be more occasions such as Redis EhCache etc.

Redis is a high-performance memory-based network may also support persistent log database type Key-Value

Spring Cache default configuration is SimpleCacheConfiguration this class
of course there are many other configuration class (the default is not turned on
when the corresponding cache import other scenes to automatically open the corresponding cache configuration

One, arrangement

First, if not installed on the machine can be used Redis Redis mounted Docker

# 拉取最新redis镜像
docker pull docker.mirrors.ustc.edu.cn/library/redis

#启动redis容器
docker run -d -p 6379:6379 --name redis1 docker.mirrors.ustc.edu.cn/library/redis

Of course, their own installation and configuration can also be Redis

Then in the project to introduce the redis Starter (starter):

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Then in the configuration file to configure the host of Redis ip :

spring.redis.host=111.111.111.111(主机ip)

After the introduction of the Redis Starter (initiator) RedisAutoConfiguration this configuration class started the
underlying configuration of RedisTemplate and StringRedisTemplate these two classes Template for the operation is similar to the JDBC Redis JdbcTemplate
to injection can simply use

StringRedisTemplate definition is operating string
and RedisTemplate is used to manipulate the object

Second, the use

Redis common five Data Type: String String List List Set Hash hash ZSet ordered set collection
method has a corresponding Template
stringRedisTemplate.opsForValue(): kv string operations
stringRedisTemplate.opsForList(): Operation List
stringRedisTemplate.opsForSet(): set of operations
stringRedisTemplate.opsForHash(): hashing operation
stringRedisTemplate.opsForZSet(): operation ordered set
redisTemplate also has these method

1, string manipulation

// 添加key-value
stringRedisTemplate.opsForValue().append("msg","HelloWorld");
// 通过key获取指定的value
System.out.println(stringRedisTemplate.opsForValue().get("msg"));

// 往list左侧添加
stringRedisTemplate.opsForList().leftPush("mylist","1");
stringRedisTemplate.opsForList().leftPush("mylist","2");
stringRedisTemplate.opsForList().leftPush("mylist","3");

Redis and concrete syntax is the same, but more elaborate

2, the operation target

Employee employee = employeeMapper.findEmployeeById(1);
redisTemplate.opsForValue().set("emp1",employee);

At this time being given: Caused by: java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [net.zjitc.springboot.bean.Employee]
Because of the need to pass the class can be serialized and stored in the class can not be serialized thus being given
the need to achieve in the entity class serializable Interface serializable is only a statement on behalf of the class can be serialized and nothing more

public class Employee implements Serializable {
	
	private Integer id;
	private String lastName;
	private String email;
	private Integer gender;
	private Integer dId;

    ...
}

Such objects can be properly stored in a Redis

Storage garbage problem:

The default is to save the object using JDK serialization mechanism to save the data in the sequence of the Redis
so data will save a lot more, such as \xAC\xED\x00\x05sr\x00garbled such
Here Insert Picture Description

Usually it is usually used in the data JSON stored in the form of
two conversion methods can be realized:

  • 1, we will have a lot of objects into JSON conversion tools to choose from such as Fastjson
  • 2, using the default sequence rules RedisTemplate

Many of the sequences defined in RedisTemplate using default JdkSerializationRedisSerializer
only need to change as JSON serializer
custom Redis a configuration class:

@Configuration
public class MyRedisConfig {

    @Bean
    public RedisTemplate<Object, Employee> empRedisTemplate(
            RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Employee> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        // 传入要转换为JSON的类的class
        Jackson2JsonRedisSerializer<Employee> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
        template.setDefaultSerializer(jackson2JsonRedisSerializer);

        return template;
    }
}

Once you've configured the injection can be used in class:

// 注入
@Autowired
RedisTemplate<Object, Employee> empRedisTemplate;

// 使用
Employee employee = employeeMapper.findEmployeeById(1);
empRedisTemplate.opsForValue().set("emp1",employee);

Here Insert Picture Description
perfect


Third, custom CacheManager

In fact, the principle is CacheManager Cache Manager to create Cache cache component
and then the actual CRUD operations by Cache cache component

Redis starter after introduction of the starter through the interior of the container is determined automatically using RedisCacheManager (Redis Cache Manager)
RedisCacheManager RedisCache created by operation of the caching component Redis as a cache to cache component data
which happens automatically configured
Just enjoy it

But…

When using caching abstraction SpringCache annotations when introduced Redis implement caching of Starter (starter)
is @Cacheable cache data is automatically stored in Redis

However, goose default or JDK is used to store a sequence of the Redis or garbled!
So how data stored as JSON?

CacheManager after the introduction of the starter default Redis is RedisCacheManager
use the default RedisCacheManager operation Redis is created when the RedisTemplate<Object,Object>Note is generic Object, Object
and the default RedisTemplate<Object,Object>serialization mechanism used is the JdkSerializationRedisSerializer it leads to storage (Chinese ) garbled

In this case the need to customize CacheManager
added to the container in a configuration CacheManager class:

// 定制缓存管理器规则
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    //初始化RedisCacheWriter
    RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
    //设置CacheManager的序列化方式为JSON
    RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();
    RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair
            .fromSerializer(jsonSerializer);
    RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig()
            .serializeValuesWith(pair);

    //设置默认超时过期时间
    //    defaultCacheConfig.entryTtl(Duration.ofSeconds(30));

    return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
}

The default CacheManager entry into force when the container is not CacheManager therefore I have written CacheManager Once added to the container automatically take effect
using the default prefix is the default value cacheNames property annotated as a prefix key is the key to avoid repeat
Here Insert Picture Description


A coded way, use the cache manager

Annotations can also be used not only way to operate separate encoding cache manager:
first injection Cache Manager can then be used directly (of course, the premise is already customized the CacheManager if you want to store JSON format Redis words)

// 缓存管理器
@Autowired
CacheManager cacheManager;

public Department getDepartmentById(Integer id)
{
        System.out.println("查询"+id+"部门");
        Department employee = departmentMapper.findEmployeeById(id);

        // 获取一个指定名称的缓存
        Cache dept = cacheManager.getCache("dept");
        // 对指定缓存进行操作 会自动添加前缀
        dept.put(id,employee);

        return employee;
}

Here Insert Picture Description


Published 174 original articles · won praise 5 · Views 240,000 +

Guess you like

Origin blog.csdn.net/Piconjo/article/details/105189645