溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot整合Redis案例分析

發布時間:2022-03-29 14:02:36 來源:億速云 閱讀:150 作者:iii 欄目:大數據

這篇文章主要介紹了SpringBoot整合Redis案例分析的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇SpringBoot整合Redis案例分析文章都會有所收獲,下面我們一起來看看吧。

Springboot整合Redis

如果沒有Redis,就先去下載
  • 下載路徑cmd,然后redis-server.exe redis.windows.conf命令既可以啟動服

  • 啟動服務后,后面的才可以進行整合
  • 在redis目錄下點擊redis-cli.exe進行測試結果查看,基本操作如下

    • key * :查看存儲內容

    • flushdb :清空數據庫

如果redis不熟悉去看

undefined

SpringData也是和SpringBoot齊名的項目!

說明:在SpringBoot2.x之后,原來使用的jedis被替換為了lettuce

jedis:采用的直連,多個線程操作的話,是不安全的,如果想要避免不安全的,使用jedis pool連接池!【類似于BIO:同步阻塞IO】

lettuce:采用netty【異步請求,性能更高點】,實例可以再多個線程中進行共享,不存在線程不安全的情況!可以減少線程數量了【類似于NIO:同步非阻塞IO】

  • 異步請求一般都需要序列化

源碼分析:

  • 源碼位置:
    SpringBoot整合Redis案例分析

	@Bean
	//當這個Bean不存在的時候,這個類就生效
	//這就說明,我們可以自己定義一個redisTemplate來替換這個默認的!
	@ConditionalOnMissingBean(name = "redisTemplate")
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        //默認的RedisTemplate沒有過多的設置,redis,對象都是需要序列化的!
        //兩個泛型都是Object類型,我們后面使用需要強制轉換:我們需要的類型<String, Object>	
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
	@ConditionalOnMissingBean	//由于String是Redis最常用的類型,所以說單獨提出來了一個Bean
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

上手測試【默認的RedisTemplate了解】

1.導入依賴
<!--操作redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

<!--上面redis不兼容時候,可以換成jedis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
2.配置連接
# SpringBoot所有的配置類,都有一個自動配置類  RedisAutoConfiguration
#  自動配置類都會綁定一個properties配置文件  RedisProperties
spring:
  redis:
    host: 127.0.0.1
    # Redis服務器連接端口
    port: 6379
    # Redis數據庫索引(默認為0)
    database: 0
    # Redis服務器連接密碼(默認為空)
    password:
    # 連接池最大連接數(使用負值表示沒有限制)
    pool:
      max-active: 200
    # 連接池最大阻塞等待時間(使用負值表示沒有限制)
      max-wait: -1
    # 連接池中的最大空閑連接
      max-idle: 10
    # 連接池中的最小空閑連接
      min-idle: 0
    # 連接超時時間(毫秒)
    timeout: 1000
3.測試
  • 實際開發中我們都不會用這種原生的方式來編寫代碼

  • 一般我們會將這些常用的操作編寫成工具類:redisUtils【后面就會有】
    • 前面還有jdbcUtils和MybatisUtils等

@SpringBootTest
class Redis03SpringbootApplicationTests {

    //注入RedisAutoConfiguration里面配置的類
    @Autowired
    public RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
		
        //redisTemplate :操作我們的數據庫,api和我們的是一樣的
        //opsForValue   :操作字符串  類似String
        //opsForList    :操作List


        //除了基本的操作,我們常用的方法都可以直接通過redisTemplate進行操作
        //比如事務和基本的CRUD

        //獲取redis的連接對象,就可以操作數據庫的連接了【一般很少來用】
/*        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
        connection.flushDb();
        connection.flushAll();*/

        redisTemplate.opsForValue().set("kami", "g1x");
        System.out.println(redisTemplate.opsForValue().get("kami"));
    }

}
4.結果

SpringBoot整合Redis案例分析

問題:寫到中文的時候,springboot是正常的,但是從redis中的redis.cli.exe運行keys *會出來亂碼

SpringBoot整合Redis案例分析

  • 解決方法:默認的RedisTemplate沒有過多的設置,redis,對象都是需要序列化的!
  • 這是默認的序列化配置

SpringBoot整合Redis案例分析

  • 默認序列化方式是JDK序列化

SpringBoot整合Redis案例分析

