一文掌握SpringBoot注解之@Cacheable 知识文集(1)

news2025/1/26 11:32:22

在这里插入图片描述

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。
🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。
🎉欢迎 👍点赞✍评论⭐收藏

🔎 SpringBoot 领域知识 🔎

链接专栏
SpringBoot 专业知识学习一SpringBoot专栏
SpringBoot 专业知识学习二SpringBoot专栏
SpringBoot 专业知识学习三SpringBoot专栏
SpringBoot 专业知识学习四SpringBoot专栏
SpringBoot 专业知识学习五SpringBoot专栏
SpringBoot 专业知识学习六SpringBoot专栏
SpringBoot 专业知识学习七SpringBoot专栏
SpringBoot 专业知识学习八SpringBoot专栏
SpringBoot 专业知识学习九SpringBoot专栏
SpringBoot 专业知识学习十SpringBoot专栏
SpringBoot 专业知识学习十一SpringBoot专栏
SpringBoot 专业知识学习十二SpringBoot专栏
SpringBoot 专业知识学习十三SpringBoot专栏

文章目录

    • 🔎 Java 注解 @Cacheable 学习(1)
      • 🍁 01. 什么是 @Cacheable 注解?有什么作用?
      • 🍁 02. 如何在 Spring Boot 应用中使用 @Cacheable 注解实现缓存功能?
      • 🍁 03. @Cacheable 注解的实现原理是什么?
      • 🍁 04. 如何避免缓存击穿?如何避免缓存雪崩?
      • 🍁 05. @Cacheable 注解的 key 属性是干什么用的?
      • 🍁 06. @Cacheable 注解的 value 属性是干什么用的?
      • 🍁 07. 可以在 @Cacheable 注解中使用 SpEL 表达式吗?如何使用?
      • 🍁 08. @Cacheable 注解的 condition 属性是用来干什么的?
      • 🍁 09. @Cacheable 注解的 sync 属性是干什么用的?
      • 🍁 10. 是否可以动态修改 @Cacheable 注解中的 key 属性?


🔎 Java 注解 @Cacheable 学习(1)

在这里插入图片描述


🍁 01. 什么是 @Cacheable 注解?有什么作用?

@Cacheable 注解是 Spring 框架提供的一个注解,用于实现方法级别的缓存功能。当方法被调用时,@Cacheable 注解会首先在缓存中查找相应的值,而不是执行方法的逻辑。如果找到了缓存中的值,则直接返回该值给调用方,而不执行方法体;如果缓存中不存在该值,则执行方法的逻辑,并将方法的返回值存储到缓存中,以供下次的调用使用。

@Cacheable 注解可以应用于公共方法,用于缓存方法的返回值,避免重复的计算或查询操作,提高系统的性能和响应速度。它基于键值对的形式存储和获取数据,通过指定缓存的名称、缓存的键以及可选的条件,可以进行有效的缓存管理。

例如,以下是一个使用 @Cacheable 注解的示例:

@Service
public class UserService {
  
  @Cacheable("users")
  public User getUserById(long userId) {
      // 从数据库查询用户
      // ...
      return user;
  }
}

在上述示例中,方法 getUserById() 使用了 @Cacheable 注解,并指定了缓存的名称为 “users”。当方法被调用时,Spring 会先检查缓存中是否存在键为 userId 的用户对象,如果存在,则直接从缓存中取出并返回;如果不存在,则执行方法的逻辑,从数据库中查询用户,并将查询结果放入缓存中。

通过使用 @Cacheable 注解,可以避免重复查询数据库的开销,提高系统的性能和响应速度。同时,@Cacheable 注解还提供了丰富的缓存管理功能,可以设置缓存的过期时间、条件判断等,以满足不同的业务需求。

@Cacheable 注解的主要作用是实现方法级别的缓存,可以有效地提高系统的性能、降低数据库等资源的压力,并提升响应速度和用户体验。具体来说,它可以帮助我们避免以下问题:

1.减少重复查询的开销:如果多次调用同一个方法,但是方法的参数相同,那么每次调用都会执行查询操作。通过使用缓存,并在第一次调用之后将返回值存储在缓存中,可以避免重复查询的开销,提高系统的性能和响应速度。

2.缓解数据库等资源的压力:当系统的访问量较大时,如果每次访问都直接查询数据库等资源,会对系统的性能和稳定性造成很大的影响,甚至可能导致崩溃。通过使用缓存,并将查询结果存储在缓存中,可以有效地缓解数据库等资源的压力,提高系统的可用性和稳定性。

3.提升用户体验:用户在访问网站或使用应用时,通常希望能够快速地获取数据并获得反馈。通过使用缓存,并在第一次访问之后将数据存储在缓存中,可以提升用户的体验,减少用户等待的时间。

除了上述作用之外,@Cacheable 注解还具有其它的优点,例如**易于实现、易于维护、可扩展性强**等。在实际开发中,我们可以根据具体业务需求,灵活地使用 @Cacheable 注解,来实现缓存功能,提升系统的性能和响应速度。


🍁 02. 如何在 Spring Boot 应用中使用 @Cacheable 注解实现缓存功能?

在 Spring Boot 应用中,使用 @Cacheable 注解实现缓存功能非常简单。以下是基本步骤:

1.添加相关依赖

在 pom.xml 配置文件中添加 Spring Boot Cache、JCache 和 Ehcache 依赖:

<dependencies>
    <!-- Spring Boot Cache 相关依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.cache</groupId>
        <artifactId>cache-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.ehcache</groupId>
        <artifactId>ehcache</artifactId>
    </dependency>
</dependencies>

2.配置缓存

在 application.properties 或 application.yml 配置文件中配置缓存相关的属性,例如缓存名称、缓存类型、过期时间等:

# 配置基于 Ehcache 的缓存
spring.cache.type=ehcache

# 配置缓存名称
spring.cache.cache-names=users

# 配置缓存过期时间,单位为秒
spring.cache.ehcache.config=classpath:ehcache.xml

上述配置说明:

  • spring.cache.type:指定使用的缓存类型,可以是 simpleehcache 等。这里使用了 ehcache
  • spring.cache.cache-names:指定缓存的名称,可以是一个或多个。
  • spring.cache.ehcache.config:指定 Ehcache 的配置文件路径。

3.标记需要缓存的方法

在需要缓存的方法上添加 @Cacheable 注解,并指定缓存的名称和键:

@Service
public class UserService {
  
    @Cacheable(value = "users", key = "#userId")
    public User getUserById(long userId) {
        // 从数据库查询用户
        // ...
        return user;
    }
}

上述代码说明:

  • @Cacheable(value = "users", key = "#userId"):指定了缓存名称为 users,缓存键为方法的参数 userId。这样,当该方法被调用时,Spring 会首先在缓存中查找键为 userId 的缓存,如果找到了,则直接返回缓存中的值;如果没有找到,则执行方法的逻辑,并将方法的返回值存储在缓存中,以备后续使用。

至此,我们就已经完成了在 Spring Boot 应用中使用 @Cacheable 注解实现缓存功能的步骤。使用 @Cacheable 注解可以简单几步实现缓存功能,并提高应用的性能和响应速度,是进行缓存优化的一种常见方式。


🍁 03. @Cacheable 注解的实现原理是什么?

@Cacheable 注解的实现原理是基于 AOP(面向切面编程)技术。在 Spring 中,我们可以使用 AOP 对方法进行增强,例如在方法执行前后/异常时,执行额外的逻辑。而使用 @Cacheable 注解,则是在被注解的方法执行前,先检查是否存在缓存。若存在,直接返回缓存中的结果;若不存在,则运行方法,并将结果缓存起来。

