解救应用启动危机: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轴&#…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...