当前位置: 首页 > news >正文

深入Spring Boot:自定义Starter开发与实践

引言

Spring Boot通过其强大的自动配置机制和丰富的Starter模块,极大地简化了Spring应用的开发过程。Starter模块封装了一组相关的依赖和配置,使得开发者可以通过简单的依赖引入,快速启用特定的功能。然而,除了使用Spring Boot提供的官方Starter模块,开发者还可以根据自己的需求开发自定义Starter,从而进一步扩展Spring Boot的功能。

本文将深入探讨Spring Boot自定义Starter的开发与实践。我们将从Starter的基本概念出发,逐步介绍自定义Starter的开发流程、核心原理以及最佳实践,并通过一个完整的示例项目展示如何开发和使用自定义Starter。

一、Spring Boot Starter基础

1.1 什么是Starter?

Starter是Spring Boot的核心组件之一,它是一种依赖管理机制,旨在简化Spring应用的开发过程。通过引入一个Starter模块,开发者可以快速启用Spring Boot提供的特定功能,而无需手动管理复杂的依赖和配置。

例如,spring-boot-starter-web是一个常用的Starter模块,它封装了Spring MVC和嵌入式Servlet容器(如Tomcat)的依赖,开发者只需在pom.xmlbuild.gradle中引入该模块,即可快速启动一个Web应用。

1.2 Starter的核心特性

  1. 依赖管理:Starter模块通过pom.xmlbuild.gradle文件管理一组相关的依赖,确保这些依赖的版本一致性和兼容性。

  2. 自动配置:Starter模块通常结合Spring Boot的自动配置机制,通过@EnableAutoConfiguration注解自动加载相关的配置类,从而实现“零配置”启动。

  3. 简化开发:通过封装常用的配置和依赖,Starter模块使得开发者可以更专注于业务逻辑的实现,而无需手动管理复杂的配置代码。

1.3 官方Starter模块

Spring Boot提供了大量的官方Starter模块,涵盖了Web开发、数据访问、消息队列、安全等多个领域。例如:

  • spring-boot-starter-web:支持Web开发,包括Spring MVC和嵌入式Servlet容器。

  • spring-boot-starter-data-jpa:支持JPA数据访问,包括Spring Data JPA和Hibernate。

  • spring-boot-starter-security:支持Spring Security,用于用户认证和授权。

  • spring-boot-starter-actuator:支持Spring Boot Actuator,用于监控应用的运行状态。

这些官方Starter模块为开发者提供了强大的功能支持,但它们并不能满足所有场景的需求。在某些情况下,开发者可能需要开发自定义Starter模块,以实现特定的功能或集成第三方库。

二、为什么需要自定义Starter?

尽管Spring Boot提供了丰富的官方Starter模块,但在实际开发中,开发者可能遇到以下场景,需要开发自定义Starter:

  1. 集成第三方库:当需要集成某个第三方库时,可以通过开发自定义Starter模块,封装该库的依赖和配置,使其更易于使用。

  2. 封装通用功能:在企业级开发中,项目之间可能存在一些通用的功能模块,如日志管理、配置管理等。通过开发自定义Starter模块,可以将这些通用功能封装起来,便于在多个项目中复用。

  3. 简化项目配置:通过自定义Starter模块,可以将复杂的配置逻辑封装起来,通过简单的配置文件或注解实现功能的启用和定制。

  4. 扩展Spring Boot功能:自定义Starter模块可以扩展Spring Boot的功能,使其支持更多的技术栈或框架。

开发自定义Starter模块不仅可以提升开发效率,还可以提高代码的可维护性和可扩展性。

三、开发自定义Starter的基本步骤

开发自定义Starter模块的核心目标是封装依赖和配置,使得开发者可以通过简单的依赖引入快速启用特定的功能。以下是开发自定义Starter的基本步骤:

3.1 创建Starter项目

开发自定义Starter模块的第一步是创建一个独立的项目。通常,Starter项目包含两个模块:

  1. 核心模块:封装核心功能和依赖。

  2. 自动配置模块:封装自动配置逻辑。

例如,我们创建一个名为my-spring-boot-starter的项目,包含以下结构:

复制

my-spring-boot-starter
├── my-spring-boot-starter-core
│   ├── src/main/java/com/example/core
│   └── src/main/resources
└── my-spring-boot-starter-autoconfigure├── src/main/java/com/example/autoconfigure└── src/main/resources

3.2 核心模块开发

核心模块是Starter模块的核心部分,它封装了功能实现和依赖。例如,如果我们要开发一个日志管理的Starter模块,核心模块可以包含日志管理的工具类和依赖。

3.2.1 定义功能接口

在核心模块中,定义一个功能接口,用于声明Starter模块提供的功能。例如:

java复制

