[Spring] SpringBoot2 简介(二)—— 高级配置

news2024/10/3 22:26:38

目录

一、@Conditional 注解

1、SpringBoot 如何获取 Bean 对象

2、SpringBoot 创建 Condition 类

3、切换内置 web 服务器

二、@EnableXXX 注解

1、SpringBoot 不能直接获取其他 jar 包/工程中的 Bean

2、原因分析

3、封装 @Import

4、@Import 注解

5、SpringBoot 自动配置原理

三、自定义 starter 起步依赖

1、步骤分析

2、实现步骤

3、@ConditionalOnMissingBean

四、SpringBoot 监听机制

1、Java 监听机制

2、SpringBoot 监听机制

3、CommandLineRunner 与 ApplicationRunner

4、ApplicationContextInitializer

5、SpringApplicationRunListener

五、SpringBoot 监控

1、监控概述

2、使用方法

3、info 或其他信息不显示

4、显示组件完整信息

六、SpringBoot 项目部署

1、部署 jar 包方式

2、部署 war 包方式

3、项目部署问题汇总


一、@Conditional 注解

Condition 是在 Spring 4.0 增加的条件判断功能,通过这个可以功能可以实现选择性的创建 Bean 对象的操作。

  • 我们可以想这么一个问题:有一个 User 对象,只有符合某种条件的时候,才能被 Spring 当作 Bean 对象,加入到 IOC 容器中。
  • 也就是,SpringBoot 是如何知道应该创建哪些 Bean。

通过 @Conditional 就可以实现这个操作。

1、SpringBoot 如何获取 Bean 对象

在解决上述问题之前,我们先来了解一下如何获取 Bean 对象。

(1)获取 IOC 容器

  • 想要获取 Bean 对象,首先要获取 IOC 容器对象,也就是 ApplicationContext;
  • 我们启动 SpringBoot 的 run 方法,其实就是返回了一个 IOC 容器;
ConfigurableApplicationContext context = SpringApplication.run(DemoConditionApplication.class, args);

(2)获取 Bean 对象

  • 这里我们获取一个 redisTemplate 的对象;
  • 注意此时还没有导入 redis 的相关依赖;
package com.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class DemoConditionApplication {
    public static void main(String[] args) {
        // 启动 SpringBoot,获取 IOC 容器
        ConfigurableApplicationContext context = SpringApplication.run(DemoConditionApplication.class, args);
        // 获取 Bean 对象
        Object redisTemplate = context.getBean("redisTemplate");
        System.out.println(redisTemplate);
    }
}
  • 启动后就会发现,SpringBoot 找不到 redisTemplate 这个 Bean; 

(3)补充 Redis 相关依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • 添加 Redis 的起步依赖后,就可以获取到 redisTemplate 的 Bean 对象了:

2、SpringBoot 创建 Condition 类

实际上,创建 Bean 对象的条件可以有很多。

在这里选择上文中的导入依赖后就能创建 Bean 的条件进行举例说明 @Conditional 的具体使用。

(1)提出问题

在刚才获取 Bean 对象的过程中,一开始由于没有导入 Redis 依赖,导致获取不到 Bean 对象。而 redisTemplate 的 Bean 对象创建,依赖于 Redis 的起步依赖

  • 换句话说,SpringBoot 如何知道当没有引入 Redis 的起步依赖时,不该创建 redisTemplate 的 Bean 对象

下面通过一个案例来说明:

  • 在 Spring 的 IOC 容器中有一个 User 的 Bean。
  • 要求:导入 RedisTemplate 后,加载这个 Bean;没有导入,则不加载。

(2)创建 UserCondition 类(重点部分)

  • @Conditional() 修饰某个 Bean 对象时,需要传入 Condition 类数组;
  • Condition 类要求实现 matches 方法;
  • matches 方法就是创建 Bean 对象的判断条件,返回值为 true/false

