大多数应用程序都需要在某一时刻处理输入和输出问题。Spring Boot提供实用程序和与一系列技术的集成,以便在您需要IO功能时提供帮助。本节介绍缓存和验证等标准IO功能,以及调度和分布式事务等更高级的主题。我们还将介绍调用远程REST或SOAP服务以及发送电子邮件。

1. Caching

Spring框架支持透明地向应用程序添加缓存。在其核心,抽象将缓存应用于方法,从而根据缓存中的可用信息减少执行次数。缓存逻辑以透明方式应用,不会对调用者造成任何干扰。只要使用@EnableCering注释启用了缓存支持,Spring Boot就会自动配置缓存基础设施。

Check the relevant section of the Spring Framework reference for more details.

简而言之,要将缓存添加到服务的操作中,请将相关注释添加到其方法中,如下例所示:

Java
Kotlin
import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; @Component public class MyMathService { @Cacheable("piDecimals") public int computePiDecimal(int precision) { ... } } 
           
           

此示例演示了如何在可能代价高昂的操作上使用缓存。在调用cultePiDecimal之前,抽象在piDecimals缓存中查找与i参数匹配的条目。如果找到条目,缓存中的内容将立即返回给调用方,并且不会调用该方法。否则,将调用该方法,并在返回值之前更新缓存。

You can also use the standard JSR-107 (JCache) annotations (such as @CacheResult) transparently. However, we strongly advise you to not mix and match the Spring Cache and JCache annotations.

如果您没有添加任何特定的缓存库,则Spring Boot会自动配置一个使用内存中并发映射的简单提供程序。当需要缓存时(如前面示例中的piDecimals),此提供程序会为您创建缓存。Simple提供程序并不是真正推荐用于生产用途,但对于入门和确保您理解这些功能来说,它是非常好的。当您决定使用缓存提供程序时,请务必阅读其文档,以了解如何配置您的应用程序使用的缓存。几乎所有提供程序都要求您显式配置在应用程序中使用的每个缓存。其中一些提供了一种方法来定制由spring.cache.cache-name属性定义的默认缓存。

It is also possible to transparently update or evict data from the cache.

1.1. Supported Cache Providers

缓存抽象并不提供实际的存储,而是依赖于由org.springFrawork.cache.Cacheorg.springframework.cache.CacheManager接口实现的抽象。

如果您尚未定义CacheManager类型的Bean或名为cacheResolverCacheResolver(请参阅CachingConfigurer),Spring Boot将尝试检测以下提供程序(按指定顺序):

It is also possible to force a particular cache provider by setting the spring.cache.type property. Use this property if you need to disable caching altogether in certain environments (such as tests).
Use the spring-boot-starter-cache “Starter” to quickly add basic caching dependencies. The starter brings in spring-context-support. If you add dependencies manually, you must include spring-context-support in order to use the JCache or Caffeine support.

如果CacheManager是由Spring Boot自动配置的,那么在它完全初始化之前,您可以通过公开实现CacheManagerCustomizer接口的Bean来进一步调优其配置。下面的示例设置一个标志,表示值不应向下传递到基础映射:

Java
Kotlin
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer; import org.springframework.cache.concurrent.ConcurrentMapCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class MyCacheManagerConfiguration { @Bean public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() { return (cacheManager) -> cacheManager.setAllowNullValues(false); } } 
            
            
In the preceding example, an auto-configured ConcurrentMapCacheManager is expected. If that is not the case (either you provided your own config or a different cache provider was auto-configured), the customizer is not invoked at all. You can have as many customizers as you want, and you can also order them by using @Order or Ordered.

1.1.1. Generic

如果上下文定义了至少一个org.springFrawork.cache.CacheBean,则使用泛型缓存。创建了包装该类型的所有Bean的CacheManager

1.1.2. JCache (JSR-107)

JCache是通过类路径上存在的javax.cache.Spi.CachingProvider(即类路径上存在一个符合JSR-107标准的缓存库)引导的,而JCacheCacheManager是由Spring-boot-starter-cache“starter”提供的。有各种兼容的库可用,而Spring Boot为Ehcache3、Hazelcast和Infinisspan提供了依赖项管理。也可以添加任何其他兼容的库。

可能会出现多个提供程序,在这种情况下,必须显式指定提供程序。即使JSR-107标准没有强制使用标准化的方式来定义配置文件的位置,Spring Boot也会尽最大努力使用实现细节来设置缓存,如下面的示例所示:

Properties
Yaml
# Only necessary if more than one provider is present
spring.cache.jcache.provider=com.example.MyCachingProvider
spring.cache.jcache.config=classpath:example.xml
             
             
When a cache library offers both a native implementation and JSR-107 support, Spring Boot prefers the JSR-107 support, so that the same features are available if you switch to a different JSR-107 implementation.
Spring Boot has general support for Hazelcast. If a single HazelcastInstance is available, it is automatically reused for the CacheManager as well, unless the spring.cache.jcache.config property is specified.

有两种方法可以定制底层的javax.cache.cacheManager

  • 通过设置spring.cache.cache-name属性,可以在启动时创建缓存。如果定义了定制的javax.cache.configuration.ConfigurationBean,则使用它来自定义它们。

  • CacheManager Bean通过<org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer>CacheManager的引用进行调用,以实现完全定制。

If a standard javax.cache.CacheManager bean is defined, it is wrapped automatically in an org.springframework.cache.CacheManager implementation that the abstraction expects. No further customization is applied to it.

1.1.3. Hazelcast

Spring Boot对Hazelcast有一般支持。如果已经自动配置了HazelCastInstance,并且com.hazelcast:Hazelcast-Spring在类路径上,那么它会自动包装在CacheManager中。

Hazelcast can be used as a JCache compliant cache or as a Spring CacheManager compliant cache. When setting spring.cache.type to hazelcast, Spring Boot will use the CacheManager based implementation. If you want to use Hazelcast as a JCache compliant cache, set spring.cache.type to jcache. If you have multiple JCache compliant cache providers and want to force the use of Hazelcast, you have to explicitly set the JCache provider.

1.1.4. Infinispan

Infinispan没有默认配置文件位置,因此必须显式指定。否则,将使用默认引导。

Properties
Yaml
spring.cache.infinispan.config=infinispan.xml
             
             

通过设置spring.cache.cache-name属性,可以在启动时创建缓存。如果定义了自定义ConfigurationBuilderBean,则使用它来自定义缓存。

为了与Spring Boot的Jakarta EE 9基线兼容,必须使用Infinisspan的-jakarta模块。对于具有-jakarta变量的每个模块,必须使用该变量来代替标准模块。例如,必须分别使用infinisspan-core-jakartainfinispanCommons-jakarta来代替infinisspan-coreinfinisspan-Commons

1.1.5. Couchbase

如果Spring data Couchbase可用,并且Couchbase已配置,则Couchbase CacheManager将自动配置。可以通过设置spring.cache.cache-name属性在启动时创建额外的缓存,并且可以使用spring.cache.Couchbase.*属性配置缓存默认值。例如,以下配置创建的cache1cache2缓存的条目过期为10分钟:

Properties
Yaml
spring.cache.cache-names=cache1,cache2
spring.cache.couchbase.expiration=10m
             
             

如果您需要对配置进行更多控制,可以考虑注册一个CouchbaseCacheManagerBuilderCustomizerBean。以下示例显示为cache1cache2配置特定条目过期的定制器:

Java
Kotlin
import java.time.Duration; import org.springframework.boot.autoconfigure.cache.CouchbaseCacheManagerBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.couchbase.cache.CouchbaseCacheConfiguration; @Configuration(proxyBeanMethods = false) public class MyCouchbaseCacheManagerConfiguration { @Bean public CouchbaseCacheManagerBuilderCustomizer myCouchbaseCacheManagerBuilderCustomizer() { return (builder) -> builder .withCacheConfiguration("cache1", CouchbaseCacheConfiguration .defaultCacheConfig().entryExpiry(Duration.ofSeconds(10))) .withCacheConfiguration("cache2", CouchbaseCacheConfiguration .defaultCacheConfig().entryExpiry(Duration.ofMinutes(1))); } } 
             
             

1.1.6. Redis

如果Redis可用并已配置,则会自动配置RedisCacheManager。可以通过设置spring.cache.cache-name属性在启动时创建额外的缓存,并且可以使用spring.cache.redis.*属性配置缓存默认值。例如,以下配置创建的cache1cache2缓存的生存时间为10分钟:

Properties
Yaml
spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=10m
             
             
By default, a key prefix is added so that, if two separate caches use the same key, Redis does not have overlapping keys and cannot return invalid values. We strongly recommend keeping this setting enabled if you create your own RedisCacheManager.
You can take full control of the default configuration by adding a RedisCacheConfiguration @Bean of your own. This can be useful if you need to customize the default serialization strategy.