6.這時候我們就需要自己來寫配置類
  • 自己寫了后,原來默認的RedisTemplate就會失效

  • 創建一個config

  • @Configuration
    public class RedisConfig {
    
        //編寫我們自己的RedisTemplate
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
    
            //這里面到底怎么配置看后面
    
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    }


上手測試【自定義的RedisTemplate——實際一般使用】

1.先創建一個pojo,user
//將它變為組件,方便調用
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String name;
    private Integer age;
}
2.測試類寫序列化json對象操作【這里默認的序列化是JDK序列化】
    @Test
    public void test() throws JsonProcessingException {
        //真實開發中一般都使用json來傳遞對象,所以要序列化json
        User user = new User("葛", 3);
        //所以要序列化成json對象【變成了json字符串】
        String jsonUser = new ObjectMapper().writeValueAsString(user);
        redisTemplate.opsForValue().set("user", jsonUser);
        System.out.println(redisTemplate.opsForValue().get("user"));
    }
  • 如果不用上面的序列化json對象操作會報錯!String jsonUser = new ObjectMapper().writeValueAsString(user);

  • 下面是關于對象的保存,但是一般都是用json對象

  • SpringBoot整合Redis案例分析

    • 解決方法:在實體類中序列化即可【在企業中,我們所有的pojo都會序列化!SpringBoot】
    • //將它變為組件,方便調用
      @Component
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User implements Serializable {
      
          private String name;
          private Integer age;
      }