现在我们的需求就是,导入 RedisTemplate 类的时候,才返回 true:

  • 当加载不到这个类的时候,出现异常,就返回 false;
public class UserCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        boolean flag = true;
        try {
            Class.forName("org.springframework.data.redis.core.RedisTemplate");
        } catch (ClassNotFoundException e) {
            flag = false;
        }
        return flag;
    }
}

(3)创建 SpringConfig 类

  • User 类随便新建一个即可;
  • SpringConfig 中,实现注入 User 的方法(@Bean 修饰方法);
  • @Conditional 传入我们刚写好的 UserCondition,其中的 matches 方法会判断是否创建这个 Bean;
@Configuration
public class SpringConfig {
    @Bean
    @Conditional(value = {UserCondition.class})
    public User createUser() {
        return new User();
    }
}

(4)启动测试

  • 由于我们刚才导入了 Redis 的起步依赖,已经包含了 RedisTemplate,此时获取 User 的 Bean 对象,是可以直接获取到的。

  • 然后我们将 Redis 的起步依赖注释掉,重新 Build 项目,启动 SpringBoot,就会发现 Bean 对象找不到了。

3、切换内置 web 服务器

SpringBoot 的 web 环境中默认使用 tomcat 作为内置服务器,其实 SpringBoot 提供了 4 种内置服务器供我们选择,我们可以很方便的进行切换。

(1)切换原理

  • SpringBoot 如何切换服务器。本质上也是通过 @Conditional 注解,来判断是否引入了依赖、传递了参数,最终决定启用哪一个服务器。

(2)切换方法

  • 首先要用 <exclusion> 将 tomcat 从依赖中移除;
  • 然后引入 jetty 的依赖;

二、@EnableXXX 注解

SpringBoot 中提供了很多 Enable 开头的注解(比如 @EnableAutoConfiguration),这些注解都是用于动态启用某些功能的。

而其底层原理是使用 @Import 注解导入一些配置类,实现 Bean 的动态加载。

  • 比如:引入了 redisTemplate 之后,就可以直接使用 @Autowired 注入属性了。

1、SpringBoot 不能直接获取其他 jar 包/工程中的 Bean

我们可以创建两个模块:一个用来启动 SpringBoot,一个用来定义 Bean。

注意,由于我们会给启动 SpringBoot 的模块,添加定义 Bean 的模块作为依赖,所以包路径不能相同,否则在同一项目下,是可以获取到 User 类的。

(1)创建实体类、配置类

  • 在 Demo-Enable-Bean 模块中,创建一个 User 类、一个 UserConfig 类;
  • 在 UserConfig 类中,注入一个 User 的 Bean;

(2)引入 Demo-Enable-Bean 作为依赖

  • 在 Demo-Enable 模块中,引入 Demo-Enable-Bean;

(3)启动 Demo-Enable 的 SpringBoot

  • 在启动类中,获取 User 的 Bean 对象,观察是否能获取到;
@SpringBootApplication
public class DemoEnableApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DemoEnableApplication.class, args);
        User user = (User) context.getBean("createUser");
        System.out.println(user);
    }
}
  • 输出结果:

2、原因分析

原因其实很简单,前面也遇到过。

在启动类的注解 @SpringBootApplication 中,有 @ComponentScan 这个注解。默认情况下只会扫描当前引导类所在包及其子包。

因此只需要加上一行注解即可:

但是写字符串数组毕竟比较麻烦,所以还可以使用 @Import 导入我们需要的类:

3、封装 @Import

虽然 @Import 可以直接写上我们需要的 UserConfig 类,问题就在于:

  • 当我们需要这个定义 Bean 的模块(以后就是 jar 包)中的所有关于 User 的类呢?一个个导入会很麻烦。
  • 并且如果在启动 SpringBoot 的模块中,Import 大量其他 jar 包的类,也会提高耦合度。

这个时候就可以在定义 Bean 的模块中,给 User 写一个 @EnableUser 注解,在其中将所有与 User 相关的类全部 Import。