如果您需要对配置进行更多控制,可以考虑注册一个RedisCacheManagerBuilderCustomizerBean。以下示例显示为cache1cache2配置特定生存时间的定制器:

Java
Kotlin
import java.time.Duration; import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; @Configuration(proxyBeanMethods = false) public class MyRedisCacheManagerConfiguration { @Bean public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() { return (builder) -> builder .withCacheConfiguration("cache1", RedisCacheConfiguration .defaultCacheConfig().entryTtl(Duration.ofSeconds(10))) .withCacheConfiguration("cache2", RedisCacheConfiguration .defaultCacheConfig().entryTtl(Duration.ofMinutes(1))); } } 
             
             

1.1.7. Caffeine

Caffeine是对Guava缓存的Java 8重写,取代了对Guava的支持。如果存在咖啡因,则会自动配置CaffeineCacheManager(由Spring-ot-starter-cache“starter”提供)。可以在启动时通过设置spring.cache.cache-name属性来创建缓存,并且可以通过以下方法之一(按指定的顺序)自定义缓存:

  1. spring.cache.caffeine.spec定义的缓存规范

  2. 定义了com.github.benmanes.caffeine.cache.CaffeineSpecBean

  3. 定义了com.github.benmanes.caffeine.cache.CaffeineBean

例如,以下配置创建的cache1cache2缓存的最大大小为500,生存时间为10分钟

Properties
Yaml
spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
             
             

如果定义了CaffeineCacheManager Bean,它将自动与<com.github.benmanes.caffeine.cache.CacheLoader>CaffeineCacheManager关联。由于CacheLoader将与由缓存管理器管理的所有缓存相关联,因此必须将其定义为CacheLoader<;Object;。自动配置会忽略任何其他泛型类型。

1.1.8. Cache2k

Cache2k是内存缓存。如果存在Cache2k Spring集成,则会自动配置SpringCache2kCacheManager

通过设置spring.cache.cache-name属性,可以在启动时创建缓存。可以使用Cache2kBuilderCustomizerBean来自定义缓存默认设置。以下示例显示一个定制器,该定制器将缓存容量配置为200个条目,过期时间为5分钟:

Java
Kotlin
import java.util.concurrent.TimeUnit; import org.springframework.boot.autoconfigure.cache.Cache2kBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class MyCache2kDefaultsConfiguration { @Bean public Cache2kBuilderCustomizer myCache2kDefaultsCustomizer() { return (builder) -> builder.entryCapacity(200) .expireAfterWrite(5, TimeUnit.MINUTES); } } 
             
             

1.1.9. Simple

如果找不到其他提供程序,则配置一个使用ConcurentHashMap作为缓存存储的简单实现。如果应用程序中不存在缓存库,则这是默认设置。默认情况下,缓存是根据需要创建的,但您可以通过设置缓存名称属性来限制可用缓存列表。例如,如果只需要cache1cache2缓存,请按如下方式设置cache1cache2属性:

Properties
Yaml
spring.cache.cache-names=cache1,cache2
             
             

如果您这样做了,并且您的应用程序使用了未列出的缓存,则它在运行时会在需要缓存时失败,但不会在启动时失败。这类似于使用未声明缓存时“真正的”缓存提供程序的行为方式。

1.1.10. None

当您的配置中存在@EnableCaching时,也需要一个合适的缓存配置。如果您需要在某些环境中完全禁用缓存,请强制缓存类型为None以使用无操作实现,如下例所示:

Properties
Yaml
spring.cache.type=none
             
             

2. Hazelcast

如果类路径上有Hazelcast并且找到了合适的配置,则Spring Boot会自动配置您可以注入到应用程序中的Hazelcast实例

Spring Boot首先尝试通过检查以下配置选项来创建客户端:

  • com.hazelcast.client.config.ClientConfigBean的存在。

  • spring.hazelCast.config属性定义的配置文件。

  • 存在hazelCast.client.config系统属性。

  • 工作目录或类路径根目录中的Hazelcast-client.xml

  • 工作目录或类路径根目录中的Hazelcast-client.yaml(或Hazelcast-client.yml)。

如果无法创建客户端,则Spring Boot会尝试配置嵌入式服务器。如果您定义com.hazelCast.config.ConfigBean,则Spring Boot将使用该Bean。如果您的配置定义了实例名称,则Spring Boot会尝试定位现有实例,而不是创建新实例。