具体来说,当使用 @Cacheable 注解标注方法时,Spring AOP 会切入该方法并触发一个切点(Pointcut),进而执行缓存逻辑,这个切面类叫做 CacheInterceptor。 CacheInterceptor 类包含了 CacheManager 和 Cache 对象,它根据给定的缓存名从 CacheManager 中获取缓存。如果缓存名对应的 Cache 对象不存在,则创建新的 Cache 对象,并将其添加到 CacheManager 中。接着,CacheInterceptor 类会检查缓存中是否已经存在给定的键对应的 Entry(实际数据存储在内部的 Entry 中),如果存在,则直接返回缓存中保存的数据;否则,方法会被执行,并且方法的返回值将被添加到缓存中。

总体来说,@Cacheable 注解的实现原理可以概括如下:

1.当方法被调用时,检查 Cache 中是否已经存在指定的缓存键。

2.如果缓存存在,则直接从缓存中获取结果并返回。方法体中的实际逻辑不会执行。

3.如果缓存不存在,则执行方法体中的逻辑,并将结果保存至缓存中。

4.当下一次执行缓存相同的方法时,自动使用缓存中存储的数据,避免了重复执行逻辑,并提高了方法的执行效率。

需要注意的是,在缓存的实现过程中,会涉及到缓存的清除、更新等操作,因此,缓存的实现不是那么简单的。在实际场景中,还需要结合使用 @CachePut 和 @CacheEvict 等注解来实现完整的缓存机制。


🍁 04. 如何避免缓存击穿?如何避免缓存雪崩?

**缓存击穿**是指当一个非常热门的缓存键失效时,同时有大量的请求涌入数据库或其他后端系统,导致系统负载过高,甚至引发服务不可用的情况。为了避免缓存击穿,可以考虑以下几种策略:

1.设置适当的过期时间和预加载:为缓存设置适当的过期时间,避免缓存无限期存储,并考虑在缓存过期之前提前预加载数据,以确保缓存数据的实时性。

2.使用互斥锁(Mutex Lock):当缓存键失效时,在查询后端系统之前,使用互斥锁来保证只有一个线程能够查询后端并更新缓存,其他线程等待并共享结果。

3.基于布隆过滤器进行缓存穿透预防:使用布隆过滤器在缓存层面进行简单的校验,过滤掉那些根本不存在于后端系统的请求,减轻数据库负载。

4.异步更新缓存:当缓存键失效时,不阻塞请求并直接返回旧的缓存数据,然后使用后台任务异步更新缓存,提高请求的响应速度。

5.搭建分布式缓存:将缓存分布到多个节点上,避免单一缓存节点失效导致的缓存击穿问题,并且可以通过负载均衡策略来分散请求。

6.合理设置缓存容量:合理估计缓存容量,根据实际需求设置缓存容量大小,避免大规模缓存失效导致的负载问题。

**缓存雪崩**是指当大量缓存数据在同一时间内过期或者失效时,大量的请求涌入数据库或者后端系统,导致系统负载过高,可能会引发服务不可用的情况。为了避免缓存雪崩,可以考虑以下几种策略:

1.设置随机的缓存失效时间:不同的缓存数据设置不同的过期时间,避免所有缓存数据在同一时间内过期导致缓存雪崩。

2.采用热点数据预加载策略:在系统运行期间,统计出热点数据并预先加载到缓存中,确保热点数据在缓存中存在而不是在同一时间内全部失效。

3.采用缓存数据持久化策略:除了缓存,系统还可以在本地或者远端存储备份数据。当缓存失效后,可以从备份数据中加载,避免缓存雪崩的影响。

4.控制缓存数据的并发更新:为缓存数据设置互斥锁,避免多个请求并发更新导致数据库负载过高。

5.使用多级缓存:在系统中,使用 多级缓存(例如:一级缓存、二级缓存、三级缓存等)的方式来降低热点数据单一缓存失效对整个系统造成的冲击。


🍁 05. @Cacheable 注解的 key 属性是干什么用的?

@Cacheable 注解是 Spring 框架提供的缓存注解之一,用于将方法的返回结果缓存在缓存中,下次相同的方法调用时可以直接从缓存中获取结果,而不需要再执行方法体。

