@Cacheable缓存相关使用总结

本篇文章主要讲解Spring当中@Cacheable缓存相关使用

在实际项目开发中,有些数据是变更频率比较低,但是查询频率比较高的,此时为了提升系统性能,可以使用缓存的机制实现,避免每次从数据库获取

第一步:使用@EnableCaching注解开启缓存

开启缓存功能,配置类中需要加上这个注解,有了这个注解之后,spring才知道你需要使用缓存的功能,其他和缓存相关的注解才会有效,Spring中主要是通过aop实现的,通过aop来拦截需要使用缓存的方法,实现缓存的功能

第二步:在方法或类上添加@Cacheable注解,表明某一个方法或者某一个类里的所有方法开启缓存功能;
@Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。

对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略,需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的(因为是Aop实现的,Aop是核心是代理,内部调用无法被代理,也就不会生效)。@Cacheable可以指定三个属性,value、key和condition。

测试相关的类如下:ArticleService主要是提供模拟缓存的接口

package com.ym.example.demo.cachable;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Component;

import java.util.*;


@Component
public class ArticleService {
   private Map<Long, String> articleMap = new HashMap<>();

   @Cacheable(cacheNames = {"cacheTest"})
   public List<String> list(){
      System.out.println("获取文章列表");
      return Arrays.asList("Spring", "MySQL", "java高并发", "Maven");
   }

   @Cacheable(value = {"cacheTest"})
   public List<String> listValue(){
      System.out.println("获取文章列表");
      return Arrays.asList("Spring", "MySQL", "java高并发", "Maven");
   }

   /**
   * @Author yangming
   * @Description
    * @Cacheable可以标记在方法上,也可以标记在一个类上,当标记在一个方法上是,表示该方法时支持缓存的,当标记到一个类上时,则表示该类所有的方法都是支持缓存的
    * 对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。
    * Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略
    * 这里需要注意,因为Spring缓存是通过aop实现的,aop又是依赖的代理模式,所以当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的
    * value和cacheNames一样,都是指定缓存的名称,这个cache名称可以是一个,也可以是多个,需要指定多个cache时其是一个数组
    * 可以将Cache理解为一个HashMap,系统中可以有很多歌Cache,每个Cache都有一个名字,你需要将方法的返回值放在哪个缓存中,需要通过缓存的名称来指定
    * key属性用来指定Spring缓存方法的返回结果时对应的key,因为Cache可以理解为一个HashMap,缓存以key-value的形式存储在HashMap中,value就是需要缓存的值(即方法返回值)
    * key属性支持spel表达式,当我们没有指定该属性时,Spring将使用默认策略生成key(org.springframework.cache.interceptor.SimpleKeyGenerator),默认会以方法参数创建key
    * 自定义策略是指我们可以通过SpEL表达式来指定我们的key,这里的SpEL表达式可以使用方法参数及他们对应的属性,使用方法参数时我们可以直接使用"#参数名"或者"#p参数index"
    * Spring还未我们提供了一个root对象可以用来生成key,通过该root对象我们可以获取到以下信息
    * methodName  当前方法名                #root.methodName
    * method      当前方法                  #root.method.name
    * target      当前被调用的对象            #root.target
    * targetClass 当前被调用的对象的class     #root.targetClass
    * args        当前方法参数组成的数组       #root.args[0]
    * caches      当前被调用的方法使用的cache  #root.caches[0].name
    *
   * @Date 2023/8/12 10:36
   * @param page
   * @param pageSize
   **/
   @Cacheable(value = {"cacheTest"}, key = "#root.target.class.name+'-'+#page+'-'+#pageSize")
   public String getPage(int page, int pageSize){
      String msg = String.format("page-%s-pageSize-%s", page, pageSize);
      System.out.println("从db中获取数据: " + msg);
      return msg;
   }

