小架構step系列07:查找日志配置文件

1 概述

日志這里采用logback,其為springboot默認的日志工具。其整體已經被springboot封裝得比較好了,扔個配置文件到classpath里就能夠使用。

但在實際使用中,日志配置文件有可能需要進行改動,比如日志的打印級別,平時可能定的是WARN或者ERROR級別,如果出點問題,可能希望臨時能夠調整為INFO或者DEBUG,方便產生更加豐富的日志以定位問題。如果配置文件是放到classpath里,也就會被打包到jar包里,修改配置文件就需要重新打包、部署、啟動等,很可能做不到只修改配置文件并生效。要想改變配置文件的位置,就有必要了解一下這個配置文件是如何加載的。

2 原理

2.1 logback是如何被依賴的

前面看對spring-boot-starter的依賴的時候,有個不起眼的依賴:spring-boot-starter-logging

https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter/2.7.18/spring-boot-starter-2.7.18.pom

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot</artifactId><version>2.7.18</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId><version>2.7.18</version><scope>compile</scope></dependency><!--  省略其它依賴 -->
<dependencies>

?查看spring-boot-starter-logging的依賴:https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-logging/2.7.18/spring-boot-starter-logging-2.7.18.pom

<dependencies><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.12</version><scope>compile</scope></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-to-slf4j</artifactId><version>2.17.2</version><scope>compile</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jul-to-slf4j</artifactId><version>1.7.36</version><scope>compile</scope></dependency>
</dependencies>

?logback-classic包提供了logback打印日志功能。

2.2 查找logback.xml配置文件

2.2.1 觸發查找的Listener

spring-boot-2.7.18.jar包里提供了META-INF/spring.factories配置文件,里面配置了LoggingApplicationListener:

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener

2.2.2 查找過程

Springboot提供了一個LoggingApplicationListener,其繼實現了GenericApplicationListener接口,該接口最終繼承了ApplicationListener。

按Springboot的規則,實現了ApplicationListener接口的都會被Springboot統一調用。這個類就是響應springboot的準備環境對象事件來初始化日志對象LogbackLoggingSystem的:

// 源碼位置:org.springframework.boot.context.logging.LoggingApplicationListener
public void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationStartingEvent) {onApplicationStartingEvent((ApplicationStartingEvent) event);}else if (event instanceof ApplicationEnvironmentPreparedEvent) {// 1. 在PreparedEvent的時候加載日志配置文件onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);}else if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent((ApplicationPreparedEvent) event);}else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event).getApplicationContext().getParent() == null) {onContextClosedEvent();}else if (event instanceof ApplicationFailedEvent) {onApplicationFailedEvent();}
}
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {SpringApplication springApplication = event.getSpringApplication();if (this.loggingSystem == null) {this.loggingSystem = LoggingSystem.get(springApplication.getClassLoader());}// 2. 調用日志初始化接口initialize(event.getEnvironment(), springApplication.getClassLoader());
}
protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {getLoggingSystemProperties(environment).apply();// 3. 獲取環境變量里配置的日志文件,在環境變量里配置了才有this.logFile = LogFile.get(environment);if (this.logFile != null) {this.logFile.applyToSystemProperties();}this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);initializeEarlyLoggingLevel(environment);initializeSystem(environment, this.loggingSystem, this.logFile);initializeFinalLoggingLevels(environment, this.loggingSystem);registerShutdownHookIfNecessary(environment, this.loggingSystem);
}// 源碼位置:org.springframework.boot.logging.LogFile
public static LogFile get(PropertyResolver propertyResolver) {// 4. 如果配置了logging.file.name、logging.file.path環境變量,則它們組成一個log文件的路徑,用此路徑初始化一個日志文件對象//    FILE_NAME_PROPERTY = "logging.file.name"//    FILE_PATH_PROPERTY = "logging.file.path"String file = propertyResolver.getProperty(FILE_NAME_PROPERTY);String path = propertyResolver.getProperty(FILE_PATH_PROPERTY);if (StringUtils.hasLength(file) || StringUtils.hasLength(path)) {return new LogFile(file, path);}return null;
}// 回到LoggingApplicationListener繼續處理環境變量里配置的日志文件
// 源碼位置:org.springframework.boot.context.logging.LoggingApplicationListener
protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {getLoggingSystemProperties(environment).apply();// 3. 獲取環境變量里配置的日志文件,在環境變量里配置了才有this.logFile = LogFile.get(environment);if (this.logFile != null) {// 5. 把環境變量里的配置日志文件路徑和文件名設置到系統屬性里this.logFile.applyToSystemProperties();}this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);initializeEarlyLoggingLevel(environment);initializeSystem(environment, this.loggingSystem, this.logFile);initializeFinalLoggingLevels(environment, this.loggingSystem);registerShutdownHookIfNecessary(environment, this.loggingSystem);
}// 源碼位置:org.springframework.boot.logging.LogFile
public void applyToSystemProperties() {// 6. 提供系統屬性為參數applyTo(System.getProperties());
}
public void applyTo(Properties properties) {// 7. 把配置文件的路徑和文件名設置到系統屬性里,可以在logback.xml里作為變量引用,如${LOG_PATH}//    LoggingSystemProperties.LOG_PATH = "LOG_PATH"//    LoggingSystemProperties.LOG_FILE = "LOG_FILE"put(properties, LoggingSystemProperties.LOG_PATH, this.path);put(properties, LoggingSystemProperties.LOG_FILE, toString());
}
private void put(Properties properties, String key, String value) {if (StringUtils.hasLength(value)) {properties.put(key, value);}
}// 回到LoggingApplicationListener繼續處理環境變量里配置的日志文件
// 源碼位置:org.springframework.boot.context.logging.LoggingApplicationListener
protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {getLoggingSystemProperties(environment).apply();// 3. 獲取環境變量里配置的日志文件,在環境變量里配置了才有this.logFile = LogFile.get(environment);if (this.logFile != null) {// 5. 把環境變量里的配置日志文件路徑和文件名設置到系統屬性里this.logFile.applyToSystemProperties();}this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);initializeEarlyLoggingLevel(environment);// 8. 初始化LogbackLoggingSystem對象initializeSystem(environment, this.loggingSystem, this.logFile);initializeFinalLoggingLevels(environment, this.loggingSystem);registerShutdownHookIfNecessary(environment, this.loggingSystem);
}
private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system, LogFile logFile) {// 9. 讀取logging.config配置(在命令行配置),CONFIG_PROPERTY = "logging.config"String logConfig = StringUtils.trimWhitespace(environment.getProperty(CONFIG_PROPERTY));try {LoggingInitializationContext initializationContext = new LoggingInitializationContext(environment);// 10. 調用LogbackLoggingSystem對象的初始化方法,//     如果配置了logging.config,則把配置的文件作為logConfig參數傳入,否則logConfig參數為nullif (ignoreLogConfig(logConfig)) {system.initialize(initializationContext, null, logFile);}else {system.initialize(initializationContext, logConfig, logFile);}}// 省略其它代碼
}// 源碼位置:org.springframework.boot.logging.logback.LogbackLoggingSystem
// 注意:configLocation有null和非null兩種情況
public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {LoggerContext loggerContext = getLoggerContext();if (isAlreadyInitialized(loggerContext)) {return;}// 11. 調用父類的初始化方法,父類為AbstractLoggingSystemsuper.initialize(initializationContext, configLocation, logFile);loggerContext.getTurboFilterList().remove(FILTER);markAsInitialized(loggerContext);if (StringUtils.hasText(System.getProperty(CONFIGURATION_FILE_PROPERTY))) {getLogger(LogbackLoggingSystem.class.getName()).warn("Ignoring '" + CONFIGURATION_FILE_PROPERTY+ "' system property. Please use 'logging.config' instead.");}
}// 源碼位置:org.springframework.boot.logging.AbstractLoggingSystem
public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {// 12. 如果logging.config配置的值不為空,加載配置指定的日志配置文件if (StringUtils.hasLength(configLocation)) {initializeWithSpecificConfig(initializationContext, configLocation, logFile);return;}// 13. 當沒有配置logging.config時,則加載默認的配置文件,這里重點關注默認的initializeWithConventions(initializationContext, logFile);
}
private void initializeWithSpecificConfig(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) {// 配置了logging.config的時候,主要是先把里面可能出現${}占位符替換為實際值,// 然后得到一個正常的日志配置文件路徑,按正常流程處理,參考下面對loadConfiguration()的說明configLocation = SystemPropertyUtils.resolvePlaceholders(configLocation);loadConfiguration(initializationContext, configLocation, logFile);
}
private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) {// 14. 獲取可能的默認的日志配置文件路徑String config = getSelfInitializationConfig();if (config != null && logFile == null) {reinitialize(initializationContext);return;}if (config == null) {config = getSpringInitializationConfig();}if (config != null) {loadConfiguration(initializationContext, config, logFile);return;}loadDefaults(initializationContext, logFile);
}
protected String getSelfInitializationConfig() {// 15. getStandardConfigLocations()獲取默認的日志配置文件return findConfig(getStandardConfigLocations());
}// 源碼位置:org.springframework.boot.logging.logback.LogbackLoggingSystem
protected String[] getStandardConfigLocations() {// 16. 默認支持四種配置文件名稱,注意其順序,帶test的在前面,logback.xml是最后一種//     如果開發環境了放logback-test.xml和logback.xml,生產環境只放logback.xml,//     則可以開發環境用的是帶test的,不影響生產文件的修改,會比較便利return new String[] { "logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml" };
}// 回到AbstractLoggingSystem的getSelfInitializationConfig(),調用findConfig()
// 源碼位置:org.springframework.boot.logging.AbstractLoggingSystem
protected String getSelfInitializationConfig() {// 17. 調findConfig()查找配置文件的路徑return findConfig(getStandardConfigLocations());
}
private String findConfig(String[] locations) {// 18. 遍歷每個可能的配置文件名,調用Spring提供的ClassPathResource,從classpath中檢查文件是否存在,即上面指定的4中文件需要放到classpath中//     如果存在,則在文件名的前面加上classpath:路徑前綴,注意這里體現順序,只要找到第一個就返回for (String location : locations) {ClassPathResource resource = new ClassPathResource(location, this.classLoader);if (resource.exists()) {return "classpath:" + location;}}return null;
}// 回到AbstractLoggingSystem的initializeWithConventions(),繼續處理獲取到的日志文件路徑
// 源碼位置:org.springframework.boot.logging.AbstractLoggingSystem
private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) {// 14. 獲取可能的默認的日志配置文件路徑String config = getSelfInitializationConfig();if (config != null && logFile == null) {// 15. 重新初始化,這里并沒有傳入找到的文件,因為里面還會再找一次reinitialize(initializationContext);return;}if (config == null) {config = getSpringInitializationConfig();}if (config != null) {loadConfiguration(initializationContext, config, logFile);return;}loadDefaults(initializationContext, logFile);
}// 源碼位置:org.springframework.boot.logging.logback.LogbackLoggingSystem
protected void reinitialize(LoggingInitializationContext initializationContext) {getLoggerContext().reset();getLoggerContext().getStatusManager().clear();// 16. 加載配置文件,這里重新調了getSelfInitializationConfig(),從classpath找配置文件路徑,參考上面步驟17loadConfiguration(initializationContext, getSelfInitializationConfig(), null);
}
protected void loadConfiguration(LoggingInitializationContext initializationContext, String location, LogFile logFile) {// 如果logFile有值,則調父類的方法加載配置文件,沒有用到location,這里先忽略// logFile是前面從環境變量里獲取的日志配置文件路徑和文件名super.loadConfiguration(initializationContext, location, logFile);LoggerContext loggerContext = getLoggerContext();stopAndReset(loggerContext);try {// 17. 用url的方式加載文件,ResourceUtils.getURL(location)把以classpath前綴的路徑轉為文件絕對路徑,比如classpath:logback.xmlconfigureByResourceUrl(initializationContext, loggerContext, ResourceUtils.getURL(location));}catch (Exception ex) {throw new IllegalStateException("Could not initialize Logback logging from " + location, ex);}reportConfigurationErrorsIfNecessary(loggerContext);
}// 源碼位置:org.springframework.boot.logging.logback.LogbackLoggingSystem
private void configureByResourceUrl(LoggingInitializationContext initializationContext, LoggerContext loggerContext, URL url) throws JoranException {if (XML_ENABLED && url.toString().endsWith("xml")) {JoranConfigurator configurator = new SpringBootJoranConfigurator(initializationContext);configurator.setContext(loggerContext);// 18. SpringBootJoranConfigurator繼承了logback-classic包的類GenericConfigurator,從而轉到logback-classic包進行日志文件處理了//     GenericConfigurator提供了doConfigure()方法實際加載配置文件,由logback包完成日志對象的初始化configurator.doConfigure(url);}else {new ContextInitializer(loggerContext).configureByResource(url);}
}// 上面看的是如果配置了日志文件(如logback.xml的情況),回到AbstractLoggingSystem.initialize()看看沒有配置日志文件的情況
// 源碼位置:org.springframework.boot.logging.AbstractLoggingSystem
private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) {// 14. 獲取可能的默認的日志配置文件路徑String config = getSelfInitializationConfig();if (config != null && logFile == null) {reinitialize(initializationContext);return;}// 19. 如果沒有配置日志文件,可找spring提供的日志配置文件if (config == null) {config = getSpringInitializationConfig();}if (config != null) {loadConfiguration(initializationContext, config, logFile);return;}loadDefaults(initializationContext, logFile);
}// 源碼位置:org.springframework.boot.logging.AbstractLoggingSystem
protected String getSpringInitializationConfig() {// 20. 找配置文件return findConfig(getSpringConfigLocations());
}
protected String[] getSpringConfigLocations() {// 21. 先找標準文件,參考步驟16可得logback-test.groovy、logback-test.xml、logback.groovy、logback.xmlString[] locations = getStandardConfigLocations();// 22. 給每個文件名加上-spring后綴,作為新的文件名,如logback.xml轉為logback-spring.xmlfor (int i = 0; i < locations.length; i++) {String extension = StringUtils.getFilenameExtension(locations[i]);locations[i] = locations[i].substring(0, locations[i].length() - extension.length() - 1) + "-spring." + extension;}return locations;
}// 回到AbstractLoggingSystem.initialize()繼續加載帶-spring后綴的日志配置文件
// 源碼位置:org.springframework.boot.logging.AbstractLoggingSystem
private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) {// 14. 獲取可能的默認的日志配置文件路徑String config = getSelfInitializationConfig();if (config != null && logFile == null) {reinitialize(initializationContext);return;}// 19. 如果沒有配置日志文件,可找spring提供的日志配置文件if (config == null) {config = getSpringInitializationConfig();}// 23. 加載日志配置文件,方式同步驟17if (config != null) {loadConfiguration(initializationContext, config, logFile);return;}// 24. 如果spring的配置文件也沒有,則加載默認的,保證一定可以打印日志loadDefaults(initializationContext, logFile);
}// 默認的日志是把日志格式等硬編碼在代碼里的,一般也不使用,大概參考一下即可
// 源碼位置:org.springframework.boot.logging.logback.DefaultLogbackConfiguration
private void defaults(LogbackConfigurator config) {config.conversionRule("clr", ColorConverter.class);config.conversionRule("wex", WhitespaceThrowableProxyConverter.class);config.conversionRule("wEx", ExtendedWhitespaceThrowableProxyConverter.class);config.getContext().putProperty("CONSOLE_LOG_PATTERN", resolve(config, "${CONSOLE_LOG_PATTERN:-"+ "%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) "+ "%clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} "+ "%clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"));String defaultCharset = Charset.defaultCharset().name();config.getContext().putProperty("CONSOLE_LOG_CHARSET", resolve(config, "${CONSOLE_LOG_CHARSET:-" + defaultCharset + "}"));config.getContext().putProperty("FILE_LOG_PATTERN", resolve(config, "${FILE_LOG_PATTERN:-"+ "%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] "+ "%-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"));config.getContext().putProperty("FILE_LOG_CHARSET", resolve(config, "${FILE_LOG_CHARSET:-" + defaultCharset + "}"));config.logger("org.apache.catalina.startup.DigesterFactory", Level.ERROR);config.logger("org.apache.catalina.util.LifecycleBase", Level.ERROR);config.logger("org.apache.coyote.http11.Http11NioProtocol", Level.WARN);config.logger("org.apache.sshd.common.util.SecurityUtils", Level.WARN);config.logger("org.apache.tomcat.util.net.NioSelectorPool", Level.WARN);config.logger("org.eclipse.jetty.util.component.AbstractLifeCycle", Level.ERROR);config.logger("org.hibernate.validator.internal.util.Version", Level.WARN);config.logger("org.springframework.boot.actuate.endpoint.jmx", Level.WARN);
}