package com.example.core;public interface MyService {void doSomething();
}
3.2.2 实现功能接口

实现上述接口,提供具体的功能实现。例如:

java复制

package com.example.core;public class MyServiceImpl implements MyService {@Overridepublic void doSomething() {System.out.println("MyService is doing something...");}
}
3.2.3 管理依赖

在核心模块的pom.xml文件中,管理相关的依赖。例如:

xml复制

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency>
</dependencies>

3.3 自动配置模块开发

自动配置模块是Starter模块的关键部分,它通过Spring Boot的自动配置机制,实现功能的自动加载和配置。

3.3.1 创建自动配置类

在自动配置模块中,创建一个自动配置类,通过@Conditional注解定义配置的加载条件。例如:

java复制

package com.example.autoconfigure;import com.example.core.MyService;
import com.example.core.MyServiceImpl;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ConditionalOnClass(MyService.class)
public class MyAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic MyService myService() {return new MyServiceImpl();}
}

在上述代码中,@ConditionalOnClass注解确保只有当MyService类在类路径中时,才会加载该配置类;@ConditionalOnMissingBean注解确保只有当Spring容器中没有MyService的Bean时,才会创建一个默认的MyServiceImpl实例。

3.3.2 定义spring.factories文件

Spring Boot通过spring.factories文件加载自动配置类。在自动配置模块的resources目录下创建一个META-INF/spring.factories文件,并添加以下内容:

properties复制

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfigure.MyAutoConfiguration

这样,Spring Boot在启动时会自动加载MyAutoConfiguration类,并根据条件注解决定是否启用该配置。

3.3.3 管理依赖

在自动配置模块的pom.xml文件中,添加对核心模块的依赖。例如:

xml复制

<dependencies><dependency><groupId>com.example</groupId><artifactId>my-spring-boot-starter-core</artifactId><version>1.0.0</version></dependency>
</dependencies>

3.4 打包与发布

开发完成后,将Starter模块打包为jar文件,并发布到Maven仓库。这样,其他项目可以通过引入该Starter模块的依赖,快速启用其功能。

四、自定义Starter的核心原理

4.1 自动配置机制

Spring Boot的自动配置机制是自定义Starter的核心。通过@EnableAutoConfiguration注解,Spring Boot会自动扫描META-INF/spring.factories文件中定义的自动配置类,并根据条件注解决定是否启用这些配置。

条件注解是自动配置的关键,常用的条件注解包括:

  • @ConditionalOnClass:当指定的类在类路径中时,加载配置。

  • @ConditionalOnMissingClass:当指定的类不在类路径中时,加载配置。

  • @ConditionalOnBean:当Spring容器中存在指定的Bean时,加载配置。

  • @ConditionalOnMissingBean:当Spring容器中不存在指定的Bean时,加载配置。

  • @ConditionalOnProperty:当指定的配置属性满足条件时,加载配置。

通过这些条件注解,开发者可以灵活地控制配置的加载时机,从而实现“零配置”启动。

4.2 条件注解的使用

条件注解是自定义Starter的核心,通过合理使用条件注解,可以实现灵活的自动配置。

4.2.1 @ConditionalOnClass

@ConditionalOnClass注解用于判断指定的类是否在类路径中。如果指定的类存在,则加载配置。例如:

java复制

@Configuration
@ConditionalOnClass(MyService.class)
public class MyAutoConfiguration {// 配置内容
}

在上述代码中,只有当MyService类在类路径中时,才会加载MyAutoConfiguration类。

4.2.2 @ConditionalOnMissingBean

@ConditionalOnMissingBean注解用于判断Spring容器中是否已经存在指定的Bean。如果不存在,则创建一个默认的Bean。例如:

java复制

@Bean
@ConditionalOnMissingBean
public MyService myService() {return new MyServiceImpl();
}

在上述代码中,只有当Spring容器中没有MyService的Bean时,才会创建一个MyServiceImpl实例。

4.2.3 @ConditionalOnProperty

@ConditionalOnProperty注解用于判断配置文件中的属性是否满足条件。例如:

java复制

@Configuration
@ConditionalOnProperty(name = "my.service.enabled", havingValue = "true")
public class MyAutoConfiguration {// 配置内容
}

在上述代码中,只有当application.properties文件中定义了my.service.enabled=true时,才会加载MyAutoConfiguration类。

4.3 配置绑定

Spring Boot支持将配置文件中的属性绑定到Java对象中,从而实现配置的动态管理。

4.3.1 定义配置属性类

通过@ConfigurationProperties注解定义配置属性类,将配置文件中的属性绑定到Java对象中。例如:

java复制

package com.example.autoconfigure;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "my.service")
public class MyServiceProperties {private boolean enabled;private String message;// 省略getter和setter方法
}

在上述代码中,my.service.enabledmy.service.message属性将被绑定到MyServiceProperties类的enabledmessage字段中。

