发表于: 2019-12-23 18:48:02

1 1172


一、今天完成的事

1.完成缓存

修改了之前的缓存策略,使用springboot注解的方式配置redis

1.添加依赖

  <!-- 缓存依赖 -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-cache</artifactId>
       </dependency>
       <!-- redis依赖,不引入则默认使用ConcurrenMapCacheManager -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-redis</artifactId>
       </dependency>

2.配置文件

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0
spring.redis.password=
spring.redis.timeout=500ms

spring.cache.type=redis
spring.cache.redis.time-to-live=5000ms

3.在程序中添加注解

   @Override
   @CachePut(value = "wx-video",key = "'videoLike'")
   public VideoLike queryVideoLike(Long vid, Long sid) {
       return wXVideoMapper.queryVideoLike(vid,sid);
   }

   @Override
   @CachePut(value = "wx-video",key = "'videoCollection'")
   public VideoCollection queryVideoCollection(Long vid, Long sid) {
       return wXVideoMapper.queryVideoCollection(vid, sid);
   }

   @Override
   @CachePut(value = "wx-video",key = "'studentId'")
   public Long queryStudentId(String openId) {
       return wXVideoMapper.queryStudentId(openId);
   }
 @Override
   @Cacheable(value = "wx-video",key = "'video'")
   public Video queryVideoById(Long id) {
       return  wXVideoMapper.queryVideoById(id);
   }
/**
    * 获取列表
    *
    * @param start
    * @return
    * @throws Exception
    */
   @GetMapping(value = "/u/videoList")
   @Cacheable(value = "wx-video",key = "'videoList'")
   public PageInfo<Video> getVideoList(@RequestParam(value = "start", defaultValue = "1") int start,
                                        @RequestParam(value = "size", defaultValue = "10") int size,
                                        Video video, String token) throws Exception {
       //获取sid
       WxVideoController wxVideoController = new WxVideoController();
       String openId =  wxVideoController.getIdFromOpenId(token);
       Long sid  = wxVideoService.queryStudentId(openId);
       System.out.println(sid);
       video.setCollection_sid(sid);
       video.setLike_sid(sid);
       PageHelper.startPage(start, size);
       List<Video> videoList = wxVideoService.selectVideoList(video, token);
       return new PageInfo<>(videoList);
   }

/**
    * 收藏
    *
    * @param vid
    * @param key   认证码 1收藏,0取消
    * @param token
    * @return
    */
   @PutMapping(value = "/u/video/updateCollection")
   @CacheEvict(value = "wx-video",allEntries=true)
   public boolean updateCollection(int key, Long vid, String token) throws Exception {
       Video video = wxVideoService.queryVideoById(vid);
       //获取id
       WxVideoController wxVideoController = new WxVideoController();
       String openId = wxVideoController.getIdFromOpenId(token);
       Long sid = wxVideoService.queryStudentId(openId);
       int collections = video.getNumber_of_collections();
       if (key == 1) {
           collections += 1;
           wxVideoService.setVideoCollection(video.getId(), sid);
       } else {
           collections -= 1;
           wxVideoService.delVideoCollection(video.getId(), sid);
       }
       return wxVideoService.setCollection(vid, collections);
   }

   /**
    * 点赞
    *
    * @param vid 视频id
    * @param key 认证码 1 点赞,0取消
    * @return boolen
    */
   @PutMapping(value = "/u/video")
   @CacheEvict(value = "wx-video",allEntries=true)
   public boolean setLike(int key, Long vid, String token) throws Exception {
       Video video = wxVideoService.queryVideoById(vid);
       //获取sid
       WxVideoController wxVideoController = new WxVideoController();
       String openId = wxVideoController.getIdFromOpenId(token);
       Long sid = wxVideoService.queryStudentId(openId);
       int like = video.getNumber_of_likes();
       if (key == 1) {
           like += 1;
           wxVideoService.addVideoLike(video.getId(), sid);
       } else {
           like -= 1;
           wxVideoService.delVideoLike(video.getId(), sid);
       }

       return wxVideoService.setLike(like, vid);
   }