2.2.3 小結

SpringBoot加載日志配置文件的核心過程:
  • 如果在啟動參數里通過-Dlogging.config指定了日志配置文件,則直接加載此日志配置文件;這種方法指定的配置文件,可以使用${}占位符引用系統屬性或者系統環境變量。
  • 如果沒有手工指定,則從classpath目錄下按順序加載四種日志配置文件(logback-test.groovy、logback-test.xml、logback.groovy、logback.xml),只要加載到一個就返回。
  • 如果還是沒有找到日志配置文件,則加上-spring后綴再嘗試按順序加載logback-test-spring.groovy、logback-test-spring.xml、logback-spring.groovy、logback-spring.xml,只要加載到一個就返回。
  • 如何還沒有加載到日志配置文件,則加載默認的,默認的日志配置是硬編碼到代碼里的。

3 使用

了解原理之后,可以來考慮一下,如何使用。Springboot提供的日志配置文件名有4種:logback-test.groovy、logback-test.xml、logback.groovy、logback.xml,一般情況已經夠用了,看看如何用好就可以。

3.1 不需要修改配置文件的場景

如果日志配置文件放到服務器環境上就不需要改動了,那么最簡單的方式就是直接放到classpath中,在idea里就是放到resources目錄下,打包時則是放到classes目錄下打包。按上面原理就可以直接加載使用。