   /**
   * @Author yangming
   * @Description 没有指定key。默认为方法参数创建key,该方法的key为SimpleKey [1,10]
   * @Date 2023/8/12 10:55
   * @param page
   * @param pageSize
   **/
   @Cacheable(value = {"cacheTest"})
   public String getPageKey(int page, int pageSize){
      String msg = String.format("page-%s-pageSize-%s", page, pageSize);
      System.out.println("从db中获取数据: " + msg);
      return msg;
   }

   /**
    * @Author yangming
    * @Description 没有指定key。默认为方法参数创建key,该方法的key为SimpleKey []
    * @Date 2023/8/12 10:55
    **/
   @Cacheable(value = {"cacheTest"})
   public String getPageKey(){
      String msg = "测试key";
      System.out.println("从db中获取数据: " + msg);
      return msg;
   }

   /**
   * @Author yangming
   * @Description 有时候希望方法调用走缓存,有时候不希望走缓存,condition为true表示先尝试从缓存中取,如果缓存中没有,则执行方法,并将方法返回结果放到缓存中,
    *             condition为false表示不走缓存,直接执行方法,并且返回的结果也不会放到缓存中
   * @Date 2023/8/11 19:39
   * @param id
   * @param cache
   **/
   @Cacheable(cacheNames = "cacheTest", key="'getById'+#id", condition = "#cache")
   public String getById(Long id, boolean cache){
      System.out.println("getById获取数据!");
      return "Spring缓存: " + UUID.randomUUID().toString();
   }

   /**
   * @Author yangming
   * @Description 当condition为空或者为true的情况下,unless才有效,condition为false的时候,unless无效,
    *             unless为true,表示方法防结果不放到缓存中,unless为false,表示方法返回结果要放到缓存中
    * condition和unless对比
    * 缓存的使用过程中有两个点:
    * 1、查询缓存中是否有数据;
    * 2、如果缓存中没有数据,则去执行目标方法,然后将方法结果放到缓存中
    * Spring中通过condition和unless对这2点进行干预
    * condition作用在上面2个点的过程中,当为true的时候,会尝试从缓存中获取数据,如果没有,会执行方法,然后将方法返回值丢到缓存中;
    *                               当为false的时候,则直接调用目标方法,并且结果不会放到缓存中
    * unless在condition为true的时候才有效,用来判断上面的第2点,看要不要将执行结果放到缓存中,
    *                               如果为true,表示执行的结果不放到缓存中,
    *                               如果为false,表示执行的结果要放到缓存中,在unless中可以使用spel表达式通过#result来获取方法返回值
   * @Date 2023/8/11 19:50
   * @param id
   **/
   @Cacheable(cacheNames = "cacheTest", key = "'findById'+#id", unless = "#result==null")
   public String findById(Long id){
      this.articleMap.put(1L, "Spring系列");
      System.out.println("-----获取文章: " + id + "-------");
      return this.articleMap.get(id);
   }

/**
   * @Author yangming
   * @Description @CachePut也可以标注在类或者方法上,被标注的方法每次都会被调用,然后方法执行完毕之后,会将方法结果放到缓存中;当标注在类上,相当于在类的所有方法上都标注了@CachePut
    * @CachePut有3种情况,结果不会放到缓存
    * 1、当方法向外抛出异常的时候
    * 2、当condition的计算结果为false的时候
    * 3、unless的计算结果为true的时候
    * value,cacheNames,key,condition,unless的用法和@Cacheable中类似
   * @Date 2023/8/12 11:05
   * @param id
   * @param content
   **/
   @CachePut(cacheNames = "cacheTest", key = "'findById'+#id")
   public String add(Long id, String content){
      System.out.println("新增文章: " + id);
      this.articleMap.put(id, content);
      return content;
   }

