SpringBoot + Redis:基本配置及使用

注:本篇博客SpringBoot版本爲2.1.5.RELEASE,SpringBoot1.0版本有些配置不適用

1、SpringBoot 配置Redis

  1.1 pom 引入spring-boot-starter-data-redis 包

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

  1.2 properties配置文件配置redis信息

  默認鏈接本地6379端口的redis服務,通常須要修改配置,例如:java

# Redis數據庫索引(默認爲0)
spring.redis.database=0
# Redis服務器地址
spring.redis.host=127.0.0.1
# Redis服務器鏈接端口
spring.redis.port=6379
# Redis服務器鏈接密碼(默認爲空)
spring.redis.password=
# 鏈接池最大鏈接數(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=20
# 鏈接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=-1
# 鏈接池中的最大空閒鏈接
spring.redis.jedis.pool.max-idle=10
# 鏈接池中的最小空閒鏈接
spring.redis.jedis.pool.min-idle=0
# 鏈接超時時間(毫秒)
spring.redis.timeout=1000

2、RedisTemplate<K,V>類的配置

  Spring 封裝了RedisTemplate<K,V>對象來操做redis。git

  2.1 Spring對RedisTemplate<K,V>類的默認配置(瞭解便可)

  Spring在 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration類下配置的兩個RedisTemplate的Bean。github

  (1) RedisTemplate<Object, Object>redis

  這個Bean使用JdkSerializationRedisSerializer進行序列化,即key, value須要實現Serializable接口,redis數據格式比較難懂,例如spring

  

  (2) StringRedisTemplate,即RedisTemplate<String, String>數據庫

  key和value都是String。當須要存儲實體類時,須要先轉爲String,再存入Redis。通常轉爲Json格式的字符串,因此使用StringRedisTemplate,須要手動將實體類轉爲Json格式。如緩存

ValueOperations<String, String> valueTemplate = stringTemplate.opsForValue();
Gson gson = new Gson();

valueTemplate.set("StringKey1", "hello spring boot redis, String Redis");
String value = valueTemplate.get("StringKey1");
System.out.println(value);

valueTemplate.set("StringKey2", gson.toJson(new Person("theName", 11)));
Person person = gson.fromJson(valueTemplate.get("StringKey2"), Person.class);
System.out.println(person);

  

  2.2 配置一個RedisTemplate<String,Object>的Bean

   Spring配置的兩個RedisTemplate都不太方便使用,因此能夠配置一個RedisTemplate<String,Object> 的Bean,key使用String便可(包括Redis Hash 的key),value存取Redis時默認使用Json格式轉換。以下服務器

    @Bean(name = "template")
    public RedisTemplate<String, Object> template(RedisConnectionFactory factory) {
        // 建立RedisTemplate<String, Object>對象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置鏈接工廠
        template.setConnectionFactory(factory);
        // 定義Jackson2JsonRedisSerializer序列化對象
        Jackson2JsonRedisSerializer<Object> jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修飾符範圍,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化輸入的類型,類必須是非final修飾的,final修飾的類,好比String,Integer等會報異常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);
        StringRedisSerializer stringSerial = new StringRedisSerializer();
        // redis key 序列化方式使用stringSerial
        template.setKeySerializer(stringSerial);
        // redis value 序列化方式使用jackson
        template.setValueSerializer(jacksonSeial);
        // redis hash key 序列化方式使用stringSerial
        template.setHashKeySerializer(stringSerial);
        // redis hash value 序列化方式使用jackson
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();
        return template;
    }

  因此能夠這樣使用mybatis

@Autowired
private RedisTemplate<String, Object> template;
public void test002() {
ValueOperations<String, Object> redisString = template.opsForValue();
// SET key value: 設置指定 key 的值
redisString.set("strKey1", "hello spring boot redis");
// GET key: 獲取指定 key 的值
String value = (String) redisString.get("strKey1");
System.out.println(value);

redisString.set("strKey2", new User("ID10086", "theName", 11));
User user = (User) redisString.get("strKey2");
System.out.println(user);
}  

  

  2.3 配置Redis operations 的Bean

  RedisTemplate<K,V>類如下方法,返回值分別對應操做Redis的String、List、Set、Hash等,能夠將這些operations 注入到Spring中,方便使用app

  

  /**
     * redis string
     */
    @Bean
    public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    /**
     * redis hash
     */
    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    /**
     * redis list
     */
    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }

    /**
     * redis set
     */
    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    /**
     * redis zset
     */
    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }

3、RedisTemplate類的API使用

   RedisTemplate是Spring封裝的類,它的API基本上對應了Redis的命令,下面列舉了一小部分的使用,更多的請查看Javadoc。

    @Autowired
    private HashOperations<String, String, Object> redisHash;// Redis Hash

    @Test
    public void test003() {
        Map<String, Object> map = new HashMap<>();
        map.put("id", "10010");
        map.put("name", "redis_name");
        map.put("amount", 12.34D);
        map.put("age", 11);
        redisHash.putAll("hashKey", map);
        // HGET key field 獲取存儲在哈希表中指定字段的值
        String name = (String) redisHash.get("hashKey", "name");
        System.out.println(name);
        // HGET key field
        Double amount = (Double) redisHash.get("hashKey", "amount");
        System.out.println(amount);
        // HGETALL key 獲取在哈希表中指定 key 的全部字段和值
        Map<String, Object> map2 = redisHash.entries("hashKey");
        System.out.println(map2);
        // HKEYS key 獲取在哈希表中指定 key 的全部字段
        Set<String> keySet = redisHash.keys("hashKey");
        System.out.println(keySet);
        // HVALS key 獲取在哈希表中指定 key 的全部值
        List<Object> valueList = redisHash.values("hashKey");
        System.out.println(valueList);
    }