3.2 需要修改配置文件的場景

有下面幾種場景需要更改日志配置文件:
  • 在生產環境中,一般日志級別只會開到WARN甚至ERROR級別,如果想看INFO甚至DEBUG級別的日志就有可能看不到,在定位棘手問題時可能需要更詳細的日志信息。此時如果想修改一下日志級別,那么就希望配置文件能夠改動一下。
  • 日志配置的一些參數配置不理想,想調整一下。比如日志文件過大或者過小,不利于日志文件維護。
  • 增加一些場景的日志打印,比如原來沒有加spring相關的日志控制,比較影響問題定位,希望加上spring相關日志只有ERROR才打印的控制等。
如果是在生產環境中,若因為日志配置文件的改動,就需要重新打包并重啟,那代價有點大。所以偏向不把配置文件放到jar中,此時可以在啟動參數指定-Dlogging.config=logback.xml,則會加載jar外同級目錄的配置文件;如果配置文件在別的目錄,也可以指定絕對路徑。

3.3 測試和生產分開的場景

如果配置文件是打包到jar里的,那么生產環境使用的配置文件和平時開發測試用的配置文件有可能是不一樣的。如果只維護一個文件,那么很容易把測試的配置帶到了生產環境中,這是不允許的。按照上面的加載文件順序的原理,帶test的是放前面的,比如logback-test.xml是在logback.xml前面的,那就可以同時維護這兩個文件,開發測試的時候使用帶test的,打包到生產環境的時候只打包不帶test的配置文件,由于打包工具是工具化的,就不容易出現漏掉的情況。