   /**
   * @Author yangming
   * @Description @CacheEvict是用来清除缓存的,可以标注在类或者方法上,被标注在方法上,则目标方法被调用的时候,会清除指定的缓存;当标注在类上,相当于在类的所有方法上标注了@CacheEvict
   * value,cacheNames,key,condition的用法和@Cacheable中类似,@CacheEvict多了allEntries和beforeInvocation属性
    * allEntries:表示是否清理cacheNames指定的缓存中的所有缓存信息,默认为false
    *             可以将cache理解为一个HashMap,当allEntries为true的时候,相当于HashMap.clear(),
    *             当allEntries为false的时候,只会干掉key对应的数据,相当于HashMap.remove(key)
    * beforeInvocation:表示何时执行清除操作(方法执行前 or 方法执行成功之后)
    *              true:表示@CacheEvict 标注的方法执行之前,执行清除操作
    *              false:表示@CacheEvict 标注的方法执行成功之后,执行清除操作,当方法弹出异常的时候,不会执行清除操作
   * @Date 2023/8/12 11:25
   * @param id
   **/
   @CacheEvict(cacheNames = "cacheTest", key = "'findById'+#id")
   public void delete(Long id){
      System.out.println("根据id删除文章: " + id);
      this.articleMap.remove(id);
   }

   @Caching(cacheable = {@Cacheable(value = "cacheTest", key="#root.methodName")},
           put={@CachePut(value = "cacheTest", key = "#root.methodName")})
   public void testCaching(){

   }
}

CacheConfig提供缓存相关的配置,这个CacheMangager有多种实现,本例是使用的ConcurrentMapCacheManager实现,也可以是RedisCacheManager的实现

package com.ym.example.demo.cachable;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author yangming
 * @date 2023/8/11 19:24
 * @desc @EnableCaching表示开启缓存,有了这个注解之后,Spring才知道你需要使用缓存的功能,其他和缓存相关的注解才会生效
 *       Spring中主要是通过aop实现的,通过aop来拦截需要使用缓存的方法,实现缓存的功能
 * @package com.ym.example.demo.cachable
 */
@EnableCaching
@ComponentScan
@Configuration
public class CacheConfig {

   /**
   * @Author yangming
   * @Description 开启缓存之后,还需要在配置类中定义一个bean,作为缓存管理器,类型为CacheManager,
    *             CacheManager是一个接口,有好几个实现,比如使用redis,ConcurrentMap为存储缓存信息,
    *             本例使用的是ConcurrentMapCacheManager,内部使用ConcurrentHashMap将缓存信息直接存储在本地jvm内存中
    *             不过线上环境一般是集群的方式,可以通过redis实现
   * @Date 2023/8/12 10:45
   **/
   @Bean
   public CacheManager cacheManager(){
      ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager("cacheTest");
      return cacheManager;
   }
}

CacheTest是测试相关的方法

package com.ym.example.demo.cachable;

import org.junit.Test;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author yangming
 * @date 2023/8/11 19:26
 * @package com.ym.example.demo.cachable
 */
public class CacheTest {

   @Test
   public void test(){
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      context.register(CacheConfig.class);
      context.refresh();;
      ArticleService articleService = context.getBean(ArticleService.class);
      System.out.println(articleService.list());
      System.out.println(articleService.list());
   }

    执行结果:
    获取文章列表
    [Spring, MySQL, java高并发, Maven]
    [Spring, MySQL, java高并发, Maven]


   @Test
   public void test1(){
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      context.register(CacheConfig.class);
      context.refresh();;
      ArticleService articleService = context.getBean(ArticleService.class);
      //page=1,pageSize=10调用2次
      System.out.println(articleService.getPage(2, 10));
      System.out.println(articleService.getPage(2, 10));

      //page=2,pageSize=10调用2次
      System.out.println(articleService.getPage(3, 10));
      System.out.println(articleService.getPage(3, 10));

      {
         System.out.println("下面打印出cacheTest缓存中的key列表");
         ConcurrentMapCacheManager cacheManager = context.getBean(ConcurrentMapCacheManager.class);
         ConcurrentMapCache cacheTest = (ConcurrentMapCache) cacheManager.getCache("cacheTest");
         cacheTest.getNativeCache().keySet().stream().forEach(System.out::println);
      }
   }