@Cacheable 注解的 key 属性用于指定缓存的键(key),该键用于唯一标识缓存中存储的数据。在使用 @Cacheable 注解时,Spring 会根据指定的键来查找缓存中是否存在对应的数据,如果存在则直接返回缓存中的数据,而不会执行被注解的方法。

key 属性支持 SpEL(Spring Expression Language)表达式,这样可以根据方法的参数、返回值等信息动态地生成缓存键。通过 SpEL 表达式,可以根据具体的业务需求来构建唯一的键,以确保不同的方法调用可以在缓存中正确地区分开来。

例如,假设有一个通过用户 ID 查询用户信息的方法,可以使用 @Cacheable 注解,并将用户 ID 作为 key 属性的一部分,以便将用户信息缓存在不同的缓存键中,如:

@Cacheable(value = "userCache", key = "'user:' + #userId")
public User getUserById(String userId) {
    // ...
    // 查询用户信息的具体逻辑
    // ...
}

在上述示例中,key = "'user:' + #userId" 指定了缓存的键为以字符串 'user:'为前缀,后面拼接上参数 #userId 的值。这样不同的用户 ID 将会生成不同的缓存键,确保查询结果被正确地缓存和获取。

请注意,SpEL 表达式中的 #userId 表示方法参数 userId 的值。您可以根据实际情况来构建适合的缓存键,以满足具体的业务需求。


🍁 06. @Cacheable 注解的 value 属性是干什么用的?

@Cacheable 注解是 Spring 框架提供的缓存注解之一,用于将方法的返回结果缓存在缓存中。其中,value 属性用于指定缓存的名称。可以通过 value 属性设置成一个字符串类型的值,并在 @Cacheable 中用作缓存的名称。

在 Spring Boot 应用中,可以使用 @CacheConfig 注解或在配置文件中配置 spring.cache.cache-names 属性来设置多个缓存。当使用多个缓存时,可以通过 @Cacheable 注解的 value 属性来指定相应的缓存名称。例如:

@Cacheable(value = "userCache")
public User getUserById(String userId) {
    // ...
    // 查询用户信息的具体逻辑
    // ...
}

在上述示例中,@Cacheable(value = "userCache") 指定了缓存的名称为 userCache。这个名称在应用中必须是唯一的,用于标识不同的缓存实例。

请注意,value 属性接受一个字符串类型的值,可自定义。它不是指缓存的实际数据,而是表示缓存实例的名称。因此,应该为每个缓存实例选择一个明确的名称便于维护和管理。

如果没有指定 value 属性,则会使用默认的缓存名称。在 Spring Boot 中,默认的缓存名称为 simple,如果 @Cacheable 注解中没有指定其他名称,则数据会被存储在名为 simple 的缓存中。


🍁 07. 可以在 @Cacheable 注解中使用 SpEL 表达式吗?如何使用?

@Cacheable 注解支持使用 SpEL(Spring Expression Language)表达式来配置缓存。

在 @Cacheable 注解中使用 SpEL 表达式的方式是在 key 属性或 condition 属性中使用。通过 SpEL 表达式,可以根据方法的参数、返回值等信息动态地生成缓存键(key)或者控制缓存的条件。

1.使用 SpEL 表达式生成缓存键

@Cacheable(value = "userCache", key = "'user:' + #userId")
public User getUserById(String userId) {
    // ...
    // 查询用户信息的具体逻辑
    // ...
}

在上述示例中,key = "'user:' + #userId" 表达式通过拼接字符串 'user:' 和方法参数 #userId 的值来生成缓存键。

2.使用 SpEL 表达式控制缓存条件

@Cacheable(value = "userCache", condition = "#result != null")
public User getUserById(String userId) {
    // ...
    // 查询用户信息的具体逻辑
    // ...
}

在上述示例中,condition = "#result != null" 表达式表示只有方法的返回值不为 null 时才会进行缓存。如果结果为 null,那么不会将结果缓存起来。