这样我们就可以在别的项目里,只需要写一个 @EnableUser,就能达到目的。

(1)@EnableUser

  • 写上元注解;
  • 添加关于 User 的类;
// 元注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 导入关于 User 的所有类
@Import(value = {UserConfig.class})
public @interface EnableUser {

}

(2)在 SpringBoot 的启动类中添加 @EnableUser

@SpringBootApplication
@EnableUser
public class DemoEnableApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DemoEnableApplication.class, args);
        User user = (User) context.getBean("createUser");
        System.out.println(user);
    }
}

4、@Import 注解

@EnableXXX 底层依赖于 @lmport 注解导入一些类,使用 @lmport 导入的类会被 Spring 加载到 lOC 容器中。

@lmport 提供 4 种导入方法:

  • 导入Bean;
  • 导入配置类;
  • 导入 ImportSelector 的实现类;(一般用于加载配置文件中的类)
  • 导入 ImportBeanDefinitionRegistrar 的实现类。

5、SpringBoot 自动配置原理

SpringBoot 能够快速启动,得益于其自动配置的机制。关键就在于 @EnableAutoConfiguration 这个注解。

  • @EnableAutoConfiguration 注解内部使用 @Import(AutoconfigurationImportselector.class) 来加载配置类。
  • 而 Importselector 的实现类,又会从配置文件:META-INF/spring.factorles 中加载大量配置类。
  • 当 SpringBoot 启动时,就会自动加载这些配置类,初始化 Bean。
  • 并不是所有 Bean 都会被初始化,在配置类中使用 @Conditinal 来加载满足条件的配置类。

三、自定义 starter 起步依赖

需求:自定义 redis-starter,要求当导入 Jedis 依赖时,SpringBoot 自动创建 Jedis 的 Bean。

1、步骤分析

参考 MyBatis 的起步依赖构造,我们发现:

  • starter 模块不写代码,专门用来整合依赖,其中依赖了 autoconfigure;
  • autoconfigure 模块就包含了 MyBatis 的配置类 MyBatisAutoConfiguration,其中就定义了 Bean 对象;
  • 而要想 Spring 能够识别 MyBatis 的配置类,就会有一个 spring.factorles 配置文件,配置文件中就有 MyBatis 的配置类;

可以发现,后两步其实就是 SpringBoot 的自动配置原理。

因此,大致步骤为:

  • 创建 redis-spring-boot-autoconfigure 模块;
  • 创建 redis-spring-boot-starter 模块,依赖 redis-spring-boot-autoconfigure 模块;
  • 在 redis-spring-boot-autoconfigure 模块中初始化 Jedis 的Bean,并定义 META-INF/spring.factories 文件;
  • 在测试模块中引入自定义的 redis-starter 依赖,测试获取 Jedis 的 Bean,操作 redis。

2、实现步骤

(1)创建两个模块

  • 创建 starter 和 autoconfigure 模块;

  • starter 依赖 autoconfigure,autoconfigure 依赖 jedis;

(2)定义 RedisProperties

由于 Jedis 的初始化需要 host 和 port,并且我们不希望在代码中写死。

  • 因此可以使用配置文件来设置 host 和 port;
  • 相应的要增设一个 RedisProperties 类来绑定对应的配置文件(自行补上 set、get);
  • @ConfigurationProperties 绑定前缀为 redis 的配置文件;
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
    private String host = "localhost";
    private Integer port = 6379;
}

(3)定义 RedisAutoConfiguration

由于 @Bean 修饰的 Jedis 对象,需要 RedisProperties 类来作为参数,因此要添加 @EnableConfigurationProperties 来引入这个 Bean:

  • 需要注意的是,Spring boot 2.2.1 默认关闭对 @ConfigurationProperties 的扫描;
  • 有三种方式可以解决,但在这种自定义 starter 的需求下,只能使用 @EnableConfigurationProperties 来完成引入
@Configuration
@EnableConfigurationProperties(value = {RedisProperties.class})
public class RedisAutoConfiguration {
    @Bean
    public Jedis jedis(RedisProperties redisProperties) {
        return new Jedis(redisProperties.getHost(), redisProperties.getPort());
    }
}

(4)编写配置文件 spring.factories

  • 在 resource 下创建目录:META-INF/spring.factories;
  • 添加 RedisAutoConfiguration 的全类名;
  • 注意,一定要 RedisAutoConfiguration 的全类名是 绿色 才可以;

(5)测试

  • 在 SpringBoot 启动类的项目中添加我们所编写的 RedisStarter 依赖;
  • 获取其中 Jedis 的 Bean 对象;

3、@ConditionalOnMissingBean

当用户自定义了 Bean 对象时,可以替代我们自定义的 starter 中的 Bean 对象。

  • name = "xxx",表示用户定义了 id 为 xxx 的 Bean 时,就不会生成 @ConditionalOnMissingBean 修饰的 Bean。

四、SpringBoot 监听机制

1、Java 监听机制

SpringBoot 的监听机制,其实是对 Java 提供的事件监听机制的封装。

Java 中的事件监听机制定义了以下几个角色:

  • 事件:Event,继承 java.util.EventObject 类的对象;
  • 事件源:Source,任意对象 Object;
  • 监听器:Listener,实现 java.util.EventListener 接口的对象;

2、SpringBoot 监听机制

SpringBoot 在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口,在项目启动时完成一些操作。

  • SpringBoot 内部已经将注册监听器等任务都做好了;
  • SpringBoot 将接口提供,我们只需要实现接口,就能完成监听到事件源之后的操作;

接口则有如下 4 个:

  • ApplicationContextInitializer(需要手动配置);
  • SpringApplicationRunListener(需要手动配置);
  • CommandLineRunner;
  • ApplicationRunner;

(1)实现 4 个接口,并启动 SpringBoot

  • 将上面 4 个接口都实现后,为每个实现方法添加输出;
  • 启动 SpringBoot,观察输出;

  • 由输出可知,只有后 2 个监听器被调用了,因为我们还没有配置前 2 个监听器;

3、CommandLineRunner 与 ApplicationRunner

先来看这两个不需要手动配置的监听器。

这 2 个监听器的 run 方法在 SpringBoot 启动后会自动调用,我们期望可以用 run() 方法来做一些事情。

(1)程序代码

  • 分别作对应的输出;

(2)run() 方法的参数 args

实际使用中,我们希望提前将 redis 中的一些数据加载进缓存中。

  • 打印 args,CommandLineRunner 中 输出 Arrays.asList(args);
  • 打印 args,ApplicationRunner 中 输出 Arrays.asList(args.getSourceArgs());

此时启动 SpringBoot,会发现这两个输出都是空的。

我们可以在启动项中添加一些参数:

  • 若没有“程序实参”这个选项,可以在旁边的“修改选项中添加”;
  • 在“程序实参”中写上一个键值对,然后启动 SpringBoot,就能输出到控制台了;

4、ApplicationContextInitializer

ApplicationContextInitializer 监听器需要使用 META-INF/spring.factories 配置文件来进行引入。

(1)spring.factories

  • 添加键值对:ApplicationContextInitializer 类路径 = 实现类的类路径;

(2)程序代码

  • 在 initialize 方法中,进行一个输出;
  • 注意:不需要 @Component; 

(3)启动 SpringBoot

  • 启动 SpringBoot,发现项目启动之前就已经有输出了;
  • 实际上,Initializer 可以用于在项目还未启动之前,去检测一些资源是否存在;

5、SpringApplicationRunListener

按照配置 ApplicationContextInitializer 的方法同样在 spring.factories 中进行配置:

(1)出现报错

  • <init> 报错一般是指:缺少了构造方法。
  • 这里的问题就是:没有一个有参构造,参数为(SpringApplication,String[])。

