Spring Boot 背后技术详解

Spring Boot 是一个开源的 Java-based 微服务框架,旨在简化 Spring 应用的创建和部署过程。它通过自动配置和约定优于配置的原则,使得开发者能够快速构建独立的、生产级别的应用程序。在这篇博客中,我们将深入探讨 Spring Boot 背后的关键技术,并通过实际代码示例来讲解其工作原理。

第一部分:Spring Boot 简介

1.1 Spring Boot 的诞生背景

Spring Boot 的诞生主要是为了解决 Spring 应用开发过程中的痛点。在传统的 Spring 应用开发中,需要进行大量的配置工作,例如 XML 配置、注解配置等,这给开发者带来了很大的困扰。Spring Boot 通过自动配置和约定优于配置的原则,大大简化了 Spring 应用的配置过程,使得开发者能够更加专注于业务逻辑的实现。

1.2 Spring Boot 的核心特性

Spring Boot 的核心特性主要包括:

  • 自动配置:Spring Boot 根据应用的依赖、配置和类路径下的内容自动配置 Spring 应用。例如,当你的应用中包含了 Spring Data JPA 依赖时,Spring Boot 会自动配置 JPA 相关的 Bean。

  • 独立运行:Spring Boot 应用可以打包成一个独立的 JAR 或 WAR 文件,并且可以通过 Java 命令直接运行,无需部署到外部应用服务器。

  • 内置容器:Spring Boot 内置了 Tomcat、Jetty 和 Undertow 等容器,使得开发者可以更加方便地开发和测试 Web 应用。

  • 生产就绪特性:Spring Boot 提供了多种生产就绪特性,例如指标监控、健康检查、外部化配置等,使得应用更加易于运维。

1.3 Spring Boot 的快速入门

下面,我们将通过一个简单的 Spring Boot 应用示例来讲解其基本使用方法。

1.3.1 创建 Spring Boot 项目

首先,我们可以使用 Spring Initializr(https://start.spring.io/)来创建一个 Spring Boot 项目。选择 Maven 或 Gradle 作为构建工具,添加 Spring Web 依赖,然后生成项目。

1.3.2 编写主程序

在生成的项目中,我们会看到一个名为 Application 的主程序类,它包含了 main 方法。这个类是 Spring Boot 应用的入口点。

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@SpringBootApplication 注解是一个组合注解,它包含了 @Configuration@EnableAutoConfiguration 和 @ComponentScan 三个注解。

  • @Configuration:表示该类是一个配置类,可以包含多个 @Bean 方法。
  • @EnableAutoConfiguration:启用 Spring Boot 的自动配置功能。
  • @ComponentScan:启用组件扫描,自动发现并注册 Spring 组件。

1.3.3 编写控制器

接下来,我们创建一个简单的 Web 控制器。

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello, Spring Boot!";
    }
}

@RestController 注解是一个组合注解,它包含了 @Controller 和 @ResponseBody 两个注解。@GetMapping 注解用于处理 HTTP GET 请求。

1.3.4 运行应用

运行 Application 类的 main 方法,启动 Spring Boot 应用。在浏览器中访问 http://localhost:8080/hello,我们可以看到输出结果为 “Hello, Spring Boot!”。

至此,我们完成了一个简单的 Spring Boot 应用的创建和运行。在后续部分,我们将深入探讨 Spring Boot 背后的关键技术原理。

第二部分:Spring Boot 自动配置原理

Spring Boot 的自动配置是其核心特性之一,它能够根据项目中添加的依赖、配置和类路径下的内容自动配置 Spring 应用。这一特性极大地简化了 Spring 应用的配置过程,使得开发者能够更加专注于业务逻辑的实现。

2.1 自动配置的实现机制

Spring Boot 自动配置的实现主要依赖于以下几个关键组件:

  • @EnableAutoConfiguration 注解:这个注解是自动配置的入口,它告诉 Spring Boot 启用自动配置。@EnableAutoConfiguration 注解通过 @Import 注解导入了一个名为 AutoConfigurationImportSelector 的类,这个类负责加载自动配置类。

  • AutoConfigurationImportSelector 类:这个类实现了 ImportSelector 接口,它会扫描类路径下的所有 JAR 文件,查找并加载 META-INF/spring.factories 文件中定义的自动配置类。

  • spring.factories 文件:这个文件位于每个 Spring Boot Starter 的 JAR 文件中,它包含了键值对,其中键是自动配置类的全限定名,值是自动配置类的列表。Spring Boot 会根据这些自动配置类的条件注解来决定是否加载它们。

  • 条件注解:Spring Boot 提供了一系列条件注解,如 @ConditionalOnClass@ConditionalOnMissingBean 等,用于在自动配置类中定义加载条件。例如,@ConditionalOnClass 表示只有在类路径下存在指定的类时才加载自动配置。

2.2 自动配置类的编写

自动配置类通常是使用 @Configuration 注解的 Java 类,它们包含了一个或多个 @Bean 方法,用于创建和配置 Spring Beans。自动配置类通常会结合条件注解来确保只有在满足特定条件时才会创建 Bean。

例如,Spring Boot 的 HttpEncodingAutoConfiguration 类负责自动配置字符编码过滤器(CharacterEncodingFilter):

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

    private final HttpProperties.Encoding properties;

    public HttpEncodingAutoConfiguration(HttpProperties properties) {
        this.properties = properties.getEncoding();
    }

    @Bean
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
        return filter;
    }
}

在这个例子中,HttpEncodingAutoConfiguration 类使用了多个条件注解来确保只有在满足以下条件时才会创建 CharacterEncodingFilter Bean:

  • 应用是一个 Servlet Web 应用(@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET))。
  • 类路径下存在 CharacterEncodingFilter 类(@ConditionalOnClass(CharacterEncodingFilter.class))。
  • 配置文件中 spring.http.encoding.enabled 属性为 true(默认值)或未显式设置(@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true))。
  • 容器中没有已经定义的 CharacterEncodingFilter Bean(@ConditionalOnMissingBean)。

2.3 禁用特定的自动配置

在某些情况下,你可能想要禁用特定的自动配置类。这可以通过在 application.properties 或 application.yml 配置文件中使用 spring.autoconfigure.exclude 属性来实现。

例如,要禁用 HttpEncodingAutoConfiguration,你可以在配置文件中添加以下内容:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.http.HttpEncodingAutoConfiguration

或者,如果你使用的是 YAML 格式的配置文件:

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.http.HttpEncodingAutoConfiguration

通过这种方式,你可以精确控制哪些自动配置类被加载,哪些被禁用。

第三部分:Spring Boot 独立运行原理

Spring Boot 应用可以打包成一个独立的 JAR 或 WAR 文件,并且可以通过 Java 命令直接运行,无需部署到外部应用服务器。这一特性使得 Spring Boot 应用更加便于部署和迁移。

3.1 Spring Boot Maven 插件

Spring Boot 提供了一个 Maven 插件 spring-boot-maven-plugin,用于将 Spring Boot 应用打包成一个可执行的 JAR 文件。这个插件会将应用的依赖、类文件、资源文件等打包到一个单独的 JAR 文件中,并且会为这个 JAR 文件生成一个启动脚本,使得 JAR 文件可以直接通过 Java 命令运行。

在 pom.xml 文件中,你可以添加如下配置来使用这个插件:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

当你执行 mvn package 命令时,Maven 会调用这个插件,生成一个可执行的 JAR 文件。这个 JAR 文件包含了应用的所有依赖和资源,可以通过以下命令运行:

java -jar target/myapp-0.0.1-SNAPSHOT.jar

3.2 Spring Boot Gradle 插件

对于使用 Gradle 的项目,Spring Boot 提供了 spring-boot-gradle-plugin 插件,它同样可以将 Spring Boot 应用打包成一个可执行的 JAR 或 WAR 文件。

在 build.gradle 文件中,你可以添加如下配置来应用这个插件:

plugins {
    id 'org.springframework.boot' version '2.5.5'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

apply plugin: 'io.spring.boot'

jar {
    baseName = 'myapp'
    version = '0.0.1-SNAPSHOT'
}

执行 gradle build 命令后,Gradle 会生成一个可执行的 JAR 文件,你可以使用 Java 命令来运行它:

java -jar build/libs/myapp-0.0.1-SNAPSHOT.jar

3.3 Spring Boot 应用启动原理

Spring Boot 应用的启动过程主要是由 SpringApplication 类来完成的。当你调用 SpringApplication.run() 方法时,会发生以下主要步骤:

  1. 启动监听器SpringApplication 会加载并启动所有可用的 ApplicationListener。这些监听器可以监听应用的启动事件,例如 ApplicationStartingEventApplicationEnvironmentPreparedEvent 等。

  2. 环境准备SpringApplication 会准备应用的运行环境,包括配置文件、命令行参数等。它会创建一个 ConfigurableEnvironment 对象,这个对象包含了所有的配置属性。

  3. 应用上下文创建SpringApplication 会根据应用的类型(servlet 或 reactive)创建一个相应的 ApplicationContext 实例,例如 AnnotationConfigServletWebServerApplicationContext 或 ReactiveWebServerApplicationContext

  4. 自动配置SpringApplication 会应用自动配置,加载 spring.factories 文件中定义的自动配置类。

  5. 命令行运行器:如果应用是直接通过命令行运行的,SpringApplication 会创建一个 CommandLineRunner 或 ApplicationRunner 的 Bean,并调用它们的 run 方法。

  6. 启动完毕:最后,SpringApplication 会发布 ApplicationStartedEvent 和 ApplicationReadyEvent 事件,通知所有的监听器应用已经启动完毕。

通过这个过程,Spring Boot 应用被启动并准备好接受请求。

第四部分:Spring Boot 内置容器原理

Spring Boot 内置了 Tomcat、Jetty 和 Undertow 等容器,这使得开发者可以更加方便地开发和测试 Web 应用。这一特性使得 Spring Boot 应用可以独立运行,无需部署到外部应用服务器。

4.1 内置容器的自动配置

Spring Boot 的自动配置机制同样适用于内置容器。当你添加了 Spring Web 依赖时,Spring Boot 会自动配置一个适合的 Web 容器。例如,如果你添加了 spring-boot-starter-web 依赖,Spring Boot 会默认配置 Tomcat 作为 Web 容器。

4.2 自定义内置容器配置

虽然 Spring Boot 提供了默认的内置容器配置,但你也可以通过配置文件来自定义这些配置。例如,你可以通过 application.properties 或 application.yml 文件来配置服务器的端口、连接池大小等。

server.port=8081
server.tomcat.max-threads=200

或者,如果你使用的是 YAML 格式的配置文件:

server:
  port: 8081
  tomcat:
    max-threads: 200

4.3 切换内置容器

如果你想要使用 Jetty 或 Undertow 而不是默认的 Tomcat,你可以在 pom.xml 或 build.gradle 文件中排除 Tomcat 依赖,并添加相应的 Jetty 或 Undertow 依赖。

例如,要在 Maven 项目中使用 Jetty,你可以添加如下依赖:

<dependency>
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-tomcat org.springframework.boot spring-boot-starter-jetty 

在 Gradle 项目中,你可以这样配置:

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-jetty'
    exclude module: 'spring-boot-starter-tomcat'
}

通过这种方式,你可以轻松切换 Spring Boot 使用的内置 Web 容器。

4.4 内置容器的启动和关闭

Spring Boot 应用的启动和关闭是通过 SpringApplication 和 ApplicationContext 来管理的。当你调用 SpringApplication.run() 方法时,Spring Boot 会创建一个 WebServer 实例,并在应用启动时启动它。在应用关闭时,Spring Boot 会优雅地关闭 WebServer,释放所有资源。

例如,如果你使用的是 Tomcat,Spring Boot 会创建一个 TomcatWebServer 实例。这个实例会负责启动和关闭 Tomcat 服务器。

第五部分:Spring Boot 生产就绪特性

Spring Boot 提供了多种生产就绪特性,例如指标监控、健康检查、外部化配置等,使得应用更加易于运维。这些特性可以帮助开发者更好地监控和管理生产环境中的应用。

5.1 指标监控

Spring Boot Actuator 是 Spring Boot 的一个模块,它提供了生产就绪特性,包括指标监控、健康检查等。要使用 Spring Boot Actuator,你可以在项目中添加 spring-boot-starter-actuator 依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Actuator 会暴露多个 HTTP 端点,通过这些端点,你可以获取应用的运行状态、指标等信息。例如,/actuator/health 端点可以提供应用的健康信息。

5.2 健康检查

健康检查是 Actuator 提供的一个核心功能,它可以帮助你检查应用的运行状态。你可以通过配置文件来定制健康检查的信息。

management:
  endpoint:
    health:
      show-details: always

在上面的配置中,show-details 属性被设置为 always,这意味着健康检查端点会始终显示详细信息。

5.3 外部化配置

Spring Boot 支持外部化配置,这意味着你可以在不同的环境中使用不同的配置文件。Spring Boot 会自动加载 application.properties 或 application.yml 文件中的配置。

此外,Spring Boot 还支持 Profile-specific 配置。你可以创建 application-{profile}.properties 或 application-{profile}.yml 文件,然后在启动应用时指定使用的 Profile。

java -jar myapp.jar --spring.profiles.active=prod

通过这种方式,你可以根据不同的环境(开发、测试、生产等)使用不同的配置。

5.4 安全管理

Spring Boot Security 是 Spring Security 的一个模块,它提供了安全管理的功能。通过 Spring Boot Security,你可以轻松地为应用添加认证和授权等安全特性。

要使用 Spring Boot Security,你可以在项目中添加 spring-boot-starter-security 依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

然后,你可以通过配置文件或 Java 配置来定制安全策略。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/resources/**", "/signup", "/about").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .and()
            .httpBasic();
    }
}

在上面的例子中,我们定义了所有请求都需要认证,除了 /resources/**/signup 和 /about 路径。

通过这些生产就绪特性,Spring Boot 使得应用的监控、管理和部署变得更加简单和高效。

结论

Spring Boot 通过其创新的自动配置、独立的运行能力、内置的 Web 容器、生产就绪特性以及对微服务架构的支持,彻底改变了 Java 应用开发的面貌。它不仅简化了开发流程,提高了开发效率,还通过模块化和插件的机制,为开发者提供了一种可扩展和可定制的开发体验。

随着云计算和微服务架构的日益普及,Spring Boot 已经成为现代 Java 应用开发的事实标准。它为开发者提供了一套完整的工具链,使得开发者可以专注于业务逻辑的实现,而不是繁琐的配置和框架的集成。

通过本博客的探讨,我们可以看到 Spring Boot 的设计哲学是尽可能地减少开发者的工作量,让开发者能够更快地交付可用的软件。无论是初创公司还是大型企业,Spring Boot 都能够提供一种快速、简便且可靠的应用开发解决方案。

未来,随着 Spring Boot 生态系统的不断发展和完善,我们可以期待更多的创新和改进,进一步推动 Java 应用开发的发展。对于开发者来说,掌握 Spring Boot 不仅能够提升个人的技术能力,还能够更好地适应现代软件开发的需求。

随着技术的不断进步,Spring Boot 也可能会面临新的挑战和机遇。例如,容器化和云原生应用的发展可能会对 Spring Boot 的部署和运行方式产生影响。此外,随着函数即服务(Function-as-a-Service, FaaS)的兴起,Spring Boot 可能需要适应新的架构范式,提供更加灵活和轻量级的部署选项。

