成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

springboot中如何使用redis

這篇文章將為大家詳細(xì)講解有關(guān)springboot中如何使用redis,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),遼陽(yáng)企業(yè)網(wǎng)站建設(shè),遼陽(yáng)品牌網(wǎng)站建設(shè),網(wǎng)站定制,遼陽(yáng)網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,遼陽(yáng)網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

正文

很多時(shí)候,我們會(huì)在springboot中配置redis,但是就那么幾個(gè)配置就配好了,沒(méi)辦法知道為什么,這里就詳細(xì)的講解一下
這里假設(shè)已經(jīng)成功創(chuàng)建了一個(gè)springboot項(xiàng)目。

redis連接工廠類

第一步,需要加上springboot的redis jar包

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

然后我們寫一個(gè)配置類,創(chuàng)建了一個(gè)redis連接的工廠的spring bean。(Redis連接工廠會(huì)生成到Redis數(shù)據(jù)庫(kù)服務(wù)器的連接)

@Configuration
public class RedisConfig {
  @Bean
  public RedisConnectionFactory redisCF(){
    //如果什么參數(shù)都不設(shè)置,默認(rèn)連接本地6379端口
    JedisConnectionFactory factory = new JedisConnectionFactory();
    factory.setPort(6379);
    factory.setHostName("localhost");
    return factory;
  }
}

單元測(cè)試,看看這個(gè)工廠方法的使用

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class RedisTest {
  
  @Autowired
  RedisConnectionFactory factory;
    
  @Test
  public void testRedis(){
    //得到一個(gè)連接
    RedisConnection conn = factory.getConnection();
    conn.set("hello".getBytes(), "world".getBytes());
    System.out.println(new String(conn.get("hello".getBytes())));
  }

}

輸出結(jié)果 :world,說(shuō)明已經(jīng)成功獲取到連接,并且往redis獲取添加數(shù)據(jù),

template(模版)

但是我們發(fā)現(xiàn)每次添加的key和value都是byte數(shù)組類型(使用很麻煩),于是spring為我們帶來(lái)了redis template(模版)

Spring Data Redis提供了兩個(gè)模板:
RedisTemplate
StringRedisTemplate

首先我們先創(chuàng)建一個(gè)RedisTemplate模板類,類型的key是String類型,value是Object類型(如果key和value都是String類型,建議使用StringRedisTemplate)

  @Bean
  public RedisTemplate redisTemplate(RedisConnectionFactory factory){
    //創(chuàng)建一個(gè)模板類
    RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
    //將剛才的redis連接工廠設(shè)置到模板類中
    template.setConnectionFactory(factory);
    return template;
  }

單元測(cè)試

@Autowired  
  RedisTemplate<String, Object> template;
  
  @Test
  public void testRedisTemplate(){
    template.opsForValue().set("key1", "value1");
    System.out.println(template.opsForValue().get("key1"));
  }

得到結(jié)果輸出value1,是不是很方便了呢。

 如果是操作集合呢,也很方便的哈。

  @Test
  public void testRedisTemplateList(){
  
    Pruduct prud = new Pruduct(1, "洗發(fā)水", "100ml");
    Pruduct prud2 = new Pruduct(2, "洗面奶", "200ml");
    //依次從尾部添加元素
    template.opsForList().rightPush("pruduct", prud);
    template.opsForList().rightPush("pruduct", prud);
    //查詢索引0到商品總數(shù)-1索引(也就是查出所有的商品)
    List<Object> prodList = template.opsForList().range("pruduct", 0,template.opsForList().size("pruduct")-1);
    for(Object obj:prodList){
      System.out.println((Pruduct)obj);
    }
    System.out.println("產(chǎn)品數(shù)量:"+template.opsForList().size("pruduct"));
    
  }

key和value序列化

當(dāng)保存一條數(shù)據(jù)的時(shí)候,key和value都要被序列化成json數(shù)據(jù),取出來(lái)的時(shí)候被序列化成對(duì)象,key和value都會(huì)使用序列化器進(jìn)行序列化,spring data redis提供多個(gè)序列化器

GenericToStringSerializer:使用Spring轉(zhuǎn)換服務(wù)進(jìn)行序列化;
JacksonJsonRedisSerializer:使用Jackson 1,將對(duì)象序列化為JSON;
Jackson2JsonRedisSerializer:使用Jackson 2,將對(duì)象序列化為JSON;
JdkSerializationRedisSerializer:使用Java序列化;
OxmSerializer:使用Spring O/X映射的編排器和解排器(marshaler和unmarshaler)實(shí)現(xiàn)序列化,用于XML序列化;
StringRedisSerializer:序列化String類型的key和value。