(2)SpringApplication

  • SpringApplication:就是项目启动后的事件源
  • 事件源上可以产生很多生命周期不同的相关事件,所以监听器需要事件源作为构造所需的参数;

(3)编写构造函数

  • 参考 SpringBoot 官方的实现类,定义构造函数,其中包含上述 2 个参数;
  • 在新版本中,SpringApplicationRunListener 的 running 方法已经被弃用了,使用 ready 取代它;

  • 下面给出完整代码: 
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
    public MySpringApplicationRunListener(SpringApplication springApplication, String[] args) {
        // structor
    }

    @Override
    public void starting(ConfigurableBootstrapContext bootstrapContext) {
        System.out.println("starting--项目启动中");
    }

    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        System.out.println("environmentPrepared--环境对象准备");
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("contextPrepared--上下文对象准备");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("contextLoaded--上下文对象加载(耗时操作)");
    }

    @Override
    public void started(ConfigurableApplicationContext context, Duration timeTaken) {
        System.out.println("started--上下文对象加载完成");
    }

    @Override
    public void ready(ConfigurableApplicationContext context, Duration timeTaken) { // running
        System.out.println("ready--项目启动完成,开始运行");
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("failed--项目启动失败");
    }
}

(4)启动 SpringBoot

五、SpringBoot 监控

1、监控概述

SpringBoot 自带监控功能 Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、 Bean 加载情况、配置属性、日志信息等。

 可以通过监控信息来排除故障。

2、使用方法

  • 导入相关依赖:spring-boot-starter-actruator;
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • 访问:http://localhost:8080/acruator

3、info 或其他信息不显示

我们看到当访问的页面只有 health 相关的功能,那是因为新版本中,info 端点默认是不启用的,在 application.properties 中配置的 info 开头的变量默认也是不启用的。

(1)解决方法

修改配置,添加下面两个参数:

  • management.endpoints.web.exposure.include = health, info;
  • management.info.env.enabled = true;

  • 再次访问,这时可以看到,info 端点已经出现了;

(2)为 info 添加参数信息

  • 同样在 application.properties 中配置 info 的参数值;

  • 然后访问 info 端点链接; 

4、显示组件完整信息

(1)显示 health 完整信息

  • 当访问 health 端点的时候,会发现只有一个 status 为 up 的信息。

  • 如果希望显示完整信息,可以修改 show-details 属性。

  • 再次访问 health,就能显示详细信息。 

  • 由于还没有开启其他组件,因此现在只有对磁盘和ping的监控。

(2)添加 redis 组件

  • 添加 redis 起步依赖;
  • 启动 redis 服务器:redis-server.exe;

(3)开启所有的 endpoint

  • 其实就是将上文中,只开启 info、health 的参数值,修改为 * 即可;
  • 将所有的监控 endpoint 暴露出来;

  • 访问 actuator 就会发现多出了一大堆信息;

六、SpringBoot 项目部署

当 SpringBoot 项目开发完成,应该怎么将它放到服务器、生产环境上运行。

SpringBoot 项目开发完毕后,支持 2 种方式部署到服务器:

  • jar 包(官方推荐,使用内置的 Tomcat)
  • war 包(使用外部的 Tomcat)

1、部署 jar 包方式

(1)创建工程

  • 添加 web 起步依赖;
  • 创建一个 Controller 类,包含一个访问路径;

(2)打包

  • 使用 maven 的 package 功能,将项目打包 jar 包;

(3)启动 jar 包

  • 输入命令:java -jar xxx.jar;
  • 启动成功即可访问 UserController;

 

2、部署 war 包方式

(1)继承父类、实现父类方法

  • 继承 SpringBootServletInitializer;
  • 实现 configure 方法,返回值为 SpringApplicationBuilder;
@SpringBootApplication
public class DemoDeployApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(DemoDeployApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(DemoDeployApplication.class);
    }
}

(2)修改 pom.xml 文件的打包方式

  • 将 <packaging> 改为 war 包方式;
  • 然后使用 maven 的 package 打成 war 包;