    执行结果:
    从db中获取数据: page-2-pageSize-10
    page-2-pageSize-10
    page-2-pageSize-10
    从db中获取数据: page-3-pageSize-10
    page-3-pageSize-10
    page-3-pageSize-10
    下面打印出cacheTest缓存中的key列表
    com.ym.example.demo.cachable.ArticleService-3-10
    com.ym.example.demo.cachable.ArticleService-2-10


   @Test
   public void test2(){
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      context.register(CacheConfig.class);
      context.refresh();;
      ArticleService articleService = context.getBean(ArticleService.class);

      //第一次,缓存中没有,执行方法,将结果放到缓存
      System.out.println(articleService.getById(1L, true));
      //第二次,缓存中有,直接从缓存中获取
      System.out.println(articleService.getById(1L, true));
      //第三次,condition为false,表示不从缓存取,直接执行方法,同时方法执行结果也不放到缓存
      System.out.println(articleService.getById(1L, false));
      //第四次,condition为true,缓存有,直接从缓存中取
      System.out.println(articleService.getById(1L, true));
   }

    执行结果:
    getById获取数据!
    Spring缓存: 1df6227d-53ae-46a6-9a70-a85e32e39f08
    Spring缓存: 1df6227d-53ae-46a6-9a70-a85e32e39f08
    getById获取数据!
    Spring缓存: 7ff6c668-87f1-4432-8844-61bf66b6e3ef
    Spring缓存: 1df6227d-53ae-46a6-9a70-a85e32e39f08



   @Test
   public void test3(){
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      context.register(CacheConfig.class);
      context.refresh();;
      ArticleService articleService = context.getBean(ArticleService.class);

      //第一次,没有缓存,执行方法,unless为false,表示执行结果要放到缓存中
      System.out.println(articleService.findById(1L));
      //第二次,第一次之后,缓存有数据,直接从缓存中取数据
      System.out.println(articleService.findById(1L));
      //第三次,缓存中没有,执行方法,result==null,unless为true,表示执行结果不放到缓存中
      System.out.println(articleService.findById(2L));
      //第四次,为了验证第三次的结论
      System.out.println(articleService.findById(2L));

      {
         System.out.println("下面打印出cacheTest缓存中的key列表");
         ConcurrentMapCacheManager cacheManager = context.getBean(ConcurrentMapCacheManager.class);
         ConcurrentMapCache cacheTest = (ConcurrentMapCache) cacheManager.getCache("cacheTest");
         cacheTest.getNativeCache().keySet().stream().forEach(System.out::println);
      }
   }

    执行结果:
    -----获取文章: 1-------
    Spring系列
    Spring系列
    -----获取文章: 2-------
    null
    -----获取文章: 2-------
    null
    下面打印出cacheTest缓存中的key列表
    findById1


   @Test
   public void test4(){
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      context.register(CacheConfig.class);
      context.refresh();;
      ArticleService articleService = context.getBean(ArticleService.class);

      articleService.getPageKey(1,10);
      articleService.getPageKey();

      {
         System.out.println("下面打印出cacheTest缓存中的key列表");
         ConcurrentMapCacheManager cacheManager = context.getBean(ConcurrentMapCacheManager.class);
         ConcurrentMapCache cacheTest = (ConcurrentMapCache) cacheManager.getCache("cacheTest");
         cacheTest.getNativeCache().keySet().stream().forEach(System.out::println);
      }
   }
    
    执行结果:
    从db中获取数据: page-1-pageSize-10
    从db中获取数据: 测试key
    下面打印出cacheTest缓存中的key列表
    SimpleKey []
    SimpleKey [1,10]