4.3.2 使用配置属性

在自动配置类中,可以通过@EnableConfigurationProperties注解启用配置属性类。例如:

java复制

@Configuration
@EnableConfigurationProperties(MyServiceProperties.class)
public class MyAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic MyService myService(MyServiceProperties properties) {MyServiceImpl service = new MyServiceImpl();service.setMessage(properties.getMessage());return service;}
}

在上述代码中,MyServiceProperties类的属性将被注入到MyServiceImpl实例中。

4.4 自定义Starter的加载机制

Spring Boot通过spring.factories文件加载自定义Starter的自动配置类。在启动时,Spring Boot会扫描META-INF/spring.factories文件中定义的自动配置类,并根据条件注解决定是否启用这些配置。

例如,spring.factories文件的内容如下:

properties复制

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfigure.MyAutoConfiguration

在上述代码中,MyAutoConfiguration类将被加载并根据条件注解决定是否启用。

五、自定义Starter开发实践

5.1 示例项目:开发一个日志管理Starter

为了更好地理解自定义Starter的开发过程,我们通过一个具体的示例项目展示如何开发一个日志管理Starter模块。该Starter模块将封装日志管理的功能,包括日志记录和日志级别管理。

5.1.1 创建项目结构

创建一个名为log-spring-boot-starter的项目,包含以下结构:

复制

log-spring-boot-starter
├── log-spring-boot-starter-core
│   ├── src/main/java/com/example/log/core
│   └── src/main/resources
└── log-spring-boot-starter-autoconfigure├── src/main/java/com/example/log/autoconfigure└── src/main/resources
5.1.2 核心模块开发

在核心模块中,定义日志管理的功能接口和实现类。

定义功能接口

java复制

package com.example.log.core;public interface LogService {void log(String message);
}
实现功能接口

java复制

package com.example.log.core;public class LogServiceImpl implements LogService {@Overridepublic void log(String message) {System.out.println("Log: " + message);}
}
管理依赖

在核心模块的pom.xml文件中,管理相关的依赖。例如:

xml复制

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency>
</dependencies>
5.1.3 自动配置模块开发

在自动配置模块中,创建一个自动配置类,实现日志管理功能的自动配置。

创建自动配置类

java复制

package com.example.log.autoconfigure;import com.example.log.core.LogService;
import com.example.log.core.LogServiceImpl;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ConditionalOnClass(LogService.class)
public class LogAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic LogService logService() {return new LogServiceImpl();}
}
定义spring.factories文件

在自动配置模块的resources目录下创建一个META-INF/spring.factories文件,并添加以下内容:

properties复制

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.log.autoconfigure.LogAutoConfiguration
管理依赖

在自动配置模块的pom.xml文件中,添加对核心模块的依赖。例如:

xml复制

<dependencies><dependency><groupId>com.example</groupId><artifactId>log-spring-boot-starter-core</artifactId><version>1.0.0</version></dependency>
</dependencies>
5.1.4 打包与发布

开发完成后,将Starter模块打包为jar文件,并发布到Maven仓库。这样,其他项目可以通过引入该Starter模块的依赖,快速启用日志管理功能。

5.2 示例项目:使用自定义Starter

为了验证自定义Starter的功能,我们创建一个Spring Boot项目,并引入上述日志管理Starter模块。

5.2.1 创建Spring Boot项目

通过Spring Initializr创建一个Spring Boot项目,选择spring-boot-starter-web依赖。

5.2.2 引入自定义Starter依赖

pom.xml文件中,引入日志管理Starter模块的依赖。例如:

xml复制

<dependency><groupId>com.example</groupId><artifactId>log-spring-boot-starter</artifactId><version>1.0.0</version>
</dependency>
5.2.3 使用日志管理功能

在Spring Boot项目中,注入LogService并使用其功能。例如:

java复制

package com.example.demo;import com.example.log.core.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class LogController {@Autowiredprivate LogService logService;@GetMapping("/log")public String logMessage() {logService.log("Hello, Log Service!");return "Message logged successfully.";}
}

运行项目并访问/log接口,可以看到控制台输出日志信息:

Log: Hello, Log Service!

通过上述示例,我们可以看到自定义Starter模块的开发和使用过程。开发者可以通过简单的依赖引入,快速启用日志管理功能,而无需手动管理复杂的配置代码。

六、自定义Starter的最佳实践

开发自定义Starter模块时,需要注意以下最佳实践,以确保Starter模块的可扩展性和易用性。

6.1 遵循Spring Boot的命名规范

Spring Boot的Starter模块通常以spring-boot-starter-<name>命名,例如spring-boot-starter-web。自定义Starter模块也应遵循这一命名规范,以便开发者能够快速识别其功能。

