Java学习,一文掌握Java之SpringBoot框架学习文集(3)

在这里插入图片描述

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。
🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。
🎉欢迎 👍点赞✍评论⭐收藏

SpringBoot知识专栏学习

SpringBoot知识云集访问地址备注
SpringBoot知识点(1)https://blog.csdn.net/m0_50308467/article/details/135322153SpringBoot专栏
SpringBoot知识点(2)https://blog.csdn.net/m0_50308467/article/details/135323253SpringBoot专栏
SpringBoot知识点(3)https://blog.csdn.net/m0_50308467/article/details/135373512SpringBoot专栏

文章目录

  • 🏆 学习Java框架之Spring Boot
    • 🔎 Java框架之Spring Boot学习(3)
      • 🍁🍁 01、Spring Boot 中的自动配置是怎样实现的?
      • 🍁🍁 02、Spring Boot 中的条件注解是如何工作的?
      • 🍁🍁 03、@ConditionalOnBean 和 @ConditionalOnMissingBean 有什么区别?
      • 🍁🍁 04、Spring Boot 的自动配置是如何解析属性的?
      • 🍁🍁 05、如何自定义 Spring Boot 的自动配置类?
      • 🍁🍁 06、Spring Boot 如何处理循环依赖?
      • 🍁🍁 07、Spring Boot 中的热部署是如何实现的?
      • 🍁🍁 08、Spring Boot 中的配置优先级是怎样的?
      • 🍁🍁 09、如何在 Spring Boot 中实现异步调用?
      • 🍁🍁 10、Spring Boot 中如何实现跨域请求?

🏆 学习Java框架之Spring Boot

🔎 Java框架之Spring Boot学习(3)

🍁🍁 01、Spring Boot 中的自动配置是怎样实现的?

在 Spring Boot 中,自动配置(Auto-configuration)是一种基于条件化(Conditional)的配置方式。它可以根据应用的 classpath、依赖和配置来自动配置 Spring 应用程序,而无需进行过多的手动配置。

Spring Boot 的自动配置实际上是通过 Spring 的条件化注解来实现的,
主要有以下条件注解:
@ConditionalOnClass
@ConditionalOnMissingClass
@ConditionalOnBean
@ConditionalOnMissingBean
@ConditionalOnProperty
@ConditionalOnResource
@ConditionalOnWebApplication 等。

这些注解通过判断应用所引入的类、Bean 等是否存在,或者应用的配置属性、资源、Web 应用类型是否符合特定的条件,来决定是否生效该自动配置。

如果满足条件,就会创建对应的 Bean、配置信息等。如果不满足,对应的 Bean、配置信息就会忽略或移除。

Spring Boot 还提供了 @EnableAutoConfiguration 注解,它可以根据应用的 classpath 来自动启动并配置 Spring Boot 应用程序的各种组件和功能。

具体来说,它会从 META-INF/spring.factories 中加载自动配置类,并根据自动配置的条件判断来决定是否生效。

通过自动配置,Spring Boot 可以让开发者专注于业务开发而无需关心繁琐的配置。同时也能提高开发效率、降低开发成本和错误率。因此,自动配置是 Spring Boot 框架的一个重要特性。

🍁🍁 02、Spring Boot 中的条件注解是如何工作的?

在 Spring Boot 中,条件注解(Conditional Annotations)是一种用于根据特定条件来装配 Bean 和配置组件的机制。条件注解允许我们基于运行时环境、配置属性或其他条件来动态地确定是否应该创建特定的 Bean。

Spring Boot 提供了一系列内置的条件注解,例如:

1. @ConditionalOnClass:当类路径中存在指定的类时,条件匹配。

2. @ConditionalOnMissingClass:当类路径中不存在指定的类时,条件匹配。

3. @ConditionalOnBean:当 Spring 上下文中存在指定的 Bean 时,条件匹配。

4. @ConditionalOnMissingBean:当 Spring 上下文中不存在指定的 Bean 时,条件匹配。

5. @ConditionalOnProperty:当指定的配置属性存在且值满足条件时,条件匹配。

6. @ConditionalOnResource:当指定的资源存在时,条件匹配。

