<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring Data Redis 最佳實(shí)踐!

          共 17613字,需瀏覽 36分鐘

           ·

          2020-03-28 23:21

          Spring Data Redis 是Spring 框架提供的用于操作Redis的方式,最近整理了下它的用法,解決了使用過程中遇到的一些難點(diǎn)與坑點(diǎn),希望對大家有所幫助。本文涵蓋了Redis的安裝、Spring Cache結(jié)合Redis的使用、Redis連接池的使用和RedisTemplate的使用等內(nèi)容。

          Redis安裝

          這里提供Linux和Windows兩種安裝方式,由于Windows下的版本最高只有3.2版本,所以推薦使用Linux下的版本,目前最新穩(wěn)定版本為5.0,也是本文中使用的版本。

          Linux

          這里我們使用Docker環(huán)境下的安裝方式。

          • 下載Redis5.0的Docker鏡像;
          docker pull redis:5.0
          • 使用Docker命令啟動Redis容器;
          docker run -p 6379:6379 --name redis \
          -v /mydata/redis/data:/data \
          -d redis:5.0 redis-server --appendonly yes

          Windows

          想使用Windows版本的朋友可以使用以下安裝方式。

          • 下載Windows版本的Redis,下載地址:https://github.com/MicrosoftArchive/redis/releases
          5f296c778cd3df4d1b8a4320919443ca.webp
          • 下載完后解壓到指定目錄;
          efa14d6118e30f751fe428041068c250.webp
          • 在當(dāng)前地址欄輸入cmd后,執(zhí)行redis的啟動命令:redis-server.exe redis.windows.conf
          d1c3d3636b2c83fa358c1c54b906c493.webp

          Spring Cache 操作Redis

          Spring Cache 簡介

          當(dāng)Spring Boot 結(jié)合Redis來作為緩存使用時(shí),最簡單的方式就是使用Spring Cache了,使用它我們無需知道Spring中對Redis的各種操作,僅僅通過它提供的@Cacheable 、@CachePut 、@CacheEvict 、@EnableCaching等注解就可以實(shí)現(xiàn)緩存功能。

          常用注解

          @EnableCaching

          開啟緩存功能,一般放在啟動類上。

          @Cacheable

          使用該注解的方法當(dāng)緩存存在時(shí),會從緩存中獲取數(shù)據(jù)而不執(zhí)行方法,當(dāng)緩存不存在時(shí),會執(zhí)行方法并把返回結(jié)果存入緩存中。一般使用在查詢方法上,可以設(shè)置如下屬性:

          • value:緩存名稱(必填),指定緩存的命名空間;
          • key:用于設(shè)置在命名空間中的緩存key值,可以使用SpEL表達(dá)式定義;
          • unless:條件符合則不緩存;
          • condition:條件符合則緩存。

          @CachePut

          使用該注解的方法每次執(zhí)行時(shí)都會把返回結(jié)果存入緩存中。一般使用在新增方法上,可以設(shè)置如下屬性:

          • value:緩存名稱(必填),指定緩存的命名空間;
          • key:用于設(shè)置在命名空間中的緩存key值,可以使用SpEL表達(dá)式定義;
          • unless:條件符合則不緩存;
          • condition:條件符合則緩存。

          @CacheEvict

          使用該注解的方法執(zhí)行時(shí)會清空指定的緩存。一般使用在更新或刪除方法上,可以設(shè)置如下屬性:

          • value:緩存名稱(必填),指定緩存的命名空間;
          • key:用于設(shè)置在命名空間中的緩存key值,可以使用SpEL表達(dá)式定義;
          • condition:條件符合則緩存。

          使用步驟

          • 在pom.xml中添加項(xiàng)目依賴:

          <dependency>
          <groupId>org.springframework.bootgroupId>
          <artifactId>spring-boot-starter-data-redisartifactId>
          dependency>
          • 修改配置文件application.yml,添加Redis的連接配置;
          spring:
          redis:
          host: 192.168.6.139 # Redis服務(wù)器地址
          database: 0 # Redis數(shù)據(jù)庫索引(默認(rèn)為0)
          port: 6379 # Redis服務(wù)器連接端口
          password: # Redis服務(wù)器連接密碼(默認(rèn)為空)
          timeout: 1000ms # 連接超時(shí)時(shí)間
          • 在啟動類上添加@EnableCaching注解啟動緩存功能;
          @EnableCaching
          @SpringBootApplication
          public class MallTinyApplication {

          public static void main(String[] args) {
          SpringApplication.run(MallTinyApplication.class, args);
          }

          }
          • 接下來在PmsBrandServiceImpl類中使用相關(guān)注解來實(shí)現(xiàn)緩存功能,可以發(fā)現(xiàn)我們獲取品牌詳情的方法中使用了@Cacheable注解,在修改和刪除品牌的方法上使用了@CacheEvict注解;
          /**
          * PmsBrandService實(shí)現(xiàn)類
          * Created by macro on 2019/4/19.
          */

          @Service
          public class PmsBrandServiceImpl implements PmsBrandService {
          @Autowired
          private PmsBrandMapper brandMapper;

          @CacheEvict(value = RedisConfig.REDIS_KEY_DATABASE, key = "'pms:brand:'+#id")
          @Override
          public int update(Long id, PmsBrand brand) {
          brand.setId(id);
          return brandMapper.updateByPrimaryKeySelective(brand);
          }

          @CacheEvict(value = RedisConfig.REDIS_KEY_DATABASE, key = "'pms:brand:'+#id")
          @Override
          public int delete(Long id) {
          return brandMapper.deleteByPrimaryKey(id);
          }

          @Cacheable(value = RedisConfig.REDIS_KEY_DATABASE, key = "'pms:brand:'+#id", unless = "#result==null")
          @Override
          public PmsBrand getItem(Long id) {
          return brandMapper.selectByPrimaryKey(id);
          }

          }
          • 我們可以調(diào)用獲取品牌詳情的接口測試下效果,此時(shí)發(fā)現(xiàn)Redis中存儲的數(shù)據(jù)有點(diǎn)像亂碼,并且沒有設(shè)置過期時(shí)間;
          64fb1f11450a2063bf96887969f2cd56.webp

          存儲JSON格式數(shù)據(jù)

          此時(shí)我們就會想到有沒有什么辦法讓Redis中存儲的數(shù)據(jù)變成標(biāo)準(zhǔn)的JSON格式,然后可以設(shè)置一定的過期時(shí)間,不設(shè)置過期時(shí)間容易產(chǎn)生很多不必要的緩存數(shù)據(jù)。

          • 我們可以通過給RedisTemplate設(shè)置JSON格式的序列化器,并通過配置RedisCacheConfiguration設(shè)置超時(shí)時(shí)間來實(shí)現(xiàn)以上需求,此時(shí)別忘了去除啟動類上的@EnableCaching注解,具體配置類RedisConfig代碼如下;
          /**
          * Redis配置類
          * Created by macro on 2020/3/2.
          */

          @EnableCaching
          @Configuration
          public class RedisConfig extends CachingConfigurerSupport {

          /**
          * redis數(shù)據(jù)庫自定義key
          */

          public static final String REDIS_KEY_DATABASE="mall";

          @Bean
          public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
          RedisSerializer serializer = redisSerializer();
          RedisTemplate redisTemplate = new RedisTemplate<>();
          redisTemplate.setConnectionFactory(redisConnectionFactory);
          redisTemplate.setKeySerializer(new StringRedisSerializer());
          redisTemplate.setValueSerializer(serializer);
          redisTemplate.setHashKeySerializer(new StringRedisSerializer());
          redisTemplate.setHashValueSerializer(serializer);
          redisTemplate.afterPropertiesSet();
          return redisTemplate;
          }

          @Bean
          public RedisSerializer redisSerializer() {
          //創(chuàng)建JSON序列化器
          Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class);
          ObjectMapper objectMapper = new ObjectMapper();
          objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
          objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
          serializer.setObjectMapper(objectMapper);
          return serializer;
          }

          @Bean
          public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
          RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
          //設(shè)置Redis緩存有效期為1天
          RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
          .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1));
          return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
          }

          }
          • 此時(shí)我們再次調(diào)用獲取商品詳情的接口進(jìn)行測試,會發(fā)現(xiàn)Redis中已經(jīng)緩存了標(biāo)準(zhǔn)的JSON格式數(shù)據(jù),并且超時(shí)時(shí)間被設(shè)置為了1天。
          86c0580d174ca88899d1e5c241baf738.webp

          使用Redis連接池

          SpringBoot 1.5.x版本Redis客戶端默認(rèn)是Jedis實(shí)現(xiàn)的,SpringBoot 2.x版本中默認(rèn)客戶端是用Lettuce實(shí)現(xiàn)的,我們先來了解下Jedis和Lettuce客戶端。

          Jedis vs Lettuce

          Jedis在實(shí)現(xiàn)上是直連Redis服務(wù),多線程環(huán)境下非線程安全,除非使用連接池,為每個(gè) RedisConnection 實(shí)例增加物理連接。

          Lettuce是一種可伸縮,線程安全,完全非阻塞的Redis客戶端,多個(gè)線程可以共享一個(gè)RedisConnection,它利用Netty NIO框架來高效地管理多個(gè)連接,從而提供了異步和同步數(shù)據(jù)訪問方式,用于構(gòu)建非阻塞的反應(yīng)性應(yīng)用程序。

          使用步驟

          • 修改application.yml添加Lettuce連接池配置,用于配置線程數(shù)量和阻塞等待時(shí)間;
          spring:
          redis:
          lettuce:
          pool:
          max-active: 8 # 連接池最大連接數(shù)
          max-idle: 8 # 連接池最大空閑連接數(shù)
          min-idle: 0 # 連接池最小空閑連接數(shù)
          max-wait: -1ms # 連接池最大阻塞等待時(shí)間,負(fù)值表示沒有限制
          • 由于SpringBoot 2.x中默認(rèn)并沒有使用Redis連接池,所以需要在pom.xml中添加commons-pool2的依賴;
          <dependency>
          <groupId>org.apache.commonsgroupId>
          <artifactId>commons-pool2artifactId>
          dependency>
          • 如果你沒添加以上依賴的話,啟動應(yīng)用的時(shí)候就會產(chǎn)生如下錯誤;
          Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
          at org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration$LettucePoolingClientConfigurationBuilder.(LettucePoolingClientConfiguration.java:84) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE]
          at org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration.builder(LettucePoolingClientConfiguration.java:48) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE]
          at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration$PoolBuilderFactory.createBuilder(LettuceConnectionConfiguration.java:149) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
          at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration.createBuilder(LettuceConnectionConfiguration.java:107) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
          at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration.getLettuceClientConfiguration(LettuceConnectionConfiguration.java:93) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
          at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration.redisConnectionFactory(LettuceConnectionConfiguration.java:74) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
          at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration$$EnhancerBySpringCGLIB$$5caa7e47.CGLIB$redisConnectionFactory$0() ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
          at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration$$EnhancerBySpringCGLIB$$5caa7e47$$FastClassBySpringCGLIB$$b8ae2813.invoke() ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
          at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
          at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
          at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration$$EnhancerBySpringCGLIB$$5caa7e47.redisConnectionFactory() ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
          at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91]
          at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
          ... 111 common frames omitted

          自由操作Redis

          Spring Cache 給我們提供了操作Redis緩存的便捷方法,但是也有很多局限性。比如說我們想單獨(dú)設(shè)置一個(gè)緩存值的有效期怎么辦?我們并不想緩存方法的返回值,我們想緩存方法中產(chǎn)生的中間值怎么辦?此時(shí)我們就需要用到RedisTemplate這個(gè)類了,接下來我們來講下如何通過RedisTemplate來自由操作Redis中的緩存。

          RedisService

          定義Redis操作業(yè)務(wù)類,在Redis中有幾種數(shù)據(jù)結(jié)構(gòu),比如普通結(jié)構(gòu)(對象),Hash結(jié)構(gòu)、Set結(jié)構(gòu)、List結(jié)構(gòu),該接口中定義了大多數(shù)常用操作方法。

          /**
          * redis操作Service
          * Created by macro on 2020/3/3.
          */

          public interface RedisService {

          /**
          * 保存屬性
          */

          void set(String key, Object value, long time);

          /**
          * 保存屬性
          */

          void set(String key, Object value);

          /**
          * 獲取屬性
          */

          Object get(String key);

          /**
          * 刪除屬性
          */

          Boolean del(String key);

          /**
          * 批量刪除屬性
          */

          Long del(List keys);

          /**
          * 設(shè)置過期時(shí)間
          */

          Boolean expire(String key, long time);

          /**
          * 獲取過期時(shí)間
          */

          Long getExpire(String key);

          /**
          * 判斷是否有該屬性
          */

          Boolean hasKey(String key);

          /**
          * 按delta遞增
          */

          Long incr(String key, long delta);

          /**
          * 按delta遞減
          */

          Long decr(String key, long delta);

          /**
          * 獲取Hash結(jié)構(gòu)中的屬性
          */

          Object hGet(String key, String hashKey);

          /**
          * 向Hash結(jié)構(gòu)中放入一個(gè)屬性
          */

          Boolean hSet(String key, String hashKey, Object value, long time);

          /**
          * 向Hash結(jié)構(gòu)中放入一個(gè)屬性
          */

          void hSet(String key, String hashKey, Object value);

          /**
          * 直接獲取整個(gè)Hash結(jié)構(gòu)
          */

          Map hGetAll(String key);

          /**
          * 直接設(shè)置整個(gè)Hash結(jié)構(gòu)
          */

          Boolean hSetAll(String key, Map map, long time);

          /**
          * 直接設(shè)置整個(gè)Hash結(jié)構(gòu)
          */

          void hSetAll(String key, Map map);

          /**
          * 刪除Hash結(jié)構(gòu)中的屬性
          */

          void hDel(String key, Object... hashKey);

          /**
          * 判斷Hash結(jié)構(gòu)中是否有該屬性
          */

          Boolean hHasKey(String key, String hashKey);

          /**
          * Hash結(jié)構(gòu)中屬性遞增
          */

          Long hIncr(String key, String hashKey, Long delta);

          /**
          * Hash結(jié)構(gòu)中屬性遞減
          */

          Long hDecr(String key, String hashKey, Long delta);

          /**
          * 獲取Set結(jié)構(gòu)
          */

          Set sMembers(String key);

          /**
          * 向Set結(jié)構(gòu)中添加屬性
          */

          Long sAdd(String key, Object... values);

          /**
          * 向Set結(jié)構(gòu)中添加屬性
          */

          Long sAdd(String key, long time, Object... values);

          /**
          * 是否為Set中的屬性
          */

          Boolean sIsMember(String key, Object value);

          /**
          * 獲取Set結(jié)構(gòu)的長度
          */

          Long sSize(String key);

          /**
          * 刪除Set結(jié)構(gòu)中的屬性
          */

          Long sRemove(String key, Object... values);

          /**
          * 獲取List結(jié)構(gòu)中的屬性
          */

          List lRange(String key, long start, long end);

          /**
          * 獲取List結(jié)構(gòu)的長度
          */

          Long lSize(String key);

          /**
          * 根據(jù)索引獲取List中的屬性
          */

          Object lIndex(String key, long index);

          /**
          * 向List結(jié)構(gòu)中添加屬性
          */

          Long lPush(String key, Object value);

          /**
          * 向List結(jié)構(gòu)中添加屬性
          */

          Long lPush(String key, Object value, long time);

          /**
          * 向List結(jié)構(gòu)中批量添加屬性
          */

          Long lPushAll(String key, Object... values);

          /**
          * 向List結(jié)構(gòu)中批量添加屬性
          */

          Long lPushAll(String key, Long time, Object... values);

          /**
          * 從List結(jié)構(gòu)中移除屬性
          */

          Long lRemove(String key, long count, Object value);
          }

          RedisServiceImpl

          RedisService的實(shí)現(xiàn)類,使用RedisTemplate來自由操作Redis中的緩存數(shù)據(jù)。

          /**
          * redis操作實(shí)現(xiàn)類
          * Created by macro on 2020/3/3.
          */

          @Service
          public class RedisServiceImpl implements RedisService {
          @Autowired
          private RedisTemplate redisTemplate;

          @Override
          public void set(String key, Object value, long time) {
          redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
          }

          @Override
          public void set(String key, Object value) {
          redisTemplate.opsForValue().set(key, value);
          }

          @Override
          public Object get(String key) {
          return redisTemplate.opsForValue().get(key);
          }

          @Override
          public Boolean del(String key) {
          return redisTemplate.delete(key);
          }

          @Override
          public Long del(List keys) {
          return redisTemplate.delete(keys);
          }

          @Override
          public Boolean expire(String key, long time) {
          return redisTemplate.expire(key, time, TimeUnit.SECONDS);
          }

          @Override
          public Long getExpire(String key) {
          return redisTemplate.getExpire(key, TimeUnit.SECONDS);
          }

          @Override
          public Boolean hasKey(String key) {
          return redisTemplate.hasKey(key);
          }

          @Override
          public Long incr(String key, long delta) {
          return redisTemplate.opsForValue().increment(key, delta);
          }

          @Override
          public Long decr(String key, long delta) {
          return redisTemplate.opsForValue().increment(key, -delta);
          }

          @Override
          public Object hGet(String key, String hashKey) {
          return redisTemplate.opsForHash().get(key, hashKey);
          }

          @Override
          public Boolean hSet(String key, String hashKey, Object value, long time) {
          redisTemplate.opsForHash().put(key, hashKey, value);
          return expire(key, time);
          }

          @Override
          public void hSet(String key, String hashKey, Object value) {
          redisTemplate.opsForHash().put(key, hashKey, value);
          }

          @Override
          public Map hGetAll(String key) {
          return redisTemplate.opsForHash().entries(key);
          }

          @Override
          public Boolean hSetAll(String key, Map map, long time) {
          redisTemplate.opsForHash().putAll(key, map);
          return expire(key, time);
          }

          @Override
          public void hSetAll(String key, Map map) {
          redisTemplate.opsForHash().putAll(key, map);
          }

          @Override
          public void hDel(String key, Object... hashKey) {
          redisTemplate.opsForHash().delete(key, hashKey);
          }

          @Override
          public Boolean hHasKey(String key, String hashKey) {
          return redisTemplate.opsForHash().hasKey(key, hashKey);
          }

          @Override
          public Long hIncr(String key, String hashKey, Long delta) {
          return redisTemplate.opsForHash().increment(key, hashKey, delta);
          }

          @Override
          public Long hDecr(String key, String hashKey, Long delta) {
          return redisTemplate.opsForHash().increment(key, hashKey, -delta);
          }

          @Override
          public Set sMembers(String key) {
          return redisTemplate.opsForSet().members(key);
          }

          @Override
          public Long sAdd(String key, Object... values) {
          return redisTemplate.opsForSet().add(key, values);
          }

          @Override
          public Long sAdd(String key, long time, Object... values) {
          Long count = redisTemplate.opsForSet().add(key, values);
          expire(key, time);
          return count;
          }

          @Override
          public Boolean sIsMember(String key, Object value) {
          return redisTemplate.opsForSet().isMember(key, value);
          }

          @Override
          public Long sSize(String key) {
          return redisTemplate.opsForSet().size(key);
          }

          @Override
          public Long sRemove(String key, Object... values) {
          return redisTemplate.opsForSet().remove(key, values);
          }

          @Override
          public List lRange(String key, long start, long end) {
          return redisTemplate.opsForList().range(key, start, end);
          }

          @Override
          public Long lSize(String key) {
          return redisTemplate.opsForList().size(key);
          }

          @Override
          public Object lIndex(String key, long index) {
          return redisTemplate.opsForList().index(key, index);
          }

          @Override
          public Long lPush(String key, Object value) {
          return redisTemplate.opsForList().rightPush(key, value);
          }

          @Override
          public Long lPush(String key, Object value, long time) {
          Long index = redisTemplate.opsForList().rightPush(key, value);
          expire(key, time);
          return index;
          }

          @Override
          public Long lPushAll(String key, Object... values) {
          return redisTemplate.opsForList().rightPushAll(key, values);
          }

          @Override
          public Long lPushAll(String key, Long time, Object... values) {
          Long count = redisTemplate.opsForList().rightPushAll(key, values);
          expire(key, time);
          return count;
          }

          @Override
          public Long lRemove(String key, long count, Object value) {
          return redisTemplate.opsForList().remove(key, count, value);
          }
          }

          RedisController

          測試RedisService中緩存操作的Controller,大家可以調(diào)用測試下。

          /**
          * Redis測試Controller
          * Created by macro on 2020/3/3.
          */

          @Api(tags = "RedisController", description = "Redis測試")
          @Controller
          @RequestMapping("/redis")
          public class RedisController {
          @Autowired
          private RedisService redisService;
          @Autowired
          private PmsBrandService brandService;

          @ApiOperation("測試簡單緩存")
          @RequestMapping(value = "/simpleTest", method = RequestMethod.GET)
          @ResponseBody
          public CommonResult simpleTest() {
          List brandList = brandService.list(1, 5);
          PmsBrand brand = brandList.get(0);
          String key = "redis:simple:" + brand.getId();
          redisService.set(key, brand);
          PmsBrand cacheBrand = (PmsBrand) redisService.get(key);
          return CommonResult.success(cacheBrand);
          }

          @ApiOperation("測試Hash結(jié)構(gòu)的緩存")
          @RequestMapping(value = "/hashTest", method = RequestMethod.GET)
          @ResponseBody
          public CommonResult hashTest() {
          List brandList = brandService.list(1, 5);
          PmsBrand brand = brandList.get(0);
          String key = "redis:hash:" + brand.getId();
          Map value = BeanUtil.beanToMap(brand);
          redisService.hSetAll(key, value);
          Map cacheValue = redisService.hGetAll(key);
          PmsBrand cacheBrand = BeanUtil.mapToBean(cacheValue, PmsBrand.class, true);
          return CommonResult.success(cacheBrand);
          }

          @ApiOperation("測試Set結(jié)構(gòu)的緩存")
          @RequestMapping(value = "/setTest", method = RequestMethod.GET)
          @ResponseBody
          public CommonResult> setTest() {
          List brandList = brandService.list(1, 5);
          String key = "redis:set:all";
          redisService.sAdd(key, (Object[]) ArrayUtil.toArray(brandList, PmsBrand.class));
          redisService.sRemove(key, brandList.get(0));
          Set cachedBrandList = redisService.sMembers(key);
          return CommonResult.success(cachedBrandList);
          }

          @ApiOperation("測試List結(jié)構(gòu)的緩存")
          @RequestMapping(value = "/listTest", method = RequestMethod.GET)
          @ResponseBody
          public CommonResult> listTest() {
          List brandList = brandService.list(1, 5);
          String key = "redis:list:all";
          redisService.lPushAll(key, (Object[]) ArrayUtil.toArray(brandList, PmsBrand.class));
          redisService.lRemove(key, 1, brandList.get(0));
          List cachedBrandList = redisService.lRange(key, 0, 3);
          return CommonResult.success(cachedBrandList);
          }
          }


          推薦閱讀:


          69e2903b9bda70dfcdb83764695d1c00.webp喜歡我可以給我設(shè)為星標(biāo)哦69e2903b9bda70dfcdb83764695d1c00.webp

          cc2c881204ae78a8de84e02ae732783c.webp

          好文章,我?在看?

          814ff69afde2646a7392a63796f155b6.webp
          瀏覽 79
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    中文字幕在线观看就是爽 | 亚洲小视频在线观看 | 一本色道综合久久欧美日韩精品 | 麻豆国产精品一区 | 亚洲小电影在线观看 |