4、使用Redis緩存數據庫數據

   Redis有不少使用場景,一個demo就是緩存數據庫的數據。Redis做爲一個內存數據庫,存取數據的速度比傳統的數據庫快得多。使用Redis緩存數據庫數據,能夠減輕系統對數據庫的訪問壓力,及加快查詢效率等好處。下面講解如何使用 SpringBoot + Redis來緩存數據庫數據(這裏數據庫使用MySql)。

  4.1 配置Redis做爲Spring的緩存管理

  Spring支持多種緩存技術:RedisCacheManager、EhCacheCacheManager、GuavaCacheManager等,使用以前須要配置一個CacheManager的Bean。配置好以後使用三個註解來緩存數據:@Cacheable,@CachePut 和 @CacheEvict。這三個註解能夠加Service層或Dao層的類名上或方法上(建議加在Service層的方法上),加上類上表示全部方法支持該註解的緩存;三註解須要指定Key,以返回值做爲value操做緩存服務。因此,若是加在Dao層,當新增1行數據時,返回數字1,會將1緩存到Redis,而不是緩存新增的數據。

  RedisCacheManager的配置以下:

   /**
     * <p>SpringBoot配置redis做爲默認緩存工具</p>
     * <p>SpringBoot 2.0 以上版本的配置</p>
     */
    @Bean
    public CacheManager cacheManager(RedisTemplate<String, Object> template) {
        RedisCacheConfiguration defaultCacheConfiguration =
                RedisCacheConfiguration
                        .defaultCacheConfig()
                        // 設置key爲String
                        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getStringSerializer()))
                        // 設置value 爲自動轉Json的Object
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getValueSerializer()))
                        // 不緩存null
                        .disableCachingNullValues()
                        // 緩存數據保存1小時
                        .entryTtl(Duration.ofHours(1));
        RedisCacheManager redisCacheManager =
                RedisCacheManagerBuilder
                        // Redis 鏈接工廠
                        .fromConnectionFactory(template.getConnectionFactory())
                        // 緩存配置
                        .cacheDefaults(defaultCacheConfiguration)
                        // 配置同步修改或刪除 put/evict
                        .transactionAware()
                        .build();
        return redisCacheManager;
    }

  4.2 @Cacheabl、@CachePut、@CacheEvict的使用

package com.github.redis;

import com.github.mybatis.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
/**
 * 指定默認緩存區
 * 緩存區:key的前綴,與指定的key構成redis的key,如 user::10001
 */
@CacheConfig(cacheNames = "user")
@Service
public class RedisCacheUserService {

    @Autowired
    private UserDao dao;

    /**
     * @Cacheable 緩存有數據時,從緩存獲取;沒有數據時,執行方法,並將返回值保存到緩存中
     * @Cacheable 通常在查詢中使用
     * 1) cacheNames 指定緩存區,沒有配置使用@CacheConfig指定的緩存區
     * 2) key 指定緩存區的key
     * 3) 註解的值使用SpEL表達式
     * eq ==
     * lt <
     * le <=
     * gt >
     * ge >=
     */
    @Cacheable(cacheNames = "user", key = "#id")
    public User selectUserById(String id) {
        return dao.selectUserById(id);
    }

    @Cacheable(key="'list'")
    public List<User> selectUser() {
        return dao.selectUser();
    }

    /**
     * condition 知足條件緩存數據
     */
    @Cacheable(key = "#id", condition = "#number ge 20") // >= 20
    public User selectUserByIdWithCondition(String id, int number) {
        return dao.selectUserById(id);
    }

    /**
     * unless 知足條件時否決緩存數據
     */
    @Cacheable(key = "#id", unless = "#number lt 20") // < 20
    public User selectUserByIdWithUnless(String id, int number) {
        return dao.selectUserById(id);
    }

    /**
   * @CachePut 必定會執行方法,並將返回值保存到緩存中 * @CachePut 通常在新增和修改中使用
*/ @CachePut(key = "#user.id") public User insertUser(User user) { dao.insertUser(user); return user; } @CachePut(key = "#user.id", condition = "#user.age ge 20") public User insertUserWithCondition(User user) { dao.insertUser(user); return user; } @CachePut(key = "#user.id") public User updateUser(User user) { dao.updateUser(user); return user; } /** * 根據key刪除緩存區中的數據 */ @CacheEvict(key = "#id") public void deleteUserById(String id) { dao.deleteUserById(id); } /** * allEntries = true :刪除整個緩存區的全部值,此時指定的key無效 * beforeInvocation = true :默認false,表示調用方法以後刪除緩存數據;true時,在調用以前刪除緩存數據(如方法出現異常) */ @CacheEvict(key = "#id", allEntries = true) public void deleteUserByIdAndCleanCache(String id) { dao.deleteUserById(id); } }

5、項目地址

  項目github地址,裏面的測試類均有對上面涉及的內容進行測試。喜歡的幫忙點個Star

  https://github.com/caizhaokai/spring-boot-demo

相關文章
相關標籤/搜索