总之,Spring Boot 是一个强大而灵活的框架,它不仅为 Java 应用开发提供了坚实的基础,还为未来的技术创新和变革奠定了基础。对于希望在这个快速变化的技术领域中保持竞争力的开发者来说,深入理解和掌握 Spring Boot 是一个不可或缺的技能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/597570.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Day61:单调栈 739. 每日温度 496.下一个更大元素 I

739. 每日温度 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 示例 1: 输…

发表博客之:gemm/threadblock/threadblock_swizzle.h 文件夹讲解,cutlass深入讲解

文章目录 [发表博客之&#xff1a;gemm/threadblock/threadblock_swizzle.h 文件夹讲解&#xff0c;cutlass深入讲解](https://cyj666.blog.csdn.net/article/details/138514145)先来看一下最简单的struct GemmIdentityThreadblockSwizzle结构体 发表博客之&#xff1a;gemm/th…

vue2 webpack-dev-server Unknown promise rejection reason

在vue.config.js中添加如下配置&#xff0c;重启项目即可 module.exports defineConfig({devServer: {client: {overlay: false,},} })参考

探索中位数快速排序算法:高效寻找数据集的中间值

在计算机科学领域&#xff0c;寻找数据集的中位数是一个常见而重要的问题。而快速排序算法作为一种高效的排序算法&#xff0c;可以被巧妙地利用来解决中位数查找的问题。本文将深入探讨中位数快速排序算法的原理、实现方法以及应用场景&#xff0c;带你领略这一寻找中间值的高…

vue 金额组件,输入提示单位:‘千’、‘万’、‘十万’...并用‘,’三个格式化

近期项目中遇到一个需求&#xff0c;金额输入框&#xff0c;输入过程中自动提示‘千’、‘万’、‘十万’、‘百万’......等单位提示&#xff0c;鼠标失去焦点后&#xff0c;并用‘,’三位隔开计数。 例如&#xff1a; 输入&#xff1a;12345.99 失去焦点&#xff1a;12,34…

Vue--》从零开始打造交互体验一流的电商平台(一)

今天开始使用 vue3 ts 搭建一个电商项目平台&#xff0c;因为文章会将项目的每处代码的书写都会讲解到&#xff0c;所以本项目会分成好几篇文章进行讲解&#xff0c;我会在最后一篇文章中会将项目代码开源到我的github上&#xff0c;大家可以自行去进行下载运行&#xff0c;希…

【Node.js工程师养成计划】之express中间件与接口规范

一、Express中间件的概念与基本应用 const express require(express)// 加一个注释&#xff0c;用以说明&#xff0c;本项目代码可以任意定制更改 const app express()const PORT process.env.PORT || 3000// // 挂载路由 // app.use(/api, router)// // 挂载统一处理服务端…

【倪亲斫经典水墨云纹仲尼式】倪诗韵亲斫古琴

【倪亲斫经典水墨云纹仲尼式】倪诗韵亲斫古琴 松透润&#xff0c;适合大曲文曲潇湘欸乃平沙&#xff0c;余韵悠长&#xff0c;手感极其舒适&#xff0c;久弹不疲。

[Linux][网络][TCP][三][超时重传][快速重传][SACK][D-SACK][滑动窗口]详细讲解

目录 1.超时重传1.什么是超时重传&#xff1f;2.超时时间是如何确定的&#xff1f; 2.快速重传3.SACK4.D-SACK1.ACK丢失2.网络延迟 5.滑动窗口0.问题抛出1.发送方的滑动窗口2.如何表示发送方的四个部分&#xff1f;3.接收方的滑动窗口4.滑动窗口的完善理解 1.超时重传 1.什么是…

C++手写协程项目(协程实现线程结构体、线程调度器定义,线程挂起函数、线程切换函数、线程恢复函数、线程结束函数、线程结束判断函数,模块测试)

协程结构体定义 之前我们使用linux下协程函数实现了线程切换&#xff0c;使用的是ucontext_t结构体&#xff0c;和基于这个结构体的四个函数。现在我们要用这些工具来实现我们自己的一个线程结构体&#xff0c;并实现线程调度和线程切换、挂起。 首先我们来实现以下线程结构体…

Splay 树简介

【Splay 树简介】 ● Treap 树解决平衡的办法是给每个结点加上一个随机的优先级&#xff0c;实现概率上的平衡。Splay 树直接用旋转调整树的形态&#xff0c;通过旋转改善树的平衡性。计算量小&#xff0c;效果好。 ● Splay 树的旋转主要分为“单旋”和“双旋”。 所谓“单旋”…

基于52单片机的AS608指纹密码锁电路原理图+源程序+PCB实物制作

目录 1、前言 2、实物图 3、PCB图 4、原理图 5、程序 资料下载地址&#xff1a;基于52单片机的AS608指纹密码锁电路原理图源程序PCB实物制作 1、前言 这是一个基于AS608STC89C52单片机的指纹识别和键盘密码锁。 里面包括程序&#xff0c;原理图&#xff0c;pcb图和实…

OpenNJet:云原生技术中的创新者与实践者

目录 引言OpenNJet介绍OpenNJet优势1. 性能无损动态配置2. 灵活的CoPilot框架3. 支持HTTP/34. 支持国密5. 企业级应用6. 高效安全 OpenNJet 编译与安装环境准备编译环境配置配置yum源yum 安装软件包创建符号连接修改 ld.so.conf 配置 编译代码 部署 WEB SERVER配置OpenNJet部署…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-13-按键实验

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

FTP协议与工作原理

一、FTP协议 FTP&#xff08;FileTransferProtocol&#xff09;文件传输协议&#xff1a;用于Internet上的控制文件的双向传输&#xff0c;是一个应用程序&#xff08;Application&#xff09;。基于不同的操作系统有不同的FTP应用程序&#xff0c;而所有这些应用程序都遵守同…

计算机网络【应用层】邮件和DNS

文章目录 电子邮件DNSDNS提供的服务&#xff1a;域名分级域名解析流程DNS资源记录DNS服务器类型 电子邮件 使用SMTP协议发送邮件之前&#xff0c;需要将二进制多媒体数据编码为ASCII码SMTP一般不使用中间邮件服务器发送邮件&#xff0c;如果收件服务器没开机&#xff0c;那么会…

解决jar包中没有主清单目录的问题

文章目录 解决jar包中没有主清单目录的问题问题描述环境描述方法一 | 阿里巴巴构造器的通用解决方案方式二 | 指定MANIFEST.MF路径 解决jar包中没有主清单目录的问题 问题描述 很简单可能很多人都遇到过&#xff0c;maven项目打成jar包后执行报错&#xff1a;jar包中没有主清单…

在模方中已经选好水岸线了,但是点处理瓦块的时候还是提示水岸线没选

答&#xff1a;能部分位置不闭合&#xff0c;双击右键闭合一下&#xff0c;可以强行闭合缺口。 模方是一款针对实景三维模型的冗余碎片、水面残缺、道路不平、标牌破损、纹理拉伸模糊等共性问题研发的实景三维模型修复编辑软件。模方4.1新增自动单体化建模功能&#xff0c;支持…

高情商回复(不是)

背景介绍 在抖音上有这样的视频&#xff0c;视频就是一张图&#xff0c;图上问了一个问题&#xff1a;饭局上&#xff0c;你去帮领导盛饭&#xff0c;领导接过后说&#xff1a;‘盛这么多&#xff0c;喂猪呢&#xff1f;’咋回&#xff1f; 底下有一个搞笑评论&#xff1a;猪可…

迅雷永久破解

链接&#xff1a;https://pan.baidu.com/s/1ZGb1ljTPPG3NFsI8ghhWbA?pwdok7s 下载后解压 以管理员身份运行绿化.bat&#xff0c;会自动生成快捷方式&#xff0c;如果没有可以在program中运行Thunder.exe
最新文章