例如,如果开发一个日志管理的Starter模块,可以命名为log-spring-boot-starter

6.2 使用条件注解控制配置加载

通过合理使用条件注解,可以灵活地控制配置的加载时机,从而实现“零配置”启动。常用的条件注解包括@ConditionalOnClass@ConditionalOnMissingBean@ConditionalOnProperty等。

例如,通过@ConditionalOnClass注解可以判断指定的类是否在类路径中,从而决定是否加载配置。

6.3 提供默认配置和自定义配置

自定义Starter模块应提供默认配置,同时允许开发者通过配置文件或注解自定义配置。通过@ConfigurationProperties注解可以将配置文件中的属性绑定到Java对象中,从而实现配置的动态管理。

例如,可以通过定义MyServiceProperties类,将配置文件中的属性绑定到Java对象中。

6.4 提供清晰的文档和示例

自定义Starter模块的文档和示例是帮助开发者快速上手的关键。文档应包括Starter模块的功能介绍、依赖引入、配置方法和使用示例。

例如,可以通过Markdown格式编写文档,介绍如何引入依赖、配置属性和使用功能。

6.5 测试自定义Starter

开发自定义Starter模块时,需要进行充分的测试,以确保其功能正确性和兼容性。可以通过编写单元测试和集成测试,验证Starter模块的依赖管理、自动配置和功能实现。

例如,可以通过Spring Boot的测试支持模块spring-boot-starter-test编写测试用例,验证Starter模块的功能。

七、自定义Starter的高级特性

7.1 配置属性的动态刷新

Spring Boot支持配置属性的动态刷新,通过@RefreshScope注解可以实现配置的动态更新。

例如,可以通过定义@RefreshScope注解的Bean,实现配置属性的动态刷新。

java复制

@RefreshScope
@Bean
public MyService myService(MyServiceProperties properties) {MyServiceImpl service = new MyServiceImpl();service.setMessage(properties.getMessage());return service;
}

在上述代码中,当配置文件中的my.service.message属性发生变化时,MyServiceImpl实例的message字段将自动更新。

7.2 提供自定义注解

自定义Starter模块可以通过提供自定义注解,简化配置和功能启用。

例如,可以通过定义@EnableMyService注解,启用日志管理功能。

java复制

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MyAutoConfiguration.class)
public @interface EnableMyService {
}

在上述代码中,@EnableMyService注解通过@Import注解导入MyAutoConfiguration类,从而启用日志管理功能。

7.3 集成第三方库

自定义Starter模块可以封装第三方库的依赖和配置,使其更易于使用。

例如,可以通过定义@ConditionalOnClass注解,判断第三方库的类是否在类路径中,从而决定是否加载配置。

java复制

@Configuration
@ConditionalOnClass(LogService.class)
public class LogAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic LogService logService() {return new LogServiceImpl();}
}

在上述代码中,只有当第三方库的LogService类在类路径中时,才会加载LogAutoConfiguration类。

八、总结

自定义Starter模块是Spring Boot扩展功能的重要方式之一。通过开发自定义Starter模块,开发者可以封装依赖和配置,简化项目开发过程,提升开发效率。

本文从Starter的基本概念出发,详细介绍了自定义Starter的开发流程、核心原理以及最佳实践,并通过一个完整的示例项目展示了如何开发和使用自定义Starter模块。希望本文对您在Spring Boot项目中开发自定义Starter有所帮助。

在实际开发中,开发者可以根据项目需求和个人偏好选择合适的开发方式。无论开发何种类型的Starter模块,都应遵循Spring Boot的设计理念,提供简洁、易用且功能强大的模块,帮助开发者更高效地构建Spring Boot应用。

相关文章:

深入Spring Boot:自定义Starter开发与实践

引言 Spring Boot通过其强大的自动配置机制和丰富的Starter模块&#xff0c;极大地简化了Spring应用的开发过程。Starter模块封装了一组相关的依赖和配置&#xff0c;使得开发者可以通过简单的依赖引入&#xff0c;快速启用特定的功能。然而&#xff0c;除了使用Spring Boot提…...

MasterSAM downloadService任意文件读取(CVE-2024-55457)(附脚本)

免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 0x0…...

【Pytest】基础到高级功能的理解使用

文章目录 第一部分&#xff1a;Pytest 简介1.1 什么是 Pytest&#xff1f;1.2 Pytest 的历史1.3 Pytest 的核心概念1.4 Pytest 的特点1.5 为什么选择 Pytest&#xff1f; 第二部分&#xff1a;Pytest 的基本使用2.1 安装 Pytest2.2 编写第一个测试用例2.2.1 创建一个简单的测试…...

【Linux系统编程】—— 从零开始实现一个简单的自定义Shell