   @Test
   public void test5(){
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      context.register(CacheConfig.class);
      context.refresh();;
      ArticleService articleService = context.getBean(ArticleService.class);

      //增加2个文章,由于add方法上有@CachePut注解,所以新增之后会自动丢到缓存中
      articleService.add(1L, "java高并发系列");
      articleService.add(2L, "MySQL高手系列");

      //然后调用findById获取,看看是否会走缓存
      System.out.println("调用findById方法,会尝试从缓存中获取");
      System.out.println(articleService.findById(1L));
      System.out.println(articleService.findById(2L));

      {
         System.out.println("下面打印出cacheTest缓存中的key列表");
         ConcurrentMapCacheManager cacheManager = context.getBean(ConcurrentMapCacheManager.class);
         ConcurrentMapCache cacheTest = (ConcurrentMapCache) cacheManager.getCache("cacheTest");
         cacheTest.getNativeCache().keySet().stream().forEach(System.out::println);
      }
   }

    执行结果:
    新增文章: 1
    新增文章: 2
    调用findById方法,会尝试从缓存中获取
    java高并发系列
    MySQL高手系列
    下面打印出cacheTest缓存中的key列表
    findById2
    findById1


   @Test
   public void test6(){
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      context.register(CacheConfig.class);
      context.refresh();;
      ArticleService articleService = context.getBean(ArticleService.class);

      //第一次调用findById,缓存中没有,则调用方法,将结果丢到缓存中
      System.out.println(articleService.findById(1L));
      //第二次调用findById,缓存存在,直接从缓存中取
      System.out.println(articleService.findById(1L));

      //执行删除操作,delete方法上加了@CacheEvict注解,会清除缓存
      articleService.delete(1L);

      //再次调用findById方法,缓存中没有了,则会调用目标方法
      System.out.println(articleService.findById(1L));
   }

    执行结果:
    -----获取文章: 1-------
    Spring系列
    Spring系列
    根据id删除文章: 1
    -----获取文章: 1-------
    Spring系列
}

@Caching:缓存注解组
当我们在类上或者同一个方法上同时使用@Cacheable、@CachePut和@CacheEvic这几个注解中的多个的时候,此时可以使用@Caching这个注解来实现
 

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Caching {
Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};
}

@CacheConfig:提取公共配置
这个注解标注在类上,可以将其他几个缓存注解(@Cacheable、@CachePut和@CacheEvic)的公共参数给提取出来放在@CacheConfig中。比如当一个类中有很多方法都需要使用(@Cacheable、@CachePut和@CacheEvic)这些缓存注解的时候,大家可以看一下这3个注解的源码,他们有很多公共的属性,比如:cacheNames、keyGenerator、cacheManager、cacheResolver,若这些属性值都是一样的,可以将其提取出来,放在@CacheConfig中,不过这些注解(@Cacheable、@CachePut和@CacheEvic)中也可以指定属性的值对@CacheConfig中的属性值进行覆盖。

@CacheConfig(cacheNames = "cache1")
public class ArticleService {
    @Cacheable(key = "'findById'+#id")
    public String findById(Long id) {
        this.articleMap.put(1L, "spring系列");
        System.out.println("----获取文章:" + id);
        return articleMap.get(id);
    }
}

spring中的缓存主要是利用spring中aop实现的,通过Aop对需要使用缓存的bean创建代理对象,通过代理对象拦截目标方法的执行,实现缓存功能。重点在于 @EnableCaching 这个注解,可以从 @Import 这个注解看起
 

@Import(CachingConfigurationSelector.class)
public @interface EnableCaching {

}

最终会给需要使用缓存的bean创建代理对象,并且会在代理中添加一个拦截器
org.springframework.cache.interceptor.CacheInterceptor ,这个类中的 invoke 方法是关键,
会拦截所有缓存相关的目标方法的执行,有兴趣可以去细看一下。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/71848.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代驾小程序怎么做