您还可以通过配置指定要使用的Hazelcast配置文件,如下例所示:

Properties
Yaml
spring.hazelcast.config=classpath:config/my-hazelcast.xml
           
           

否则,Spring Boot会尝试从默认位置查找Hazelcast配置:工作目录或类路径根目录中的hazelCast.xml,或相同位置中的.yaml/.yml。我们还检查是否设置了hazelCast.config系统属性。有关详细信息,请参阅Hazelcast文档。

By default, @SpringAware on Hazelcast components is supported. The ManagementContext can be overridden by declaring a HazelcastConfigCustomizer bean with an @Order higher than zero.
Spring Boot also has explicit caching support for Hazelcast. If caching is enabled, the HazelcastInstance is automatically wrapped in a CacheManager implementation.

3. Quartz Scheduler

Spring Boot为使用Quartz调度器提供了几个便利,包括Spring-ot-starter-Quartz“starter”。如果Quartz可用,则自动配置Scheduler(通过SchedulerFactoryBean抽象)。

以下类型的Bean将自动拾取并与Scheduler关联:

  • JobDetail:定义特定的作业。JobDetail实例可以使用JobBuilder接口构建。

  • 日历

  • 触发器:定义触发特定作业的时间。

默认情况下,使用内存中的JobStore。但是,如果应用程序中有DataSourceBean并且相应地配置了spring.Quartz.job-store-type属性,则可以配置基于JDBC的存储,如下例所示:

Properties
Yaml
spring.quartz.job-store-type=jdbc
           
           

使用JDBC存储时,可以在启动时初始化架构,如下例所示:

Properties
Yaml
spring.quartz.jdbc.initialize-schema=always
           
           
By default, the database is detected and initialized by using the standard scripts provided with the Quartz library. These scripts drop existing tables, deleting all triggers on every restart. It is also possible to provide a custom script by setting the spring.quartz.jdbc.schema property.

若要使Quartz使用应用程序主DataSource以外的DataSource,请声明一个DataSourceBean,并使用@QuartzDataSource注释其@Bean方法。这样做可以确保SchedulerFactoryBean和架构初始化都使用特定于Quartz的DataSource。同样,为了让Quartz使用应用程序主TransactionManager之外的TransactionManager,请声明一个TransactionManagerBean,并用@QuartzTransactionManager注释其@Bean方法。

默认情况下,配置创建的作业不会覆盖已从永久作业存储中读取的已注册作业。若要覆盖现有作业定义,请设置spring.quartz.overwrite-existing-jobs属性。

Quartz Scheduler配置可以使用spring.Quartz属性和SchedulerFactoryBeanCustomizerBean进行自定义,它们允许编程SchedulerFactoryBean自定义。高级Quartz配置属性可以使用spring.Quartz.Properties.*进行自定义。

In particular, an Executor bean is not associated with the scheduler as Quartz offers a way to configure the scheduler through spring.quartz.properties. If you need to customize the task executor, consider implementing SchedulerFactoryBeanCustomizer.

作业可以定义设置器以注入数据映射属性。常规Bean也可以以类似的方式注入,如下例所示:

Java
Kotlin
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; public class MySampleJob extends QuartzJobBean {  // fields ...  private MyService myService; private String name;  // Inject "MyService" bean public void setMyService(MyService myService) { this.myService = myService; } // Inject the "name" job data property public void setName(String name) { this.name = name; } @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { this.myService.someMethod(context.getFireTime(), this.name); } } 
           
           

4. Sending Email

Spring框架提供了使用JavaMailSender接口发送电子邮件的抽象,而Spring Boot为其提供了自动配置以及一个启动模块。

See the reference documentation for a detailed explanation of how you can use JavaMailSender.

如果spring.mail.host和相关的库(由Spring-ot-starter-mail定义)可用,则会创建一个默认的JavaMailSender。发送者可以通过spring.mail命名空间中的配置项进一步定制。有关详细信息,请参阅MailProperties

特别是,某些默认超时值是无限的,您可能希望对其进行更改,以避免无响应的邮件服务器阻止线程,如下例所示:

Properties
Yaml
spring.mail.properties[mail.smtp.connectiontimeout]=5000
spring.mail.properties[mail.smtp.timeout]=3000
spring.mail.properties[mail.smtp.writetimeout]=5000
           
           

还可以使用JNDI中的现有会话配置Java MailSender

Properties
Yaml
spring.mail.jndi-name=mail/Session
           
           

当设置了jndi-name时,它优先于所有其他与会话相关的设置。

5. Validation

只要类路径上有JSR-303实现(比如Hibernate验证器),就会自动启用Bean验证1.1支持的方法验证特性。这允许在Bean方法的参数和/或返回值上使用javax.valify约束进行注释。对于要在其方法中搜索内联约束批注的目标类,需要在类型级别使用@valated批注来批注具有此类批注的目标类。

例如,以下服务触发第一个参数的验证,确保其大小在8到10之间:

Java
Kotlin
import jakarta.validation.constraints.Size; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @Service @Validated public class MyBean { public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code, Author author) { return ... } } 
           
           