文章目录 什么是自主shell命令行解释器&#xff1f;实现shell的基础认识全局变量的配置初始化环境变量实现内置命令&#xff08;如 cd 和 echo&#xff09;cd命令&#xff1a;echo命令&#xff1a; 构建命令行提示符获取并解析用户输入的命令执行内置命令与外部命令Shell的主循…...

探索云原生可观测性:技术与团队协作的深度结合

TheNewStack 出品的电子书《Cloud Native Observability for DevOps Teams》读后感&#xff0c;老书新读&#xff0c;还是另有一番领悟。 阅读原文请转到&#xff1a;https://jimmysong.io/blog/cloud-native-observability-devops/ 最近读了 TheNewStack 发布的电子书《Cloud …...

Vue基础(2)

19、组件之间传递数据 组件与组件之间不是完全独立的&#xff0c;而是有交集的&#xff0c;那就是组件与组 件之间是可以传递数据的 传递数据的解决方案就是 props ComponentA.vue <template><!-- 使用ComponentB组件&#xff0c;并传递title属性 --><h3>…...

Yearning开源MySQL SQL审核平台

一款MYSQL SQL语句/查询审计工具&#xff0c;为DBA与开发人员使用. 本地部署&#xff0c;注重隐私&#xff0c;简单高效的MYSQL审计平台。 它可以通过流程审批&#xff0c;实现真实线上环境sql的审核和执行&#xff0c;还可以回滚执行&#xff0c;能够确保线上SQL更新的可靠性…...

《鸿蒙Next应用商店:人工智能开启智能推荐与运营新时代》

在科技飞速发展的当下&#xff0c;鸿蒙Next系统的出现为操作系统领域带来了新的变革与机遇&#xff0c;而人工智能技术的融入更是让其应用商店的智能化推荐和运营迈向了一个全新的高度。 用户画像精准构建 在鸿蒙Next系统中&#xff0c;应用商店可以借助系统强大的权限管理和…...

SSTI注入

ssti漏洞成因 ssti服务端模板注入&#xff0c;ssti主要为python的一些框架 jinja2 mako tornado django&#xff0c;PHP框架smarty twig&#xff0c;java框架jade velocity等等使用了渲染函数时&#xff0c;由于代码不规范或信任了用户输入而导致了服务端模板注入&#xff0c;…...

根据经纬度查询地理位置信息API

API 概述 接口名称&#xff1a;查询地理位置信息V2接口类型&#xff1a;HTTP GET接口地址&#xff1a;https://api.kertennet.com/geography/locationInfo_v2请求编码格式&#xff1a;utf-8 请求说明 请求头部 标签类型必填说明参数示例Content-Typestring是请求的内容类型…...

【知识分享】PCIe5.0 TxRx 电气设计参数汇总

目录 0 引言 1 参考时钟--Refclk 2 发射端通道设计 3 发送均衡技术 4 接收端通道设计 5 接收均衡技术 6 结语 7 参考文献 8 扩展阅读 0 引言 PCI Express Base Specification 5.0的电气规范中&#xff0c;关键技术要点如下&#xff1a; 1. 支持2.5、5.0、8.0、16.0和3…...

Airsim 项目结构分析

Airsim 项目结构分析 本文只分析最核心的 AirLib 项目结构&#xff0c;以及其与 Unreal 项目的关系 假如已经根据 Airsim 主页&#xff0c;克隆了完整项目。 Build on Linux - AirSim 克隆源码 # go to the folder where you clone GitHub projects git clone https://git…...

STM32+W5500+以太网应用开发+003_TCP服务器添加OLED(u8g2)显示状态

STM32W5500以太网应用开发003_TCP服务器添加OLED&#xff08;u8g2&#xff09;显示状态 实验效果3-TCP服务器OLED1 拷贝显示驱动代码1.1 拷贝源代码1.2 将源代码添加到工程1.3 修改代码优化等级1.4 添加头文件路径1.5 修改STM32CubeMX工程 2 修改源代码2.1 添加头文件2.2 main函…...

SQLmap 注入-03 获得用户信息

1: Sqlmap 先进入库&#xff0c;然后进入table, 然后列出column: sqlmap -u "http://192.168.56.133/mutillidae/index.php?pageuser-info.php&usernamexiaosheng&passwordabc&user-info-php-submit-buttonViewAccountDetails" --batch -p username -D …...

Kafka 和 MQ 的区别

1.概述 1.1.MQ简介 消息中间件&#xff0c;其实准确的叫法应该叫消息队列&#xff08;message queue&#xff09;&#xff0c;简称MQ。其本质上是个队列&#xff0c;有FIFO的性质&#xff0c;即first in first out&#xff0c;先入先出。 目前市场上主流的MQ有三款&#xff…...

若依报错:无法访问com.ruoyi.common.annotation