RedisTemplate會(huì)默認(rèn)使用JdkSerializationRedisSerializer,這意味著key和value都會(huì)通過(guò)Java進(jìn)行序列化。StringRedisTemplate默認(rèn)會(huì)使用StringRedisSerializer

例如,假設(shè)當(dāng)使用RedisTemplate的時(shí)候,我們希望將Product類型的value序列化為JSON,而key是String類型。RedisTemplate的setKeySerializer()和setValueSerializer()方法就需要如下所示:

@Bean
  public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
    // 創(chuàng)建一個(gè)模板類
    RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
    // 將剛才的redis連接工廠設(shè)置到模板類中
    template.setConnectionFactory(factory);
    // 設(shè)置key的序列化器
    template.setKeySerializer(new StringRedisSerializer());
    // 設(shè)置value的序列化器
    //使用Jackson 2,將對(duì)象序列化為JSON
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    //json轉(zhuǎn)對(duì)象類,不設(shè)置默認(rèn)的會(huì)將json轉(zhuǎn)成hashmap
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);
    template.setValueSerializer(jackson2JsonRedisSerializer);

    return template;
  }

到這里,大家肯定會(huì)對(duì)springboot使用redis有了簡(jiǎn)單的了解。

springboot緩存某個(gè)方法

申明緩存管理器

在某些時(shí)候,我們可能有這樣的需求,用戶登錄的時(shí)候,我們會(huì)從數(shù)據(jù)庫(kù)中讀取用戶所有的權(quán)限,部門等信息。而且每次刷新頁(yè)面都需要判斷該用戶有沒(méi)有這個(gè)權(quán)限,如果不停的從數(shù)據(jù)庫(kù)中讀并且計(jì)算,是非常耗性能的,所以我們這個(gè)時(shí)候就要用到了springboot為我們帶來(lái)的緩存管理器

首先在我們的RedisConfig這個(gè)類上加上@EnableCaching這個(gè)注解。

這個(gè)注解會(huì)被spring發(fā)現(xiàn),并且會(huì)創(chuàng)建一個(gè)切面(aspect) 并觸發(fā)Spring緩存注解的切點(diǎn)(pointcut) 。 根據(jù)所使用的注解以及緩存的狀態(tài), 這個(gè)切面會(huì)從緩存中獲取數(shù)據(jù), 將數(shù)據(jù)添加到緩存之中或者從緩存中移除某個(gè)值。 

接下來(lái)我們需要申明一個(gè)緩存管理器的bean,這個(gè)作用就是@EnableCaching這個(gè)切面在新增緩存或者刪除緩存的時(shí)候會(huì)調(diào)用這個(gè)緩存管理器的方法

/**
   * 申明緩存管理器,會(huì)創(chuàng)建一個(gè)切面(aspect)并觸發(fā)Spring緩存注解的切點(diǎn)(pointcut)
   * 根據(jù)類或者方法所使用的注解以及緩存的狀態(tài),這個(gè)切面會(huì)從緩存中獲取數(shù)據(jù),將數(shù)據(jù)添加到緩存之中或者從緩存中移除某個(gè)值
   
   * @return
   */
  @Bean
  public RedisCacheManager cacheManager(RedisTemplate redisTemplate) {
    return new RedisCacheManager(redisTemplate);
  }

 當(dāng)然,緩存管理器除了RedisCacheManager還有一些其他的。例如

  • SimpleCacheManager

  • NoOpCacheManager

  • ConcurrentMapCacheManager

  • CompositeCacheManager

  • EhCacheCacheManager

ConcurrentMapCacheManager,這個(gè)簡(jiǎn)單的緩存管理器使用java.util.concurrent.ConcurrentHashMap作為其緩存存儲(chǔ)。它非常簡(jiǎn)單,因此對(duì)于開(kāi)發(fā)、測(cè)試或基礎(chǔ)的應(yīng)用來(lái)講,這是一個(gè)很不錯(cuò)的選擇.

添加緩存

接下來(lái)我們?cè)赾ontroller層的方法內(nèi)加上注解,然后啟動(dòng)我們的項(xiàng)目。

@RequestMapping("/getPrud")
  @Cacheable("prudCache")
  public Pruduct getPrud(@RequestParam(required=true)String id){
    System.out.println("如果第二次沒(méi)有走到這里說(shuō)明緩存被添加了");
    return pruductDao.getPrud(Integer.parseInt(id));
  }

發(fā)現(xiàn)打印的這段話只被打印一次,說(shuō)明在走到這個(gè)方法的時(shí)候觸發(fā)了一個(gè)切面,并且查找返回緩存中的數(shù)據(jù)。