解析约束消息中的{PARAMETERS}时使用应用程序的MessageSource。这允许您使用应用程序的Messages.Properties文件来处理Bean验证消息。一旦解析了参数,就可以使用Bean验证的默认插值器来完成消息插补。

要定制用于构建<代码>ValidatorFactory ValidationConfigurationCustomizer>的<代码>配置 ,请定义一个ValidatorFactory Bean。当定义了多个定制器Bean时,将根据它们的@order注释或有序实现按顺序调用它们。

6. Calling REST Services

如果您的应用程序调用远程REST服务,那么Spring Boot使用RestTemplateWebClient非常方便。

6.1. RestTemplate

如果需要从应用程序调用远程REST服务,可以使用Spring框架的RestTemplate类。由于RestTemplate实例在使用前通常需要进行定制,因此Spring Boot不提供任何自动配置的RestTemplateBean。但是,它会自动配置RestTemplateBuilder,在需要时可用来创建RestTemplateBuilder实例。自动配置的RestTemplateBuilder确保将合理的HttpMessageConverters应用于RestTemplateBuilder实例。

下面的代码显示了一个典型的示例:

Java
Kotlin
import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class MyService { private final RestTemplate restTemplate; public MyService(RestTemplateBuilder restTemplateBuilder) { this.restTemplate = restTemplateBuilder.build(); } public Details someRestCall(String name) { return this.restTemplate.getForObject("/{name}/details", Details.class, name); } } 
            
            
RestTemplateBuilder includes a number of useful methods that can be used to quickly configure a RestTemplate. For example, to add BASIC auth support, you can use builder.basicAuthentication("user", "password").build().

6.1.1. RestTemplate Customization

有三种主要方法可用于RestTemplate自定义,具体取决于您希望自定义应用的范围有多广。

为了尽可能缩小任何定制的范围,注入自动配置的RestTemplateBuilder,然后根据需要调用它的方法。每个方法调用都返回一个新的RestTemplateBuilder实例,因此定制只影响生成器的这次使用。

要进行应用程序范围的累加性定制,请使用RestTemplateCustomizerBean。所有此类Bean都自动注册到自动配置的RestTemplateBuilder,并应用于使用它构建的任何模板。

以下示例显示了为除192.168.0.5以外的所有主机配置代理使用的定制器:

Java
Kotlin
import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner; import org.apache.hc.client5.http.routing.HttpRoutePlanner; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.protocol.HttpContext; import org.springframework.boot.web.client.RestTemplateCustomizer; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; public class MyRestTemplateCustomizer implements RestTemplateCustomizer { @Override public void customize(RestTemplate restTemplate) { HttpRoutePlanner routePlanner = new CustomRoutePlanner(new HttpHost("proxy.example.com")); HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(routePlanner).build(); restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient)); } static class CustomRoutePlanner extends DefaultProxyRoutePlanner { CustomRoutePlanner(HttpHost proxy) { super(proxy); } @Override protected HttpHost determineProxy(HttpHost target, HttpContext context) throws HttpException { if (target.getHostName().equals("192.168.0.5")) { return null; } return super.determineProxy(target, context); } } } 
             
             

最后,您可以定义自己的RestTemplateBuilderBean。这样做将替换自动配置的构建器。如果您希望将任何RestTemplateCustomizerBean应用于您的定制构建器,就像自动配置所做的那样,使用RestTemplateBuilderConfigurer配置它。下面的示例公开了一个RestTemplateBuilder,该RestTemplateBuilder与Spring Boot的自动配置所做的操作相匹配,只是还指定了自定义连接和读取超时:

