注解方式使用redis缓存

5 篇文章 0 订阅

参考:
Redis详解 - SpringBoot整合Redis,RedisTemplate和注解两种方式的使用
springboot注解方式使用redis缓存
以注解的方式使用redis缓存得用法@CachePut , @CacheEvict, @Cacheable

第一步:引入依赖

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--此处引用了jedis,版本号啥的没写www-->
<dependency>
 <groupId>redis.clients</groupId>
 <artifactId>jedis</artifactId>
</dependency>


第二步:在启动类加注解@EnableCaching

@SpringBootApplication
@EnableCaching//这里!!
@MapperScan()//这是mybatis-plus扫描的地方

public class SellApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(SellApplication.class, args);
    }
}

有关@EnableCaching请看SpringBoot启动类@SpringBootApplication注解及执行流程



第三步:Spring配置(springboot不需要这不(应该)(反正找的博客用springboot的没有,应该也许自动装配了))
(1)启用缓存注解功能

<cache:annotation-driven cache-manager=“SpringRedisCacheManager"/>

注:注解在controller中使用就配置在springMVC配置文件中,service中使用就配置在spring的配置文件中
(2)配置Redis连接信息
在这里插入图片描述
Properties配置文件:
在这里插入图片描述
(3)配置ObjectMapper ,注入SpringDataRedis和RedisCacheManager:
在这里插入图片描述



第四步:代码中使用注解

常见注解

  • @Cacheable:用于查询和添加缓存,第一次查询时候返回该方法返回值,并向Redis服务器保存数据
  • 属性如图:
    -在这里插入图片描述

以后调用该方法先从 Redis 中查是否有数据,如果有直接返回 Redis 缓存的数据,而不执行方法里的代码。如果没有则正常执行方法体中的代码。

valuecacheNames 属性做键,key 属性则可以看作为 value 的子键, 一个 value 可以有多个 key 组成不同值存在 Redis 服务器。

验证了下,value 和 cacheNames 的作用是一样的,都是标识主键。
两个属性不能同时定义,只能定义一个,否则会报错。

condition 和 unless 是条件 后面会讲用法。


  • @CachePut:更新 Redis 中对应键的值。属性和 @Cacheable 相同

  • @CacheEvict:删除 Redis 中对应键的值。


添加缓存

在需要加缓存的方法上添加注解 @Cacheable(cacheNames = "product", key = "123"),

cacheNames 和 key 都必须填,如果不填 key ,默认的 key 是当前的方法名,更新缓存时会因为方法名不同而更新失败。

如在订单列表上加缓存

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @Cacheable(cacheNames = "product", key = "123")
    public ResultVO list() {
 
        // 1.查询所有上架商品
        List<ProductInfo> productInfoList = productInfoService.findUpAll();
 
        // 2.查询类目(一次性查询)
        //用 java8 的特性获取到上架商品的所有类型
        List<Integer> categoryTypes = productInfoList.stream().map(e -> e.getCategoryType()).collect(Collectors.toList());
        List<ProductCategory> productCategoryList = categoryService.findByCategoryTypeIn(categoryTypes);
 
        List<ProductVO> productVOList = new ArrayList<>();
        //数据拼装
        for (ProductCategory category : productCategoryList) {
            ProductVO productVO = new ProductVO();
            //属性拷贝
            BeanUtils.copyProperties(category, productVO);
            //把类型匹配的商品添加进去
            List<ProductInfoVO> productInfoVOList = new ArrayList<>();
            for (ProductInfo productInfo : productInfoList) {
                if (productInfo.getCategoryType().equals(category.getCategoryType())) {
                    ProductInfoVO productInfoVO = new ProductInfoVO();
                    BeanUtils.copyProperties(productInfo, productInfoVO);
                    productInfoVOList.add(productInfoVO);
                }
            }
            productVO.setProductInfoVOList(productInfoVOList);
            productVOList.add(productVO);
        }
 
        return ResultVOUtils.success(productVOList);
    }

