请叫我头头哥

SpringBoot进阶教程(五十三)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用

在上一篇文章(《SpringBoot(二十四)整合Redis》)中,已经实现了Spring Boot对Redis的整合,既然已经讲到Cache了,今天就介绍介绍缓存注解。各家互联网产品现在数据量越来越大,其快速增长造成网络拥塞和服务器超载,导致客户访问延迟增大,服务质量日益显现出来。缓存技术被认为是减轻服务器负载、降低网络拥塞、增强可扩展性的有效途径之一。

v概念介绍

 Spring为我们提供了几个注解来支持Spring Cache。其核心主要是@Cacheable和@CacheEvict。使用@Cacheable标记的方法在执行后Spring Cache将缓存其返回结果,而使用@CacheEvict标记的方法会在方法执行前或者执行后移除Spring Cache中的某些元素。下面我们将来详细介绍一下Spring基于注解对Cache的支持所提供的几个注解。

Spring Cache常见概念介绍

名称解释
Cache 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache等
CacheManager 缓存管理器,管理各种缓存(cache)组件
@Cacheable 主要针对方法配置,能够根据方法的请求参数对其进行缓存
@CacheEvict 清空缓存
@CachePut 保证方法被调用,又希望结果被缓存。
与@Cacheable区别在于是否每次都调用方法,常用于更新
@EnableCaching 开启基于注解的缓存
keyGenerator 缓存数据时key生成策略
serialize 缓存数据时value序列化策略
@CacheConfig 统一配置本类的缓存注解的属性

注解(@Cacheable/@CachePut/@CacheEvict)的主要参数

名称解释example
value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 e.g.
@Cacheable(value=”mycache”) 或者
@Cacheable(value={”cache1”,”cache2”}
key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,
如果不指定,则缺省按照方法的所有参数进行组合
e.g.
@Cacheable(value=”testcache”,key=”#id”)
condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,
只有为 true 才进行缓存/清除缓存
e.g.@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
unless 否定缓存。当条件结果为TRUE时,就不会缓存。 e.g.@Cacheable(value=”testcache”,unless=”#userName.length()>2”)
allEntries
(@CacheEvict )
是否清空所有缓存内容,缺省为 false,如果指定为 true,
则方法调用后将立即清空所有缓存
e.g.
@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation
(@CacheEvict)
是否在方法执行前就清空,缺省为 false,如果指定为 true,
则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法
执行抛出异常,则不会清空缓存
e.g.
@CachEvict(value=”testcache”,beforeInvocation=true)

v准备工作

1.1 引入依赖pom.xml

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

激活启动类注解@EnableCaching

SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用

v实战演练

2.1 添加service层

package com.demo.service;

import com.demo.pojo.UserDetails;

/**
 * Created by toutou on 2019/1/20.
 */
public interface CacheService {
    UserDetails getUserDetailsByUid(int uid);

    UserDetails updateUserInfo(UserDetails userDetails);

    int delUserInfoById(int uid);
}
package com.demo.service;

import com.demo.dao.UserDetailsMapper;
import com.demo.pojo.UserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * Created by toutou on 2019/1/20.
 */
@Service
public class CacheServiceImpl implements CacheService{

    @Autowired
    UserDetailsMapper userDetailsMapper;

    @Override
    @Cacheable(value = "user_details", key = "#uid", unless="#result == null")
    public UserDetails getUserDetailsByUid(int uid){
        System.out.println(" Cacheable 有请求过来了");
        UserDetails userDetails = userDetailsMapper.getUserDetailsByUid(uid);
        return userDetails;
    }

    @Override
    @CachePut(value = "user_details", key = "#user.id")
    public UserDetails updateUserInfo(UserDetails user){
        System.out.println(" CachePut 有请求过来了");
        if(userDetailsMapper.updateByPrimaryKeySelective(user) > 0) {
            // 这里也可以直接在updateByPrimaryKeySelective的方法里,修改后直接查询出该记录返回UserDetails实例,看需求。
            user = userDetailsMapper.getUserDetailsByUid(user.getId());
            return user;
        }else{
            return null;
        }
    }

    @Override
    @CacheEvict(value = "user_details", key = "#uid")
    public int delUserInfoById(int uid){
        System.out.println(" CacheEvict 有请求过来了");
        return userDetailsMapper.deleteByPrimaryKey(uid);
    }
}

unless="#result == null"是指当查询为空时,不缓存,默认是空也会缓存。

2.2 添加CacheController

package com.demo.controller;

import com.demo.pojo.UserDetails;
import com.demo.service.CacheService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by toutou on 2019/1/20.
 */
@RestController
@Slf4j
public class CacheController {

    @Autowired
    CacheService cacheService;

    @RequestMapping(value = "/cache/getuserbyid")
    public UserDetails getUserDetailsByUid(int uid){
        try {
            return cacheService.getUserDetailsByUid(uid);
        }catch (Exception e){
            System.out.println(e.toString());
            return null;
        }
    }

    @RequestMapping(value = "/cache/updateuserinfo")
    public int updateUserInfo(int uid, String city){
        UserDetails userDetails = new UserDetails();
        userDetails.setId(uid);
        userDetails.setCity(city);
        userDetails = cacheService.updateUserInfo(userDetails);
        return userDetails == null ? 0 : userDetails.getUid();
    }

    @RequestMapping(value = "/cache/deluserinfobyid")
    public int delUserInfoById(int uid){
        return cacheService.delUserInfoById(uid);
    }
}

2.3 实现Serializable接口

SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用

v效果展示

3.1 Cacheable效果

当我们本地请求http://localhost:8081/cache/getuserbyid?uid=5接口时,可以看到控制台输出Cacheable 有请求过来了,而后续再次请求该接口时,不会再输出Cacheable 有请求过来了,这是因为直接走了缓存机制了,CacheServiceImpl的方法不再被调用。

SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用

通过Redis可以看到,user_details::5的记录已被创建。

SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用

3.2 CachePut效果

当我们本地请求http://localhost:8081/cache/updateuserinfo?uid=5&city=首都 接口时,将更新数据库和Redis中对应的字段值。

SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用

查询接口,更新成功。控制台再次输出Cacheable 有请求过来了

SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用

3.3 CacheEvict效果

当我们本地请求http://localhost:8081/cache/deluserinfobyid?uid=5 接口时,将删除数据中和Redis中的数据。

SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用

v博客总结

Redis和@Cacheable、@CachePut、@CacheEvict结合使用,效果挺好,结合这篇和上篇文章(《SpringBoot(二十四)整合Redis》),可以尝试着结合使用试试。

v源码地址

https://github.com/toutouge/javademosecond/tree/master/hellospringboot


作  者:请叫我头头哥
出  处:http://www.cnblogs.com/toutou/
关于作者:专注于基础平台的项目开发。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是作者坚持原创和持续写作的最大动力!

posted @ 2019-01-20 22:16  请叫我头头哥  阅读(18460)  评论(0编辑  收藏  举报
//Setting ico for cnblogs