4 架構一小步

增加日志配置文件:
  • 開發測試環境,在代碼src/main/resources目錄下放一個帶test的配置文件(如logback-test.xml),springboot優先加載帶test是日志配置文件;一般也放一個不帶test的配置文件,作為代碼版本管理的一部分。
  • 在部署環境的時候,不把logback.xml文件打包到jar中,而是放到和jar包同級的config/logback.xml中,使用啟動參數-Dlogging.config手工指定配置文件。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88255.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88255.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88255.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一文講清楚React Hooks

文章目錄一文講清楚React Hooks一、什么是 React Hooks&#xff1f;二、常用基礎 Hooks2.1 useState&#xff1a;狀態管理基本用法特點2.2 useEffect&#xff1a;副作用處理基本用法依賴數組說明2.3 useContext&#xff1a;上下文共享基本用法特點三、其他常用 Hooks3.1 useRed…

Apache http 強制 https

1. 修改一下文件配置 sudo nano /etc/apache2/sites-enabled/000-default.conf<VirtualHost *:80>ServerName hongweizhu.comServerAlias www.hongweizhu.comServerAdmin webmasterlocalhostDocumentRoot /var/www/html# 強制重定向到HTTPSRewriteEngine OnRewriteCond …

【讀代碼】GLM-4.1V-Thinking:開源多模態推理模型的創新實踐