7. @ConditionalOnWebApplication:当应用程序是一个 Web 应用程序时,条件匹配。

这些条件注解可以根据应用的具体情况以及自定义的条件进行组合和定制。它们可以应用在配置类、Bean 方法上,通过条件判断来决定是否加载、注册相关组件。

当满足条件时,Bean 或配置会被创建和应用;当不满足条件时,它们会被忽略或者被移除。

条件注解的工作原理是基于 Spring 的条件化(Conditional)机制。条件注解本质上是一个条件化注解,它会在应用启动时进行条件判断,并根据条件结果来决定是否启用相关的 Bean 或配置。

只有满足特定条件的注解才会生效。这样可以根据不同的条件来定制化地配置应用,提供更灵活的自动装配机制。

以下给你举几个条件注解的示例。

1. @ConditionalOnClass:当类路径中存在指定的类时,条件匹配。

@Configuration
@ConditionalOnClass(MyClass.class)
public class MyConfiguration {// ... 定义需要配置的 Bean 或组件 ...
}

在这个例子中,MyConfiguration 类只有在类路径中存在 MyClass.class 类时才会被装配为配置类。否则,该配置类将被忽略。

2. @ConditionalOnBean:当 Spring 上下文中存在指定的 Bean 时,条件匹配。

@Configuration
@ConditionalOnBean(DataSource.class)
public class MyConfiguration {// ... 定义需要配置的 Bean 或组件 ...
}

在这个例子中,MyConfiguration 类只有当 Spring 上下文中存在 DataSource Bean 时,才会被装配为配置类。如果不存在该 Bean,该配置类将被忽略。

3. @ConditionalOnProperty:当指定的配置属性存在且值满足条件时,条件匹配。

@Configuration
@ConditionalOnProperty(prefix = "myapp", name = "enabled", havingValue = "true")
public class MyConfiguration {// ... 定义需要配置的 Bean 或组件 ...
}

在这个例子中,MyConfiguration 类只有当名为 myapp.enabled 的配置属性值为 true 时,才会被装配为配置类。如果配置属性不存在或者值不满足条件,该配置类将被忽略。

🍁🍁 03、@ConditionalOnBean 和 @ConditionalOnMissingBean 有什么区别?

在 Spring Boot 中,@ConditionalOnBean@ConditionalOnMissingBean 是两个条件注解,用于在装配 Bean 或配置组件时进行条件判断。它们的区别如下所示:

1. @ConditionalOnBean:该注解的条件是判断 Spring 上下文中是否存在指定的 Bean。如果存在指定的 Bean,则条件匹配,相关的 Bean 或配置组件会被加载和应用。

@Configuration
@ConditionalOnBean(DataSource.class)
public class MyConfiguration {// ... 定义需要配置的 Bean 或组件 ...
}

上面的例子中,只有当 Spring 上下文中存在 DataSource Bean 时,MyConfiguration 类才会被装配为配置类。

2. @ConditionalOnMissingBean:该注解的条件是判断 Spring 上下文中是否不存在指定的 Bean。如果不存在指定的 Bean,则条件匹配,相关的 Bean 或配置组件会被加载和应用。

@Configuration
@ConditionalOnMissingBean(DataSource.class)
public class MyConfiguration {// ... 定义需要配置的 Bean 或组件 ...
}

上面的例子中,只有当 Spring 上下文中不存在 DataSource Bean 时,MyConfiguration 类才会被装配为配置类。

简而言之:

@ConditionalOnBean 用于判断 Bean 是否存在,条件匹配时加载和应用相关的组件;
@ConditionalOnMissingBean 则用于判断 Bean 是否不存在,条件匹配时加载和应用相关的组件。

总结一下它们的区别,并列出一个简单的表格:

条件注解条件判断说明条件匹配时是否加载配置类
@ConditionalOnBean判断是否存在指定的 Bean,存在则条件匹配是,加载相关的 Bean 或配置类
@ConditionalOnMissingBean判断是否不存在指定的 Bean,不存在则条件匹配是,加载相关的 Bean 或配置类

总之,这两个注解是常用的 Spring Boot 条件注解之一,它们通常与其它条件注解、自动配置类等一起使用,帮助您更加灵活地控制应用程序的自动配置和启动过程。