(3)将 war 包交给 tomcat

  • 将 war 放到 tomcat 目录的 webapps 目录下;

(4)启动 tomcat

  • 找到 bin 目录下的 startup.bat,启动 tomcat;

(5)访问 UserController

  • 先访问 locathost:8080,显示 tomcat 的主页面;
  • 注意:由于使用的是外置的 tomcat,因此 URL 需要加上工程路径;

 

3、项目部署问题汇总

(1)无效源发行版本、无效目标发行版本

主要原因是:编译环境使用的 JDK 和运行环境使用的 JDK 版本不一样。

  • 首先要明确自己的 java 版本:windows 使用 java -version 查看版本;
  • 然后参考这篇文章修改:https://blog.csdn.net/weixin_44368270/article/details/131155839

(2)使用外置 tomcat 时,application.properties 等配置文件不生效

  • 因为 SpringBoot 中的 application 配置配置文件,对应的都是内置的服务器;
  • 当我们使用了外置服务器,就没有效果了;

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

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

相关文章

前端领域的插件式设计

插件&#xff0c;是一个常见的概念。 例如&#xff0c;当我们需要把我们前端代码中的 css 样式提取打包&#xff0c;我们可以用 webpack 的 mini-css-extract-plugin&#xff0c;或者你如果用 rollup 的话&#xff0c;可以选择 rollup-plugin-postcss。 再比如我们可以给 bab…

Python 数组和列表:创建、访问、添加和删除数组元素

Python 没有内置支持数组&#xff0c;但可以使用 Python 列表来代替。 数组 本页将向您展示如何使用列表作为数组&#xff0c;但要在 Python 中使用数组&#xff0c;您需要导入一个库&#xff0c;比如 NumPy 库。数组用于在一个变量中存储多个值&#xff1a; 示例&#xff0…

VSCode 开发 Vue 语法提示

一. 打开应用商店&#xff0c;搜索 vetur &#xff0c;选择第一个&#xff0c;点击安装。 二. 安装完成后&#xff0c;还可以下载 Vue Language Features 解决代码警告的问题。 最后重启 VSCode 就可以使用啦。另外输入 按回车键还可以自动生成 vue 代码格式哦。 原创作者&…

GPT-3 内幕机制可视化解析

GPT-3 内幕机制可视化解析 GPT-3是一个基于Transformer的语言模型,通过不同的层次提取语言不同层面的特性,构建整个语言的语义信息,它学习的过程跟人类正常学习的过程是类似的,开始的时候是一个无监督预训练,如图5-5所示,GPT-3模型可以将网络上的所有文档下载下来,包含 …

AD9371 官方例程HDL详解之JESD204B TX侧时钟生成 (三)

AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 &#xff1a; AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射&#xff1a; AD9371 官方例程之 tx_jesd 与 xcvr接口映射 AD9371 官方例程 时钟间的关系与生成 &#xff1a; AD9371 官方…

Sui提供dApp Kit 助力快速构建React Apps和dApps

近日&#xff0c;Mysten Labs推出了dApp Kit&#xff0c;这是一个全新的解决方案&#xff0c;可用于在Sui上开发React应用程序和去中心化应用程序&#xff08;dApps&#xff09;。mysten/dapp-kit是专门为React定制的全新SDK&#xff0c;旨在简化诸如连接钱包、签署交易和从RPC…

Python生成词云

成品&#xff1a; 代码&#xff1a; import os# 下面的两个包大家注意别导错了 from imageio.v2 import imread from wordcloud import wordcloud# mytext文本是字符串类型的 mytext str() # os.getcwd()是获得当前目录的路径&#xff0c;好像没啥用 读取 with open(os.getcw…

35岁运维工程师到底该何去何从?