一、基本介紹 1.1 項目背景 GLM-4.1V-Thinking是清華大學KEG實驗室推出的新一代開源視覺語言模型,基于GLM-4-9B-0414基礎模型構建。該項目通過引入"思維范式"和強化學習課程采樣(RLCS)技術,顯著提升了模型在復雜任務中的推理能力。其創新點包括: 64k超長上下文…

從代碼生成到智能運維的革命性變革

AI大模型重塑軟件開發&#xff1a;從代碼生成到智能運維的革命性變革 希望對大家有一定的幫助&#xff0c;進行參考 目錄AI大模型重塑軟件開發&#xff1a;從代碼生成到智能運維的革命性變革 希望對大家有一定的幫助&#xff0c;進行參考一、范式轉移&#xff1a;軟件開發進入&…

豆包編寫Java程序小試

今天下載了一本第四版電氣工程師手冊&#xff0c;非常棒的一本書&#xff0c;在給PDF添加目錄的時候&#xff0c;由于目錄有將近60頁&#xff0c;使用老馬開發的PdgCntEditor有點卡頓&#xff0c;不過補充下&#xff0c;老馬這個PdgCntEditor還是非常好的。所以我決定用Java編一…

SpringBoot整合騰訊云新一代行為驗證碼

一 產品介紹 騰訊云官方介紹鏈接 騰訊云新一代行為驗證碼&#xff08;Captcha&#xff09;&#xff0c;基于十道安全防護策略&#xff0c;為網頁、App、小程序開發者打造立體、全面的人機驗證。在保護注冊登錄、活動秒殺、點贊發帖、數據保護等各大場景下業務安全的同時&…

SenseGlove新一代外骨骼力反饋手套Rembrand來襲!亞毫米級手部動捕+指尖觸覺力采集+5Dof主動力反饋多模態

在遠程機器人操作領域&#xff0c;精準的觸覺感知與靈活的動作控制始終是核心需求。SenseGlove 新推出的 Rembrandt 力反饋外骨骼數據手套&#xff0c;以先進技術為支撐&#xff0c;為遠程操控人形機器人手部提供了無縫解決方案&#xff0c;讓操作更精準、更高效。值得一提的是…

Linux 信號機制:操作系統的“緊急電話”系統

想象一下&#xff0c;你正在電腦前專心工作&#xff0c;突然手機響了——這是一個通知&#xff0c;要求你立即處理一件新事情&#xff08;比如接電話&#xff09;。 Linux 系統中的信號&#xff08;Signal&#xff09;?? 機制&#xff0c;本質上就是操作系統內核或進程之間用…

論文略讀:Prefix-Tuning: Optimizing Continuous Prompts for Generation

2021 ACL固定預訓練LM&#xff0c;為LM添加可訓練&#xff0c;任務特定的前綴這樣就可以為不同任務保存不同的前綴這種前綴可以看成連續可微的soft prompt&#xff0c;相比于離散的token&#xff0c;更好優化&#xff0c;效果更好訓練的時候只需要更新prefix部分的參數&#xf…

CSS基礎選擇器、文本屬性、引入方式及Chorme調試工具

CSS基礎 1.1 CSS簡介 CSS 是層疊樣式表 ( Cascading Style Sheets ) 的簡稱. 有時我們也會稱之為 CSS 樣式表或級聯樣式表。 CSS 是也是一種標記語言 CSS 主要用于設置 HTML 頁面中的文本內容&#xff08;字體、大小、對齊方式等&#xff09;、圖片的外形&#xff08;寬高、邊…

RabbitMQ 高級特性之事務