无法访问com.ruoyi.common.annotation 若依的父工程的pom文件中设置了jdk为1.8&#xff0c;将idea的jdk也改为1.8即可。...

MCU、MPU、SOC、ECU、CPU、GPU的区别到底是什么

MCU、MPU、SOC、ECU、CPU、GPU的区别 参数MCUMPUSoCECUCPUGPU处理能力低至中中至高综合&#xff0c;视具体设计而定专用于汽车控制中至高高&#xff08;并行能力强&#xff09;集成度高低高高低&#xff08;需配合主板使用&#xff09;低&#xff08;通常作为外部设备&#xff…...

档案事业与数据要素之间有什么关系?

在数字时代背景下&#xff0c;档案事业正经历着前所未有的变革。随着大数据、云计算、人工智能等技术的快速发展&#xff0c;档案数据已成为重要的基础性战略资源和关键生产要素。那么档案事业与数据要素之间究竟有什么关系&#xff1f; 一、档案数据要素的内涵与价值 数据要…...

HarmonyOS NEXT:华为分享-碰一碰开发分享

随着科技的不断进步&#xff0c;智能手机和智能设备之间的互联互通变得越来越重要。华为作为科技行业的领军企业&#xff0c;一直致力于为用户提供更加便捷、高效的使用体验。HarmonyOS NEXT系统的推出&#xff0c;特别是其中的“碰一碰”功能&#xff0c;为用户带来了前所未有…...

nuxt3项目打包部署到服务器后配置端口号和开启https

nuxt3打包后的项目部署相对于一般vite打包的静态文件部署要稍微麻烦一些&#xff0c;还有一个主要的问题是开发环境配置的.env环境变量在打包后部署时获取不到&#xff0c;具体的解决方案可以参考我之前文章 nuxt3项目打包后获取.env设置的环境变量无效的解决办法。 这里使用的…...

面试:Hadoop,块,HDFS的优缺点,HDFS的读写流程

Hadoop CDH会简化Hadoop的安装 Hue主要用于数据分析和处理&#xff0c;而CM(Cloudera Manager)则主要用于集群的管理和运维。 HDFS HDFS的块 块是 HDFS 系统当中的最小存储单位, 在hadoop2.0和3.0中默认128MB 在HDFS上的文件会被拆分成多个块&#xff0c;每个块作为独立的单…...

Codeforces Round 903 (Div. 3) E. Block Sequence

题解&#xff1a; 想到从后向前DP f[i] 表示从 i ~ n 转化为“美观”所需要的最少的步骤 第一种转移方式&#xff1a;直接删除掉第i个元素&#xff0c;那么就是上一步 f[i 1] 加上 1;第二种转移方式&#xff1a;从第 i a[i] 1 个元素直接转移&#xff0c;不需要增加步数&a…...

web-view环境下,H5页面打开其他小程序

在Web-view环境下&#xff0c;H5页面无法直接打开其他小程序。正确的实现方式是先从H5页面跳转回当前小程序&#xff0c;再由当前小程序跳转到目标小程序。具体实现方法如下&#xff1a; H5页面跳转回小程序时&#xff0c;调用wx.miniProgram.navigateTo()方法。 小程序跳转到…...

C语言之饭店外卖信息管理系统

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 C语言之饭店外卖信息管理系统 目录 设计题目设计目的设计任务描述设计要求输入和输出要求验…...

【三维分割】Gaga:通过3D感知的 Memory Bank 分组任意高斯

文章目录 摘要一、引言二、主要方法2.1 3D-aware Memory Bank2.2 三维分割的渲染与下游应用 三、实验消融实验应用: Scene Manipulation 地址&#xff1a;https://www.gaga.gallery 标题&#xff1a;Gaga: Group Any Gaussians via 3D-aware Memory Bank 来源&#xff1a;加利福…...

【Linux系统】—— 编译器 gcc/g++ 的使用

【Linux系统】—— 编译器 gcc/g 的使用 1 用 gcc 直接编译2 翻译环境2.1 预处理&#xff08;进行宏替换&#xff09;2.2 编译&#xff08;生成汇编&#xff09;2.3 汇编&#xff08;生成机器可识别代码&#xff09;2.4 链接2.5 记忆小技巧2.6 编译方式2.7 几个问题2.7.1 如何理…...

读西瓜书的数学准备

1&#xff0c;高等数学&#xff1a;会求偏导数就行 2&#xff0c;线性代数&#xff1a;会矩阵运算就行 参考&#xff1a;线性代数--矩阵基本计算&#xff08;加减乘法&#xff09;_矩阵运算-CSDN博客 3&#xff0c;概率论与数理统计&#xff1a;知道啥是随机变量就行...

【数据结构篇】顺序表 超详细

目录 一.顺序表的定义 1.顺序表的概念及结构 1.1线性表 2.顺序表的分类 2.1静态顺序表 2.2动态顺序表 二.动态顺序表的实现 1.准备工作和注意事项 2.顺序表的基本接口&#xff1a; 2.0 创建一个顺序表 2.1 顺序表的初始化 2.2 顺序表的销毁 2.3 顺序表的打印 3.顺序…...

Flink把kafa数据写入Doris的N种方法及对比。

用Flink+Doris来开发实时数仓,首要解决是如何接入kafka实时流,下面是参考Doris官方文档和代码,在自己项目开发的实践中总结,包括一些容易踩坑的细节。 目录 Routine Load方法 接入kafka实时数据 踩坑的问题细节 Flink Doris Connector方法 完整示例 Routine Load方法…...

leetcode刷题记录(七十八)——105. 从前序与中序遍历序列构造二叉树

&#xff08;一&#xff09;问题描述 105. 从前序与中序遍历序列构造二叉树 - 力扣&#xff08;LeetCode&#xff09;105. 从前序与中序遍历序列构造二叉树 - 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一…...

imread和jpeg_read在MATLAB中处理图像时的不同

目录 1.功能差异 2.输出格式 3.颜色空间 4.处理阶段 5.用途 6.性能 1.功能差异 imread&#xff1a;这个函数用于读取各种格式的图像文件&#xff08;包括JPEG、PNG、BMP等&#xff09;并将其转换为MATLAB中的矩阵。它适用于读取图像并直接在空间域中进行处理。jpeg_read…...

P9069 [Ynoi Easy Round 2022] 堕天作战 TEST_98 Solution

Description 给定长为 n n n 的序列 a ( a 1 , a 2 , ⋯ , a n ) a(a_1,a_2,\cdots,a_n) a(a1​,a2​,⋯,an​)&#xff0c;有 m m m 个操作&#xff0c;分以下两种&#xff1a; modify ⁡ ( l , r , k ) \operatorname{modify}(l,r,k) modify(l,r,k)&#xff1a;对于所有…...

SCPI命令笔记