3.剛才測試的是默認的序列化(JDK),這時候我們自己寫其他方式的序列化
  1. 創建一個config

  2. SpringBoot整合Redis案例分析

    //這里面到底怎么配置看后面Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>();//配置具體的序列化template.setKeySerializer(objectJackson2JsonRedisSerializer);


    • 多種序列化方式

    1. 寫法例子

  3. 自己寫很費勁,用已經寫好的例子即可

    連接中有不同地方,復制連接中import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer; import java.rmi.UnknownHostException; /** * @author zhangzhixi */@Configurationpublic class RedisConfig {    @Bean    @SuppressWarnings("all")    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {        // 自定義 String Object        RedisTemplate<String, Object> template = new RedisTemplate();        template.setConnectionFactory(redisConnectionFactory);         // Json 序列化配置        Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);        // ObjectMapper 轉譯        ObjectMapper objectMapper = new ObjectMapper();        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);        objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);         // String 的序列化        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();         // key 采用String的序列化方式        template.setKeySerializer(stringRedisSerializer);        // hash 的key也采用 String 的序列化方式        template.setHashKeySerializer(stringRedisSerializer);        // value 序列化方式采用 jackson        template.setValueSerializer(objectJackson2JsonRedisSerializer);        // hash 的 value 采用 jackson        template.setHashValueSerializer(objectJackson2JsonRedisSerializer);        template.afterPropertiesSet();         return template;    }}


    • 企業中直接拿去使用即可
  4. 編寫工具類

    package com.kami.utils;/** * @author zhangzhixi * @date 2021/3/1 23:33 */import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import org.springframework.util.CollectionUtils;import java.util.List;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit;/** * @author mxz */@Componentpublic final class RedisUtil {    @Autowired    private RedisTemplate<String, Object> redisTemplate;    /**     * 指定緩存失效時間     *     * @param key  鍵     * @param time 時間(秒)     * @return     */    public boolean expire(String key, long time) {        try {            if (time > 0) {                redisTemplate.expire(key, time, TimeUnit.SECONDS);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 根據 key 獲取過期時間     *     * @param key 鍵(不能為 Null)     * @return 時間(秒) 返回0代表永久有效     */    public long getExpire(String key) {        return redisTemplate.getExpire(key, TimeUnit.SECONDS);    }    /**     * 判斷 key 是否存在     *     * @param key 鍵(不能為 Null)     * @return true 存在 false 不存在     */    public boolean hashKey(String key) {        try {            return redisTemplate.hasKey(key);        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 刪除緩存     *     * @param key 可以傳一個值 或多個     */    public void del(String... key) {        if (key != null && key.length > 0) {            redisTemplate.delete(key[0]);        } else {            redisTemplate.delete(CollectionUtils.arrayToList(key));        }    }    //==================================String====================================    /**     * 普通緩存獲取     *     * @param key 鍵     * @return 值     */    public Object get(String key) {        return key == null ? null : redisTemplate.opsForValue().get(key);    }    /**     * 普通緩存放入     *     * @param key   鍵     * @param value 值     * @return true 成功 false 失敗     */    public boolean set(String key, Object value) {        try {            redisTemplate.opsForValue().set(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 普通緩存放入并設置時間     *     * @param key   鍵     * @param value 值     * @param time  時間(秒) time > 0 若 time <= 0 將設置無限期     * @return true 成功 false 失敗     */    public boolean set(String key, Object value, long time) {        try {            if (time > 0) {                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);            } else {                set(key, value);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 遞增     *     * @param key   鍵     * @param delta 要增加幾(大于0)     * @return     */    public long incr(String key, long delta) {        if (delta < 0) {            throw new RuntimeException("遞增因子必須大于0");        }        return redisTemplate.opsForValue().increment(key, delta);    }    /**     * 遞減     *     * @param key   鍵     * @param delta 要減少幾(小于0)     * @return     */    public long decr(String key, long delta) {        if (delta < 0) {            throw new RuntimeException("遞減因子必須大于0");        }        return redisTemplate.opsForValue().decrement(key, delta);    }    // ================================Map=================================    /**     * HashGet     *     * @param key  鍵 不能為null     * @param item 項 不能為null     */    public Object hget(String key, String item) {        return redisTemplate.opsForHash().get(key, item);    }    /**     * 獲取hashKey對應的所有鍵值     *     * @param key 鍵     * @return 對應的多個鍵值     */    public Map<Object, Object> hmget(String key) {        return redisTemplate.opsForHash().entries(key);    }    /**     * HashSet     *     * @param key 鍵     * @param map 對應多個鍵值     */    public boolean hmset(String key, Map<String, Object> map) {        try {            redisTemplate.opsForHash().putAll(key, map);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * HashSet 并設置時間     *     * @param key  鍵     * @param map  對應多個鍵值     * @param time 時間(秒)     * @return true成功 false失敗     */    public boolean hmset(String key, Map<String, Object> map, long time) {        try {            redisTemplate.opsForHash().putAll(key, map);            if (time > 0) {                expire(key, time);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 向一張hash表中放入數據,如果不存在將創建     *     * @param key   鍵     * @param item  項     * @param value 值     * @return true 成功 false失敗     */    public boolean hset(String key, String item, Object value) {        try {            redisTemplate.opsForHash().put(key, item, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 向一張hash表中放入數據,如果不存在將創建     *     * @param key   鍵     * @param item  項     * @param value 值     * @param time  時間(秒) 注意:如果已存在的hash表有時間,這里將會替換原有的時間     * @return true 成功 false失敗     */    public boolean hset(String key, String item, Object value, long time) {        try {            redisTemplate.opsForHash().put(key, item, value);            if (time > 0) {                expire(key, time);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 刪除hash表中的值     *     * @param key  鍵 不能為null     * @param item 項 可以使多個 不能為null     */    public void hdel(String key, Object... item) {        redisTemplate.opsForHash().delete(key, item);    }    /**     * 判斷hash表中是否有該項的值     *     * @param key  鍵 不能為null     * @param item 項 不能為null     * @return true 存在 false不存在     */    public boolean hHasKey(String key, String item) {        return redisTemplate.opsForHash().hasKey(key, item);    }    /**     * hash遞增 如果不存在,就會創建一個 并把新增后的值返回     *     * @param key  鍵     * @param item 項     * @param by   要增加幾(大于0)     */    public double hincr(String key, String item, double by) {        return redisTemplate.opsForHash().increment(key, item, by);    }    /**     * hash遞減     *     * @param key  鍵     * @param item 項     * @param by   要減少記(小于0)     */    public double hdecr(String key, String item, double by) {        return redisTemplate.opsForHash().increment(key, item, -by);    }    // ============================set=============================    /**     * 根據key獲取Set中的所有值     *     * @param key 鍵     */    public Set<Object> sGet(String key) {        try {            return redisTemplate.opsForSet().members(key);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }    /**     * 根據value從一個set中查詢,是否存在     *     * @param key   鍵     * @param value 值     * @return true 存在 false不存在     */    public boolean sHasKey(String key, Object value) {        try {            return redisTemplate.opsForSet().isMember(key, value);        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 將數據放入set緩存     *     * @param key    鍵     * @param values 值 可以是多個     * @return 成功個數     */    public long sSet(String key, Object... values) {        try {            return redisTemplate.opsForSet().add(key, values);        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    /**     * 將set數據放入緩存     *     * @param key    鍵     * @param time   時間(秒)     * @param values 值 可以是多個     * @return 成功個數     */    public long sSetAndTime(String key, long time, Object... values) {        try {            Long count = redisTemplate.opsForSet().add(key, values);            if (time > 0) {                expire(key, time);            }            return count;        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    /**     * 獲取set緩存的長度     *     * @param key 鍵     */    public long sGetSetSize(String key) {        try {            return redisTemplate.opsForSet().size(key);        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    /**     * 移除值為value的     *     * @param key    鍵     * @param values 值 可以是多個     * @return 移除的個數     */    public long setRemove(String key, Object... values) {        try {            Long count = redisTemplate.opsForSet().remove(key, values);            return count;        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    // ===============================list=================================    /**     * 獲取list緩存的內容     *     * @param key   鍵     * @param start 開始     * @param end   結束 0 到 -1代表所有值     */    public List<Object> lGet(String key, long start, long end) {        try {            return redisTemplate.opsForList().range(key, start, end);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }    /**     * 獲取list緩存的長度     *     * @param key 鍵     */    public long lGetListSize(String key) {        try {            return redisTemplate.opsForList().size(key);        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    /**     * 通過索引 獲取list中的值     *     * @param key   鍵     * @param index 索引 index>=0時, 0 表頭,1 第二個元素,依次類推;index<0時,-1,表尾,-2倒數第二個元素,依次類推     */    public Object lGetIndex(String key, long index) {        try {            return redisTemplate.opsForList().index(key, index);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }    /**     * 將list放入緩存     *     * @param key   鍵     * @param value 值     */    public boolean lSet(String key, Object value) {        try {            redisTemplate.opsForList().rightPush(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 將list放入緩存     *     * @param key   鍵     * @param value 值     * @param time  時間(秒)     */    public boolean lSet(String key, Object value, long time) {        try {            redisTemplate.opsForList().rightPush(key, value);            if (time > 0) {                expire(key, time);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 將list放入緩存     *     * @param key   鍵     * @param value 值     * @return     */    public boolean lSet(String key, List<Object> value) {        try {            redisTemplate.opsForList().rightPushAll(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 將list放入緩存     *     * @param key   鍵     * @param value 值     * @param time  時間(秒)     * @return     */    public boolean lSet(String key, List<Object> value, long time) {        try {            redisTemplate.opsForList().rightPushAll(key, value);            if (time > 0) {                expire(key, time);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 根據索引修改list中的某條數據     *     * @param key   鍵     * @param index 索引     * @param value 值     * @return     */    public boolean lUpdateIndex(String key, long index, Object value) {        try {            redisTemplate.opsForList().set(key, index, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 移除N個值為value     *     * @param key   鍵     * @param count 移除多少個     * @param value 值     * @return 移除的個數     */    public long lRemove(String key, long count, Object value) {        try {            Long remove = redisTemplate.opsForList().remove(key, count, value);            return remove;        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    // ===============================HyperLogLog=================================    public long pfadd(String key, String value) {        return redisTemplate.opsForHyperLogLog().add(key, value);    }    public long pfcount(String key) {        return redisTemplate.opsForHyperLogLog().size(key);    }    public void pfremove(String key) {        redisTemplate.opsForHyperLogLog().delete(key);    }    public void pfmerge(String key1, String key2) {        redisTemplate.opsForHyperLogLog().union(key1, key2);    }}


    • 我們真實的分發中,或者在你們的公司,一般都可以看到一個公司自己封裝RedisUtil

  5. 轉到測試類

    @SpringBootTestclass Redis02SpringbootApplicationTests {     @Autowired    // 指定我們自己定義的redis序列化配置    private RedisTemplate<String, Object> redisTemplate;     @Autowired    private RedisUtil redisUtil;    @Test    void test1() {        // 清空數據庫        redisTemplate.getConnectionFactory().getConnection().flushDb();         User user = new User("zhangsha", 23);        redisUtil.set("user", user);        System.out.println(redisUtil.get("user"));    }}


    • 這時候注入的RedisTemplate需要導入的是我們的

  6. 結果就是輸出前加了轉譯【不再是亂碼】

    1. redis目錄中的redis-cle.exe

    2. 執行結果

    3. SpringBoot整合Redis案例分析

關于“SpringBoot整合Redis案例分析”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“SpringBoot整合Redis案例分析”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女