Why cache? I don’t want to explain too much here, we have touched both mobile and front-end! Redis is a lightweight key-value database, similar to SP on Android or localStorage in the front end. It is to put the data to be cached into key-value pairs. When used, the value can be retrieved through key and directly cached, so that there is no need to call the interface or query the database again. Understand that, and you’ll feel much simpler!

GitHub:github.com/baiyuliang/…

Pom. XML is introduced into:

<! --redis-->
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
     <version>2.3.4. RELEASE</version>
 </dependency>
Copy the code

Application. Yml adds redis configuration:

spring:
  redis:
    host: 39.xxx.x.xx
    port: 6379
    database: 1                # redis16 which library, default 0
    client-name: redis
    password: 123456
    timeout: 3000              Connection timeout (ms)
    jedis.pool.max-active: 8   Redis maximum number of connections in the connection pool
    jedis.pool.max-idle: 8     # Redis maximum number of free connections in the connection pool
    jedis.pool.max-wait: - 1    The maximum waiting time in the connection pool of redis, -1, indicates that there is no limit
    jedis.pool.min-idle: 0     The minimum number of free connections in redis connection pool
Copy the code

Create RedisConfig:

package com.byl.springboottest.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        template.setDefaultSerializer(serializer);
        return template;
    }

    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1))
                .disableCachingNullValues()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        returnRedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build(); }}Copy the code

Start testing:

1. EnableCaching @enablecaching: Application entry:

@EnableCaching// Enable caching
@SpringBootApplication
public class SpringboottestApplication {

    public static void main(String[] args) { SpringApplication.run(SpringboottestApplication.class, args); }}Copy the code

2. Add @cacheable annotation to a method of the Service:

@Service
public class UserServiceImpl implements UserService {

    @Resource
    UserRepository userRepository;

    @Cacheable(cacheNames = "user", condition = "#id>0", unless = "#result==null")
    @Override
    public User getUserById(Integer id) {
        return userRepository.getOne(id);
    }

    @Override
    public User getUserByName(String username) {
        returnuserRepository.findByUserName(username); }}Copy the code

The cacheNames cache name, the condition cache condition (only id>0 is cached), and unless is also a cache condition, but it is not cached if it is valid.

Run the project, the browser input: http://localhost:8080/byl/user/2, to test the corresponding method of cache:

First run result:

Console:

That the first time from the database query without error!

View Redis database:

Cache successful!

I’ll change my browser and run it again:

At this point, the console does not print any Sql data, indicating that Redis has been successfully integrated!

When we need to update the cache, we can add @cacheput to a method and remove the cache with @cacheevict!

To use @cacheable, you should declare cacheNames, which is to separate your cache information from other Cacheable information. You can use the same type of business in a unified module, such as user, to query information in Redis:

Specify another name, and the corresponding folder will be generated!

User ::2 is the key, because if we do not specify a key, the cache will automatically store the parameter value as the key. We can use the keyGenerator property to customize the key generation mechanism, but note that the key values stored must be regular. So when you update or delete the cache, you can cache the data exactly by the corresponding key operation!

Here is an example of a custom keyGenerator:

@Configuration
public class MyCacheConfig {

    @Bean("myKeyGenerator")
    public KeyGenerator keyGenerator(a) {
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                return method.getName() + "[" + Arrays.asList(objects).toString() + "]"; }}; }}Copy the code

Use the method name and parameters as keys!

To reference this keyGenerator:

@Cacheable(cacheNames = "user", condition = "#id>0", unless = "#result==null" ,keyGenerator = "myKeyGenerator")
Copy the code

If we declare @cacheable directly on a method, we will cache the results of the method by default. In real development, in the Service layer, methods return results with a fixed-format data model, such as:

{
	code:1.msg:"Succeeded in getting the list".data: {total:1.list:[{...}]}}Copy the code

This may not meet our actual needs, because we only want to cache the data from the database, not the data returned by the business layer. In this case, we can directly use the code to cache data access:

    @Resource
    RedisCacheManager redisCacheManager;// Cache manager

    // @Cacheable(cacheNames = "user",condition = "#id>0", unless = "#result==null")
    @Override
    public User getUserById(Integer id) {
        User user;
        Cache cache = redisCacheManager.getCache("user");//cacheNames
        if (cache.get("getUserById"+ id) ! =null) {
            user = (User) cache.get("getUserById" + id).get();// Get value by key
            if(user ! =null) {
                System.out.println("Get result from cache >>" + user.getNickName());
                return user;
            }
        }
        user = userRepository.findById(id).get();
        cache.put("getUserById" + id, user);// Cache data
        return user;
    }
Copy the code

We first empty redis database, then run the program, the browser input: http://localhost:8080/byl/user/2

View redis database:

Refresh the browser again:

Of course, there are n more methods to cache, which you can use when appropriate: