使用 Spring Boot 和 GraalVM 的原生镜像
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:历代文学,移动端可微信小程序搜索“历代文学”)总架构师,
15年
工作经验,精通Java编程
,高并发设计
,Springboot和微服务
,熟悉Linux
,ESXI虚拟化
以及云原生Docker和K8s
,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。
技术合作请加本人wx(注明来自csdn):foreast_sea
1. 概述
在本文中,我们将了解原生镜像,以及如何从 Spring Boot 应用程序和 GraalVM 的原生镜像构建器创建原生镜像。我们指的是 Spring Boot 3,但我们将在本文末尾解决与 Spring Boot 2 的差异。
2. 原生镜像
本机映像是一种将 Java 代码构建为独立可执行文件的技术。此可执行文件包括应用程序类、来自其依赖项的类、运行时库类以及来自 JDK 的静态链接本机代码。JVM 已打包到本机映像中,因此目标系统上不需要任何 Java 运行时环境,但构建工件取决于平台。因此,我们需要为每个支持的目标系统构建一个版本,当我们使用 Docker 等容器技术时,这会更容易,我们可以将容器构建为可以部署到任何 Docker 运行时的目标系统。
2.1. GraalVM 和原生镜像构建器
通用递归应用程序和算法语言虚拟机 (Graal VM) 是为 Java 和其他 JVM 语言编写的高性能 JDK 发行版,同时支持 JavaScript、Ruby、Python 和其他几种语言。它提供了一个 Native Image 构建器 – 一种从 Java 应用程序构建原生代码并将其与 VM 一起打包成独立可执行文件的工具。它由 Spring Boot Maven 和 Gradle Plugin 官方支持,但有一些例外(最糟糕的是 Mockito 目前不支持原生测试)。
2.2. 特殊功能
在构建原生镜像时,我们遇到了两个典型特征。
预先 (AOT) 编译是将高级 Java 代码编译为本机可执行代码的过程。通常,这是由 JVM 的 Just-in-time 编译器 (JIT) 在运行时完成的,它允许在执行应用程序时进行观察和优化。在 AOT 编译的情况下,此优势将丢失。
通常,在 AOT 编译之前,可以选择有一个单独的步骤,称为 AOT 处理,即从代码中收集元数据并将其提供给 AOT 编译器。划分为这两个步骤是有意义的,因为 AOT 处理可以是特定于框架的,而 AOT 编译器更通用。下图给出了一个概述:
Java 平台的另一个特点是,只需将 JAR 放入 Classpath 中,即可在目标系统上实现可扩展性。由于启动时的反射和注释扫描,我们在应用程序中获得了扩展行为。
遗憾的是,这会减慢启动时间,并且不会带来任何好处,尤其是对于云原生应用程序,其中甚至服务器运行时和 Java 基类也被打包到 JAR 中。因此,我们省去了这个功能,然后可以使用 Closed World Optimization 构建应用程序。
这两项功能都减少了运行时需要执行的工作量。
2.3. 优势
本机映像具有各种优势,例如即时启动和减少内存消耗。它们可以打包到轻量级容器映像中,以便更快、更高效地部署,并且它们减少了攻击面。
2.4. 限制
由于 Closed World Optimization,在编写应用程序代码和使用框架时,我们必须注意一些限制。不久:
- 类初始值设定项可以在构建时执行,以实现更快的启动和更好的峰值性能。但我们必须意识到,这可能会破坏代码中的一些假设,例如,当加载一个必须在构建时可用的文件时。
- 反射和动态代理在运行时成本高昂,因此在 Closed World 假设下在构建时进行了优化。在构建时执行时,我们可以在类初始化器中不受限制地使用它。任何其他用法都必须向 AOT 编译器公布,Native Image 构建器会尝试通过执行静态代码分析来访问该编译器。如果失败,我们必须提供此信息,例如,通过配置文件。
- 这同样适用于所有基于反射的技术,例如 JNI 和 Serialization。
- 此外,本机映像生成器还提供了自己的本机接口,该接口比 JNI 简单得多,开销也较低。
- 对于本机映像构建,字节码在运行时不再可用,因此无法使用针对 JVMTI 的工具进行调试和监控。然后,我们必须使用本机调试器和监控工具。
关于 Spring Boot,我们必须意识到,运行时不再完全支持配置文件、条件 bean 和 .enable 属性等功能。如果我们使用 profiles,则必须在构建时指定它们。
3. 基本设置
在构建原生镜像之前,我们必须安装这些工具。
3.1. GraalVM 和原生镜像
首先,我们按照安装说明安装当前版本的 GraalVM 和原生映像构建器。(Spring Boot 需要 22.3 版本)我们应该确保安装目录可以通过 GRAALVM_HOME 环境变量获得,并且 “<GRAALVM_HOME>/bin” 已添加到 PATH 变量中。
3.2. 原生编译器
在构建过程中,Native Image 构建器会调用特定于平台的原生编译器。因此,我们需要这个原生编译器,按照我们平台的 “Prerequisite” 说明进行操作。这将使构建平台相关。我们必须知道,只能在特定于平台的命令行中运行构建。例如,使用 Git Bash 在 Windows 上运行构建将不起作用。我们需要改用 Windows 命令行。
3.3. Docker
作为先决条件,我们将确保安装 Docker,稍后需要运行本机映像。Spring Boot Maven 和 Gradle 插件使用 Paketo Tiny Builder 构建容器。
4. 使用 Spring Boot 配置和构建项目
将本机构建功能与 Spring Boot 一起使用非常简单。例如,通过使用 Spring Initializr 并添加应用程序代码来创建我们的项目。然后,要使用 GraalVM 的原生映像构建器构建原生映像,我们需要使用 GraalVM 本身提供的 Maven 或 Gradle 插件来扩展我们的构建。
4.1. Maven 浏览器
Spring Boot Maven 插件的目标是 AOT 处理(即,不是 AOT 编译自身,而是为 AOT 编译器收集元数据,例如,在代码中注册反射的使用)和构建可与 Docker 一起运行的 OCI 映像。我们可以直接调用这些目标:
mvn spring-boot:process-aot
mvn spring-boot:process-test-aot
mvn spring-boot:build-image
我们不需要这样做,因为 Spring Boot 父 POM 定义了一个将这些目标绑定到构建的本机配置文件。我们需要使用此激活的配置文件进行构建:
mvn clean package -Pnative
如果我们还想执行本机测试,则可以激活第二个配置文件:
mvn clean package -Pnative,nativeTest
如果我们想要构建原生镜像,就必须添加 native-maven-plugin 的相应目标。因此,我们也可以定义一个原生配置文件。因为这个插件是由父 POM 管理的,所以我们可以保留版本号:
<profiles><profile><id>native</id><build><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><executions><execution><id>build-native</id><goals><goal>compile-no-fork</goal></goals><phase>package</phase></execution></executions></plugin></plugins></build></profile>
</profiles>
目前,本机测试执行不支持 Mockito。因此,我们可以排除 Mocking 测试,或者通过将以下内容添加到我们的 POM 中来跳过本机测试:
<build><pluginManagement><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><configuration><skipNativeTests>true</skipNativeTests></configuration></plugin></plugins></pluginManagement>
</build>
4.2. 在没有父 POM 的情况下使用 Spring Boot
如果我们不能从 Spring Boot Parent POM 继承,而是将其用作导入范围的依赖项,则必须自己配置插件和配置文件。然后,我们必须将以下内容添加到我们的 POM 中:
<build><pluginManagement><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>${native-build-tools-plugin.version}</version><extensions>true</extensions></plugin></plugins></pluginManagement>
</build>
<profiles><profile><id>native</id><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><image><builder>paketobuildpacks/builder:tiny</builder><env><BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE></env></image></configuration><executions><execution><id>process-aot</id><goals><goal>process-aot</goal></goals></execution></executions></plugin><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><configuration><classesDirectory>${project.build.outputDirectory}</classesDirectory><metadataRepository><enabled>true</enabled></metadataRepository><requiredVersion>22.3</requiredVersion></configuration><executions><execution><id>add-reachability-metadata</id><goals><goal>add-reachability-metadata</goal></goals></execution></executions></plugin></plugins></build></profile><profile><id>nativeTest</id><dependencies><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-launcher</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><id>process-test-aot</id><goals><goal>process-test-aot</goal></goals></execution></executions></plugin><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><configuration><classesDirectory>${project.build.outputDirectory}</classesDirectory><metadataRepository><enabled>true</enabled></metadataRepository><requiredVersion>22.3</requiredVersion></configuration><executions><execution><id>native-test</id><goals><goal>test</goal></goals></execution></executions></plugin></plugins></build></profile>
</profiles>
<properties><native-build-tools-plugin.version>0.9.17</native-build-tools-plugin.version>
</properties>
4.3. 格拉德尔
Spring Boot Gradle 插件提供用于 AOT 处理的任务(即,不是 AOT 编译自身,而是为 AOT 编译器收集元数据,例如,在代码中注册反射的使用情况)和构建可与 Docker 一起运行的 OCI 映像:
gradle processAot
gradle processTestAot
gradle bootBuildImage
如果我们想构建原生镜像,我们必须添加 Gradle 插件来构建 GraalVM 原生镜像:
plugins {// ...id 'org.graalvm.buildtools.native' version '0.9.17'
}
然后,我们可以通过调用
gradle nativeTest
gradle nativeCompile
目前,本机测试执行不支持 Mockito。因此,我们可以通过配置 graalvmNative 扩展来排除 Mocking 测试或跳过原生测试,如下所示:
graalvmNative {testSupport = false
}
5. 扩展本机映像生成配置
如前所述,我们必须为 AOT 编译器注册反射、类路径扫描、动态代理等的每次用法。因为 Spring 的内置原生支持是一个非常年轻的功能,目前并不是所有的 Spring 模块都有内置支持,所以我们目前需要自己添加这个。这可以通过手动创建 build configuration 来完成。尽管如此,使用 Spring Boot 提供的接口还是更容易,这样 Maven 和 Gradle 插件都可以在 AOT 处理期间使用我们的代码来生成构建配置。
指定其他本机配置的一种可能性是 Native Hints。那么,让我们看看目前缺少的内置支持的两个示例,以及如何将其添加到我们的应用程序中以使其正常工作。
5.1. 示例:Jackson 的 PropertyNamingStrategy
在 MVC Web 应用程序中,REST 控制器方法的每个返回值都由 Jackson 序列化,并自动将每个属性命名为 JSON 元素。我们可以通过在应用程序属性文件中配置 Jackson 的 PropertyNamingStrategy 来全局影响名称映射:
spring.jacksonproperty-naming-strategy=SNAKE_CASE
SNAKE_CASE 是 PropertyNamingStrategies 类型的静态成员的名称。不幸的是,此成员通过反射解决了。因此,AOT 编译器需要知道这一点,否则,我们将收到一条错误消息:
Caused by: java.lang.IllegalArgumentException: Constant named 'SNAKE_CASE' not foundat org.springframework.util.Assert.notNull(Assert.java:219) ~[na:na]at org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration$StandardJackson2ObjectMapperBuilderCustomizer.configurePropertyNamingStrategyField(JacksonAutoConfiguration.java:287) ~[spring-features.exe:na]
为此,我们可以通过如下简单的方式实现和注册 RuntimeHintsRegistrar:
@Configuration
@ImportRuntimeHints(JacksonRuntimeHints.PropertyNamingStrategyRegistrar.class)
public class JacksonRuntimeHints {static class PropertyNamingStrategyRegistrar implements RuntimeHintsRegistrar {@Overridepublic void registerHints(RuntimeHints hints, ClassLoader classLoader) {try {hints.reflection().registerField(PropertyNamingStrategies.class.getDeclaredField("SNAKE_CASE"));} catch (NoSuchFieldException e) {// ...}}}}
注意:从 3.0.0-RC2 版本开始,在 Spring Boot 中解决此问题的拉取请求已经合并,因此它可以与 Spring Boot 3 一起开箱即用。
5.2. 示例:GraphQL 架构文件
如果我们想实现 GraphQL API,我们需要创建一个架构文件并将其定位在“classpath:/graphql/*.graphqls”下,Springs GraphQL 自动配置会自动检测到它。这是通过 Classpath scanning 以及集成的 GraphiQL 测试客户端的欢迎页面完成的。因此,要在本机可执行文件中正常工作,AOT 编译器需要了解这一点。我们可以用同样的方式注册它:
@ImportRuntimeHints(GraphQlRuntimeHints.GraphQlResourcesRegistrar.class)
@Configuration
public class GraphQlRuntimeHints {static class GraphQlResourcesRegistrar implements RuntimeHintsRegistrar {@Overridepublic void registerHints(RuntimeHints hints, ClassLoader classLoader) {hints.resources().registerPattern("graphql/**/").registerPattern("graphiql/index.html");}}}
Spring GraphQL 团队已经在努力解决这个问题,因此我们可能会在未来版本中内置它。
6. 编写测试
要测试 RuntimeHintsRegistrar 实现,我们甚至不需要运行 Spring Boot 测试,我们可以创建一个简单的 JUnit 测试,如下所示:
@Test
void shouldRegisterSnakeCasePropertyNamingStrategy() {// arrangefinal var hints = new RuntimeHints();final var expectSnakeCaseHint = RuntimeHintsPredicates.reflection().onField(PropertyNamingStrategies.class, "SNAKE_CASE");// actnew JacksonRuntimeHints.PropertyNamingStrategyRegistrar().registerHints(hints, getClass().getClassLoader());// assertassertThat(expectSnakeCaseHint).accepts(hints);
}
如果我们想通过集成测试来测试它,我们可以检查 Jackson ObjectMapper 是否具有正确的配置:
@SpringBootTest
class JacksonAutoConfigurationIntegrationTest {@AutowiredObjectMapper mapper;@Testvoid shouldUseSnakeCasePropertyNamingStrategy() {assertThat(mapper.getPropertyNamingStrategy()).isSameAs(PropertyNamingStrategies.SNAKE_CASE);}}
要使用 native 模式对其进行测试,我们必须运行一个 native test:
# Maven
mvn clean package -Pnative,nativeTest
# Gradle
gradle nativeTest
如果我们需要为 Spring Boot Tests 提供特定于测试的 AOT 支持,我们可以使用 AotTestExecutionListener 接口实现TestRuntimeHintsRegistrar或TestExecutionListener。我们可以在官方文档中找到详细信息。
7. Spring Boot 2
Spring 6 和 Spring Boot 3 在原生镜像构建方面迈出了一大步。但是对于之前的主要版本,这也是可能的。我们只需要知道目前还没有内置支持,即有一个补充的 Spring Native 计划来处理这个主题。因此,我们必须在我们的项目中手动包含和配置它。对于 AOT 处理,有一个单独的 Maven 和 Gradle 插件,该插件未合并到 Spring Boot 插件中。当然,集成库提供的原生支持程度不如现在(将来会更多)。
7.1. Spring 原生依赖
首先,我们必须为 Spring Native 添加 Maven 依赖项:
<dependency><groupId>org.springframework.experimental</groupId><artifactId>spring-native</artifactId><version>0.12.1</version>
</dependency>
但是,对于 Gradle 项目,Spring Native 是由 Spring AOT 插件自动添加的。
需要注意的是,每个 Spring Native 版本只支持一个特定的 Spring Boot 版本——比如 Spring Native 0.12.1 只支持 Spring Boot 2.7.1。因此,我们应该确保在pom.xml中使用兼容的 Spring Boot Maven 依赖项。
7.2. 构建包
要构建 OCI 映像,我们需要显式配置构建包。
使用 Maven,我们需要使用 Paketo Java buildpacks 的带有本机映像配置的 spring-boot-maven-plugin:
<build><pluginManagement><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><image><builder>paketobuildpacks/builder:tiny</builder><env><BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE></env></image></configuration></plugin></plugins></pluginManagement>
</build>
在这里,我们将使用各种可用构建器(如 base 和 full)中的小型构建器来构建原生镜像。此外,我们还通过向 BP_NATIVE_IMAGE 环境变量提供 true 值来启用 buildpack。
同样,在使用 Gradle 时,我们可以将 tiny 构建器以及 BP_NATIVE_IMAGE 环境变量添加到 build.gradle 文件中:
bootBuildImage {builder = "paketobuildpacks/builder:tiny"environment = ["BP_NATIVE_IMAGE" : "true"]
}
7.3. Spring AOT 插件
接下来,我们需要添加 Spring AOT 插件,该插件执行提前转换,有助于改善本机映像的占用空间和兼容性。
因此,让我们将最新的 spring-aot-maven-plugin Maven 依赖项添加到我们的 pom.xml中:
<plugin><groupId>org.springframework.experimental</groupId><artifactId>spring-aot-maven-plugin</artifactId><version>0.12.1</version><executions><execution><id>generate</id><goals><goal>generate</goal></goals></execution></executions>
</plugin>
同样,对于 Gradle 项目,我们可以在 build.gradle 文件中添加最新的 org.springframework.experimental.aot 依赖项:
plugins {id 'org.springframework.experimental.aot' version '0.10.0'
}
此外,正如我们之前提到的,这会自动将 Spring Native 依赖项添加到 Gradle 项目中。
Spring AOT 插件提供了几个选项来确定源生成。例如,removeYamlSupport 和 removeJmxSupport 等选项分别删除 Spring Boot Yaml 和 Spring Boot JMX 支持。
7.4. 构建并运行镜像
就是这样!我们已准备好使用 Maven 命令构建 Spring Boot 项目的本机映像:
$ mvn spring-boot:build-image
7.5. 原生镜像构建
接下来,我们将添加一个名为 native 的配置文件,该配置文件支持一些插件,例如 native-maven-plugin 和 spring-boot-maven-plugin:
<profiles><profile><id>native</id><build><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>0.9.17</version><executions><execution><id>build-native</id><goals><goal>build</goal></goals><phase>package</phase></execution></executions></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><classifier>exec</classifier></configuration></plugin></plugins></build></profile>
</profiles>
此配置文件将在打包阶段从构建中调用 native-image 编译器。
但是,在使用 Gradle 时,我们会将最新的 org.graalvm.buildtools.native 插件添加到 build.gradle 文件中:
plugins {id 'org.graalvm.buildtools.native' version '0.9.17'
}
就是这样!我们已准备好通过在 Maven package 命令中提供本机配置文件来构建本机映像:
mvn clean package -Pnative
8. 总结
在本教程中,我们探索了使用 Spring Boot 和 GraalVM 的原生构建工具构建原生镜像。我们了解了 Spring 的内置原生支持。所有代码实现都可以在 GitHub 上找到(Spring Boot 2 示例)。
相关文章:
使用 Spring Boot 和 GraalVM 的原生镜像
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:历代文学,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计…...
Flutter解压文件并解析数据
Flutter解压文件并解析数据 前言 在 Flutter 开发中,我们经常需要处理文件的读取和解压。 这在处理应用数据更新、安装包、存档文件等场景中尤为常见。 本文将介绍如何在Flutter中使用archive插件来解压文件并解析数据。 准备 在开始之前,我们需要…...
深入理解 JavaScript 引擎与消息队列的底层原理
深入理解 JavaScript 引擎与消息队列的底层原理 JavaScript 是现代 Web 开发中最为重要的编程语言之一,它的运行和执行方式常常是开发者关注的重点。为了更好地理解 JavaScript 的执行过程,我们需要深入探索 JavaScript 引擎的工作原理,尤其…...
使用 ANSYS Forming 和 LS-DYNA 进行金属成形仿真简介
了解金属成型 金属成型是制造业中的关键过程,其中原材料通过变形转化为所需的形状。这可能包括冲压、弯曲和深拉等操作。这些工艺的质量和效率在很大程度上取决于对各种参数的精确控制,例如材料特性、工具几何形状和加工条件。为了优化这些参数并确保成功…...
001-mysql安装
[rootcentos701 ~]# hostname -I 10.0.0.200 172.17.0.1 [rootcentos701 ~]# hostname centos701 [rootcentos701 ~]# rpm -qa | grep mariadb [rootcentos701 ~]# rpm -e --nodeps mariadb-libs-5.5.65-1.el7.x86_64 [rootcentos701 ~]# useradd mysql -s /sbin/nologin #创建…...
以攻击者的视角进行软件安全防护
1. 前言 孙子曰:知彼知己者,百战不殆;不知彼而知己,一胜一负,不知彼,不知己,每战必殆。 摘自《 孙子兵法谋攻篇 》在2500 年前的那个波澜壮阔的春秋战国时代,孙子兵法的这段话&…...
Go 语言性能优化全解析
在当今的软件开发环境中,Go 语言(Golang)因其简洁的语法、高效的并发模型和快速的编译速度而备受青睐。然而,随着应用程序复杂性的增加,即使是在 Go 中也可能会遇到性能瓶颈。为了帮助开发者构建高性能的应用程序&…...
《智能体雏形开发(高阶实操)》二、智能体雏形开发
基于阿里云百炼平台开发智能体应用:生成日报与周报 在智能体开发中,生成结构化的日报与周报是一个典型的任务。本篇文章将基于阿里云百炼平台,结合 Python 开发环境,介绍如何开发一个从日志文件提取信息并生成摘要的智能体。我们将从需求分析、任务设计到核心功能实现逐步…...
【k8s】kubelet 和 API Server的关系
文章目录 概述1. # kubelet 和 API Server 之间的关系**1. 角色和功能****1.1 kubelet****1.2 API Server** **2. 交互关系****2.1 kubelet 从 API Server 获取指令****2.2 kubelet 向 API Server 上报状态****2.3 kubelet 与 API Server 的认证和授权** **3. 典型交互场景****…...
POSTGRESQL跟ORACLE语法区别和相同之处
跟ORACLE语法区别之处 1. Update和delete语法区别 Pg 和MySQL Update和delete的时候表名不能加别名 2. 插入数字类型不一样 ORACLE 对number类型的数据可以用’’ 字符串标记插入,但是PG不行,必须要进行正确的数据类型 3. SEQ使用不同 ORACEL的SEQ…...
Distance in Tree 树形dp练习(树中两点距离为k的数量板子)
Distance in Tree 题面翻译 题目大意 输入点数为 N N N一棵树 求树上长度恰好为 K K K的路径个数 输入格式 第一行两个数字 N , K N,K N,K,如题意 接下来的 N − 1 N-1 N−1行中,每行两个整数 u , v u,v u,v表示一条树边 ( u , v ) (u,v) (u,v) 输出格式 一个整数 a n…...
【MySQL】库的操作+表的操作
库的操作表的操作 1.库的操作 1.1创建数据库1.2删除数据库1.3查找数据库1.4修改数据库1.5数据库备份和恢复1.6查看连接情况 2.库的操作 2.1创建表2.2查看表结构2.3修改表2.4删除表 点赞???收藏???关注??? 你的支持是对我最大的鼓励,我们一起努力吧???…...
vue异步更新,$nextTick
如果将isShowEdit改为true,就会显示输入框和确认按钮、 如果isShowEdit为false的话就显示“大标题”和编辑 想要获取元素焦点,但是vue是异步更新,会出错显示this.$refs.inp是undefined,是因为input元素并没有更新完成,所以需要使用…...
【3D AIGC】Img-to-3D、Text-to-3D、稀疏重建(2024年文章汇总)
文章目录 1. Wonderworld:拓展图片边界,生成3D场景2. 3DTopia-XL:扩散模型辅助生成3. 3DGS-Enhancer: 通过视图一致2D Diffusion,提升无界3D Gaussian Splatting (NlPs2024 Spotlight)4. L3DG:Latent 3D Gaussian Diff…...
简单的springboot使用sse功能
什么是sse? 1、SSE 是Server-Sent Events(服务器发送事件) 2、SSE是一种允许服务器主动向客户端推送实时更新的技术。 3、它基于HTTP协议,并使用了其长连接特性,在客户端与服务器之间建立一条持久化的连接。 通过这条连接&am…...
Nginx 防止IP伪造,绕过IP限制
背景介绍 在使用Nginx时,需要将IP地址转发到后置应用中,往往需要增加配置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 在后端程序通过读取请求头里的X-Forwarded-For来获取用户客户端IP。 public String getRemortIP(HttpServle…...
原生js仿el-table动态表头
解决动态表头数据量过大导致页面卡顿的问题解决固定前几列导致表头设置宽度失效或者错位的问题功能: 固定前几列合并指定单元格 <div class"tableJoint2"><div><table id"tableData"></table></div><div>…...
【opencv入门教程】9.视频加载
文章选自: 一、VideoCapture类 用于从视频文件、图像序列或摄像头捕获视频的类。函数:CV_WRAP VideoCapture();brief 默认构造函数CV_WRAP explicit VideoCapture(const String& filename, int apiPreference CAP_ANY);brief 使用 API 首选项打开…...
数据结构 ——无头单链表
数据结构 ——无头单链表 一、无头单链表的定义与特性 1、单链表简介 单链表是一种常见的基础数据结构,它由一系列节点组成,每个节点包含数据部分和指向下一个节点的指针。无头单链表是单链表的一种变体,其特点是没有明确的头节点࿰…...
【UE5】制作插件 并调试【vs2022】
视频教程:好看视频-轻松有收获 https://www.youtube.com/watch?vIjpa9mI2b5I 原文:【UE】制作插件_ue插件-CSDN博客 C制作插件 1. 我们可以在C工程中创建更多类型的插件,这里我们选择“空白”作为模板来创建插件 点击“创建插件”按钮后…...
Prometheus 采集postgresql监控数据
postgres_exporter 前言 postgres_exporter 是一个用于监控 PostgreSQL 数据库的 Prometheus 导出器。它允许你收集有关 PostgreSQL 数据库性能和状态的指标,并将这些指标暴露给 Prometheus,从而可以在 Grafana 等可视化工具中进行展示和告警。 postgres_exporter download…...
网络分层模型( OSI、TCP/IP、五层协议)
1、网络分层模型 计算机网络是一个极其复杂的系统。想象一下最简单的情况:两台连接在网络上的计算机需要相互传输文件。不仅需要确保存在一条传输数据的通路,还需要完成以下几项工作: 发起通信的计算机必须激活数据通路,这包括发…...
POI遍历行所有单元格的两种方式,getPhysicalNumberOfCells方式有问题,勿用
今天看POI源码的时候,发现HSSFWorkbook类型的工作簿,行数据是用TreeMap<Integer, HSSFRow>存储的,列数据是用HSSFCell[]数组来存的;XSSFWorkbook类型的工作簿,行数据是用SortedMap<Integer, XSSFRow>存储的…...
Latex转word(docx)或者说PDF转word 一个相对靠谱的方式
0. 前言 投文章过程中总会有各种各样的要求,其中提供word格式的手稿往往是令我头疼的一件事。尤其在多公式的文章中,其中公式转换是一个头疼的地方,还有很多图表,格式等等,想想就让人头疼欲裂。实践中摸索出一条相对靠…...
敖汉宝塔油页岩露天矿山安全自动化监测
1. 项目简介 本次项目位于内蒙古自治区赤峰市敖汉旗宝国吐乡大青山村,地理位置好。主营许可经营项目:无一般经营项目:页岩油生产;页岩油、润滑油、建筑材料(不含油漆)销售等单位规模1-20人,单位…...
Android笔记【14】结合LaunchedEffect实现计时器功能。
一、问题 cy老师第五次作业 结合LaunchedEffect实现计时器功能。要求:动态计时,每秒修改时间,计时的时间格式为“00:00:00”(小时:分钟:秒)提交源代码的文本和运行截图…...
三维重建(单目、双目、多目、点云、SFM、SLAM)
1 相机几何与标定1.1 相机模型中的坐标系1.2 四种坐标系之间的转换1.3 相机内参1.4 相机标定 2 传统三维重建2.1 RGBD三维重建2.1.1 KinectFusion2.1.2 BundleFusion 2.1 MVS三维重建2.2.1 COLMAP2.2.2 OpenMVS 3 点云三维重建3.1 3D点云任务3.2 点云数据3.3 特征提取3.3.1 Poi…...
软体机器人动态手内笔旋转研究
人工智能咨询培训老师叶梓 转载标明出处 软体机器人因其在安全互动方面的优势而备受关注,但在高速动态任务中却面临挑战。最近,卡内基梅隆大学机器人研究所的研究团队提出了一种名为SWIFT的系统,旨在通过学习和试错来实现软体机器人手的动态…...
福昕PDF低代码平台
福昕PDF低代码平台简介 福昕PDF 低代码平台是一款创新的工具,旨在简化PDF处理和管理的流程。通过这个平台,用户可以通过简单的拖拽界面上的按钮,轻松完成对Cloud API的调用工作流,而无需编写复杂的代码。这使得即使没有编程经验的…...
【笔记】Linux中使用到的一些操作
1、查找指定文件并执行删除 find . -name "checkpoint_*_*.pth" -type f -exec rm -f {} \; 2、查看每个文件夹占用空间 du -h --max-depth1 3、移动文件 mv valid.zip ./xg mv 文件 目标位置 4、删除文件夹 rmdir folder rm -r folder # 递归删除文件夹下所有内容…...
深入浅出:PHP中的表单处理全解析
引言 在Web开发的世界里,表单是用户与服务器之间交互的重要桥梁。它们允许用户提交信息,并通过后端语言(如PHP)进行处理。本文将带你深入了解PHP中的表单处理,从基础的创建和提交到高级的安全措施和实用技巧ÿ…...
智已汽车x-signature 登录算法 签到
智已汽车x-signature 登录算法 签到 python代码成品...
一、测试工具LoadRunner Professional脚本编写-录制前设置
设置基于URL的脚本 原因:基于HTML的脚本会导致login接口不能正确录制 设置UTF-8 原因:不勾选此项会导致脚本中文变为乱码...
LSTM+改进的itransformer时间序列预测模型代码
代码在最后 本次设计了一个LSTM基于差分多头注意力机制的改进的iTransformer时间序列预测模型结合了LSTM(长短期记忆网络)和改进版的iTransformer(差分多头注意力机制),具备以下优势: 时序特征建模能力&am…...
linux中 Systemd 和 cgroups 的关系详解
systemd 是 Linux 的一个初始化系统和服务管理器,它依赖于 Linux 内核的 cgroups(Control Groups)功能来实现对系统资源的高效管理。以下是对两者关系的详细解读: 1. 什么是 cgroups? cgroups 是 Linux 内核提供的一种…...
发布Apache2.4** 局域网无法访问
1。 防火墙关闭 或者 设置入站规则 2,查看httpd.conf 文件 设置配置 原 Listen 80 修改成 Listen 192.168.31.127:90 3.确保 本地IP 是否正确...
【JAVA】Java高级:多数据源管理与Sharding:在Spring Boot应用中实现多数据源的管理
一个电商平台可能需要一个数据库来存储用户信息,另一个数据库来存储订单信息,甚至可能还有一个数据库用于数据分析。这种情况下,如何在Spring Boot应用中实现多数据源的管理就显得尤为重要。 1. 多数据源管理的重要性 在实际应用中…...
Android 分词的两种方式
前言: 本文分别介绍了原生和三方(Jieba)两种分词方式的使用和注意事项 1、安卓原生BreakIterator分词 比较简单,但是效果不太行 /*** 功能:原生分词* 参数:text:需要分词的语句* 返回值:return…...
【开源免费】基于SpringBoot+Vue.JS中小型医院网站(JAVA毕业设计)
博主说明:本文项目编号 T 078 ,文末自助获取源码 \color{red}{T078,文末自助获取源码} T078,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…...
数据结构代码归纳
1.线性表 线性表的顺序表示 定义与初始化 typedef struct SqList{ElemType data[MaxSize];//ElemType *data 开动态数组 int length; }Sqlist; void InitList(SqList &L){L.length0;//若静态数组//若动态数组 //L.data(ElemType*)malloc(sizeof(ElemType)*MaxSize); }…...
2024-金盾信安杯线上赛 WP
Misc 大赛宗旨 记事本打开,一眼零宽隐写 B 神工具一把梭,得到一串 base 编码 base64 解码得到 flag flag 值:flag{5d5555fa-1303-4b43-8eef-d6ea7c64c361} esab 根据题目 esab 可以发现这正是 base 的逆向,所以可以先逆向一下…...
iOS如何自定义一个类似UITextView的本文编辑View
对于IOS涉及文本输入常用的两个View是UITextView和UITextField,一个用于复杂文本输入,一个用于简单文本输入,在大多数开发中涉及文本输入的场景使用这两个View能够满足需求。但是对于富文本编辑相关的开发,这两个View就无法满足自…...
JavaWeb文件上传
文件上传总览 文件上传主要是指将本地文件(包括但不限于图片、视频、音频等)上传到服务器,提供其他用户浏览或下载的过程。在日常生活中,我们在很多情况下都需要使用文件上传功能,比如:发微博、发朋友圈等…...
C#实现1ms定时器不精准?如何实现一个高性能高精度的1ms定时器?(附完整示例Demo)
在C#日常开发中,我们经常需要使用定时器(Timer)进行周期性任务的执行。 例如,每隔1秒打印一条日志,或每隔100毫秒执行某个数据刷新逻辑。 但是,当我们尝试在C#中实现一个1毫秒(1ms)…...
LeetCode 3. 无重复字符的最长子串
题目链接:3. 无重复字符的最长子串 首先想到的就是暴力破解,直接两层循环遍历,因为它说求无重复,那就可以用 set 来存储遍历到的字符,如果遍历到了同样的字符(在 set 中存在),就直接跳出第二层循环&#x…...
深度解析 Ansible:核心组件、配置、Playbook 全流程与 YAML 奥秘(上)
文章目录 一、ansible的主要组成部分二、安装三、相关文件四、ansible配置文件五、ansible 系列 一、ansible的主要组成部分 ansible playbook:任务剧本(任务集),编排定义ansible任务集的配置文件,由ansible顺序依次执…...
记一次由docker容器使得服务器cpu占满密码和密钥无法访问bug
Bug场景: 前几天在服务器上部署了一个免费影视网站,这个应用需要四个容器,同时之前的建站软件workpress也是使用docker部署的,也使用了三个容器。在使用workpress之前,我将影视软件的容器全部停止。 再使用workpress…...
功能篇:JAVA实现记住我功能
在Java Web应用程序中实现“记住我”功能,通常涉及以下几个步骤: 1. 创建一个持久化的标识符(如一个令牌或哈希值),并将其与用户账户关联。 2. 将这个标识符保存到客户端的cookie中。 3. 在服务器端,当用户…...
实现 DataGridView 下拉列表功能(C# WinForms)
本文介绍如何在 WinForms 中使用 DataGridViewComboBoxColumn 实现下拉列表功能,并通过事件响应来处理用户的选择。以下是实现步骤和示例代码。 1. 效果展示 该程序的主要功能是展示如何在 DataGridView 中插入下拉列表,并在选择某一项时触发事件。 2.…...
2024年上半年网络工程师综合知识真题及答案解析
2024年上半年网络工程师综合知识真题及答案解析 以下不属于5G网络优点的是()A.传输过程中消耗的资源少,对设备的电池更友好B.支持大规模物联网,能够连接大量低功耗设备,提供更高效的管理C.引入了网络切片技术,允许将物理网络划分为多个虚拟网络D.更好的安全性,采用更…...