-
Notifications
You must be signed in to change notification settings - Fork 626
Spring Boot中使用Redis实现缓存
sqmax edited this page Jan 1, 2019
·
3 revisions
在大流量的场景下,缓存可以有效地提高数据的读取速度。缓存一般会遇到以下三个概念:
- 命中:指应用程序从cache里获取数据,取到后返回。
- 失效:缓存时间到了,缓存也就失效了。
- 更新:应用程序把数据存到数据库中,再放回缓存里面去。
基于注解实现缓存主要有一下三个注解:
@Cacheable,@CachePut,@CacheEvict
使用缓存时,注意被缓存的对象必须是可序列化的。
下面介绍使用注解实现Redis缓存的的具体过程。
- 在启动类上加注解
@EnableCaching
。
@SpringBootApplication
@EnableCaching
public class SellApplication {
public static void main(String[] args) {
SpringApplication.run(SellApplication.class, args);
}
}
- 在需要缓存的返回给前端数据的Controller方法上
@Cacheable
注解,第一次访问该注解的下的方法时,数据会被缓存,下次再访问该接口时就会直接从缓存中读取。
@GetMapping("/list")
@Cacheable(cacheNames = "product",key = "123")
public ResultVO list(){
//1.查询所有的上架的商品
List<ProductInfo> productInfoList=productService.findUpAll();
//2.查询在架商品所属类目(一次性查询)
// List<Integer> categoryTypeList=new ArrayList<>();
// //传统方法
// for(ProductInfo productInfo: productInfoList){
// categoryTypeList.add(productInfo.getCategoryType());
// }
//精简方法lamba表达式
List<Integer> categoryTypeList=productInfoList.stream()
.map(e->e.getCategoryType()).collect(Collectors.toList());
List<ProductCategory> productCategoryList=categoryService.findByCategoryTypeIn(categoryTypeList);
//3. 数据拼装
List<ProductVO> productVOList=new ArrayList<>();
for(ProductCategory productCategory: productCategoryList){
ProductVO productVO=new ProductVO();
productVO.setCategoryName(productCategory.getCategoryName());
productVO.setCategoryType(productCategory.getCategoryType());
List<ProductInfoVO> productInfoVOList=new ArrayList<>();
for(ProductInfo productInfo: productInfoList){
if(productInfo.getCategoryType().equals(productCategory.getCategoryType())){
ProductInfoVO productInfoVO=new ProductInfoVO();
BeanUtils.copyProperties(productInfo,productInfoVO);
productInfoVOList.add(productInfoVO);
}
}
productVO.setProductInfoVOList(productInfoVOList);
productVOList.add(productVO);
}
// ResultVO resultVO=new ResultVO();
// resultVO.setData(productVOList);
// resultVO.setCode(0);
// resultVO.setMsg("成功");
ResultVO resultVO=ResultVOUtil.success(productVOList);
return resultVO;
}
- 修改该数据的方法上需要加上
@CachePut(cacheNames = "product",key = "123")
注解,每次访问该注解下的方法,返回的数据会被写入redis当中,数据必须是可序列化的。但有时我们的方法返回的不是自定义类型,这时我们可以用@CacheEvict(cacheNames="product",key="123)
注解,访问该注解下的方法之后,redis会把缓存的数据清除掉。如下面修改商品信息的方法必须用@CacheEvict(cacheNames="product",key="123)
注解。
/**
* 保存/更新
* @param form
* @param bindingResult
* @return
*/
@PostMapping("/save")
//@CachePut(cacheNames = "product",key = "123")
@CacheEvict(cacheNames="product",key="123)
public ModelAndView save(@Valid ProductForm form,
BindingResult bindingResult,
Map<String,Object> map){
if(bindingResult.hasErrors()){
map.put("msg",bindingResult.getFieldError().getDefaultMessage());
map.put("url","sell/seller/product/index");
return new ModelAndView("common/error",map);
}
ProductInfo productInfo=new ProductInfo();
try{
//如果productId不为空,说明是已有商品
if(!StringUtils.isEmpty(form.getProductId())){
productInfo=productService.findOne(form.getProductId());
}else{
form.setProductId(KeyUtil.genUniqueKey());
}
BeanUtils.copyProperties(form,productInfo);
productService.save(productInfo);
}catch (SellException e){
map.put("msg",e.getMessage());
map.put("url","/sell/seller/product/index");
return new ModelAndView("common/error",map);
}
map.put("url","/sell/seller/product/list");
return new ModelAndView("common/success",map);
}
如果非要想用@CachePut(cacheNames = "product" ,key = "123")
这个注解,我们可以将注解放到Service方法上,因为Service方法一般返回的都是自定义的实体对象。
注意:key这个参数要写,若不写,key的值就是方法的参数的值。
@Override
@Cacheable(cacheNames = "product",key = "123")
public ProductInfo findOne(String productId) {
return repository.findOne(productId);
}
@Override
@CachePut(cacheNames = "product" ,key = "123")
public ProductInfo save(ProductInfo productInfo) {
return repository.save(productInfo);
}
如果一个类的多个方法cacheNames
这个参数相同,那么可以在该类上加上@CacheConfig
注解,方法上就不必再写该参数了。
@Service
@CacheConfig(cacheNames = "product")
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductInfoRepository repository;
@Override
@Cacheable(key = "1234")
public ProductInfo findOne(String productId) {
return repository.findOne(productId);
}
@Override
@CachePut(key = "1234")
public ProductInfo save(ProductInfo productInfo) {
return repository.save(productInfo);
}
}
注解@Cacheable
的参数key的值可以为SpEL表达式,还可以有condition参数、unless参数,表示缓存的条件。
@Cacheable(cacheNames="product",key="#sellerId,condition="#sellerId.length()>3,unless="#result.getCode()!=0")
public ResultVO list(@RequestParam("sellerId") String sellerId){
......
}
目录