1. 簡介與 MySQL、Redis 一樣&#xff0c;RabbitMQ 也支持事務。事務中的消息&#xff0c;要么全都發送成功&#xff0c;要么全部發送失敗&#xff0c;不會出現一部分成功一部分失敗的情況。2. 使用事務發送消息spring 中使用 RabbitMQ 開啟事務需要兩步&#xff1a;第一步&…

iframe 的同源限制與反爬機制的沖突

一、事件背景A域名接入了動態防護&#xff08;Bot 防護、反爬蟲機制&#xff09;&#xff0c;同時第三方業務B域名通過內嵌iframe的方式調用了A域名下的一個鏈接。二、動態防護介紹&#xff1a;動態防護&#xff08;也稱為 Bot 防護、反爬蟲機制&#xff09;是網站為了防止自動…

Rust 的 Copy 語義:深入淺出指南

在 Rust 中&#xff0c;Copy 是一個關鍵的特性&#xff0c;它定義了類型的復制行為。理解 Copy 語義對于掌握 Rust 的所有權系統和編寫高效代碼至關重要。一、核心概念&#xff1a;Copy vs Move特性Copy 類型非 Copy 類型 (Move)賦值行為按位復制 (bitwise copy)所有權轉移 (ow…

Qt的信號與槽(二)

Qt的信號與槽&#xff08;二&#xff09;1.自定義槽2.通過圖形化界面來生成自定義槽3.自定義信號3.信號和槽帶參數4.參數數量5.connect函數的設計&#x1f31f;hello&#xff0c;各位讀者大大們你們好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f680;系列專欄&#xf…

Java研學-MongoDB(三)

三 文檔相關 7 文檔統計查詢① 語法&#xff1a; // 精確統計文檔數 慢 準 dahuang> db.xiaohuang.countDocuments({條件}) 4 // 粗略統計文檔數 快 大致準 dahuang> db.xiaohuang.estimatedDocumentCount({條件}) 4② 例子&#xff1a; // 精確統計文檔數 name為奔波兒灞…

TCP協議格式與連接釋放

TCP報文段格式 TCP雖然是面向字節流的&#xff0c;但TCP傳送帶數據單元確是報文段。TCP報文段分為首部和數據段部分&#xff0c;而TCP的全部功能體現在它在首部中各字段的作用。因此&#xff0c;只有弄清TCP首部各字段的作用才能掌握TCP的工作原理。 TCP報文段首部的前20字節是…

CSS05:結構偽類選擇器和屬性選擇器

結構偽類選擇器 /*ul的第一個子元素*/ ul li:first-child{background: #0af6f6; }/*ul的最后一個子元素*/ ul li:last-child{background: #d27bf3; } /*選中p1&#xff1a;定位到父元素&#xff0c;選擇當前的第一個元素 選擇當前p元素的父級元素&#xff0c;選中父級元素的第…

使用策略模式 + 自動注冊機制來構建旅游點評系統的搜索模塊

? 目標&#xff1a; 搜索模塊支持不同內容類型&#xff08;攻略、達人、游記等&#xff09;每種搜索邏輯用一個策略類表示自動注冊&#xff08;基于注解 Spring 容器&#xff09;新增搜索類型時&#xff0c;只需添加一個類 一個注解&#xff0c;無需改工廠、注冊表等&#x…

第八十九篇 大數據開發中的數據算法:貪心策略 - 生活中的“精打細算”藝術

在資源有限的世界里&#xff0c;貪心算法教會我們&#xff1a;局部最優的累積&#xff0c;往往是通往全局最高效的捷徑。本文通過3個生活化場景原創圖表&#xff0c;揭示大數據開發中最實用的優化策略。目錄一、貪心算法核心思想&#xff1a;當下即最優二、三大核心應用場景詳解…

【論文閱讀】Dynamic Few-Shot Visual Learning without Forgetting

系統概述如下: (a) 一個基于卷積神經網絡(ConvNet)的識別模型,該模型包含特征提取器和分類器; (b) 一個少樣本分類權重生成器。這兩個組件都是在一組基礎類別上訓練的,我們為這些類別準備了大量訓練數據。在測試階段,權重生成器會接收少量新類別的訓練數據以及基礎類別的…