Java
Kotlin
import java.time.Duration; import org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class MyRestTemplateBuilderConfiguration { @Bean public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer configurer) { return configurer.configure(new RestTemplateBuilder()).setConnectTimeout(Duration.ofSeconds(5)) .setReadTimeout(Duration.ofSeconds(2)); } } 
             
             

最极端(也是很少使用)的选择是在不使用配置器的情况下创建您自己的RestTemplateBuilderBean。除了替换自动配置的构建器之外,这还防止使用任何RestTemplateCustomizerBean。

6.2. WebClient

如果您的类路径上有Spring WebFlux,您还可以选择使用WebClient来调用远程REST服务。与RestTemplate相比,该客户端具有更多的功能,并且完全是反应性的。您可以在Spring框架文档的专用部分中了解更多关于WebClient的信息。

Spring Boot为您创建和预配置WebClient.Builder。强烈建议将其注入到您的组件中,并使用它来创建WebClient实例。Spring Boot正在配置构建器以共享HTTP资源,以与服务器相同的方式反映编解码器设置(请参阅WebFlux HTTP编解码器自动配置),等等。

下面的代码显示了一个典型的示例:

Java
Kotlin
import org.neo4j.cypherdsl.core.Relationship.Details; import reactor.core.publisher.Mono; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; @Service public class MyService { private final WebClient webClient; public MyService(WebClient.Builder webClientBuilder) { this.webClient = webClientBuilder.baseUrl("https://example.org").build(); } public Mono<Details> someRestCall(String name) { return this.webClient.get().uri("/{name}/details", name).retrieve().bodyToMono(Details.class); } } 
            
            

6.2.1. WebClient Runtime

Spring Boot将自动检测使用哪个ClientHttpConnector来驱动WebClient,这取决于应用程序类路径上可用的库。目前,支持反应器Netty、Jetty RS客户端、ApacheHttpClient和JDK的HttpClient。

Spring-Boot-starter-WebFluxstarter默认依赖于io.projectreactor.netty:reactor-netty,它同时提供了服务器和客户端实现。如果您选择使用Jetty作为反应式服务器,则应该添加对Jetty反应式HTTP客户端库org.eclipse.jetty:jetty-reactive-httpclient.的依赖对服务器和客户端使用相同的技术有其优势,因为它将自动在客户端和服务器之间共享HTTP资源。

开发人员可以通过提供定制的ReacterResourceFactoryJettyResourceFactoryBean来覆盖Jetty和反应器Netty的资源配置--这将同时应用于客户端和服务器。

如果您希望覆盖客户端选择,您可以定义自己的ClientHttpConnector并完全控制客户端配置。

您可以在Spring框架参考文档中了解有关WebClient配置选项的更多信息。

6.2.2. WebClient Customization

有三种主要方法可用于WebClient自定义,具体取决于您希望自定义应用的范围有多广。

为了尽可能缩小任何定制的范围,注入自动配置的WebClient.Builder,然后根据需要调用它的方法。WebClient.Builder实例是有状态的:构建器上的任何更改都会反映在随后使用它创建的所有客户端中。如果您希望使用相同的构建器创建多个客户端,还可以考虑使用WebClient.Builder Other=Builder.clone();来克隆构建器。

要对所有WebClient.Builder实例进行应用程序范围的累加性定制,您可以声明WebClientCustomizerBean并在注入点本地更改WebClient.Builder

最后,您可以回退到原来的API并使用WebClient.create()。在这种情况下,不会应用自动配置或WebClientCustomizer

7. Web Services

Spring Boot提供了Web服务自动配置,因此您所要做的就是定义您的端点

Spring Web Services特性可以通过Spring-ot-starter-webservices模块轻松访问。

SimpleWsdl11DefinitionSimpleXsdSchema可以分别为您的WSDL和XSD自动创建Bean。要执行此操作,请配置它们的位置,如下例所示:

Properties
Yaml
spring.webservices.wsdl-locations=classpath:/wsdl
           
           

7.1. Calling Web Services with WebServiceTemplate

如果需要从应用程序调用远程Web服务,可以使用WebServiceTemplate类。由于WebServiceTemplate实例在使用前通常需要进行定制,因此Spring Boot不提供任何自动配置的WebServiceTemplateBean。但是,它会自动配置一个WebServiceTemplateBuilder,在需要时可以用它来创建WebServiceTemplate实例。

