一,Spring Cache介绍
- Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
- Spring Cache提供了一层抽象,底层刻意切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。
- CacheManager是Spring提供的各种缓存技术抽象接口。
- 针对不同的缓存技术需要实现不同的CacheManager
- CacheManager通过阅读底层源码不难发现其实是由Map进行实现的缓存,将数据保存在内存中(项目重启数据会清除)
CacheManaer | 描述 |
EhCacheCacheManager | 使用EhCache作为缓存技术 |
GuavaCacheManager | 使用Google的GuavaCache作为缓存技术 |
RedisCacheManager |
使用Redis作为缓存技术 |
二,Spring Cache常用注解
注解 | 说明 |
@EnableCaching | 开启缓存注解功能 |
@Cacheable |
在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓数据;若没有数据,调用方法将方法返回值放到缓存中 |
@CachePut | 将方法的返回值放到缓存中 |
@CacheEvict | 将一条或多条数据从缓存中删除 |
在spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术依赖包,并在启动类上使用@EnableCaching开启缓存支持即可
例如,使用Redis作为缓存技术,只需要导入Spring data Redis的maven坐标即可。
//例1,(将方法的返回值放到缓存中)
@CachePut(value = "userCache",key = "#user.id") //key的值是user的id
@PostMapping
public User save(User user){
userService.save(user);
return user;
}
CachePut: 将方法的返回值放入缓存
value: 缓存的名称,每个缓存名称下面可以有多个key
key:缓存的key
//例2,(将一条或多条数据从缓存中删除)
//首先这个有三种写法
//1,@CacheEvict(value = "userCache",key = "#id")
//2,@CacheEvict(value = "userCache",key = "#root.args[0]")
//3,@CacheEvict(value = "userCache",key = "#p0")
@CacheEvict(value = "userCache",key = "#id")
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id){
userService.removeById(id);
}
//例3,@Cacheable(在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓数据;若没有数据,调用方法将方法返回值放到缓存中)
//@Cacheable(value = "dish",key = "'dish_'+#dish.getCategoryId()+ '_'+ #dish.getStatus()",unless= "#result == null")
@Cacheable(value = "userCache",key = "#id",unless= "#result == null")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
User user = userService.getById(id);
return user;
}
condition :条件,当不为空时候才会去缓存
unless:当条件成立的时候是不缓存
以上是Spring Cache的简单应用,下面将结合项目进行分享!
1.引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2.yml配置
#Redis相关配置
redis:
host: 127.0.0.1
port: 6379
database: 0 #默认有十六个数据库
#Redis连接池配置
jedis:
pool:
max-active: 8 #最大连接数
max-wait: 1ms #连接池最大阻塞等待时间
max-idle: 4 #连接池中的最大空闲连接
min-idle: 0 #连接池中的最小空闲连接
#设置缓存有效期
cache:
redis:
time-to-live: 18000000
基于注解进行实现的缓存,将数据缓存到Redis中
@Service
@Slf4j
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
@Autowired
private SetmealMapper setmealMapper;
@Autowired
private SetmealDishMapper setmealDishMapper;
@Autowired
CacheManager cacheManager;
@Override
@Cacheable(value = "list",key = "'setmeal'+#setmealBo.categoryId+'_'+#setmealBo.Status")
public R<List<Setmeal>> list(SetmealBo setmealBo) {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq(setmealBo.getCategoryId() != null, "category_id", setmealBo.getCategoryId())
.eq(setmealBo.getStatus() != null, "status", setmealBo.getStatus()).orderByDesc("create_time");
try {
List list = setmealMapper.selectList(queryWrapper);
return R.success(list);
} catch (Exception e) {
e.printStackTrace();
return R.error("查询失败!");
}
}
}
到此总结一下可能会出现的问题:
问题:DefaultSerializer 需要一个可序列化的有效负载,但收到了一个 [model.Admin] 类型的对象
解决:这个问题是因为实体类没有实现 Serializable 进行序列化,加上即可
@Data
public class R<T> implements Serializable {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
private Map map = new HashMap(); //动态数据
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
public static <T> R<T> error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R<T> add(String key, Object value) {
this.map.put(key, value);
return this;
}
}
补充:
@CacheEvict(value = "list",allEntries = true)
根据value值删除所有缓存值
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/105083.html