【探花交友】SpringCache
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
目录
通用缓存SpringCache
实现缓存逻辑有2种方式
-
每个接口单独控制缓存逻辑
-
统一控制缓存逻辑Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术并支持使用JCacheJSR-107注解简化我们开发
-
Cache接口为缓存的组件规范定义包含缓存的各种操作集合
-
Cache接口下Spring提供了各种xxxCache的实现如RedisCacheEhCacheCache ,ConcurrentMapCache等
-
每次调用需要缓存功能的方法时Spring会检查检查指定参数的指定的目标方法是否已经被调用过如果有就直接从缓存中获取方法调用后的结果如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
-
使用Spring缓存抽象时我们需要关注以下两点
1、确定方法需要被缓存以及他们的缓存策略
2、从缓存中读取之前缓存存储的数据
内部使用AOP的形式对redis操作进行简化
重要概念
名称 | 解释 |
---|---|
@Cacheable | 主要针对方法配置能够根据方法的请求参数对其进行缓存 |
@CacheEvict | 清空缓存 |
入门案例
导入依赖
导入SpringDataRedis的依赖并在application.yml中配置 略
开启缓存支持
然后在启动类注解@EnableCaching开启缓存
@SpringBootApplication
@EnableCaching //开启缓存
public class DemoApplication{
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
编写UserInfoService
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
注解会先查询是否已经有缓存有会使用缓存没有则会执行方法并缓存。
@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
运行会报错观察它们的返回类型原因在于methodName
是String
而methoh
是Method
。
此处的User
实体类一定要实现序列化public class User implements Serializable
否则会报java.io.NotSerializableException
异常。
到这里你已经可以运行程序检验缓存功能是否实现。
清除@CacheEvict
@CachEvict
的作用 主要针对方法配置能够根据一定的条件对缓存进行清空 。
//根据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
@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;
}
发布视频清空缓存
//发布视频
@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);
}