使用 SpEL 表达式可以根据具体的业务需求来动态地配置缓存。可以根据方法的参数、返回值、调用对象等信息来生成或者控制缓存的键和条件。

需要注意的是,SpEL 表达式必须放在单引号(')或者双引号(")中,并且要以 # 开头,以表示占位符。在表达式中,可以使用方法的参数名、返回值名、调用对象名等表示所需的信息。

当在 @Cacheable 注解中使用 SpEL 表达式时,可以使用如下常用的变量和方法:

  1. 方法参数:使用 #参数名 的形式表示方法的参数值。例如,#userId 表示方法的参数 userId 的值。

  2. 返回值:使用 #result 表示方法的返回值。可以在 condition 属性中使用该变量来控制缓存的条件。

  3. 注解属性:可以使用 @注解名.属性名 的形式获取注解的属性值。

  4. 类名和方法名:可以使用 #root.targetClass 获取目标类的类对象,使用 #root.methodName 获取方法名。

  5. 执行上下文:可以使用 #root.args 获取方法的所有参数数组,使用 #root.caches 获取所有相匹配的缓存实例。

下面是一个示例,展示如何在 @Cacheable 注解中使用 SpEL 表达式:

@Cacheable(value = "userCache", key = "'user:' + #userId", condition = "#result != null")
public User getUserById(String userId) {
    // ...
    // 查询用户信息的具体逻辑
    // ...
}

在上述示例中,使用了三个 SpEL 表达式:

  • key = "'user:' + #userId":通过拼接字符串 'user:' 和方法参数 #userId 的值来生成缓存键。
  • condition = "#result != null":只有方法的返回值不为 null 时才会进行缓存。

除了上述示例中的用法,还可以根据具体的业务需求来使用其他的 SpEL 表达式来配置缓存。可以参考 SpEL 表达式语法和 Spring 框架文档来了解更多用法和限制。


🍁 08. @Cacheable 注解的 condition 属性是用来干什么的?

@Cacheable 注解的 condition 属性用于控制是否执行方法的缓存逻辑,即是否将方法的结果放入缓存中。

通过在 condition 属性中设置一个 SpEL(Spring Expression Language)表达式,可以根据方法的返回值、参数等条件来决定是否进行缓存。只有在满足条件的情况下,才会将方法的返回值缓存起来。

条件表达式的计算结果应该是一个布尔值(true 或 false)。如果计算结果为 true,则将方法的返回值进行缓存;如果计算结果为 false,则不会进行缓存。

以下是一个使用 condition 属性的示例:

@Cacheable(value = "userCache", condition = "#result != null")
public User getUserById(String userId) {
    // ...
    // 查询用户信息的具体逻辑
    // ...
}

在上述示例中,condition = "#result != null" 表达式表示只有方法的返回值不为 null 时才会进行缓存。如果结果为 null,那么不会将结果缓存起来。

condition 属性可以根据具体的业务需求来进行灵活配置。可以使用 SpEL 表达式根据方法的返回值、参数、调用对象等信息来定义缓存的条件。

使用 condition 属性可以帮助在缓存中避免存储无效或无意义的数据。通过根据条件动态地控制缓存的逻辑,可以确保缓存中只包含有效的数据。这可以提升缓存的效率和可靠性,以及减少对缓存的占用和维护成本。


🍁 09. @Cacheable 注解的 sync 属性是干什么用的?

@Cacheable 注解的 sync 属性用于控制是否启用同步模式来保证并发安全。

sync 属性设置为 true 时,表示启用同步模式。在同一时间内,只允许一个线程执行带有 @Cacheable 注解的方法,其他线程将会被阻塞,直到缓存操作完成并返回结果。

默认情况下,sync 属性的值为 false,即不启用同步模式。在多线程并发访问的情况下,如果有多个线程同时触发了带有 @Cacheable 注解的方法,那么这些线程会并发地执行方法,并且会将结果缓存起来。这可能会导致并发安全问题,例如重复缓存相同的数据,浪费资源等。

使用同步模式可以确保在进行缓存操作时只有一个线程执行,从而避免并发安全问题。但同时也会带来一定的性能开销和响应时间延迟,因为其他线程需要等待同步锁的释放才能继续执行。

下面是一个示例,展示如何在 @Cacheable 注解中使用 sync 属性:

@Cacheable(value = "userCache", sync = true)
public User getUserById(String userId) {
    // ...
    // 查询用户信息的具体逻辑
    // ...
}

在上述示例中,通过设置 sync = true 启用同步模式。当多个线程同时触发 getUserById 方法时,只会允许一个线程执行方法并进行缓存操作,其他线程将被阻塞。

需要注意的是,在并发访问下启用同步模式可能会降低性能。因此,需要根据具体的业务需求和场景来综合考虑是否需要启用同步模式。

当使用 @Cacheable 注解的 sync 属性时,需要注意以下几点:

  1. 并发安全性:启用同步模式可以确保在并发访问时只有一个线程执行方法并进行缓存操作,从而避免并发安全问题。这对于一些读写操作都需要加锁的场景可能是必要的。

  2. 性能影响:启用同步模式会导致其他线程在缓存操作期间被阻塞,直到方法返回结果。这可能会增加响应时间延迟,并降低系统的吞吐量。因此,需要根据具体情况评估并发性能与应用的要求。

  3. 缓存一致性:启用同步模式可以确保缓存的一致性,因为只有一个线程执行缓存操作。但在某些情况下,例如对于读多写少的场景,可以使用异步缓存来提高并发性能,而牺牲一些缓存的一致性。

  4. 其他缓存注解:@CachePut@CacheEvict 注解不支持 sync 属性。@CachePut 注解用于更新缓存中的数据,而 @CacheEvict 注解用于移除缓存中的数据。在这两种情况下,是否启用同步模式取决于使用场景和并发要求。

需要根据具体的业务需求和并发场景来决定是否使用 @Cacheable 注解的 sync 属性。如果需要保证并发安全性,并且可以接受一些性能开销,那么启用同步模式可能是一个不错的选择。否则,可以根据应用的实际情况来选择是否启用同步模式。


🍁 10. 是否可以动态修改 @Cacheable 注解中的 key 属性?

@Cacheable 注解中的 key 属性用于定义缓存的键,它通常是由一个或多个属性值组合而成的字符串。这个字符串在执行缓存操作时起到了唯一标识一个缓存实体的作用。

通常情况下,@Cacheable 注解中的 key 属性会在编写代码时预先定义好,难以在运行时对其进行修改。但是,Spring 提供了一些动态缓存的解决方案,可以在运行时动态生成或修改缓存的键,以满足特定的业务需求。

下面介绍几种常见的动态缓存方案:

1.SpEL 表达式:在 @Cacheable 注解中使用 SpEL 表达式,可以根据方法的参数、返回值、执行对象等信息动态生成缓存的键。例如:

@Cacheable(value = "userCache", key = "#userId")
public User getUserById(String userId) {
    // ...
    // 查询用户信息的具体逻辑
    // ...
}

在上述示例中,key = "#userId" 表达式表示使用方法的 userId 参数作为缓存的键。这种方式可以根据参数的不同来动态生成不同的缓存键。

2.缓存前缀:可以在缓存的键前面添加一个固定的前缀,以便动态修改缓存的键。可以使用 Spring 提供的 CacheManager 接口中的 getCache() 方法来获取要操作的缓存对象,并使用 put()get() 方法来操作缓存数据。

@Autowired
private CacheManager cacheManager;

public void someMethod(String userId) {
    Cache userCache = cacheManager.getCache("userCache");
    String cacheKey = "user:" + userId; // 动态生成缓存键
    User user = userCache.get(cacheKey, User.class);
    if (user == null) {
        // 查询数据库,并将结果放入缓存中
        user = userService.getUserById(userId);
        userCache.put(cacheKey, user);
    }
}

在上述示例中,cacheKey 变量是根据 userId 参数动态生成的键值,可以在需要的时候灵活地进行修改。

无论使用哪种动态缓存方案,都需要考虑缓存的一致性和有效性。需要确保缓存的键在各种情况下都是唯一的,并且不会出现重复或冲突的情况。动态缓存要求在实际应用中谨慎使用,在需要动态修改缓存的键时才进行使用。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

echarts-wordcloud词云

echarts-wordcloud是基于echarts的一个插件&#xff0c;所以我们要首先安装echarts包&#xff0c;然后再安装echarts-wordcloud的包&#xff0c;这里我的练习项目安装的版本&#xff1b;当然&#xff0c;你可以随意安装你需要的版本&#xff1b; “echarts”: “^5.3.3”, “ec…

一文搞懂SECS/GEM(二)

继《一文搞懂SECS/GEM&#xff08;一&#xff09;》继续补充 这里写目录标题 HSMS2种连接模式&#xff08;Connect Mode&#xff09;6类消息消息交换过程Select ProcedureData ProcedureDeselect ProcedureLinktest ProcedureSeparate ProcedureReject Procedure 4种状态状态转…

【系统调用IO】open、close、read、write、lseek

目录 3 系统调用IO3.1 文件描述符3.1.1 FILE结构体3.2.2 文件描述符 3.3 open、close、read、write、lseek3.3.1 文件权限3.3.2 open3.3.3 close3.3.4 read3.3.5 write3.3.6 lseek3.3.7 代码示例 文件io和标准io的区别 橙色 3 系统调用IO 3.1 文件描述符 3.1.1 FILE结构体 …

Python 自动化测试:数据驱动

软件质量。这种测试&#xff0c;在功能测试中非常耗费人力物力&#xff0c;但是在自动化中&#xff0c;却比较好实现&#xff0c;只要实现了测试操作步骤&#xff0c;然后将多组测试数据以数据驱动的形式注入&#xff0c;就可以实现了。 前面文章学习了参数化&#xff0c;当数…

5G_射频测试_基础概念(二)

定义了测试参考点&#xff0c;不同的RRU类型 C类型传统RRU Conducted and radiated requirement reference points 4.3.1 BS type 1-C&#xff08;传统RRU一般测试点就是连接天线的射频接头&#xff09; 4.3.2 BS type 1-H&#xff08;宏站MassiveMIMO 矩阵天线&#xff…

自然语言处理研究的内容

一.基础技术 1.1 词法分析 词法分析&#xff08;Lexical Analysis&#xff09;&#xff0c;也称为词法扫描或扫描器&#xff0c;是自然语言处理&#xff08;NLP&#xff09;中的基础步骤之一&#xff0c;用于将输入的文本分割成词法单元&#xff08;Token&#xff09;。词法单…

每天都美好的一天

每天我们都会遇到不同的事情&#xff0c;开心的、愤怒的、悲伤的等等&#xff0c;今天过完明天我们还得继续&#xff0c;所以一切又显得不那么重要。一天中如果有不开心的事情发生会影响我们当天很长一段时间&#xff0c;甚至未来几天。 今天所做之事都是自己明天的基础&#…

JDK环境变量配置成功,命令提示符(CMD)中,输入java、javac、java -version等没有反应

双击环境变量里的path&#xff0c;然后把画圈的那两行移到最上边即可解决问题。 但是这样的话&#xff0c;当年再次双击path时就会呈现如下界面&#xff0c; 看起来很不方便&#xff0c;原来若Path变量值是%开头的&#xff0c;它就会显示一个字符串&#xff08;相当于每一行之…

机试指南:Ch1:绪论 Ch2:枚举和模拟

文章目录 第1章 绪论(1)如何准备机试(2)OJ和开发环境简介(3)OJ的原理、OJ的几种情况(4)学习建议(5)23版内容(6)常犯的编程小错误(7)其他小问题一览①int取值范围②return 0 缺省问题③万能头文件 #include <bits/stdc.h>④scanf、printf 比 cin、cout 更节约时间⑤不确定…

[java基础揉碎]算术运算符

算数运算符一览: *如果减号运算符加在变量前面, 这个变量会直接变成负数(加号不会): *取模(取余)11%9为什么等于2, 怎么计算的: 如果取模设计负数怎么运算的: 公式 a % b a - a / b * b *除法在java中会根据类型的不同而不同: 10/4是整数除以整数, 本来数学中应该得到2.5, …

热血江湖服务端服务器架设教程

热血江湖服务端服务器架设教程 大家好&#xff0c;我是艾西今天简单的说下热血江湖架设需要哪些东西然后怎么操作&#xff0c;不管你是自己玩还是对外开放&#xff0c;这对于有兴趣的小伙伴总的都是一件好事。技多不压身就是这么个道理&#xff0c;当你需要用上时还希望能记起…

SpringBoot(三层框架Controller,Mapper,Service)中遇到的一些注解整理

本文主要从Controller层,Service层,Mapper层这三层架构中记录用到的各种注解 还有一些MyBatis用到的注解 持续更新到本人的毕设做完为止,太多了太多了根本学不完哈哈哈 1.Controller层 1.1GetMapping/PostMapping/DeleteMapping/PutMapping 用于建立HTTP请求与处理方法之间的…

BUUCTF 从娃娃抓起 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 伟人的一句话&#xff0c;标志着一个时代的开始。那句熟悉的话&#xff0c;改变了许多人的一生&#xff0c;为中国三十年来计算机产业发展铺垫了道路。两种不同的汉字编码分别代表了汉字信息化道路上的两座伟大里程…

图片轮播大全

案例1&#xff1a;上下轮播切割重组 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" conten…

[陇剑杯 2021]webshell

[陇剑杯 2021]webshell 题目做法及思路解析&#xff08;个人分享&#xff09; 问一&#xff1a;单位网站被黑客挂马&#xff0c;请您从流量中分析出webshell&#xff0c;进行回答&#xff1a; 黑客登录系统使用的密码是_____________。 题目思路&#xff1a; 分析题目&…

幻兽帕鲁开服教程——游戏

幻兽帕鲁开服教程——游戏 1. 安装服务器2. 服务器配置调整3. 运行环境Microsoft Visual C Runtime4. 加入服务器 这是研究开服时顺手写的笔记&#xff0c;也方便后来者。 如果你熟悉你所使用的操作系统的话&#xff0c;windows和linux应该区别不大。 1. 安装服务器 1.安装ste…

什么是小程序?特点和技术架构详解

小程序是一种新的移动应用程序格式&#xff0c;一种结合了 Web 技术以及客户端技术的混合解决方案。 传统的原生应用运行起来比较流畅&#xff0c;但是也有天然的基因缺陷&#xff1a; 不支持动态化&#xff0c;发布周期长需要开发Android和iOS两套代码&#xff0c;开发成本高…

Ubuntu系统安装(如何在虚拟机下安装Ubuntu系统)

前言 Linux 的开发需要在 Linux 系统下进行&#xff0c;这就要求我们的 PC 主机安装 Linux 系统。我会在这篇文章中分享我如何安装虚拟机&#xff0c;以及我在虚拟机下安装Ubuntu系统。相信我的分享一定会给你带来帮助。 目录 前言 一、安装虚拟机软件 二、创建虚拟机 三、…

Kafka(八)使用Kafka构建数据管道

目录 1 使用场景2 构建数据管道时需要考虑的问题2.1 及时性2.2 可靠性高可用可靠性数据传递 2.3 高吞吐量2.4 数据格式2.5 转换ETLELT 2.6 安全性2.7 故障处理2.8 耦合性和灵活性临时数据管道元数据丢失末端处理 3 使用Connect API3.1 Connect的数据处理流程sourcesinkconnecto…

【C++】List模拟实现过程中值得注意的点

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.List迭代器 2.适…