【探花交友】SpringCache

目录

通用缓存SpringCache

重要概念

导入依赖

开启缓存支持

编写UserInfoService

缓存@Cacheable

发布视频清空缓存

通用缓存SpringCache

实现缓存逻辑有2种方式:

  1. 每个接口单独控制缓存逻辑

  2. 统一控制缓存逻辑Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术;并支持使用JCache(JSR-107)注解简化我们开发;

  • Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;

  • Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache ,ConcurrentMapCache等;

  • 每次调用需要缓存功能的方法时,Spring会检查检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。

  • 使用Spring缓存抽象时我们需要关注以下两点;

    1、确定方法需要被缓存以及他们的缓存策略

    2、从缓存中读取之前缓存存储的数据

内部使用AOP的形式,对redis操作进行简化

重要概念

名称 解释
@Cacheable 主要针对方法配置,能够根据方法的请求参数对其进行缓存
@CacheEvict 清空缓存

入门案例

导入依赖

导入SpringDataRedis的依赖,并在application.yml中配置 (略)

开启缓存支持

然后在启动类注解@EnableCaching开启缓存

java 复制代码
@SpringBootApplication
@EnableCaching  //开启缓存
public class DemoApplication{
 
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

编写UserInfoService

java 复制代码
package com.tanhua.server.test;

import com.tanhua.domain.db.UserInfo;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserInfoService {

    //根据id查询
    public UserInfo queryById(Long userId) {
        //从数据库查询
        UserInfo user = new UserInfo();
        user.setId(userId);
        user.setNickname("ceshi");
        return user;
    }

    //根据id修改
    public void update(Long userId) {
        UserInfo user = new UserInfo();
        user.setId(userId);
        user.setNickname("itcast");
    }
}

缓存@Cacheable

@Cacheable注解会先查询是否已经有缓存,有会使用缓存,没有则会执行方法并缓存。

java 复制代码
@Cacheable(value = "user",key = "#userId")
public UserInfo queryById(Long userId) {
    //从数据库查询
    UserInfo user = new UserInfo();
    user.setId(userId);
    user.setNickname("ceshi");
    return user;
}

此处的value是必需的,它指定了你的缓存存放在哪块命名空间。

此处的key是使用的spEL表达式,参考上章。这里有一个小坑,如果你把methodName换成method运行会报错,观察它们的返回类型,原因在于methodNameStringmethohMethod

此处的User实体类一定要实现序列化public class User implements Serializable,否则会报java.io.NotSerializableException异常。

到这里,你已经可以运行程序检验缓存功能是否实现。

清除@CacheEvict

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空 。

java 复制代码
//根据id修改
@CacheEvict(value = "user",key = "#userId")
public void update(Long userId) {
    //修改用户
    UserInfo user = new UserInfo();
    user.setId(userId);
    user.setNickname("itcast");
}

视频列表缓存处理

修改VideoService,分页列表存入缓存,发布视频删除缓存

由于使用Reids缓存处理数据时,不能缓存ResponseEntity对象,所以需要修改方法返回值为

PageResult

java 复制代码
@Cacheable(value="videoList",key="#page + '_' +  #pagesize")
public PageResult queryVideoList(Integer page, Integer pagesize) {
    //1、调用API查询 : PageReulst<Video>
    PageResult result = videoApi.findAll(page,pagesize);
    //2、获取分页中的list集合  List<Video>
    List<Video> items = (List<Video>)result.getItems();
    //3、循环视频列表,一个Video构造一个Vo
    List<VideoVo> list = new ArrayList<>();
    for (Video item : items) {
        UserInfo userInfo = userInfoApi.findById(item.getUserId());
        VideoVo vo = VideoVo.init(userInfo, item);
        //从redis中获取,当前用户是否已经关注了视频发布作者
        String key = "followUser_"+UserHolder.getUserId()+"_"+item.getUserId();
        if (redisTemplate.hasKey(key)) {
            vo.setHasFocus(1);
        }
        list.add(vo);
    }
    //4、替换result中的item数据
    result.setItems(list);
    //5、构造返回值
    result;
}

发布视频清空缓存

java 复制代码
//发布视频
@CacheEvict(value="videoList",allEntries = true)
public ResponseEntity saveVideo(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
    //1、图片上传到阿里云oss,获取请求地址
    String picUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
    //2、视频上传到fdfs上,获取请求地址
    String filename = videoFile.getOriginalFilename(); //xxxx.avi
    //获取文件后缀
    String sufix = filename.substring(filename.lastIndexOf(".")+1);

    StorePath storePath = client.uploadFile(videoFile.getInputStream(),
                                            videoFile.getSize(), sufix, null); //文件输入流,文件长度(大小),文件的后缀名,元数据(null)
    String videoUrl = webServer.getWebServerUrl() + storePath.getFullPath();
    //3、构建Video对象,并设置属性
    Video video = new Video();
    video.setPicUrl(picUrl);
    video.setVideoUrl(videoUrl);
    video.setText("传智播客是一个负责任的教育机构~"); //客户端未传递,手动模拟
    video.setUserId(UserHolder.getUserId());
    //4、调用api保存
    videoApi.save(video);
    //5、构建返回值
    return ResponseEntity.ok(null);
}
相关推荐
考虑考虑7 小时前
Jpa使用union all
java·spring boot·后端
用户3721574261358 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊9 小时前
Java学习第22天 - 云原生与容器化
java
渣哥10 小时前
原来 Java 里线程安全集合有这么多种
java
间彧10 小时前
Spring Boot集成Spring Security完整指南
java
间彧11 小时前
Spring Secutiy基本原理及工作流程
java
Java水解12 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆14 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学14 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole14 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端