代驾小程序是一款专门为用户提供代驾服务的手机应用程序。它具有以下功能&#xff1a; 1. 预约代驾&#xff1a;代驾小程序允许用户在需要代驾服务时提前进行预约。用户可以选择出发地点、目的地以及预计用车时间&#xff0c;系统会自动匹配最合适的代驾司机&#xff0c;并确保…

构建之法 - 软件工程实践教学:一线教师的13问

福州大学单红老师的软工课程总结 2020春&#xff0c;不一样的学期不一样的软工实践 单红⽼师在总结中&#xff0c;提出了13条疑惑&#xff0c;《构建之法》的作者邹欣⽼师就单红⽼师提出的每⼀条疑惑&#xff0c;给出了⾃⼰的思考&#xff0c;与他进⾏探讨交流。欢迎你也来参与…

ThinkPHP8命名规范-ThinkPHP8知识详解

本文主要讲解thinkphp8的命名规范&#xff0c;主要包括&#xff1a;遵循PHP自身的PSR-2命名规范和PSR-4自动加载规范、目录和文件命名规范、函数和类、属性命名规范、常量和配置命名规范、数据表和字段命名规范、不能使用PHP保留字。 在使用thinkphp8开发项目之前&#xff0c;…

pyspark笔记 pyspark.sql.functions

col qqpyspark 笔记 pyspark.sql.function col VS select_UQI-LIUWJ的博客-CSDN博客 取某一列 lit 创建一个包含指定值的列 date_trunc 将日期截取成由第一个参数指定的字符串值 year, yyyy, yy——截取到年month,mon,mm——截取到月day,dd ——截取到天microsecondmillis…

学习左耳听风栏目90天——第六天 6/90(学习左耳朵耗子的工匠精神,对技术的热爱)【如何拥有技术领导力】

学习左耳听风栏目90天——第六天 6/90&#xff08;学习左耳朵耗子的工匠精神&#xff0c;对技术的热爱&#xff09;【如何拥有技术领导力】

项目介绍:《WeTalk》网页聊天室 — Spring Boot、MyBatis、MySQL和WebSocket的奇妙融合

目录 引言&#xff1a; 前言&#xff1a; 技术栈&#xff1a; 主要功能&#xff1a; 功能详解&#xff1a; 1. 用户注册与登录&#xff1a; 2. 添加好友 3. 实时聊天 4. 消息未读 5. 删除聊天记录 6. 删除好友 未来展望&#xff1a; 项目地址&#xff1a; 结语&am…

预测算法|改进粒子群算法优化极限学习机IDM-PSO-ELM

回归拟合&#xff1a; 分类 本文是作者的预测算法系列的第四篇&#xff0c;前面的文章中介绍了BP、SVM、RF及其优化&#xff0c;感兴趣的读者可以在作者往期文章中了解&#xff0c;这一篇将介绍——极限学习机 过去的几十年里基于梯度的学习方法被广泛用于训练神经网络&am…

[gdc]Rendering ‘God of War Ragnark‘

gdc23&#xff0c; sony santa monica关于god of war的分享&#xff1b; back ground 作者stephen mcauley现在是santa monica的technical director&#xff1b;20年加入santa monica&#xff0c;作为rendering lead&#xff0c;有9年的经验&#xff0c;之前在ubisoft montre…

zookeeperAPI操作与写数据原理

要执行API操作需要在idea中创建maven项目 &#xff08;改成自己的阿里仓库&#xff09;导入特定依赖 添加日志文件 上边操作做成后就可以进行一些API的实现了 目录 导入maven依赖&#xff1a; 创建日志文件&#xff1a; 创建API客户端&#xff1a; &#xff08;1&#xff09…

【uniapp】uniapp自动导入自定义组件和设置分包:

文章目录 一、自动导入自定义组件&#xff1a;二、设置分包和预加载&#xff1a; 一、自动导入自定义组件&#xff1a; 【Volar 官网】https://github.com/vuejs/language-tools 二、设置分包和预加载&#xff1a; 【官方文档】https://uniapp.dcloud.net.cn/collocation…

