解救应用启动危机:Spring Boot的FailureAnalyzer机制
目录
一、走进FailureAnalyzer
二、在Spring Boot中如何生效
三、为什么可能需要自定义FailureAnalyzer
四、实现自定义基本步骤
(一)完整步骤要求
(二)注册方式说明
通过Spring Boot的spring.factories文件(建议方式)
在启动类中手动注册(本人不建议)
五、实现自定义举例
六、一些建议
一、走进FailureAnalyzer
想象一下,你正在开发一个基于Spring Boot的网络应用程序,你已经编写了一大堆代码,做了各种配置,终于迫不及待地想要启动你的应用程序,看看它是不是如你所愿地运行。
你兴奋地运行了启动命令,但突然间,控制台上出现了一堆红色的错误信息。如下:
可以立刻看到这个报错来自于LoggingFailureAnalysisReporter,其内部其实就是Spring Boot中被誉为故障排查神器的工具FailureAnalyzer
。你决定让它出马,看看能否解决你的问题。
你应该感到非常惊讶和兴奋,因为FailureAnalyzer
不仅仅找出了问题,还给出了解决方案:按照建议修复了配置,再次启动应用程序,这一次一切都运行得非常顺利。
通过这个简单的场景,你立刻感受到了FailureAnalyzer
的价值和魔力。它就像是你的应用程序启动的保险,让你在遇到问题时能够迅速找出解决方案,让你的开发过程更加流畅和高效。
二、在Spring Boot中如何生效
在Spring Boot的spring.factories
文件(位于META-INF
目录下)中已经包含了一些FailureAnalyzer
的配置,FailureAnalyzer
实现类通常在spring.factories
文件中被声明,以便在应用程序启动时被Spring Boot自动发现并注册。
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.jdbc.DataSourceFailedAnalyzer,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectFailureAnalyzer,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisJmsConnectionFailureAnalyzer,\
org.springframework.boot.autoconfigure.jms.hornetq.HornetQConnectFailureAnalyzer,\
org.springframework.boot.autoconfigure.jms.hornetq.HornetQDependencyExceptionAnalyzer,\
org.springframework.boot.autoconfigure.solr.SolrExceptionAnalyzer,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBeanNotAvailableAnalyzer,\
org.springframework.boot.cloud.CloudPlatformConnectorsFailureAnalyzer,\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessorFailureAnalyzer,\
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessorChecker,\
org.springframework.boot.devtools.autoconfigure.DevToolsMissingFilterFailureAnalyzer,\
org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfiguration$LocalDevToolsFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideAnalyzer,\
org.springframework.boot.diagnostics.analyzer.IllegalComponentScanFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidEmbeddedServletContainerConfigurationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidTemplateAvailabilityProviderAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NonCompatibleConfigurationClassFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.SingleConstructorInjectionAnalyzer
当应用程序启动失败时,Spring Boot会自动触发这个机制,尝试识别和处理启动失败的原因,并提供有用的诊断信息和解决方案。
三、为什么可能需要自定义FailureAnalyzer
当然,如果有需要的话,我们可以
自定义FailureAnalyzer
来更灵活地处理应用程序启动失败的情况,提供更精准的故障诊断和解决方案等,特别是针对做基础架构的同学。
理由 | 说明 |
---|---|
特定错误情况处理 | 默认的 |
额外的诊断信息 | 默认的 |
集成外部系统 | 应用程序与外部系统集成,而启动失败可能是由于与这些外部系统的交互出现问题所致。通过自定义可以集成额外的逻辑,例如调用外部API或检查外部系统的状态,以诊断和解决与外部系统相关的问题。 |
定制化的解决方案 | 某些错误情况需要特定的解决方案,通过自定义可以根据应用程序的特定需求或约束,提供定制化的解决方案,以更好地满足应用程序的需求。 |
四、实现自定义基本步骤
(一)完整步骤要求
要实现自定义的FailureAnalyzer,我们需要完成以下步骤:
- 自定义异常,并创建检查要求规定。
- 创建一个类并实现AbstractFailureAnalyzer接口,重写analyze()方法,用于分析异常并返回FailureAnalysis对象。
- 将自定义的FailureAnalyzer类注册到Spring Boot应用程序中。
注意在 Spring Boot 应用程序中,自定义的多个失败分析器在实现上没有固定的先后次序。当应用程序启动时,Spring Boot 会自动扫描并注册所有的失败分析器,然后按照它们的类名顺序进行调用。这意味着,无论你如何组织和编写你的失败分析器类,它们都将在应用程序启动时同时注册,并且没有先后次序。
(二)注册方式说明
要让自定义的FailureAnalyzer
生效注册到Spring Boot应用程序中,一般有两种方法:
通过Spring Boot的spring.factories
文件(建议方式)
- 在
src/main/resources
目录下创建一个名为META-INF/spring.factories
的文件(如果已存在则跳过此步骤)。 - 在
spring.factories
文件中添加用于实现的自定义FailureAnalyzer类,和上文中展示的spring.factories
文件中的格式一样。
在启动类中手动注册(本人不建议)
在Spring Boot应用程序的启动类(@SpringBootApplication)中手动注册FailureAnalyzer
:
public static void main(String[] args) {SpringApplication application = new SpringApplication(ZYFApplication.class);application.addListeners(new ConfigFileFailureAnalyzer());application.run(args);}
后续列举一些案例,但是情况请依据实际项目需求来定。我一般是以上面建议方式进行写的注册。
五、实现自定义举例
假设我们的应用程序在启动时需要加载某些特定的配置文件,但如果对应配置文件不存在将导致应用程序启动失败。默认的FailureAnalyzer
可能无法准确地识别或处理这种特定情况,因此我们可以自定义一个FailureAnalyzer
来处理这种特定的错误情况。
首先定义必要文件未找到异常如下:
package org.zyf.javabasic.spring.failureanalyzer.exception;/*** @program: zyfboot-javabasic* @description: ConfigFileNotFoundException* @author: zhangyanfeng* @create: 2024-05-02 17:25**/
public class ConfigFileNotFoundException extends RuntimeException {private final String fileNames;public ConfigFileNotFoundException(String fileNames) {super("Configuration file '" + fileNames + "' not found");this.fileNames = fileNames;}public String getFileNames() {return fileNames;}
}
接着创建检查类对我们系统要求的必要文件作出基本的检查并返回要求文件异常基本信息:
package org.zyf.javabasic.spring.failureanalyzer.checker;import com.google.common.collect.Lists;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.zyf.javabasic.spring.failureanalyzer.exception.ConfigFileNotFoundException;import javax.annotation.PostConstruct;
import java.util.List;/*** @program: zyfboot-javabasic* @description: 系统必要配置文件检查* @author: zhangyanfeng* @create: 2024-05-02 18:14**/
@Component
public class ConfigFileNotFoundChecker {private final ResourceLoader resourceLoader;public ConfigFileNotFoundChecker(ResourceLoader resourceLoader) {this.resourceLoader = resourceLoader;}public boolean exists(String fileName) {Resource resource = resourceLoader.getResource("classpath:" + fileName);return resource.exists();}@PostConstructpublic void checkConfigFiles() throws ConfigFileNotFoundException {// 要检查的文件列表List<String> filesToCheck = Lists.newArrayList();filesToCheck.add("application.yml");filesToCheck.add("zyf_application_context.xml");filesToCheck.add("report-config.xml");filesToCheck.add("urlzyf.properties");// 存储不存在的文件名List<String> notFoundFiles = Lists.newArrayList();// 检查每个文件是否存在for (String fileName : filesToCheck) {if (!exists(fileName)) {notFoundFiles.add(fileName);}}// 如果存在未找到的文件,则抛出异常if (!notFoundFiles.isEmpty()) {throw new ConfigFileNotFoundException(notFoundFiles.toString());}}
}
接着创建并实现AbstractFailureAnalyzer,重写analyze()方法如下:
package org.zyf.javabasic.spring.failureanalyzer.analyzer;import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.zyf.javabasic.spring.failureanalyzer.exception.ConfigFileNotFoundException;
import org.zyf.javabasic.spring.failureanalyzer.exception.RequiredPropertyException;/*** @program: zyfboot-javabasic* @description: 检查必要文件是否存在异常* @author: zhangyanfeng* @create: 2024-05-02 18:26**/
public class ZYFConfigFileFailureAnalyzer extends AbstractFailureAnalyzer<ConfigFileNotFoundException> {@Overrideprotected FailureAnalysis analyze(Throwable rootFailure, ConfigFileNotFoundException cause) {String description = description(cause);String action = action(cause);return new FailureAnalysis(description, action, cause);}private String description(ConfigFileNotFoundException ex) {return String.format("Failed to load configuration file '%s'.", ex.getFileNames());}private String action(ConfigFileNotFoundException ex) {return String.format("Check if the configuration file:'%s' exists.", ex.getFileNames());}
}
spring.factories中增加本次新增验证:
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.zyf.javabasic.spring.failureanalyzer.analyzer.ZYFConfigFileFailureAnalyzer
现在其中本地未创建ourlzyf.properties文件,故程序启动报错如下:
符合我们的预期。
接着如果要求针对报告配置文件 report-config.xml
中必须包含数据库连接信息和报告生成器的情况,并要求有更加详细和严格的配置文件格式验证,接着我们继续定义一个异常类且需要指明异常情况。
先定义一个这种类型返回的基本配置错误信息如下:
package org.zyf.javabasic.spring.failureanalyzer.model;/*** @program: zyfboot-javabasic* @description: 表示不同的错误类型,例如缺少必要属性、属性值格式错误等* @author: zhangyanfeng* @create: 2024-05-02 19:57**/
public class ConfigFileFormatErrorInfo {private final boolean fileNotFound;private final ErrorType errorType;private final String fileName;public ConfigFileFormatErrorInfo(boolean fileNotFound, ErrorType errorType, String fileName) {this.fileNotFound = fileNotFound;this.errorType = errorType;this.fileName = fileName;}public boolean isFileNotFound() {return fileNotFound;}public ErrorType getErrorType() {return errorType;}public String getFileName() {return fileName;}public DescriptionAndAction getDescriptionAndAction() {String description;String action;if (fileNotFound) {description = "Configuration file '" + fileName + "' not found";action = "Check if the configuration file exists.";} else {switch (errorType) {case MISSING_PROPERTY:description = "Missing required property in configuration file '" + fileName + "'";action = "Ensure all required properties are provided in the configuration file.";break;case INVALID_VALUE:description = "Invalid value for property in configuration file '" + fileName + "'";action = "Correct the value of the property in the configuration file.";break;case OTHER:default:description = "Other configuration file format error in file '" + fileName + "'";action = "Review the configuration file for formatting issues.";break;}}return new DescriptionAndAction(description, action);}public enum ErrorType {MISSING_PROPERTY,INVALID_VALUE,OTHER}
}package org.zyf.javabasic.spring.failureanalyzer.model;/*** @program: zyfboot-javabasic* @description: DescriptionAndAction* @author: zhangyanfeng* @create: 2024-05-02 20:19**/
public class DescriptionAndAction {private final String description;private final String action;public DescriptionAndAction(String description, String action) {this.description = description;this.action = action;}public String getDescription() {return description;}public String getAction() {return action;}
}
然后定义基本的异常信息如下:
package org.zyf.javabasic.spring.failureanalyzer.exception;import com.alibaba.fastjson.JSON;
import org.zyf.javabasic.spring.failureanalyzer.model.ConfigFileFormatErrorInfo;/*** @program: zyfboot-javabasic* @description: 配置文件格式问题异常* @author: zhangyanfeng* @create: 2024-05-02 19:23**/
public class ConfigFileFormatException extends RuntimeException {private final ConfigFileFormatErrorInfo errorInfo;public ConfigFileFormatException(ConfigFileFormatErrorInfo errorInfo) {super("Configuration file format error: " + JSON.toJSONString(errorInfo));this.errorInfo = errorInfo;}public ConfigFileFormatErrorInfo getErrorInfo() {return errorInfo;}}
检查指定的配置文件(report-config.xml)是否符合预期的格式要求:
- 必须包含一个名为 "dataSource" 的 Bean 定义,用于配置数据库连接信息。
- "dataSource" Bean 中必须包含以下属性:
driverClassName
:数据库驱动类名;url
:数据库连接 URL;username
:数据库用户名;password
:数据库密码。 password
属性必须已加密,即以特定字符串开头。- 必须包含一个名为 "reportGenerator" 的 Bean 定义,用于配置报告生成器。
- "reportGenerator" Bean 中必须包含一个名为
dataSource
的属性引用,指向之前定义的 "dataSource" Bean。
如果配置文件不符合上述要求之一,就会抛出相应的异常,指示配置文件格式错误。具体对应的检查实现如下:
package org.zyf.javabasic.spring.failureanalyzer.checker;import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.zyf.javabasic.spring.failureanalyzer.exception.ConfigFileFormatException;
import org.zyf.javabasic.spring.failureanalyzer.model.ConfigFileFormatErrorInfo;import javax.annotation.PostConstruct;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;import static org.zyf.javabasic.spring.failureanalyzer.model.ConfigFileFormatErrorInfo.ErrorType.*;/*** @program: zyfboot-javabasic* @description: 指定配置文件验证逻辑* @author: zhangyanfeng* @create: 2024-05-02 20:12**/
@Component
public class ConfigFileFormatChecker {@Autowiredprivate ResourceLoader resourceLoader;@PostConstructpublic void checkConfigFileFormat() {String fileName = "report-config.xml";Resource resource = resourceLoader.getResource("classpath:" + fileName);if (!resource.exists()) {throw new ConfigFileFormatException(new ConfigFileFormatErrorInfo(true, null, fileName));}Element root = null;try (InputStream inputStream = resource.getInputStream()) {DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document document = builder.parse(new InputSource(inputStream));// 获取根元素root = document.getDocumentElement();} catch (Exception e) {throw new ConfigFileFormatException(new ConfigFileFormatErrorInfo(true, OTHER, fileName));}// 检查 dataSource Bean 定义checkDataSourceDefinition(root, fileName);// 检查报告生成器定义checkReportGeneratorDefinition(root, fileName);}private void checkDataSourceDefinition(Element root, String fileName) {// 获取 dataSource 元素NodeList dataSourceList = root.getElementsByTagName("bean");for (int i = 0; i < dataSourceList.getLength(); i++) {Element dataSourceElement = (Element) dataSourceList.item(i);String id = dataSourceElement.getAttribute("id");if ("dataSource".equals(id)) {// 获取 driverClassName 属性String driverClassName = dataSourceElement.getElementsByTagName("property").item(0).getAttributes().getNamedItem("value").getNodeValue();// 获取 url 属性String url = dataSourceElement.getElementsByTagName("property").item(1).getAttributes().getNamedItem("value").getNodeValue();// 获取 username 属性String username = dataSourceElement.getElementsByTagName("property").item(2).getAttributes().getNamedItem("value").getNodeValue();// 获取 password 属性String password = dataSourceElement.getElementsByTagName("property").item(3).getAttributes().getNamedItem("value").getNodeValue();if (StringUtils.isAnyBlank(driverClassName, url, username, password)) {throw new ConfigFileFormatException(new ConfigFileFormatErrorInfo(false, MISSING_PROPERTY, fileName));}if (!isPasswordEncrypted(password)) {throw new ConfigFileFormatException(new ConfigFileFormatErrorInfo(false, INVALID_VALUE, fileName));}}}}private void checkReportGeneratorDefinition(Element root, String fileName) {// 获取 reportGenerator 元素NodeList reportGeneratorList = root.getElementsByTagName("bean");for (int i = 0; i < reportGeneratorList.getLength(); i++) {Element reportGeneratorElement = (Element) reportGeneratorList.item(i);String id = reportGeneratorElement.getAttribute("id");if ("reportGenerator".equals(id)) {// 获取 dataSource 属性的引用String dataSourceRef = reportGeneratorElement.getElementsByTagName("property").item(0).getAttributes().getNamedItem("ref").getNodeValue();if (StringUtils.isAnyBlank(dataSourceRef)) {throw new ConfigFileFormatException(new ConfigFileFormatErrorInfo(false, MISSING_PROPERTY, fileName));}}}}private boolean isPasswordEncrypted(String password) {// 检查密码是否已加密,这里可以根据具体加密方式进行验证return password.startsWith("Zyf");}
}
接着创建并实现AbstractFailureAnalyzer,重写analyze()方法如下:
package org.zyf.javabasic.spring.failureanalyzer.analyzer;import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.zyf.javabasic.spring.failureanalyzer.exception.ConfigFileFormatException;
import org.zyf.javabasic.spring.failureanalyzer.model.ConfigFileFormatErrorInfo;
import org.zyf.javabasic.spring.failureanalyzer.model.DescriptionAndAction;/*** @program: zyfboot-javabasic* @description: 指定配置文件具体格式要求* @author: zhangyanfeng* @create: 2024-05-02 20:31**/
public class ZYFConfigFileFormatFailureanalyzer extends AbstractFailureAnalyzer<ConfigFileFormatException> {@Overrideprotected FailureAnalysis analyze(Throwable rootFailure, ConfigFileFormatException cause) {ConfigFileFormatErrorInfo errorInfo = cause.getErrorInfo();String description;String action;if (errorInfo.isFileNotFound()) {description = "Configuration file '" + errorInfo.getFileName() + "' not found";action = "Check if the configuration file exists.";} else {DescriptionAndAction descriptionAndAction = errorInfo.getDescriptionAndAction();description = descriptionAndAction.getDescription();action = descriptionAndAction.getAction();}return new FailureAnalysis(description, action, cause);}
}
spring.factories中增加本次新增验证:
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.zyf.javabasic.spring.failureanalyzer.analyzer.ZYFConfigFileFailureAnalyzer,\
org.zyf.javabasic.spring.failureanalyzer.analyzer.ZYFConfigFileFormatFailureanalyzer
但是我实际report-config.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 数据库连接信息 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/zyf"/><property name="username" value="root"/><property name="password" value="Zsyf2014"/></bean><!-- 报告生成器 --><bean id="reportGenerator" class="org.zyf.javabasic.spring.beanFactory.ReportGenerator"><property name="dataSource" ref="dataSource"/><!-- 其他配置属性 --></bean>
</beans>
由于数据库加密不正确,故程序启动报错如下:
六、一些建议
如果确定了需要创建自定义的 FailureAnalyzer
时,必须有几个注意事项:
- 确保
FailureAnalyzer
能够准确地识别失败的原因,避免误导性的诊断,帮助更快地找到并解决问题。 - 在诊断中提供尽可能详细的信息,包括失败的具体原因、发生失败的位置等。
- 提供清晰的建议或解决方案,可以包括修复代码、调整配置或执行其他操作的建议。
相关源码依旧在常用的github地址中。
相关文章:

解救应用启动危机:Spring Boot的FailureAnalyzer机制
目录 一、走进FailureAnalyzer 二、在Spring Boot中如何生效 三、为什么可能需要自定义FailureAnalyzer 四、实现自定义基本步骤 (一)完整步骤要求 (二)注册方式说明 通过Spring Boot的spring.factories文件(建…...

win11个性化锁屏界面怎么关闭?
win11个性化锁屏界面关闭方法对于win11用户来说,关闭个性化锁屏界面是一个常见问题。本文将由php小编苹果详细介绍如何执行此操作,分步指导并提供操作截图。继续阅读以了解具体步骤。 win11个性化锁屏界面关闭方法 第一步,点击底部Windows图…...

白酒:白酒香型与品质消费的关系及影响
云仓酒庄的豪迈白酒作为中国白酒的品牌,其白酒香型与品质消费的关系及影响备受关注。随着消费者对品质的重视程度不断提高,了解白酒香型与品质之间的关系对于云仓酒庄和消费者都具有重要意义。 经云仓酒庄豪迈白酒分析,白酒香型与品质消费的关…...

智能BI(后端)-- 系统优化(安全性,数据存储,限流)
文章目录 安全性todo 数据存储限流限流的几种算法限流粒度限流的实现本地限流(单机限流)Redisson实现分布式限流(多机限流) 安全性 问题引入:如果用户上传一个超大的文件怎么办?比如1000G? 预防: 只要涉及…...

探索数字社交的奇迹:解读Facebook的革命性影响
1. 社交互动的全新模式 Facebook的出现不仅仅是一个社交媒体平台的诞生,更是一种全新的社交互动模式的开启。传统的社交模式主要依赖于面对面的交流,而Facebook则将社交推向了全新的数字化平台,使得人们可以在虚拟的世界里建立和维系社交关系…...

FileCodeBox-Lite:轻量级文件分享解决方案
在数字时代,文件分享是一个常见的需求,无论是个人用户还是企业团队。FileCodeBox-Lite提供了一个简单、高效且安全的文件分享解决方案。以下是对FileCodeBox-Lite项目的详细介绍。 项目简介 FileCodeBox-Lite是一个轻量级的文件分享系统,…...

【ARM】ARM寄存器和异常处理
目录 1.指令的执行过程 2. ARM处理器概述 3.ARM指令集 4.ARM存储模型 5. ARM工作模式 6.ARM寄存器组织 (1)寄存器 (2) ARM寄存器 (3)CPSR寄存器 7. ARM异常处理 (1&am…...

数仓建模【埋点设计与管理】
埋点设计与管理 埋点的作用 分析用户转化以及留存:分析用户偏好收集市场反馈保障用户数据安全定位异常其他作用 埋点数仓设计 数据进入数仓之前我们就需要设计好数仓表,埋点表的数据有几个特点: 数据量非常大,可能是所有数据集…...

Spring Clound介绍
Spring Cloud 是一系列框架的集合,它利用 Spring Boot 的开发便利性简化了分布式系统(例如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话和集群状态)的开发。Spring Cloud 旨在为开发者…...

Redhat Linux忘记密码解决方案
1、重启系统 2、将光标移动到要启动的内核 3、按e编辑当前条目 4、将光标移动以Linux开头的行,此为内核命令行 5、在末尾添加人的rd.break 6、按ctrlx继续启动,如果发现输入的rd.break不能进入到伪系统,那么改为 rd.break consoletty0 (按ctr…...

对于子数组问题的动态规划
前言 先讲讲我对于这个问题的理解吧 当谈到解决子数组问题时,动态规划(DP)是一个强大的工具,它在处理各种算法挑战时发挥着重要作用。动态规划是一种思想,它通过将问题分解成更小的子问题并以一种递归的方式解决它们,然后利用这些…...

Instal IIS on Windows Server 2022 Datacenter
和以往版本一样,没有什么不同,So easy! WinR - ServerManager.exe 打开服务器管理器,点击【添加角色和功能】,选择自己想要的角色和功能。 一、开始之前:帮助说明,点击【下一步】;…...

飞天使-k8s知识点30-kubernetes安装1.28.0版本-使用containerd方式
文章目录 安装前准备containerd 配置内核参数优化安装nerdctl以上是所有机器全部安装开始安装初始化,这步骤容易出问题! 安装前准备 内核升级包的md5,本人已验证,只要是这个md5值,放心升级 1ea91ea41eedb35c5da12fe7030f4347 ke…...

Oracle 误操作insert delete update 数据回滚
查询回滚数据 select * from tablename AS OF TIMESTAMP TO_TIMESTAMP(2023-12-29 10:29:00,yyyy-mm-dd hh24:mi:ss) where not exists (select 1 from tablename A where A.xh tablename.xh and A.TIME tablename.TIME); TO_TIMESTAMP(2023-12-29 10:29:00,yyyy-mm-dd h…...

Linux系统(CentOS)下安装配置 Nginx 超详细图文教程
一、下载并安装 1.打开nginx官网并点击右侧的download,Nginx官网下载地址 2.选择稳定版本 我放在/usr/local/nginx/下,新建文件夹 mkdir /usr/local/nginx/ 通过xftp传输到Linux的服务器上,这里方法不过多复述。 或者如果Linux联网…...

追求完美用户体验,从变量名设计的细节抓起
在一个安静的办公室里,卧龙和凤雏正坐在电脑前忙碌地工作着。阳光透过窗户洒在他们的脸上,映照出专注的神情。 “变量命名让人摸不着头脑,光看变量名很难搞清楚它的用途。”卧龙眉头紧皱,表情严肃地说道。 “哦?具体是…...

matlab实现K均值聚类
在MATLAB中实现聚类分析,可以使用MATLAB内置的聚类函数,如kmeans(用于K均值聚类),linkage和cluster(用于层次聚类),或者使用MATLAB的统计和机器学习工具箱中的其他函数。 以下是一个…...

详解BOM编程
华子目录 BOM编程window对象常见的window对象的属性常见的window对象的方法注意 history对象history对象的属性history对象的方法 screen 对象navigator 对象属性方法 location对象属性方法示例 BOM编程 JavaScript本质是在浏览器中运行,所以JavaScript提供了BOM&a…...

情感分类学习笔记(1)
文本情感分类(二):深度学习模型 - 科学空间|Scientific Spaces 一、代码理解 cw lambda x: list(jieba.cut(x)) #定义分词函数 您给出的代码定义了一个使用 jieba 分词库的分词函数。jieba 是一个用于中文分词的 Python 库。该函数 cw 是…...

EtherCAT运动控制器Delta机械手应用
ZMC406硬件介绍 ZMC406是正运动推出的一款多轴高性能EtherCAT总线运动控制器,具有EtherCAT、EtherNET、RS232、CAN和U盘等通讯接口,ZMC系列运动控制器可应用于各种需要脱机或联机运行的场合。 ZMC406支持6轴运动控制,最多可扩展至32轴&#…...

物联网杀虫灯—新型的环保杀虫设备
型号推荐:云境天合TH-FD2S】物联网杀虫灯是一种新型环保杀虫设备,其中风吸式太阳能杀虫灯作为其一种特殊类型,展现了独特的工作原理和优势。 风吸式太阳能杀虫灯以太阳能电池板为电源,白天储存电源,晚上为杀虫灯提供电…...

加盟零食店的真是大冤种
关注卢松松,会经常给你分享一些我的经验和观点。 我一朋友,在老家县城去年失业没事干,手里有一点钱但不多,就想着自己干点啥 。最后经多方打听考察,加盟了一个零食店,前前后后花去了近五六十万,…...

力扣刷题--数组--第三天
今天再做两道二分查找的题目,关于二分查找的知识可看我前两篇博客。话不多说,直接开干! 题目1:69.x 的平方根 题目详情: 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。由于返回类型是整数&#…...

开源即时通讯IM框架 MobileIMSDK v6.5 发布
一、更新内容简介 本次更新为次要版本更新,进行了bug修复和优化升级(更新历史详见:码云 Release Notes、Github Release Notes)。 MobileIMSDK 可能是市面上唯一同时支持 UDPTCPWebSocket 三种协议的同类开源IM框架。轻量级、高…...

React 第二十七章 Hook useMemo
useMemo 函数可以用于缓存计算结果,以避免不必要的重复计算。 在React的函数组件中,当组件重新渲染时,函数组件内的所有代码都会重新执行。有些计算可能是非常消耗资源的,例如进行复杂的计算或进行网络请求。如果这些计算的结果在…...

自己写的爬虫小案例
网址:aHR0cDovL2pzc2NqZ3B0Lmp4d3JkLmdvdi5jbi8/dXJsPS92aWV3L3dvcmtpbmdVbml0L3dvcmtpbmdVbml0Lmh0bWw 这串代码能够爬取勘察单位企业的详细信息。 import requests import time import csv f open(勘察单位公司信息.csv,w,encodingutf-8,newline) csv_writer …...

Kafka 环境搭建和使用之单机模式详细教程
上一篇:Kakfa 简介及相关组件介绍 下一篇:Kafka 环境搭建之伪分布式集群详细教程 Kafka 环境搭建 Kafka的环境搭建可以根据不同的需求和场景采取不同的模式,主要包括以下几种: 单机模式(Standalone Mode): 在这种模式下,Kafka、Zookeeper 以及生产者和消费者都在同一…...

Xamarin.Android项目使用ConstraintLayout约束布局
Xamarin.AndroidX.ConstraintLayout Xamarin.Android.Support.Constraint.Layout Xamarin.AndroidX.ConstraintLayout.Solver Xamarin.AndroidX.DataBinding.ViewBinding Xamarin.AndroidX.Legacy.Support.Core.UI Xamarin.AndroidX.Lifecycle.LiveData ![在这里插入图片描述]…...

探索Java 18:未来技术趋势与革新之路
Java,作为一门历史悠久而又历久弥新的编程语言,始终站在技术发展的前沿,引领着软件开发的潮流。随着Java 18的发布,我们再次见证了这门语言的自我迭代与革新。本文将深入探讨Java 18带来的新特性、技术趋势,以及它如何…...

毕业论文怎么写? 推荐4个AI工具
写作这件事一直让我们从小学时期就开始头痛,初高中时期800字的作文让我们焦头烂额,一篇作文里用尽了口水话,拼拼凑凑才勉强完成。 大学时期以为可以轻松顺利毕业,结果毕业前的最后一道坎拦住我们的是毕业论文,这玩意不…...