1. 读取设备信息 *IDN? 2. 复位仪器 *RST 3. 清除设备的状态寄存器和事件队列 *CLS 4. 读取设备数据(发一个指令&#xff0c;读取一次) READ? 5. 读取设备电压(功能和第4条命令达到一样的效果) MEAS:VOLT? 6. 读取设备电流 (功能和第4条命令达到一样的效果) MEAS:CURR? 7.…...

TCP创建通信前的三次握手(为啥不是两次?)

1.三次握手的过程 客户端发送 SYN&#xff08;同步&#xff09;报文 客户端向服务器发送 SYN 标志的数据包&#xff0c;请求建立连接&#xff0c;表示 "你好&#xff0c;我要连接你"。 服务器回复 SYNACK&#xff08;同步确认&#xff09;报文 服务器收到 SYN 后&am…...

2024.ailx10的年终总结

已经工作7年啦&#xff0c;今年网络安全行业愈发寒冷&#xff0c;几乎所有友商都在做安全GPT&#xff0c;说实话&#xff0c;AI确实颠覆了传统的网络安全运营&#xff0c;以前需要安服处置告警&#xff0c;以后可能就不需要了&#xff0c;大家日子都不好过&#xff0c;越是简单…...

洛谷P8837

[传智杯 #3 决赛] 商店 - 洛谷 代码区&#xff1a; #include<stdio.h> #include<stdlib.h> int cmp(const void*a,const void *b){return *(int*)b-*(int*)a; } int main(){int n,m;scanf("%d%d",&n,&m);int w[n];int c[m];for(int i0;i<n;…...

【Day23 LeetCode】贪心算法题

一、贪心算法 贪心没有套路&#xff0c;只有碰运气&#xff08;bushi&#xff09;&#xff0c;举反例看看是否可行&#xff0c;&#xff08;运气好&#xff09;刚好贪心策略的局部最优就是全局最优。 1、分发饼干 455 思路&#xff1a;按照孩子的胃口从小到大的顺序依次满足…...

以太网详解(五)GMII、RGMII、SGMII 接口时序约束(Quartus 平台)

文章目录 接口时序Avalon Streaming 接口时序Receive TimingTransmit Timing GMII 接口时序Receive TimingTransmit Timing RGMII 接口时序Receive TimingTransmit Timing 如何创建 .sdc 约束文件三速以太网系统时钟信号创建 set_input_delay&#xff0c;set_output_delay 约束…...

Java中的错误与异常详解

Java中的错误与异常详解 Java提供了一种机制来捕获和处理程序中的异常和错误。异常和错误都继承自 Throwable 类&#xff0c;但它们有着不同的用途和处理方式。 1. Error&#xff08;错误&#xff09; Error 是程序无法处理的严重问题&#xff0c;通常由 JVM&#xff08;Java…...

使用 HTML 开发 Portal 页全解析

前言 在当今数字化时代&#xff0c;网站作为企业和个人展示信息、提供服务的重要窗口&#xff0c;其重要性不言而喻。而 Portal 页&#xff0c;作为网站的核心页面之一&#xff0c;承担着引导用户、整合信息等关键任务。那么&#xff0c;如何使用 HTML 开发一个功能齐全、界面…...

高并发内存池_CentralCache(中心缓存)和PageCache(页缓存)申请内存的设计

三、CentralCache&#xff08;中心缓存&#xff09;_内存设计 &#xff08;一&#xff09;Span的创建 // 页编号类型&#xff0c;32位下是4byte类型&#xff0c;64位下是8byte类型 // #ifdef _WIN64 typedef unsigned long long PageID; #else _WIN32 typedef size_t PageI…...

Js:DOM中的样式(包含行内样式、滚动样式、可见区域样式等)

这部分还在更新 1、 获取行内样式&#xff1a;元素.style.样式名称 2、 获取当前正在显示的样式&#xff08;只能读&#xff0c;不能修改&#xff0c;想要修改要使用style&#xff09;&#xff1a; ① 只有ie支持&#xff1a;元素.currentStyle.样式名称 ② 其他浏览器&…...

【leetcode 26】28.找出字符串中第一个匹配项的下标 | 实现 strStr()==❗不会❗==

在一个串中查找是否出现过另一个串&#xff0c;这是KMP的看家本领。 // 方法一 class Solution {public void getNext(int[] next, String s){int j -1;next[0] j;for (int i 1; i < s.length(); i){while(j > 0 && s.charAt(i) ! s.charAt(j1)){jnext[j];}if…...

Unity自学之旅04

Unity自学之旅04 Unity自学之旅④&#x1f4dd; 跳跃&#x1f42f; 攻击&#x1f984; GUIGUI前置&#xff0c;显示收集物品数量和角色HpUGUI游戏暂停和重新开始 &#x1f917; 总结归纳 Unity自学之旅④ &#x1f4dd; 跳跃 public class PlayerBehaviorRigid : MonoBehavio…...

Unreal Engine 5 C++ Advanced Action RPG 十章笔记

第十章 Survival Game Mode 2-Game Mode Test Map 设置游戏规则进行游戏玩法 生成敌人玩家是否死亡敌人死亡是否需要刷出更多 肯定:难度增加否定:玩家胜利 流程 新的游戏模式类游戏状态新的数据表来指定总共有多少波敌人生成逻辑UI告诉当前玩家的敌人波数 3-Survival Game M…...

[Unity 热更方案] 使用Addressable进行打包管理, 使用AssetBundle进行包的加载管理.70%跟练

在正常的开发过程中我们经常遇到一些关于热更的方案,有一些已有的方案供我们选择,但是实机情况往往不尽如人意,各有优缺点. 现在我们同样有一个热更的需求,但是要求打包简单,加载过程可查,防止出现一些资源和流程的问题. 下面介绍我在项目中使用的方案. 打包方面使用Addressabl…...

人工智能领域单词:英文解释

目录 1、前言2、单词组1&#xff1a;15个3、单词组2&#xff1a;15个4、单词组3&#xff1a;15个5、单词组4&#xff1a;15个6、单词组5&#xff1a;15个 1、前言 亲爱的家人们&#xff0c;创作很不容易&#xff0c;若对您有帮助的话&#xff0c;请点赞收藏加关注哦&#xff0…...

工业网口相机:如何通过调整网口参数设置,优化图像传输和网络性能,达到最大帧率

项目场景 工业相机是常用与工业视觉领域的常用专业视觉核心部件&#xff0c;拥有多种属性&#xff0c;是机器视觉系统中的核心部件&#xff0c;具有不可替代的重要功能。 工业相机已经被广泛应用于工业生产线在线检测、智能交通,机器视觉,科研,军事科学,航天航空等众多领域 …...

NextJs - ServerAction获取文件并处理Excel

NextJs - ServerAction获取文件并处理Excel 一. 客户端二. ServerAction 处理 一. 客户端 use client; import { uploadExcel } from actions/batchInquirySystem/api; import type { UploadProps } from antd; import { Upload } from antd;/*** 创建问询内容*/ const Page …...

【深度学习项目】语义分割-FCN网络(原理、网络架构、基于Pytorch实现FCN网络)

文章目录 介绍深度学习语义分割的关键特点主要架构和技术数据集和评价指标总结 FCN网络FCN 的特点FCN 的工作原理FCN 的变体和发展FCN 的网络结构FCN 的实现&#xff08;基于Pytorch&#xff09;1. 环境配置2. 文件结构3. 预训练权重下载地址4. 数据集&#xff0c;本例程使用的…...