android开发之Android 自定义滑动解锁View

自定义滑动解锁View 需求如下&#xff1a; 近期需要做一个类似屏幕滑动解锁的功能&#xff0c;右划开始&#xff0c;左划暂停。 需求效果图如下 实现效果展示 自定义view如下 /** Desc 自定义滑动解锁View Author ZY Mail sunnyfor98gmail.com Date 2021/5/17 11:52 *…

开发工具Eclipse的使用之导入项目(import)

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Eclipse使用的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.导读 二.详细操作步骤 1.右击项…

【深度学习】StyleGANv2 2019 论文,Analyzing and Improving the Image Quality of StyleGAN

StyleGAN论文&#xff1a; 《A Style-Based Generator Architecture for Generative Adversarial Networks》 论文&#xff1a;https://arxiv.org/abs/1812.04948 代码&#xff1a; https://github.com/NVlabs/stylegan StyleGANv2论文&#xff1a; 《Analyzing and Improving …

电池的正极是带正电?

首先说明结论&#xff1a;电池正极带正电&#xff0c;负极带负电。 一个错误的实例&#xff1a; 如果说电流是从电池正极流动到电池负极&#xff0c;那么电子就是从负极流动到正极&#xff0c;那么正极就是带负电。----这个说法是错误的。这是因为&#xff0c;根据那么很出名…

简绘ChatGPT支持Midjourney绘图 支持stable diffusion绘图

简绘支持Midjourney绘图和stable diffusion绘图。 这意味着简绘具备Midjourney绘图和stable diffusion绘图功能的支持。

无涯教程-Perl - redo函数

描述 此函数将重新启动当前循环,而不会强制判断控制语句。块中不再执行任何语句。如果存在继续块,将不会执行。如果指定了LABEL,则在LABEL标识的循环开始时重新开始执行。 语法 以下是此函数的简单语法- redo LABELredo返回值 此函数不返回任何值。 例 以下是显示其基本…

Shell编程之条件测试、if语句、case语句

条件语句 一、条件测试1.1 测试命令1.1 文件测试1.2 整数比较1.3 字符串比较1.4 逻辑测试1.4.1 逻辑与 &&1.4.2 逻辑或 || 1.4.3 组合应用1.5 多个命令组合执行 ( ) { } 二、if语句2.1单分支结构2.2 多分支结构2.4 if语句练习2.4.1 单分支2.4.2 简单的交互式分数反馈 三…

元宇宙核能发电VR模拟仿真实训教学为建设新型电力系统提供重要支撑

随着“碳达峰、碳中和”目标与建设新型能源体系的提出&#xff0c;在元宇宙环境下建设电力系统是未来发展的趋势。以物联网、区块链、数字孪生、混合现实等技术为主要代表的元宇宙技术体系及其在电力和能源系统中的应用&#xff0c;将会促进智能电网的发展&#xff0c;为建设新…

VR安全宣传系列:防触电虚拟现实体验

在电气工作中&#xff0c;安全问题始终是重中之重。为了更好地提高公众的电气安全意识和技能&#xff0c;广州华锐互动开发了一种基于虚拟现实技术的模拟系统——VR防触电虚拟体验系统。这种系统可以模拟各种因操作不当导致的触电事故场景&#xff0c;并提供沉浸式的体验&#…

利用OpenSSL实现私有 CA 搭建和证书颁发

利用OpenSSL实现私有 CA 搭建和证书颁发 一、私有 CA 搭建1. 安装openssl2. 配置 openssl3. 生成 CA 自己的私钥4. 生成 CA 自己的自签证书5. 验证自签证书 二、向私有CA申请证书流程1. 生成应用私钥文件2. 根据应用私钥生成证书申请文件3. 向CA请求颁发证书4. 验证应用证书5. …
最新文章