你是否经常在网上看到类似的帖子&#xff1a; “运维35岁被裁”、“35岁运维找不到工作”&#xff0c;这样的字眼频频出现在新闻中。如何度过35岁职场危机呢&#xff0c;不妨看看这篇文章&#xff0c;或许对你有启发&#xff01; 一、35岁被称为运维半衰期&#xff0c;究竟为何…

性能测试:系统架构性能优化思路

今天谈下业务系统性能问题分析诊断和性能优化方面的内容。这篇文章重点还是谈已经上线的业务系统后续出现性能问题后的问题诊断和优化重点。 系统性能问题分析流程 我们首先来分析下如果一个业务系统上线前没有性能问题&#xff0c;而在上线后出现了比较严重的性能问题&#x…

【算法练习Day26】分发饼干摆动序列 最大子数组和

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 分发饼干摆动序列最大子数组…

金蝶云星空企业版v8.0内网穿透配置详解:实现便捷的异地远程访问

文章目录 前言1. 金蝶云星空企业版v8.0安装下载1.1 登录金蝶官网下载安装包1.2 常见的安装下载问题 2. 金蝶云星空配置SQL Sever数据库2.1 创建数据管理中心2.2 创建完成后在服务器登录管理站点 3. 下载安装注册cpolar3.1 公网访问测试 4. 固定连接公网地址 前言 金蝶云星空专注…

关于AES加密输出密文不为128位的倍数的原因

今天尝试用AES-256-OFB加密一个flag结果输出的密文是43字节&#xff0c;不是128位&#xff08;16字节&#xff09;的倍数&#xff0c;代码如下&#xff1a; import os from Crypto.Cipher import AES databflag{a7ba7128-3917-4551-8260-b3499e9dd7b12} aes AES.new(os.urand…

如何用Pytest做性能测试?5个步骤轻松学会!

Pytest其实也是可以做性能测试或者基准测试的。是非常方便的。 可以考虑使用Pytest-benchmark类库进行。 安装pytest-benchmark 首先&#xff0c;确保已经安装了pytest和pytest-benchmark插件。可以使用以下命令安装插件&#xff1a; pip install pytest pytest-benchmark …

Apollo生态系统探索:更多工具与框架的介绍

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

选择合适的软件管理视频制作排期

如果你是一名专业的视频创作者&#xff0c;那么你一定知道一个清晰、高效的项目管理对于视频制作的重要性。那么如何使用Zoho Projects项目管理软件来管理的视频制作项目&#xff0c;以便更好地规划和执行每一个细节呢&#xff1f; 这款项目管理软件具有丰富的自定义字段功能&a…

【Java集合类面试十三】、HashMap如何实现线程安全?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;HashMap如何实现线程安全…

【EtherCAT】二、下载并使用TwinCAT

下载并使用TwinCAT 引言介绍下载安装TwinCAT使用 更多精彩&#xff0c;欢迎关注 引言 TwinCAT是一款由德国Beckhoff Automation开发的工业自动化控制软件。它被广泛用于工厂自动化、过程控制、机器控制以及其他自动化领域。 而这里我们主要使用TwinCAT模拟ECAT主站。本文将介绍…

【蓝桥杯001】

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;喜欢编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;小新爱学习. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc…

golang 工程组件:grpc-gateway 环境安装+默认网关测试

grpc-gateway grpc-gateway 顾名思义是专门是grpc的网关。也是一个protobuf的编译器&#xff0c;是一个proto的插件。 grpc-gateway就是将http请求处理后转发到对应grpc服务上。很多浏览器&#xff0c;或者客户端开箱不支持grpc&#xff0c;只支持传统的restful API。 grpc网关…

Tmux:终端复用器的基本使用(三)

相关阅读 Tmuxhttps://blog.csdn.net/weixin_45791458/category_12472796.html?spm1001.2014.3001.5482 在之前的两篇文章中&#xff0c;已经给出了关于tmux中会话和窗口相关的常用命令&#xff0c;在这篇文章中&#xff0c;窗格相关的命令将会被给出。 将一个窗格水平和垂直…