當(dāng)然@Cacheable注解也可以放到這個(gè)dao層的方法里面,但是這里會(huì)報(bào)一個(gè)錯(cuò),Integer無(wú)法轉(zhuǎn)成String,因?yàn)槲覀僤ao層方法的參數(shù)類型是int,而RedisTemplate的key類型是String,這里是要注意的。

打開(kāi)redis的客戶端發(fā)現(xiàn)redis對(duì)應(yīng)的key就是我們的參數(shù)1,這個(gè)時(shí)候就會(huì)出問(wèn)題,比如說(shuō)我在其他要緩存的方法的參數(shù)也是1,就會(huì)重復(fù)。后面我們會(huì)將自定義這個(gè)key的值。

除了@Cacheable添加緩存外,springboot還為我們帶了了其他幾個(gè)注解

springboot中如何使用redis

刪除緩存

在delete的時(shí)候用@CacheEvict清楚這條緩存。

  @RequestMapping("/deletePrud")
  @CacheEvict("pruddeleteCache")
  public String deletePrud(@RequestParam(required=true)String id){
    return "SUCCESS";
  }

@CachePut將這個(gè)方法的返回值放到緩存,如果我們放一個(gè)Pruduct對(duì)象,他會(huì)將這個(gè)對(duì)象作為key,這顯然不是我們想要的。這個(gè)時(shí)候就需要自定義我們的key。

自定義key

@Cacheable和@CachePut都有一個(gè)名為key屬性,這個(gè)屬性能夠替換默認(rèn)的key,它是通過(guò)一個(gè)表達(dá)式(Spel表達(dá)式,spring提供的,很簡(jiǎn)單)計(jì)算得到的。

例如下面的就是將返回對(duì)象的id當(dāng)作key來(lái)存儲(chǔ)(但是Pruduct的id是int類型,所以需要將數(shù)字轉(zhuǎn)化成String類型)

  @RequestMapping("/savePrud")
  @CachePut(value="prudsaveCache",key="#result.id +''")
  public Pruduct savePrud(Pruduct prud){
    return prud;
  }

另外除了#result是代表函數(shù)的返回值,spring還為我們帶來(lái)了其他的一些元數(shù)據(jù)

springboot中如何使用redis

 條件化緩存

通過(guò)為方法添加Spring的緩存注解,Spring就會(huì)圍繞著這個(gè)方法創(chuàng)建一個(gè)緩存切面。但是,在有些場(chǎng)景下我們可能希望將緩存功能關(guān)閉。

@Cacheable和@CachePut提供了兩個(gè)屬性用以實(shí)現(xiàn)條件化緩存:unless和condition,這兩個(gè)屬性都接受一個(gè)SpEL表達(dá)式。如果unless屬性的SpEL表達(dá)式計(jì)算結(jié)
果為true,那么緩存方法返回的數(shù)據(jù)就不會(huì)放到緩存中。與之類似,如果condition屬性的SpEL表達(dá)式計(jì)算結(jié)果為false,那么對(duì)于這個(gè)方法緩存就會(huì)被禁用掉

表面上來(lái)看,unless和condition屬性做的是相同的事情。但是,這里有一點(diǎn)細(xì)微的差別。

unless屬性只能阻止將對(duì)象放進(jìn)緩存,但是在這個(gè)方法調(diào)用的時(shí)候,依然會(huì)去緩存中進(jìn)行查找,如果找到了匹配的值,就會(huì)返回找到的值。

與之不同,如果condition的表達(dá)式計(jì)算結(jié)果為false,那么在這個(gè)方法調(diào)用的過(guò)程中,緩存是被禁用的。就是說(shuō),不會(huì)去緩存進(jìn)行查找,同時(shí)返回值也不會(huì)放進(jìn)緩存中。

  @RequestMapping("/getPrud2")
  @CachePut(value ="prudCache",unless="#result.desc.contains('nocache')")
  public Pruduct getPrud2(@RequestParam(required=true)String id){
    System.out.println("如果走到這里說(shuō)明,說(shuō)明緩存沒(méi)有生效!");
    Pruduct p = new Pruduct(Integer.parseInt(id), "name_nocache"+id, "nocache");
    return p;
  }

上面的代碼中,如果返回的對(duì)象desc中包含nocache字符串,則不進(jìn)行緩存。

總結(jié)demo:

將類名方法名和pruduct的id作為key

@RequestMapping("/getPrud3")
  @Cacheable(value ="prudCache",key="#root.targetClass.getName() + #root.methodName + #id")
  public Pruduct getPrud3(@RequestParam(required=true)String id){
    System.out.println("如果第二次沒(méi)有走到這里說(shuō)明緩存被添加了");
    return pruductDao.getPrud(Integer.parseInt(id));
  }