🍁🍁 04、Spring Boot 的自动配置是如何解析属性的?

在 Spring Boot 中,自动配置属性的解析是通过 @ConfigurationProperties 注解实现的。@ConfigurationProperties 注解用于指定属性的前缀,并根据属性的命名规则自动映射到对应的实体类中。

以下是 Spring Boot 自动配置属性解析的流程:

1. 在自动配置类中,使用 @ConfigurationProperties 注解来指定属性的前缀。

@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {private String name;private int age;// ... 其他属性的getter和setter方法 ...
}

上面的例子中,所有以 myapp 开头的属性都会映射到 MyAppProperties 类中。

2. 在应用的 application.propertiesapplication.yml 文件中,设置对应的属性值。

myapp.name=My Application
myapp.age=20

3. 在启动时,自动配置会将应用配置文件中的属性值解析并映射到 MyAppProperties 实体类的相关属性中。

4. 在启动过程中,可以通过 @Autowired@Resource 等注解将 MyAppProperties 注入到其他需要使用它的类中。

@RestController
public class MyController {@Autowiredprivate MyAppProperties myAppProperties;
}

上面的例子中,MyAppProperties 的实例会被注入到 MyController 类中,从而可以直接使用其中定义的属性。

通过以上流程,Spring Boot 实现了自动配置属性的解析。使用 @ConfigurationProperties 注解,结合应用配置文件,可以方便地将应用的配置信息自动映射到指定的实体类中,从而实现属性的自动配置。

🍁🍁 05、如何自定义 Spring Boot 的自动配置类?

想要自定义 Spring Boot 的自动配置类,有三种常用的方式:

1. 最简单的方式是通过在 @Configuration 注解的类中定义 @Bean@Conditional 方法来重写 Spring Boot 的默认配置。这种方式可以覆盖某些默认配置,而不会影响其它自动配置。

2. 另外一种方式是通过创建一个新的自动配置类来覆盖默认的自动配置类。 这种方式可以更改更多的默认配置,但也可能会影响其它自动配置。

3. 最后一种方式是通过创建一个外部的配置类来修改默认的配置。 外部配置类可以通过 SpringApplication.setDefaultProperties(...) 方法来设置默认配置,或者通过在 application.propertiesapplication.yml 中添加配置来修改默认配置。

下面我们一一介绍这三种方式:

1. 通过定义 @Bean@Conditional 方法来重写默认配置

这种方式是最简单的方式,只需要在 @Configuration 注解的类中定义特定的 @Bean@Conditional 方法即可。

例如,下面的示例代码定义了一个新的 DataSource Bean,并覆盖默认的 DataSourceAutoConfiguration 自动配置:

@Configuration
public class DataSourceConfig {@Bean@ConditionalOnMissingBeanpublic DataSource dataSource() {// ... 创建并返回一个新的 DataSource ...}
}

这里使用 @ConditionalOnMissingBean 注解来判断当前应用程序上下文中是否已存在 DataSource Bean。

如果已存在,则不会创建新的 DataSource,否则将会创建一个新的 DataSource Bean,并使用它来替换默认的 DataSourceAutoConfiguration 自动配置。

2. 通过创建新的自动配置类来覆盖默认的自动配置类

这种方式需要创建一个新的自动配置类,并使用 @ConditionalOnClass@ConditionalOnBean@ConditionalOnProperty 等注解来控制该自动配置类的生效范围。

例如,下面的示例代码创建了一个新的 AwesomeServiceAutoConfiguration 自动配置类,并覆盖了默认的 MyServiceAutoConfiguration 自动配置:

@Configuration
@ConditionalOnClass(AwesomeService.class)
@EnableConfigurationProperties(AwesomeServiceProperties.class)
public class AwesomeServiceAutoConfiguration {@Autowiredprivate AwesomeServiceProperties properties;@Bean@ConditionalOnMissingBeanpublic AwesomeService awesomeService() {// ... 根据配置创建并返回 AwesomeService ...}
}

这里通过 @ConditionalOnClass 注解来判断当前类路径下是否存在 AwesomeService 类。

如果存在,则自动配置将会生效,否则自动配置将不会生效。 然后使用 @EnableConfigurationProperties 注解来启用该自动配置类所需的配置类,最后定义 awesomeService() 方法来创建 AwesomeService Bean,并使用 @ConditionalOnMissingBean 注解来判断当前应用程序上下文中是否已存在该 Bean。

如果已存在,则不会创建新的 AwesomeService Bean,否则将会创建一个新的 AwesomeService Bean,并用它来替换默认的 MyServiceAutoConfiguration 自动配置。

3. 通过创建外部的配置类来修改默认的配置

这种方式需要在 application.propertiesapplication.yml 中添加配置。

例如,下面的示例代码使用 myapp.server.port 属性来修改默认的服务端口号配置:

server.port=8080
myapp.server.port=8888

在这个示例中,我们添加了一个名为 myapp.server.port 的新属性,它将会覆盖默认的 server.port 服务端口号配置。

总之,以上三种方式都是常用的自定义 Spring Boot 自动配置的方法。选择哪种方式,应该根据具体情况和需求来决定。

🍁🍁 06、Spring Boot 如何处理循环依赖?

Spring Boot 可以处理简单的循环依赖,但是对于复杂的循环依赖则需要使用特殊的处理方式。

简单的循环依赖是指基于属性的 setter 依赖或构造函数注入时的循环依赖。Spring Boot 可以通过提前暴露其中一个 bean 实例,例如通过将某个依赖的 bean 实例包装在一个 ObjectHolder 中来暴露,从而解决简单的循环依赖。

对于最简单的情况,例如一个类 A 依赖于另一个类 B,而 B 又依赖于 A 实例的一个属性,在构造函数注入时,Spring Boot 会自动将一个不完整的 A 实例暴露给 B,然后在构造函数完成之后,再将完整的 A 实例注入到 B 中。

但是,如果存在复杂的循环依赖,例如循环依赖环,即 A -> B -> C -> A,Spring Boot 就不能处理了。 在这种情况下,通常需要使用 延迟注入 来解决循环依赖。延迟注入是指不在初始化时立即注入 bean,而是在使用时进行注入。

Spring Boot 中可以使用 @Lazy 注解来实现延迟注入。

例如:

@Component
public class A {@Autowired@Lazyprivate B b;// ...
}@Component
public class B {@Autowiredprivate C c;// ...
}@Component
public class C {@Autowiredprivate A a;// ...
}

在上面的示例中,A 依赖于 B,B 依赖于 C,而 C 又依赖于 A。这种循环依赖环无法通过默认的 Spring Boot 依赖注入机制处理。

但是,通过使用 @Lazy 注解,我们可以将 A 中的 B 延迟注入,直到需要使用它时再进行注入。这样就可以解决循环依赖问题了。

总之,Spring Boot 可以处理 简单的循环依赖 ,但对于 复杂的循环依赖 ,需要使用特殊的处理方式,例如 延迟注入 。在实际应用中,应该尽量避免使用复杂的循环依赖,保持依赖注入的单向性,有助于提高应用程序的可维护性。

除了使用延迟注入,还有一些其他的方法可以处理 Spring Boot 中的复杂循环依赖问题,例如使用 构造函数注入通过接口实现注入 等。下面是一些解决循环依赖问题的常用方法:

1. 使用构造函数注入

对于复杂的循环依赖问题,使用构造函数注入是一种常见的解决方案。通过使用构造函数注入,可以强制 Spring Boot 在初始化 bean 的过程中显式指定所有必需的依赖项,从而解决循环依赖问题。

示例代码如下:

@Component
public class A {private B b;@Autowiredpublic A(B b) {this.b = b;}// ...
}@Component
public class B {private C c;@Autowiredpublic B(C c) {this.c = c;}// ...
}@Component
public class C {private A a;@Autowiredpublic C(A a) {this.a = a;}// ...
}

在上面的示例中,每个 bean 都将其依赖项通过构造函数注入进来。这样就可以避免循环依赖问题。

2. 通过接口实现注入

另一种处理复杂循环依赖的方法是使用接口实现注入。通过使用接口注入,可以实现循环依赖的两个 bean 分别依赖于自己的扩展接口,而不是依赖于对方的类实现。

示例代码如下:

public interface AInterface {void setB(BInterface b);
}@Component
public class A implements AInterface {private BInterface b;@Override@Autowiredpublic void setB(BInterface b) {this.b = b;}// ...
}public interface BInterface {void setC(CInterface c);
}@Component
public class B implements BInterface {private CInterface c;@Override@Autowiredpublic void setC(CInterface c) {this.c = c;}// ...
}public interface CInterface {void setA(AInterface a);
}@Component
public class C implements CInterface {private AInterface a;@Override@Autowiredpublic void setA(AInterface a) {this.a = a;}// ...
}

在上面的示例中,A、B 和 C 分别实现了自己的扩展接口,然后通过接口注入各自的依赖关系。这种方法通过抽象和分离依赖关系,使得 Spring Boot 可以轻松地处理循环依赖问题。

总之,处理 Spring Boot 中的循环依赖问题需要根据具体情况进行选择。常用的解决方法包括使用延迟注入、构造函数注入和通过接口实现注入等。

在实际应用中,应该尽量避免出现复杂的循环依赖问题,保证依赖注入的单向性,有助于提高应用程序的可维护性。

🍁🍁 07、Spring Boot 中的热部署是如何实现的?

在 Spring Boot 中实现热部署有多种方法,下面介绍其中两种常用的方法:

1. 使用 Spring Boot DevTools

Spring Boot DevTools 是一个开发工具,可以帮助实现热部署。它使用了两个关键技术:

  • 应用程序快速重启:DevTools 监听文件系统的更改,当项目文件发生变化时,它会自动触发应用程序的重启。
  • 类加载器触发器:DevTools 使用另一个类加载器加载应用程序,这样应用程序代码的改变就可以在不重启应用程序的情况下生效。

要启用 Spring Boot DevTools,只需要将以下依赖项添加到项目的 pom.xml 文件中:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional>
</dependency>

使用 DevTools 启动应用程序后,当你修改了任何源代码文件、资源文件或配置文件时,它会自动重新加载应用程序。你可以在 IDE 中编辑文件并保存,或者使用命令行工具进行相应的更改。

2. 使用 Spring Loaded

Spring Loaded 是一个开源项目,用于支持在运行时动态加载修改后的类。它通过 Java 的 HotSwap 技术实现热交换。

要使用 Spring Loaded,首先需要将其引入项目的开发依赖中:

<dependency><groupId>org.springframework</groupId><artifactId>springloaded</artifactId><version>1.2.8.RELEASE</version><scope>provided</scope>
</dependency>

然后,在该项目的启动脚本中加入 -javaagent 参数,指定 Spring Loaded 的代理模块:

-javaagent:path/to/springloaded-{version}.jar

启动项目后,当你修改了相应的类文件时,Spring Loaded 会在后台自动加载并重新定义该类,实现热部署。

需要注意的是,Spring Boot DevTools 和 Spring Loaded 都是用于开发环境,在生产环境中并不推荐使用。在生产环境中,可以使用 Docker、Kubernetes 等部署技术来实现无缝的应用程序更新和滚动升级。

🍁🍁 08、Spring Boot 中的配置优先级是怎样的?

在 Spring Boot 中,配置的优先级是按照以下规则确定的:

1. 命令行参数(Command Line Arguments):命令行参数提供了最高的优先级。可以在运行 Spring Boot 应用程序时使用 --<option>=<value> 的格式来传递参数,

例如 java -jar myproject.jar --server.port=8080

2. 系统属性(System Properties):可以通过在 JVM 启动时使用 -D<option>=<value> 的方式来设置系统属性。

例如:java -Dserver.port=8080 -jar myproject.jar

3. 环境变量(Environment Variables):可以通过设置环境变量来配置应用程序。Spring Boot 将环境变量作为默认的属性源,同时支持使用下划线(_)或点号(.)来分隔层次结构。

例如,设置环境变量 SERVER_PORT=8080

4. 配置文件(Application Properties):Spring Boot 默认支持使用 .properties.yml 文件来配置应用程序。可以通过在 src/main/resourcesclasspath:/config 目录下添加相应的配置文件来覆盖默认配置。针对不同的环境,可以使用不同的文件名。

例如, application-dev.propertiesapplication-prod.yml,或者使用 spring.profiles.active 属性来指定活动的配置文件。可以使用 spring.config.namespring.config.location 属性来定制配置文件的名称和位置。

5. 默认配置(Default Configuration):Spring Boot 提供了一组默认的配置,例如默认的数据库连接池、默认的端口号等。当没有其他配置来源时,应用程序将使用这些默认配置。

在优先级较高的配置选项中,更具体的配置会覆盖更一般的配置。例如,命令行参数会覆盖配置文件中的参数,而配置文件中的参数会覆盖默认配置。

🍁🍁 09、如何在 Spring Boot 中实现异步调用?

在 Spring Boot 中实现异步调用有多种方法,下面介绍其中两种常用的方法:

1. 使用 @Async 注解

Spring Boot 提供了 @Async 注解,它可以应用在方法上,用来指示该方法是一个异步方法。在使用 @Async 注解时,需要注意以下几点:

  • 在 Spring Boot 应用程序的启动类上添加 @EnableAsync 注解,以启用异步执行功能。
  • 在异步方法上添加 @Async 注解,以标识该方法应该在单独的线程中执行。
  • 如果异步方法需要返回结果,可以将其返回类型设置为 Future<T>,其中 T 是返回结果的类型。

下面是一个示例:

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;@Component
public class MyService {@Asyncpublic void asyncTask() {// 异步执行的任务}@Asyncpublic Future<String> asyncTaskWithResult() {// 异步执行的任务,并返回结果return new AsyncResult<>("Task completed");}
}

2. 使用 CompletableFuture

Java 8 引入了 CompletableFuture 类,它提供了更灵活的方式来处理异步操作。在 Spring Boot 中,可以使用 CompletableFuture 来实现异步调用。下面是一个示例:

import org.springframework.stereotype.Component;
import java.util.concurrent.CompletableFuture;@Component
public class MyService {public CompletableFuture<String> asyncTask() {return CompletableFuture.supplyAsync(() -> {// 异步执行的任务return "Task completed";});}
}

在调用该方法时,会立即返回一个 CompletableFuture 对象,可以通过该对象获取异步操作的结果。

需要注意的是,上述方法需要在 Spring Boot 启动类上添加 @EnableAsync 注解启用异步执行功能,或者在配置类中使用 @EnableAsync 注解进行相应配置。

使用异步调用可以提高系统的吞吐量和响应性,但也需要注意合理使用线程池,避免线程资源的过度消耗。

🍁🍁 10、Spring Boot 中如何实现跨域请求?

在 Spring Boot 中实现跨域请求有多种方法,下面介绍其中两种常用的方法:

1. 使用 @CrossOrigin 注解

@CrossOrigin 注解是 Spring Framework 提供的一种简单的方式,用于处理跨域请求。通过在控制器类或方法上添加 @CrossOrigin 注解,可以指定允许的跨域请求的来源、方法和其他选项。

下面是一些示例:

@RestController
public class MyController {@GetMapping("/api/data")@CrossOrigin(origins = "http://example.com")public String getData() {// 处理请求并返回数据}@PostMapping("/api/save")@CrossOrigin(origins = {"http://example.com", "http://another-domain.com"})public void saveData(@RequestBody Data data) {// 处理请求并保存数据}
}

在上述示例中,@CrossOrigin 注解指定了允许跨域请求的来源,可以用字符串或字符串数组形式指定多个来源。还可以通过其他选项,如 allowedHeadersallowCredentialsexposedHeaders 等来自定义跨域请求的行为。

2. 使用 Web 安全配置类

除了使用 @CrossOrigin 注解,还可以通过 Web 安全配置类进行全局配置,以处理跨域请求。可以创建一个继承自 WebSecurityConfigurerAdapter 的配置类,并覆盖 addCorsMappings 方法,并在其中配置跨域请求的细节。

下面是一个示例:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.cors();}@Beanpublic CorsConfigurationSource corsConfigurationSource() {CorsConfiguration configuration = new CorsConfiguration();configuration.setAllowedOrigins(Arrays.asList("http://example.com"));configuration.setAllowedMethods(Arrays.asList("GET", "POST"));UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", configuration);return source;}
}

在上述示例中,通过覆盖 configure 方法并调用 http.cors(),启用了跨域请求的支持。此外,通过创建一个 CorsConfigurationSource 的 bean,并在其中设置允许跨域请求的来源和方法。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【网络】网络层协议ARP和IP协议转发流程

目录 一、IP概述 1.1 IP简介 1.2 IP协议 二、IP地址与硬件地址 三、地址解析协议ARP 3.1 ARP协议简介 3.2 ARP工作流程 3.3 ARP的四种典型情况 四、IP协议的转发流 一、IP概述 1.1 IP简介 IP地址&#xff08;Internet Protocol Address&#xff09;是指互联网协议地址…

[VUE]1-创建vue工程

目录 基于脚手架创建前端工程 1、环境要求 2、操作过程 3、工程结构 4、启动前端服务 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学习&#xff0c;擅长web应用开发、数据结构和算法&#xff0c…

如何写html邮件 —— 参考主流outook、gmail、qq邮箱渲染邮件过程

文章目录 ⭐前言⭐outlook渲染邮件⭐gmail邮箱渲染邮件⭐qq邮箱渲染邮件 ⭐编写html邮件&#x1f496;table表格的属性&#x1f496;文本&#x1f496;图片&#x1f496;按钮&#x1f496;背景图片 ⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于 …

云卷云舒:【实战篇】对象存储迁移

云卷云舒&#xff1a;【实战篇】MySQL迁移-CSDN博客 1. 简介 对象存储与块存储、文件存储并列为云计算三大存储模型。提供海量存储空间服务&#xff0c;具备快速的数据存取性能、高可靠和数据安全性&#xff0c;通过标准的RESTful API接口和丰富的SDK包来提供服务&#xff0c…

3D模型UV展开原理

今年早些时候&#xff0c;我为 MAKE 杂志写了一篇教程&#xff0c;介绍如何制作视频游戏角色的毛绒动物。 该技术采用给定的角色 3D 模型及其纹理&#xff0c;并以编程方式生成缝纫图案。 虽然我已经编写了一般摘要并将源代码上传到 GitHub&#xff0c;但我在这里编写了对使这一…

Presto CLI学习

1. 序言 作为Presto的客户端之一&#xff0c;Presto CLI是一个基于终端的交互式shell&#xff0c;对应presto源码中的presto-cli模块 Presto CLI的本质是一个self-executing jar —— presto-cli-version-executable.jar&#xff0c;就像一个普通的UNIX可执行文件 因此&#…

olap/spark-tungsten:codegen

15721这一章没什么好说的&#xff0c;不再贴课程内容了。codegen和simd在工业界一般只会选一种实现。比如phothon之前用codegen&#xff0c;然后改成了向量化引擎。一般gen的都是weld IR/LLVM IR/当前语言&#xff0c;gen成C的也要检查是不是有本地预编译版本&#xff0c;要不没…

城市建设模拟游戏:鼠托邦 RATOPIA 中文免安装版

《鼠托邦》是一款由独立游戏开发团队Cassel Games开发的基地建设模拟游戏。在游戏中&#xff0c;玩家需要管理一个庞大的地下鼠国&#xff0c;打造理想中的“鼠托邦”。玩家可以化身为糖果派对游戏中的老鼠女王&#xff0c;带领老鼠民众建设城市、勘探地下领域以扩展生存空间。…

Web前端-JavaScript(ES6)

文章目录 1.ES5数组新方法1.1 数组方法forEach遍历数组1.2 数组方法filter过滤数组1.3 数组方法some1.4 some和forEach和filter的区别1.5 find()1.6 findIndex()1.7 trim去除字符串两端的空格1.8 获取对象的属性名1.9 Object.defineProperty 2.ES6语法2.1 ES6概述2.2 为什么使用…

CTF数据分析题详解

目录 题目一(1.pcap) 题目二(2.pcap) 题目三(3.pcap) 题目四(4.pcap) CTF流量分析经典例题详解-CSDN博客 本文章涉及的所有题目附件下载地址&#xff1a; 链接&#xff1a; https://pan.baidu.com/s/18mWo5vn1zp_XbmcQrMOKRA 提取码&#xff1a;hrc4 声明&#xff1a;这里…

WorkPlus AI助理为企业提供智能客服的机器人解决方案

在数字化时代&#xff0c;企业面临着客户服务的重要挑战。AI客服机器人成为了提升客户体验和提高工作效率的关键工具。作为一款优秀的AI助理&#xff0c;WorkPlus AI助理以其智能化的特点和卓越的功能&#xff0c;为企业提供了全新的客服机器人解决方案。 为什么选择WorkPlus A…

Python机器学习入门必学必会:机器学习与Python基础

1.机器学习常见的基础概念 根据输入数据是否具有“响应变量”信息&#xff0c;机器学习被分为“监督式学习”和“非监督式学习”。“监督式学习”即输入数据中即有X变量&#xff0c;也有y变量&#xff0c;特色在于使用“特征&#xff08;X变量&#xff09;”来预测“响应变量&…

【Python从入门到进阶】46、58同城Scrapy项目案例介绍

接上篇《45、Scrapy框架核心组件介绍》 上一篇我们学习了Scrapy框架的核心组件的使用。本篇我们进入实战第一篇&#xff0c;以58同城的Scrapy项目案例&#xff0c;结合实际再次巩固一下项目结构以及代码逻辑的用法。 一、案例网站介绍 58同城是一个生活服务类平台&#xff0c…

【分布式】分布式链路跟踪技术

为什么需要分布式链路追踪 提到分布式链路追踪&#xff0c;我们要先提到微服务。相信很多人都接触过微服务。微服务是一种开发软件的架构和组织方法&#xff0c;它侧重将服务解耦&#xff0c;服务之间通过API通信。使应用程序更易于扩展和更快地开发&#xff0c;从而加速新功能…

Go-gin-example 添加注释 第一部分 新建项目及api编写

文章目录 go-gin-example环境准备初始化 Go Modules基础使用 gin 安装测试gin是否引入 gin搭建Blog APIsgo-ini简述配置文件 阶段目标 编写简单API错误码包 完成一个demo初始化项目初始化项目数据库编写项目配置包拉取go-ini配置包在conf目录下新建app.ini文件&#xff0c;写入…

【操作系统篇】什么是分段和分页

什么是分段和分页 ✔️ 典型解析✔️分页✔️页表✔️分段&#xff08;Segmentation&#xff09;✔️ 分段和分页的区别✔️分页和分段哪个更耗资源✔️它们对性能的影响是怎样的✔️分段和分页分别适合什么场景 ✔️ 典型解析 在操作系统中&#xff0c;分段和分页是两种不同的…

在做题中学习(43):长度最小的子数组

LCR 008. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a;同向双指针-------滑动窗口算法 解释&#xff1a;本是暴力枚举做法&#xff0c;因为全部是正整数&#xff0c;就可以利用单调性和双指针解决问题来节省时间 思路&#xff1a; 如上面图&am…

ES -极客学习

Elasticsearch 简介及其发展历史 起源 Lucene 于 Java 语言开发的搜索引擎库类创建于 1999 年&#xff0c;2005 年成为 Apache 顶级开源项目Lucene 具有高性能、易扩展的优点Lucene 的局限性 只能基于 Java 语言开发类库的接口学习曲线陡峭原生并不支持水平扩展原生并不支持水…

如何找到 niche 出海细分市场的 IDEA

先说结论就是&#xff1a;看榜单 Why&#xff1a;为什么看榜单&#xff1f; 大家会问为什么&#xff1f;原因很简单&#xff1a; 熟读唐诗三百首&#xff0c;不会作诗也会吟不天天看榜单上相关的优秀同行&#xff0c;你想干啥 心法就是下苦功夫坚持&#xff0c;量变引起质变…

Nginx 文件名逻辑漏洞(CVE-2013-4547)

目录 Nginx 文件名逻辑漏洞&#xff08;CVE-2013-4547&#xff09; 1.cd到CVE-2013-4547 2.执行docker-compose up -d 3.查看靶场是否开启成功 4.访问浏览器 5.上传含有一句话木马的图片 6.burp抓包 7.在shell.gif加空格 8.放包 9.访问路径 10.继续抓包 11.在aa后面…