下面的代码显示了一个典型的示例:

Java
Kotlin
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; import org.springframework.stereotype.Service; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.soap.client.core.SoapActionCallback; @Service public class MyService { private final WebServiceTemplate webServiceTemplate; public MyService(WebServiceTemplateBuilder webServiceTemplateBuilder) { this.webServiceTemplate = webServiceTemplateBuilder.build(); } public SomeResponse someWsCall(SomeRequest detailsReq) { return (SomeResponse) this.webServiceTemplate.marshalSendAndReceive(detailsReq, new SoapActionCallback("https://ws.example.com/action")); } } 
            
            

默认情况下,WebServiceTemplateBuilder使用类路径上可用的HTTP客户端库检测合适的基于HTTP的WebServiceMessageSender。您还可以按如下方式自定义读取和连接超时:

Java
Kotlin
import java.time.Duration; import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder; import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.transport.WebServiceMessageSender; @Configuration(proxyBeanMethods = false) public class MyWebServiceTemplateConfiguration { @Bean public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) { WebServiceMessageSender sender = new HttpWebServiceMessageSenderBuilder() .setConnectTimeout(Duration.ofSeconds(5)) .setReadTimeout(Duration.ofSeconds(2)) .build(); return builder.messageSenders(sender).build(); } } 
            
            

8. Distributed Transactions With JTA

通过使用从JNDI检索的事务管理器,Spring Boot支持跨多个XA资源的分布式JTA事务。

当检测到JTA环境时,将使用Spring的JtaTransactionManager来管理事务。升级了自动配置的JMS、数据源和JPA Bean以支持XA事务。您可以使用标准的Spring习惯用法,如@Transaction来参与分布式事务。如果您处于JTA环境中,并且仍然希望使用本地事务,则可以将spring.jta.Enabled属性设置为FALSE以禁用JTA自动配置。

8.1. Using a Jakarta EE Managed Transaction Manager

如果将Spring Boot应用程序打包为warear文件并将其部署到Jakarta EE应用服务器,则可以使用应用服务器的内置事务管理器。Spring Boot试图通过查看常见的JNDI位置(Java:comp/UserTransactionJava:comp/TransactionManager等)来自动配置事务管理器。在使用应用程序服务器提供的事务服务时,您通常还希望确保所有资源都由服务器管理并通过JNDI公开。Href=“0”>spring.datasource.jndi-nameBoot试图通过在JNDI路径(<代码>Java:/JmsXA 或<代码>Java:/XAConnectionFactory )中查找<代码>ConnectionFactory 来自动配置JMS,并且您可以使用spring.datasource.jndi-name属性来配置<代码>数据源

8.2. Mixing XA and Non-XA JMS Connections

在使用JTA时,主要JMSConnectionFactoryBean支持XA并参与分布式事务。您可以在不使用任何@限定符的情况下向Bean注入:

Java
Kotlin
public MyBean(ConnectionFactory connectionFactory) {
    // ...
}

            
            

在某些情况下,您可能希望使用非XAConnectionFactory来处理某些JMS消息。例如,您的JMS处理逻辑可能需要比XA超时更长的时间。

如果您想使用非XAConnectionFactory,您可以使用non XaJmsConnectionFactoryBean:

Java
Kotlin
public MyBean(@Qualifier("nonXaJmsConnectionFactory") ConnectionFactory connectionFactory) {
    // ...
}

            
            

为了保持一致性,还使用了Bean别名xaJmsConnectionFactory来提供jmsConnectionFactory

Java
Kotlin
public MyBean(@Qualifier("xaJmsConnectionFactory") ConnectionFactory connectionFactory) {
    // ...
}

            
            

8.3. Supporting an Embedded Transaction Manager

XAConnectionFactoryWrapperXADataSourceWrapper接口可用于支持嵌入式事务管理器。这些接口负责包装XAConnectionFactoryXADataSourceBean,并将它们公开为常规的ConnectionFactoryDataSourceBean,它们透明地注册到分布式事务中。DataSource和JMS自动配置使用JTA变体,前提是您在ApplicationContext中注册了JtaTransactionManagerBean和适当的XA包装器Bean。

9. What to Read Next

现在您应该已经很好地理解了Spring Boot的核心特性以及Spring Boot通过自动配置提供支持的各种技术。

接下来的几节将详细介绍如何将应用部署到云平台。您可以在下一节阅读构建容器镜像,或跳到生产就绪功能一节。