最后注意

#result 方法返回值不能用在@Cacheable上,只能用在@CachePut

springboot配置升級(jí)簡(jiǎn)單化

當(dāng)然上面的配置只是為了了解原理的哈,實(shí)際上我們使用會(huì)更簡(jiǎn)單點(diǎn)。我們重寫了RedisConfig

@Configuration
@EnableCaching//開(kāi)啟緩存
public class RedisConfig extends CachingConfigurerSupport {

  @Bean
  public KeyGenerator keyGenerator() {
    return new KeyGenerator() {
      @Override
      public Object generate(Object target, Method method, Object... params) {
        StringBuilder sb = new StringBuilder();
        sb.append(target.getClass().getName());
        sb.append(method.getName());
        for (Object obj : params) {
          sb.append(obj.toString());
        }
        return sb.toString();
      }
    };
  }  
  /**
   * 申明緩存管理器,會(huì)創(chuàng)建一個(gè)切面(aspect)并觸發(fā)Spring緩存注解的切點(diǎn)(pointcut)
   * 根據(jù)類或者方法所使用的注解以及緩存的狀態(tài),這個(gè)切面會(huì)從緩存中獲取數(shù)據(jù),將數(shù)據(jù)添加到緩存之中或者從緩存中移除某個(gè)值
   
   * @return
   */
  @Bean
  public RedisCacheManager cacheManager(RedisTemplate redisTemplate) {
    return new RedisCacheManager(redisTemplate);
  }


  @Bean
  @Primary
  public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
    // 創(chuàng)建一個(gè)模板類
    RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
    // 將剛才的redis連接工廠設(shè)置到模板類中
    template.setConnectionFactory(factory);
    // 設(shè)置key的序列化器
    template.setKeySerializer(new StringRedisSerializer());
    // 設(shè)置value的序列化器
    //使用Jackson 2,將對(duì)象序列化為JSON
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    //json轉(zhuǎn)對(duì)象類,不設(shè)置默認(rèn)的會(huì)將json轉(zhuǎn)成hashmap
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);
    template.setValueSerializer(jackson2JsonRedisSerializer);

    return template;
  }

}

然后在resources下的application.properties下配置

# REDIS (RedisProperties)
# Redis數(shù)據(jù)庫(kù)索引(默認(rèn)為0)
spring.redis.database=0 
# Redis服務(wù)器地址
spring.redis.host=127.0.0.1
# Redis服務(wù)器連接端口
spring.redis.port=6379 
# Redis服務(wù)器連接密碼(默認(rèn)為空)
spring.redis.password=
# 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制)
spring.redis.pool.max-active=8 
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制)
spring.redis.pool.max-wait=-1 
# 連接池中的最大空閑連接
spring.redis.pool.max-idle=8 
# 連接池中的最小空閑連接
spring.redis.pool.min-idle=0 
# 連接超時(shí)時(shí)間(毫秒)
spring.redis.timeout=0

大家發(fā)現(xiàn)我們并沒(méi)有注冊(cè)RedisConnectionFactory,那是因?yàn)閟pring默認(rèn)幫我們讀取application.properties文件并且注冊(cè)了一個(gè)factorybean

keyGenerator方法幫我們注冊(cè)了一個(gè)key的生成規(guī)則,就不用我們寫spel表達(dá)式了,根據(jù)反射的原理讀取類名+方法名+參數(shù)。但是我們有時(shí)候還是需要結(jié)合spel的。

然后在controller上加上@Cacheable("cachename"),之后就可以在redis看到保存了并且key的值是keyGenerator生成的名字

關(guān)于“springboot中如何使用redis”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

文章名稱:springboot中如何使用redis
瀏覽地址:http://jinyejixie.com/article2/jjidic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、響應(yīng)式網(wǎng)站外貿(mào)建站、網(wǎng)站收錄、品牌網(wǎng)站設(shè)計(jì)、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

綿陽(yáng)服務(wù)器托管
应用必备| 延川县| 满城县| 南溪县| 保康县| 库车县| 十堰市| 静乐县| 临泉县| 菏泽市| 仙桃市| 宁阳县| 金湖县| 巨鹿县| 南投市| 千阳县| 郑州市| 张家港市| 福建省| 清苑县| 长沙市| 阿尔山市| 陵水| 察雅县| 封丘县| 板桥市| 利辛县| 玉林市| 秦安县| 三河市| 姜堰市| 扎兰屯市| 贵阳市| 玛多县| 高雄县| 宝山区| 榆树市| 敖汉旗| 扎鲁特旗| 英山县| 金山区|