Using redis under SpringBoot

Keywords: Java Jedis Redis JSON SpringBoot

When our project needs to use cache and high concurrency, we can use redis connection pool, let's go straight to the topic. The project environment of this paper is win 10, springboot 2.1.5.RELEASE, redis Java client jedis 2.9.3, fastjson 1.2.47 (for serialization). This project uses the lombok plug-in, so the set and get methods are replaced by annotations.

1. Introduce redis client dependency

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

2. Add configuration in application.properties file

#redis
redis.host=127.0.0.1
redis.port=6379
redis.timeout=10
redis.poolMaxTotal=1000
redis.poolMaxIdle=500
redis.poolMaxWait=500

3. Write entity class RedisConfig receive configuration

/**
 * Read redis information of configuration file
 */
@Data
@Component
@ConfigurationProperties(prefix = "redis")//Read the configuration with the prefix redis
public class  RedisConfig {
    private String host;
    private int port;
    private int timeout;
    private String password;
    private int poolMaxTotal;
    private int poolMaxIdle;
    private int poolMaxWait;
}

4. Write a RedisPoolFactory class, which returns a redis connection pool.

@Service
public class RedisPoolFactory {

    @Autowired
    RedisConfig  redisConfig;

    /**
     * Inject redis connection pool into spring container
     * @return
     */
    @Bean
    public JedisPool JedisPoolFactory(){
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(redisConfig.getPoolMaxIdle());
        config.setMaxTotal(redisConfig.getPoolMaxTotal());
        config.setMaxWaitMillis(redisConfig.getPoolMaxWait() * 1000);
        JedisPool jp = new JedisPool(config, redisConfig.getHost(), redisConfig.getPort(),
                redisConfig.getTimeout()*1000, redisConfig.getPassword(), 0);
        return jp;
    }

}

5. Write your own redis method class
The rewritten method prefixes the key. The advantage is that the key can be classified to avoid duplicate and batch deletion.

@Service
public class RedisService {

    @Autowired
    JedisPool jedisPool;

    /**
     * Get the redis instance from the redis connection pool
     */
    public <T> T get(KeyPrefix prefix, String key, Class<T> clazz) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            //Adding prefix to key can be used for classification and avoid key repetition
            String realKey = prefix.getPrefix() + key;
            String str = jedis.get(realKey);
            T t = stringToBean(str, clazz);
            return t;
        } finally {
            returnToPool(jedis);
        }

    }

    /**
     * Storage object
     */
    public <T> Boolean set(KeyPrefix prefix, String key, T value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String str = beanToString(value);
            if (str == null || str.length() <= 0) {
                return false;
            }
            String realKey = prefix.getPrefix() + key;
            int seconds = prefix.expireSeconds();//Get expiration time
            if (seconds <= 0) {
                jedis.set(realKey, str);
            } else {
                jedis.setex(realKey, seconds, str);
            }

            return true;
        } finally {
            returnToPool(jedis);
        }

    }

    /**
     * delete
     */
    public boolean delete(KeyPrefix prefix, String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            //Generate real key
            String realKey = prefix.getPrefix() + key;
            long ret = jedis.del(realKey);
            return ret > 0;
        } finally {
            returnToPool(jedis);
        }
    }

    /**
     * Determine whether the key exists
     */
    public <T> boolean exists(KeyPrefix prefix, String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            //Generate real key
            String realKey = prefix.getPrefix() + key;
            return jedis.exists(realKey);
        } finally {
            returnToPool(jedis);
        }
    }

    /**
     * Added value
     * Redis Incr Command to increase the number value stored in the key by one. If the key does not exist, the value of the key will be initialized to 0 before the INCR operation.
     */
    public <T> Long incr(KeyPrefix prefix, String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            //Generate real key
            String realKey = prefix.getPrefix() + key;
            return jedis.incr(realKey);
        } finally {
            returnToPool(jedis);
        }
    }

    /**
     * Reduced value
     */
    public <T> Long decr(KeyPrefix prefix, String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            //Generate real key
            String realKey = prefix.getPrefix() + key;
            return jedis.decr(realKey);
        } finally {
            returnToPool(jedis);
        }
    }


    public static <T> String beanToString(T value) {
        if (value == null) {
            return null;
        }
        Class<?> clazz = value.getClass();
        if (clazz == int.class || clazz == Integer.class) {
            return String.valueOf(value);
        } else if (clazz == long.class || clazz == Long.class) {
            return String.valueOf(value);
        } else if (clazz == String.class) {
            return (String) value;
        } else {
            return JSON.toJSONString(value);
        }

    }

    public static <T> T stringToBean(String str, Class<T> clazz) {
        if (str == null || str.length() <= 0 || clazz == null) {
            return null;
        }
        if (clazz == int.class || clazz == Integer.class) {
            return (T) Integer.valueOf(str);
        } else if (clazz == long.class || clazz == Long.class) {
            return (T) Long.valueOf(str);
        } else if (clazz == String.class) {
            return (T) str;
        } else {
            return JSON.toJavaObject(JSON.parseObject(str), clazz);
        }
    }

    private void returnToPool(Jedis jedis) {
        if (jedis != null) {
            jedis.close();//Not closed, just back to connection pool
        }
    }

}

6. test

@Test
    public void RedisServiceTest() {
        Boolean aBoolean = redisService.set(GoodsKey.getGoodsStock, "huawei", "500");
        System.out.println(aBoolean);//aBoolean=true
    }
    

summary

In this paper, we use the redis connection pool and prefix the redis keys. The advantage is to facilitate classification and avoid duplication. When you need to save an object, you can serialize it and then save it.

Posted by satanclaus on Wed, 16 Oct 2019 15:44:34 -0700