【Spring Boot】夺名连环问(持续更新ing)

news2025/1/16 19:06:50

Spring的了解与特性

  • 简单介绍:快速开发Spring项目的脚手架。简化Spring应用的初始搭建以及开发过程。

  • 特性

    • 提供了很多内置的Starter结合自动配置,对主流框架的无配置集成、开箱即用。即不需要自己去引入很多依赖

    • 并且管理了常用的第三方依赖的版本,减少了版本冲突的问题

    • 简化开发,采用JavaConfig的方式可以使用0xml方式进行开发。

    • 内置Web容器无需依赖外部Web服务器,省略了Web.xml,直接运行就使Web应用。

    • 提供了监控功能,可以监控应用程序的运行状态、内存、线程池、HTTP请求统计等。

Spring与SpringBoot的关系

  • 两者都是Spring生态的产品

  • 前者是容器框架,后者是一个快速开发Spring的脚手架(真正意义上不算新的框架)

核心注解

  • @SpringBootApplication

    • @SpringBootConfiguration(标记为配置类的注解)

      • @Configuration

    • @EnableAutoConfiguration:向Spring容器中导入了一个Selector,用来加载ClassPath下SpringFactories中所定义的配置类,将这些自动加载为配置Bean。

    • @Conditional(待补充)

自动配置原理

  • 通过@SpringBootApplication中的@EnableAutoConfiguration

  • @EnableAutoConfiguration引入了@Import

  • 在Spring容器启动时会加载IoC容器解析@Import注解

  • @Import导入了@DeferredImportSeletor注解,会使SpringBoot的自动配置类的顺序在最后,方便扩展的覆盖

  • 读取META-INF/spring.factories文件

  • 过滤出所有的AutoConfigurationClass类型的类

  • 最后通过@Condition排除无效的自动配置类

为什么SpringBoot的jar可以直接运行

  • 部署SpringBoot的插件才能将package后的jar包使用:java -jar packageName运行

    • 也就是在pom.xml中要有<build>中的<plugins>中<plugin>的spring-boot-maven-plugin。如果没有这个插件在运行命令的时候会报没有主清单属性。

  • 使用插件打包后生成的其实是一个Fat jar(也就是jar包中还有jar包),包含了应用依赖的jar包和Spring Boot Loader相关的类。 

  • java - jar会去找jar中的MANIFEST.MF文件,在那里面找到真正的启动类(Main-Class)。

  • Fat jar的启动Main函数是JarLauncher,它负责创建一个LaunchedURLClassLoader加载boot-lib下面的jar,并以一个新的线程启动应用Main函数(其实就是找到MANIFEST中的Start-Class)。

  • 当然,为了去验证此说法,就需要引入依赖从而去看JarLauncher中的源码,引入此依赖后再package就可以查看源码了。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-loader</artifactId>
    </dependency>

启动原理

  • 运行主启动类的main方法,会初始化SpringApplication,从spring.factories读取listener ApplicationContextInitializer。此primarySources就是当前SpringBoot项目的class文件。

  • 在初始化SpringApplication中对一些属性的初始化,比如开启日志记录、关闭懒加载等等。不同版本的Boot在初始化的时候不一样,主要是最下面的七行。以下讲解最下面五行的作用。就不根据源码展示了。

    • 将启动类primarySources放入到名为primartSrouces的LinkedHashSet集合中

    • 推算当前Web应用类型webApplicationType

    • 读取ApplicationContextInitializer初始化器

    • 读取ApplicationListener监听器

    • 将Main方法所在的类放入mainApplicationClass中

  • 接下来就是运行run()方法了。代码太多就不展示了。主要是做了以下的操作:

    • 从上面读取的ApplicationListener监听器去读取SpringApplicationRunListener监听器运行器

    • 发布ApplicationStartingEvent事件

    • 封装命令行参数ApplicationArguments

    • 读取环境配置信息

      • 根据webApplicationType创建环境变量对象

      • 配置环境变量

      • 将现有环境信息设置为@ConfigurationProperties的数据源 并且放在第一位

      • 发布ApplicationEnvironmentPreparedEvent事件

      • 将spring.main的配置绑定到SpringApplication属性上

      • 将现有的环境信息设置为@ConfigurationProperties的数据源 更新放在第一位

    • 设置忽略bean.spring.beaninfo.ignore

    • 打印Banner

    • 实例化Spring上下文 AnnotationConfigServletWebServerApplicationContext

    • 初始化失败分析器

    • 准备上下文:将启动类作为配置类进行读取 -> 将配置注册为BeanDefinition

      • 将当前环境信息设置到context

      • 调用ApplicationContextInitializer

      • 发布ApplicationContextInitializerdEvent事件

      • 打印启动信息和profile.active(测试/生产/开发)信息

      • 将applicationArguments、printedBanner注册为Bean

      • 设置不允许同名Bean

      • 设置是否懒加载Bean

      • 读取启动类为BeanDefinition

      • 将SpringBoot的监听器添加到context发布 ApplicationPreparedEvent事件

    • 加载IoC容器(refresh()方法)其中的十二个步骤。具体干了什么可以去看我另外几篇源码解读的博文。主要两个方法

      • invokeBeanFactoryPostProcessor() -> 解析@Import 加载所有的自动配置类

      • onRefresh() 创建内置的Servlet容器

    • 待扩展(刷新后的处理)

    • 发布ApplicationStartedEvent事件
    • 发布ApplicationReadyEvent事件
    • 如果启动异常会发送ApplicationFailedEvent事件

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
    this.configureHeadlessProperty();
    // 从上面读取的ApplicationListener监听器去读取SpringApplicationRunListener监听器运行器
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    // 发布ApplicationStartingEvent事件
    listeners.starting();
​
    Collection exceptionReporters;
    try {
        // 封装命令行参数ApplicationArguments
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 读取环境配置信息
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
        // 设置忽略bean.spring.beaninfo.ignore       
        this.configureIgnoreBeanInfo(environment);
        // 打印Banner
        Banner printedBanner = this.printBanner(environment);
        // 实例化Spring上下文 AnnotationConfigServletWebServerApplicationContext
        context = this.createApplicationContext();
        // 初始化失败分析器
        exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
        // 准备上下文:将启动类作为配置类进行读取 -> 将配置注册为BeanDefinition
        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        // 加载IoC容器
        this.refreshContext(context);
        // 待扩展(刷新后的处理)
        this.afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }
​
        // 发布ApplicationStartedEvent事件
        listeners.started(context);
        this.callRunners(context, applicationArguments);
    } catch (Throwable var10) {
        this.handleRunFailure(context, var10, exceptionReporters, listeners);
        throw new IllegalStateException(var10);
    }
​
    try {
        // 发布ApplicationReadyEvent事件
        listeners.running(context);
        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var9);
    }
}

内置Tomcat启动原理 

  • 当依赖spring-boot-starter-web依赖时会在SpringBoot中添加:ServletWebServerFactoryAutoConfiguration(servlet容器自动配置类)

  • 该自动配置类通过@Import导入了可用的(通过@ConditionalOnClass判断决定使用哪一个)的Web容器工厂(默认Tomcat)

  • 在内嵌的Tomcat类中配置了一个TomcatServletWebServerFactory的Bean(Web容器工厂)

  • 它会在SpringBoot启动时加载IoC容器、在onRefrush()方法中创建内嵌的Tomcat并启动

外部Tomcat启动原理

  • SpringBoot启动后会加载SpringServletContainerInitializer类,此类会去加载实现了WebApplicationInitializer接口的类,而其中SpringBootServletInitializer这个类就实现了这个接口,而需要继承这个类去传入当前应用的启动类。

WebApplicationContext rootAppContext = this.createRootApplicationContext(servletContext);
  • 想要使用外部的Tomcat,就需要排除内部的Tomcat。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
    	<exclusion>
        	<groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  • 创建一个配置类去继承SpringBootServletInitializer去重写configure()方法,将当前模块的启动类传入进去 。

public class TomcatConfig extends SpringBootServletInitializer {
    
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(StudySpringApplication.class);
    }
}

如何自定义Starter

  • 首先知道什么是Starter:Starter又名启动器。众所周知SpringBoot是简化了企业级Spring框架的开发,采用了约定优于配置的理念,而这个理念的实现就是用Starter组件。其会把对应功能的jar包导入进来使得开发者无需在意版本冲突问题,而只需在乎业务逻辑即可,这是作为引入依赖方面的简化配置。而此处要介绍的Starter就是代替Spring的内部组件,使用自定义的组件去完成启动。步骤如下

    • 新建resources/META-INF/spring.factories。这是因为Spring Boot在启动的时候会去读取ClassPath下的这个文件信息。

    • 在spring.factories中去用伪SPI去扫描我们自定义的Starter启动器组件

读取配置文件的原理以及加载顺序

  • 通过事件监听的方式读取配置文件,而读取配置文件的类则是ConfigFileApplicationListener

读取配置文件的方式

  • 属性上使用注解@Value("${xxx.yyy}"),需要注意三点:

    • 当前类是交给IoC容器管理的Bean,否则@Value注解不生效。

    • 当前属性不能是static或者final修饰。

    • 如果配置文件中没有对应的xxx: yyy的话会报错,但是可以在@Value中给默认值比如@Value("${xxx.yyy:}"),这样默认为""

    • 缺点是一个属性对应一个,如果需要读取多个属性的话,效率低下。

  • 类上使用注解@ConfigurationProperties(prefix = "xxx")去指定配置文件中的前缀去读取多个,然后属性采用同名方式去进行批量匹配。相比于上面那种而言,如果遇到大量的配置信息,则效率会更高。

@ConfigurationProperties(prefix = "xxx")
public class MyYamlConfig {
    private String yyy;
}
  • 通过Spring的应用上下文ApplicationContext去获取Environment对象。但相较于直接获取Environment对象,这样显得多此一举,除非除了要使用ApplicationContext获取运行时环境还有其它的作用。毕竟ApplicationContext是Spring应用程序中的中央接口,由于继承了多个组件所以有多个核心的功能。

  • Spring Bean类中去注入IoC管理的Environment对象。可以使用@Resource、@Autowired来注入。然后在代码块中通过此对象的getProperty("xxx.yyy")返回String对象进行使用即可。但是如果不用自动装配的方式(也就是非Spring管理的Bean),就需要此配置类去实现EnvironmentAware接口重写setEnvironment()方法去获取Environment对象。

  • 配置类上获取外部properties后缀配置文件的方式,比如需要读取/resources/gok.properties文件。在配置类上使用注解@PropertySources。然后就可以在属性上使用@Value注解去读取。

@Configuraion
@PropertySources({@propertySource(value = "classpath:gok.properties", encoding = "UTF-8")})
public class MyYamlConfig {
    @Value("${xxx.yyy}")
    private String name;
}
  • 获取/resources/gok.yml文件。在被@Configuration注解的配置类去配置

@Configuration
public class MyYamlConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer yamlConfigurer() {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        YamlPropertiesFactoryBean yaml = new yamlPropertiesFactoryBean();
        yaml.setResources(new ClassPathResource("gok.yml"));
        configurer.setProperties(Object.requireNonNull(yaml.getObject()));
        return configurer;
    }
}
  • 采用Java原生态的方式(InputStream流)去读取文件

public class MyYamlConfig {
    public void yamlConfigurer() {
        Properties props = new Properties();
        try {
            InputStreamReader reader = new InputStreamReader(
                    this.getClass().getClassLoader().getResourceAsStream("gok.properties"),
                    StandardCharsets.UTF_8);
            props.load(reader);
        } catch (IOException e) {
        }
        String name = props.getProperty("xxx.yyy");
    }
}

解决跨域的方式

  • 首先了解什么是跨域:两个URL的协议/域名/IP/端口不同就会产生跨域。跨域是在前端才会发生的问题,因为浏览器有一个同源策略,这是防止不安全的不同域访问,所以会抛出异常(也就是跨域问题)。

  • Jsoup

    • 前端使用Ajax的jsoup方式,同时后端每个接口的参数都接收一个String callback,并且将其放到JSONObject的第一个参数返回。仅支持GET请求,而且存在安全问题。

  • CORS

    • 前端无需多做处理,后端有三种方式可以进行实现

      • 在接口上使用@CrossOrign注解,并且可以带上请求的协议以及域名/IP以及端口,比如"http://localhost:8080"

  • 让配置类(@Configuration)去实现WebMvcConfigurer接口重写addCorsMappings()方法。这个的弊端主要是浏览器会自动添加一些附加的头信息,甚至还会多发送一次附加的请求,第一次就是"options",第二次才是接口真正调用的请求方法。

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 添加映射路径
                .allowedOriginPatterns("*") // 设置放行哪些原始域 SpringBoot2.4.4低版本使用.allowedOrigins
                .allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS") // 放行哪些请求方式
                .allowCredentials(true) // 是否发送Cookie
                .maxAge(3600)
                .allowedHeaders("*"); // 暴露哪些原始请求头部信息
    }
  • Nginx

    • 使用反向代理不需要在前后端多做处理,不需要添加代码量。只需要在Nginx的nginx.conf文件的server中进行配置,这里就略微详细说明一下:listen 端口; location /前端路径/ { proxy_pass http://localhost:8080/后端路径 }。  

可以同时处理多少请求?

  • 在yml中的Tomcat中配置(因为这是Spring Boot默认的Web容器)。配置与请求线程相关的配置进行测试。

    server:
      tomcat:
      	# 最大连接数
        max-connections: 30
        # 最大等待数
        accept-count: 10
        threads:
        	# 最少线程数
        	min-spare: 10
        	# 最多线程数
        	max: 50
  • 可以使用ApiPost/JMeter进行并发测试。如下所示就是测试结果。我们不难发现:首先执行了30个线程,而后先执行完的10个线程又再一次进来执行了。这说明了1s可以处理40次请求,并且这40次请求中可以一次性处理30次,而最多可以等待10次。即配置中的accept-count(最大等待数) + max-connections(最大连接数)。

  • 在spring-configuration-metadata.json中可以发现最大连接数默认为10000,最大等待数为100。注意:我打开的是SpringBoot2.2.1版本,每个版本可能不一样

默认的日志框架以及如何切换

  • 默认情况下SpringBoot会采用slf4j(日志接口) + logback(日志框架)完成日志的实现。那么我们从哪里可以得出来呢?看过源码的基本都知道使用LoggerFactory中获取Logger对象从而记录日志的,所以我也创建了此对象来记录日志。

  •  而这个LoggerFactory与Logger都是slf4j的日志接口,其中slf4j内有三种日志框架:logback(默认)、log4j、jul-to-slf4j

  •  那么如何做到切换默认的日志实现框架呢?这里有两种情况:

    • 将logback切换为lof4j2:这样就需要将logback的场景启动器排除,因为slf4j这个日志接口只能运行1个桥接器。并且添加log4j2的场景启动器

      <!-- 如果不是Web应用就在spring-boot-starter中排除依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          <exclusions>
              <!-- 排除logback的场景启动器 -->
              <exclusion>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-logging</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
      
      <!-- Log4j2场景启动器 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-log4j2</artifactId>
      </dependency>
    • 将logback切换为log4j。就需要将logback的桥接器排除。

      <!-- 如果不是Web应用就在spring-boot-starter中排除依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          <exclusions>
              <!-- 排除logback的场景启动器 -->
              <exclusion>
                  <groupId>logback-classic</groupId>
                  <artifactId>ch.qos.logback</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
      
      <!-- Log4j桥接器 -->
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
      </dependency>

如何优化启动速度

  • 延迟初始化Bean

    • 一般在SpringBoot中拥有很多的耗时任务,比如数据库连接、初始化线程池创建等等。我们可以延迟这些操作的初始化,来达到优化启动速度的目的。可以在yml中配置:spring:main:lazy-initialization: true。来将所有的Bean延迟初始化(懒加载机制)。

  • 创建扫描索引(Spring 5.0+)

    • 通过编译时创建一个静态候选列表来提高大型应用程序的启动性能。在项目中使用@Indexed之后,编译打包后的时候会在项目中自动生成META-INF/spring.components文件。当Spring应用上下文执行ComponentScan扫描时,就会用CandidateComponentsIndexLoader读取这个文件并加载,转换为CandidateComponentsIndex对象。

    • 步骤如下:引入依赖、启动类加上注解@Indexed。首次编译运行后会在/target/classes/META-INF中生成文件

      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-indexer</artifactId>
          <optional>true</optional>
      </dependency>

  • 减少@ComponentScan即@SpringBootApplication扫描类的范围

  • 关闭SpringBoot的JMX监控,yml中设置:spring:jmx:enabled: false

  • 设置JVM参数 -noverify,不对类进行验证

  • 排除项目中多余的依赖jar

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

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

相关文章

DAY20

题目一 一个字符串 最少分隔几个部分 让它全都是回文字符串 做一个dp[][]数组 dp[i][j] 表示i....j位置上的字符串是否为回文字符串 依赖于dp[i1][j-1] 也就是左边界缩一个格子 右边界缩一个格子 basecase 对角线 dp[i][i]只有一个字符 必为回文 最后一列 倒数第二行的格子…

SpringBoot案例-部门管理-修改

目录 前言 查看页面原型&#xff0c;明确需求 页面原型 需求 阅读接口文件 思路分析 功能接口开发 控制层&#xff08;Controller类&#xff09; 业务层&#xff08;Service类&#xff09; 业务类 业务实现类 持久层&#xff08;Mapper类&#xff09; 接口测试 前…

网络编程小项目-tftp下载

tftp下载模型 TFTP通信过程总结 服务器在69号端口等待客户端的请求服务器若批准此请求&#xff0c;则使用 临时端口 与客户端进行通信。每个数据包的编号都有变化&#xff08;从1开始&#xff09;每个数据包都要得到ACK的确认&#xff0c;如果出现超时&#xff0c;则需要重新发…

Ubuntu 连接海康智能相机步骤(亲测,成功读码)

ubuntu20.04下连接海康智能相机 Ubuntu 连接海康智能相机步骤(亲测&#xff0c;已成功读码)输出的结果 Ubuntu 连接海康智能相机步骤(亲测&#xff0c;已成功读码) (就是按照海康的提供的步骤和源码连接相机&#xff0c;流水账) 安装Ubuntu20.04安装gcc和g&#xff0c;IDmvs只…

746.使用最小花费爬楼梯

class Solution {public int minCostClimbingStairs(int[] cost) {int[] dp new int[cost.length];dp[0] cost[0];dp[1] cost[1];for(int i2;i<cost.length;i){dp[i] Math.min(dp[i-1],dp[i-2])cost[i];}return Math.min(dp[cost.length-1],dp[cost.length-2]);} } 经典…

你知道什么是电商私域吗?

电商私域是当前电子商务领域中的一个热门概念&#xff0c;它指的是电商平台和商家之间建立起的用户亲密关系&#xff0c;通过运用品牌内容和数据等方式&#xff0c;通过私域流量的运营和管理&#xff0c;实现用户精细化运营和增长。 在过去&#xff0c;电商平台主要依赖于流量…

Delphi7通过VB6之COM对象调用FreeBASIC写的DLL功能

VB6写ActiveX COM组件比较方便&#xff0c;不仅PowerBASIC与VB6兼容性好&#xff0c;Delphi7与VB6兼容性也不错&#xff0c;但二者与FreeBASIC兼容性在字符串处理上差距比较大&#xff0c;FreeBASIC是C化的语言&#xff0c;可直接使用C指令。下面还是以实现MKI/CVI, MKL/CVL, M…

LinuxC编程——进程间通信(一)(管道)

目录 一、Linux平台通信方式发展史二、进程间通信方式⭐⭐⭐三、无名管道3.1 特点⭐⭐⭐3.2 函数pipe3.3 注意事项⭐⭐⭐3.4 练习 四、有名管道4.1 特点⭐⭐⭐4.2 函数 mkfifo4.3 注意事项⭐⭐4.4 练习 五、无名管道与有名管道对比⭐⭐ 复杂的编程环境通常使用多个相关的进程来…

【周末闲谈】人工智能热潮下的AIGC到底指的是什么?

生成式人工智能AIGC&#xff08;Artificial Intelligence Generated Content&#xff09;是人工智能1.0时代进入2.0时代的重要标志。 个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 系列目录 ✨第一周 二进制VS三进制 ✨第二周 文心一…

HTML5 基础标签

目录 前言 标题标签 段落标签 换行标签和水平线标签 文本格式化标签 图像标签 超链接标签 多媒体标签 列表标签 无序列表 有序列表 表格 合并单元格 表单 无语义的布局标签 字符实体 前言 当今互联网时代&#xff0c;网页是我们获取信息、交流和展示自己的重要渠…

【SpringBoot学习笔记】04. Thymeleaf模板引擎

模板引擎 所有的html元素都可以被thymeleaf替换接管 th:元素名 templates下的只能通过Controller来跳转&#xff0c;templates前后端分离&#xff0c;需要模板引擎thymeleaf支持 模板引擎的作用就是我们来写一个页面模板&#xff0c;比如有些值呢&#xff0c;是动态的&#x…

Leetcode-每日一题【剑指 Offer 27. 二叉树的镜像】

题目 请完成一个函数&#xff0c;输入一个二叉树&#xff0c;该函数输出它的镜像。 例如输入&#xff1a; 4 / \ 2 7 / \ / \ 1 3 6 9 镜像输出&#xff1a; 4 / \ 7 2 / \ / \ 9 6 3 1 示例 1&#xff1a; 输入&#xff1a;root [4,2,…

实验二十六、RC桥式正弦波振荡电路参数选择

一、题目 电路如图1所示。利用 Multisim 分析下列问题&#xff1a; &#xff08;1&#xff09;选择合适的 R f R_f Rf​ 和稳压管&#xff0c;使电路产生正弦波振荡&#xff0c;并观察起振过程&#xff1b; &#xff08;2&#xff09;调整电路参数&#xff0c;使输出电压峰值…

2. 获取自己CSDN文章列表并按质量分由小到大排序(文章质量分、博客质量分、博文质量分)(阿里云API认证)

文章目录 写在前面步骤打开CSDN质量分页面粘贴查询文章url按F12打开调试工具&#xff0c;点击Network&#xff0c;点击清空按钮点击查询是调了这个接口https://bizapi.csdn.net/trends/api/v1/get-article-score用postman测试调用这个接口&#xff08;不行&#xff0c;认证不通…

Linux 基础篇(六)sudo和添加信任用户

一、sudo 1.是什么&#xff1f; 给被信任的普通用户授权&#xff0c;让被信任的普通用户能执行root用户才能执行的命令的一个命令。 2.为什么&#xff1f; 很多时候我们要在被信任的普通用户下执行一些root用户才能执行的命令&#xff0c;如 yum… 所以需要有一个命令能给普通用…

阿里云预装LAMP应用导致MySQL不显示访问密码如何解决

&#x1f600;前言 本篇博文是关于阿里云云服务器ECS部署MySQL过程中出现的一下坑&#xff0c;希望能够帮助到您&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家…

[静态时序分析简明教程(九)]多周期路径set_multicycle_path

静态时序分析简明教程-多周期路径 一、写在前面1.1 快速导航链接 二、多周期路径2.1 多周期路径的SDC命令2.2 路径常规约束2.3 建立/保持规格2.4 位移量2.5 多时钟周期案例 三、总结 一、写在前面 一个数字芯片工程师的核心竞争力是什么&#xff1f;不同的工程师可能给出不同的…

C语言 字符指针

1、介绍 概念&#xff1a; 字符指针&#xff0c;就是字符类型的指针&#xff0c;同整型指针&#xff0c;指针指向的元素表示整型一样&#xff0c;字符指针指向的元素表示的是字符。 假设&#xff1a; char ch a;char * pc &ch; pc 就是字符指针变量&#xff0c;字符指…

群晖安装wireguard(群晖7.1)

前言 上篇文章介绍了乌班图如何安装wireguard&#xff0c;但是感觉虚拟机安装有损优雅性。 本期视频我们介绍使用群晖安装wireguard。 由于原来黑群晖内核版本太低了。 我这里升级到群晖dns918&#xff08;7.1版本&#xff09; 内核版本为4.4 实际上这仍然不满足wireguar…

知识图谱基本工具Neo4j使用笔记 四 :使用csv文件批量导入图谱数据

文章目录 一、系统说明二、说明三、简单介绍1. 相关代码以及参数2. 简单示例 四、实际数据实践1. 前期准备&#xff08;1&#xff09; 创建一个用于测试的neo4j数据库&#xff08;2&#xff09;启动neo4j 查看数据库 2. 实践&#xff08;1&#xff09; OK 上面完成后&#xff0…