本地压测结果

也可以在redis中查询到缓存的键

二、遇到的问题

三、收获

1.1.1  value属性指定Cache名称        value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。    1.1.2  使用key属性自定义key

@Cacheable("cache1")//Cache是发生在cache1上的
  public User find(Integer id) {
     returnnull;
  }
 @Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的
  public User find(Integer id) {
     returnnull;
  }

 1.1.2  使用key属性自定义key

  key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。我们这里先来看看自定义策略,至于默认策略会在后文单独介绍。    自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。下面是几个使用参数作为key的示例。

  • /**

    * key 是指传入时的参数
     *
     */
      @Cacheable(value="users", key="#id")
      public User find(Integer id) {
         returnnull;
      }
     // 表示第一个参数
     @Cacheable(value="users", key="#p0")
      public User find(Integer id) {
         returnnull;
      }
     // 表示User中的id值
      @Cacheable(value="users", key="#user.id")
      public User find(User user) {
         returnnull;
      }
      // 表示第一个参数里的id属性值
      @Cacheable(value="users", key="#p0.id")
      public User find(User user) {
         returnnull;
      }

除了上述使用方法参数作为key之外,Spring还为我们提供了一个root对象可以用来生成key。通过该root对象我们可以获取到以下信息。

当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。如:

  // key值为: user中的name属性的值
 @Cacheable(value={"users", "xxx"}, key="caches[1].name")
  public User find(User user) {
     returnnull;
  }

1.1.3  condition属性指定发生的条件 有的时候我们可能并不希望缓存一个方法所有的返回结果。通过condition属性可以实现这一功能。condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。如下示例表示只有当user的id为偶数时才会进行缓存。

    // 根据条件判断是否缓存
   @Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
  public User find(User user) {
     System.out.println("find user by user " + user);
     return user;
  }

1.2     @CachePut        在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。  //@CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟@Cacheable是一样的。    @CachePut("users")//每次都会执行方法,并将结果存入指定的缓存中    public User find(Integer id) {       returnnull;    }  1.3     @CacheEvict        @CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。下面我们来介绍一下新出现的两个属性allEntries和beforeInvocation。

1.3.1  allEntries属性       allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。

   @CacheEvict(value="users", allEntries=true)
  public void delete(Integer id) {
     System.out.println("delete user by id: " + id);
  }

1.3.2  beforeInvocation属性        清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

   @CacheEvict(value="users", beforeInvocation=true)
  public void delete(Integer id) {
     System.out.println("delete user by id: " + id);
  }

       其实除了使用@CacheEvict清除缓存元素外,当我们使用Ehcache作为实现时,我们也可以配置Ehcache自身的驱除策略,其是通过Ehcache的配置文件来指定的。由于Ehcache不是本文描述的重点,这里就不多赘述了,想了解更多关于Ehcache的信息,请查看我关于Ehcache的专栏。

1.4     @Caching

@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。


  @Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),
  @CacheEvict(value = "cache3", allEntries = true) })
  public User find(Integer id) {
     returnnull;
  }

1.5     使用自定义注解        Spring允许我们在配置可缓存的方法时使用自定义的注解,前提是自定义的注解上必须使用对应的注解进行标注。如我们有如下这么一个使用@Cacheable进行标注的自定义注解。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Cacheable(value="users")
public @interface MyCacheable {
}

      那么在我们需要缓存的方法上使用@MyCacheable进行标注也可以达到同样的效果。

   @MyCacheable
  public User findById(Integer id) {
     System.out.println("find user by id: " + id);
     User user = new User();
     user.setId(id);
     user.setName("Name" + id);
     return user;
  }
  • value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个

    例如:

    @Cacheable(value=”mycache”)

    @Cacheable(value={”cache1”,”cache2”}

  • key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合

    @Cacheable(value=”testcache”,key=”#userName”)

  • condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 @Cacheable(value=”testcache”,condition=”#userName.length()>2”)

四、明天的计划

把其他程序也做缓存



返回列表 返回列表
评论

    分享到