10.实体类
package com.learning.cache.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 学生类
*/
@Data
// 要实现Serializable接口,否则会报错
public class Student implements Serializable {
private String id;
private String name;
private Integer age;
}
2.2 value属性与cacheNames属性
2.2.1 单个缓存代码示例
package com.learning.cache.service.impl;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
// com:learning:cache会作为redis的key的一部分
@Cacheable(value="com:learning:cache:list")
@Override
public List list() {
return studentDao.selectList(null);
}
}
2.2.2 单个缓存效果截图

2.2.3 多个缓存代码示例
package com.learning.cache.service.impl;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
// 多个值,会将方法的返回结果存入到不同的缓存key中
@Cacheable(value={"com:learning:cache:list","cn:learning:cache:list"})
@Override
public List list() {
return studentDao.selectList(null);
}
}
2.2.4 多个缓存效果截图

2.3 key属性
2.3.1 方法没有参数示例
package com.learning.cache.service.impl;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Cacheable(value={"com:learning:cache:list"})
@Override
public List list() {
return studentDao.selectList(null);
}
}
2.3.2 方法没有参数截图

2.3.3 方法有一个参数示例
package com.learning.cache.service.impl;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
// String id 一个参数的key情况
@Cacheable(value={"com:learning:cache:one"})
@Override
public Student getById(String id) {
return studentDao.selectById(id);
}
}
2.3.4 方法有一个参数截图

2.3.5 方法有多个参数示例
package com.learning.cache.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Cacheable(value={"com:learning:cache:more"})
@Override
public Page page(int size, int current) {
Page page = new Page<>();
page.setCurrent(current);
page.setSize(size);
return studentDao.selectPage(page, null);
}
}
2.3.6 方法有多个参数截图

2.3.7 指定key(从参数中指定)
package com.learning.cache.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Cacheable(value="com:learning:cache:one", key="#id")
@Override
public Student getById(String id) {
return studentDao.selectById(id);
}
}
2.3.8 指定key截图

2.4 keyGenerator属性
2.4.1 自定义key生成器代码示例
package com.learning.cache.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Cacheable(value="com:learning:cache:one", keyGenerator="customKeyGenerator")
@Override
public Student getById(String id) {
return studentDao.selectById(id);
}
}
package com.learning.cache.config;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Method;
import java.sql.Statement;
import java.util.Arrays;
import java.util.UUID;
/**
* @Description 自定义Key生成器
*/
@Configuration
public class KeyGeneratorConfig {
@Bean("customKeyGenerator")
public KeyGenerator keyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
return method.getName() + Arrays.asList(objects).toString() + UUID.randomUUID();
}
};
}
}
2.4.2 自定义key生成器截图

2.5 cacheResolver属性
2.5.1 自定义cacheResolver缓存解析器代码示例
package com.learning.cache.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Cacheable(value="com:learning:cache:one",key="#id", cacheResolver="customCacheResolver")
@Override
public Student getById(String id) {
return studentDao.selectById(id);
}
}
package com.learning.cache.resolver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.*;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import java.lang.reflect.Method;
import java.util.Collection;
/**
* @Description 自定义缓存解析器
*/
@Slf4j
public class CustomCacheResolver extends SimpleCacheResolver {
public CustomCacheResolver(CacheManager cacheManager) {
super(cacheManager);
}
@Override
public Collection extends Cache> resolveCaches(CacheOperationInvocationContext> context) {
// 拿到缓存
Collection extends Cache> caches = super.resolveCaches(context);
Object target = context.getTarget();
BasicOperation operation = context.getOperation();
Method method = context.getMethod();
Object[] args = context.getArgs();
ParameterNameDiscoverer paramNameDiscoverer = new DefaultParameterNameDiscoverer();
EvaluationContext evaluationContext = new MethodBasedEvaluationContext(context.getOperation(), context.getMethod(), context.getArgs(), paramNameDiscoverer);
Expression expression = (new SpelExpressionParser()).parseExpression(((CacheableOperation) context.getOperation()).getKey());
// 获取所有的缓存的名字
context.getOperation().getCacheNames().forEach(cacheName -> {
log.info("缓存的name:{}", cacheName);
String key = cacheName + ':' + expression.getValue(evaluationContext, String.class);
log.info("缓存的key全路径:{}", key);
});
// 返回缓存
return caches;
}
}
2.5.2 自定义cacheResolver缓存解析器截图


2.6 condition属性
2.6.1 指定条件进行缓存代码示例
package com.learning.cache.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
// 指定id为1的可以缓存
@Cacheable(value="com:learning:cache:one", condition = "#id eq '1'")
@Override
public Student getById(String id) {
return studentDao.selectById(id);
}
}
2.6.2 指定条件进行缓存截图


2.7 unless属性
2.7.1 指定条件不进行缓存代码示例
package com.learning.cache.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
// 对查询结果为null的不做缓存,去掉的话会缓存空值
@Cacheable(value="com:learning:cache:one", unless = "#result == null")
@Override
public Student getById(String id) {
return studentDao.selectById(id);
}
}
2.7.2 结果为null的缓存截图

2.8 allEntries属性
2.8.1 清除全部缓存代码示例
package com.learning.cache.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.learning.cache.dao.StudentDao;
import com.learning.cache.entity.Student;
import com.learning.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description 学生服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
@Cacheable(value="com:learning:cache:one")
@Override
public Student getById(String id) {
return studentDao.selectById(id);
}
@CacheEvict(value="com:learning:cache:one", allEntries = true)
@Override
public boolean delete(String id) {
int result = studentDao.deleteById(id);
if(result > 0){
return true;
}
return false;
}
}
2.8.2 先查2次缓存起来,然后删除1条,清除所有截图





三、注意事项
- 1.@CacheEvict注解测试的时候尽量调接口测试,不要用页面去触发,例如修改某条数据,清除分页数据缓存,修改完成后页面有可能会再次调用分页接口,导致分页的@Cableable仍然缓存,造成@CacheEvict失效的假象