报错:

java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.imooc.VO.ResultVO]
 
Hibernate: select productcat0_.category_id as category1_2_, productcat0_.category_name as category2_2_, productcat0_.category_type as category3_2_, productcat0_.create_time as create_t4_2_, productcat0_.update_time as update_t5_2_ from product_category productcat0_ 
	arializationRedisSerializer.java:91)
	at org.springframework.data.redis.cache.RedisCache$CacheValueAccessor.convertToBytesIfNecessary(RedisCache.java:471)

解决错误的办法就是加序列化public class ResultVO<T> implements Serializable,让对象实现 Serializable 方法

@Data
public class ProductVO implements Serializable {
    
    private static final long serialVersionUID = 961235512220891746L;
 
    @JsonProperty("name")
    private String categoryName;
 
    @JsonProperty("type")
    private Integer categoryType;
 
    @JsonProperty("foods")
    private List<ProductInfoVO> productInfoVOList ;
}

然后再类里面生成ID,需要用到一下这个插件,在idea里下载,重启即可
在这里插入图片描述
重启项目访问订单列表,在 rdm 里查看 Redis 缓存,有 product::123 说明缓存成功。
在这里插入图片描述

但是这里有一个很严重的问题,你把数据库的信息改了,然后刷新页面,还是原来的数据,这就是因为缓存的原因,所以我们给save更新的方法也要加个更新的处理, 接口方式。
更新缓存
在需要更新缓存的方法上加注解:

 @CachePut(cacheNames = "prodcut", key = "123")

注意:

cacheNames 和 key 要跟 @Cacheable() 里的一致,才会正确更新。> @CachePut() 和@Cacheable() 注解的方法返回值要一致

删除缓存
在需要删除缓存的方法上加注解:@CacheEvict(cacheNames = "prodcut", key = "123"),执行完这个方法之后会将 Redis 中对应的记录删除。



其他常用功能

  • cacheNames 也可以统一写在类上面, @CacheConfig(cacheNames = "product") ,具体的方法上就不用写啦。
@CacheConfig(cacheNames = "product")
public class BuyerOrderController {
    @PostMapping("/cancel")
    @CachePut(key = "456")
    public ResultVO cancel(@RequestParam("openid") String openid,
                           @RequestParam("orderId") String orderId){
        buyerService.cancelOrder(openid, orderId);
        return ResultVOUtils.success();
    }
}

  • Key 也可以动态设置为方法的参数
@GetMapping("/detail")
@Cacheable(cacheNames = "prodcut", key = "#openid")
public ResultVO<OrderDTO> detail(@RequestParam("openid") String openid,
                             @RequestParam("orderId") String orderId){
    OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
    return ResultVOUtils.success(orderDTO);
}

如果参数是个对象,也可以设置对象的某个属性为 key。比如其中一个参数是 user 对象,key 可以写成 key="#user.id"


  • 缓存还可以设置条件

设置当 openid 的长度大于3时才缓存

@GetMapping("/detail")
@Cacheable(cacheNames = "prodcut", key = "#openid", condition = "#openid.length > 3")
public ResultVO<OrderDTO> detail(@RequestParam("openid") String openid,
                                 @RequestParam("orderId") String orderId){
    OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
    return ResultVOUtils.success(orderDTO);
}

还可以指定 unless 即条件不成立时缓存。#result 代表返回值,意思是当返回码不等于 0 时不缓存,也就是等于 0 时才缓存。

 
@GetMapping("/detail")
@Cacheable(cacheNames = "prodcut", key = "#openid", condition = "#openid.length > 3", unless = "#result.code != 0")
public ResultVO<OrderDTO> detail(@RequestParam("openid") String openid,
                                 @RequestParam("orderId") String orderId){
    OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
    return ResultVOUtils.success(orderDTO);
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值