Spec-Zone.ru › Spring Boot

IO

Большинству приложений в какой-то момент потребуется обрабатывать ввод и вывод. Spring Boot предоставляет утилиты и интеграции с рядом технологий, которые помогут вам, когда потребуются возможности ввода-вывода. Этот раздел охватывает стандартные функции ввода-вывода, такие как кэширование и валидация, а также более сложные темы, такие как планирование и распределенные транзакции. Мы также рассмотрим вызов удаленных REST- или SOAP-служб и отправку электронных писем.

1. Кэширование

Spring Framework предоставляет поддержку прозрачного добавления кэширования в приложение. В основе лежит абстракция, применяющая кэширование к методам, тем самым уменьшая количество выполнений, исходя из информации, доступной в кэше. Логика кэширования применяется прозрачно, без каких-либо помех для вызывающего кода. Spring Boot автоматически настраивает инфраструктуру кэша, если поддержка кэширования включена с помощью аннотации @EnableCaching.

Подробную информацию см. в соответствующем разделе справочника Spring Framework.

Короче говоря, чтобы добавить кэширование к операции вашего сервиса, добавьте соответствующую аннотацию в его метод, как показано в следующем примере:

Java
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class MyMathService {

    @Cacheable("piDecimals")
    public int computePiDecimal(int precision) {
        ...
    }

}
Kotlin
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Component

@Component
class MyMathService {

    @Cacheable("piDecimals")
    fun computePiDecimal(precision: Int): Int {
        ...
    }

}

Этот пример демонстрирует использование кэширования для потенциально дорогостоящей операции. Перед вызовом computePiDecimal, абстракция ищет запись в кэше piDecimals, соответствующую аргументу i. Если запись найдена, содержимое кэша немедленно возвращается вызывающей стороне, и метод не вызывается. В противном случае, метод вызывается, а кэш обновляется перед возвратом значения.

Вы также можете использовать стандартные аннотации JSR-107 (JCache) (например, @CacheResult) прозрачно. Однако мы настоятельно рекомендуем не смешивать аннотации Spring Cache и JCache.

Если вы не добавляете какую-либо конкретную библиотеку кэша, Spring Boot автоматически настраивает простой провайдер simple provider, использующий конкурентные карты в памяти. Когда требуется кэш (например, piDecimals в предыдущем примере), этот провайдер создает его для вас. Простой провайдер не рекомендуется для использования в производстве, но он отлично подходит для начала работы и понимания функций. Когда вы определились с провайдером кэша, убедитесь, что прочитали его документацию, чтобы понять, как настроить кэши, используемые вашим приложением. Почти все провайдеры требуют явного конфигурирования каждого используемого в приложении кэша. Некоторые предоставляют возможность настройки по умолчанию, определённых свойством spring.cache.cache-names.

Также возможно прозрачно обновить или очистить данные из кэша.

1.1. Поддерживаемые поставщики кэша

Абстракция кэша не предоставляет фактическое хранилище и полагается на абстракцию, реализованную интерфейсами org.springframework.cache.Cache и org.springframework.cache.CacheManager.

Если вы не определили бин типа CacheManager или бин CacheResolver с именем cacheResolver (см. CachingConfigurer), Spring Boot пытается обнаружить следующие поставщики (в указанном порядке):

  1. Общий

  2. JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan и другие)

  3. Hazelcast

  4. Infinispan

  5. Couchbase

  6. Redis

  7. Caffeine

  8. Cache2k

  9. Простой

Кроме того, Spring Boot для Apache Geode предоставляет автоконфигурацию для использования Apache Geode в качестве поставщика кэша.

Если поставщик кэша CacheManager автоматически настроен Spring Boot, можно вынужденно указать определённый поставщик кэша, установив свойство spring.cache.type. Используйте это свойство, если вам нужно использовать кэши no-op в определённых средах (например, в тестах).
Используйте spring-boot-starter-cache «Starter», чтобы быстро добавить базовые зависимости кэширования. Starter подключает spring-context-support. Если вы добавляете зависимости вручную, вам необходимо включить spring-context-support, чтобы использовать поддержку JCache или Caffeine.

Если поставщик кэша CacheManager автоматически настроен Spring Boot, можно дополнительно настроить его конфигурацию до полного инициализации, экспонировав бин, реализующий интерфейс CacheManagerCustomizer. Следующий пример устанавливает флаг, указывающий, что значения null не должны передаваться в подлежащую карту:

Java
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);
    }

}
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)
class MyCacheManagerConfiguration {

    @Bean
    fun cacheManagerCustomizer(): CacheManagerCustomizer<ConcurrentMapCacheManager> {
        return CacheManagerCustomizer { cacheManager ->
            cacheManager.isAllowNullValues = false
        }
    }

}
В предыдущем примере ожидается автоматически настроенный ConcurrentMapCacheManager бин. Если это не так (вы предоставили свою конфигурацию или был настроен другой поставщик кэша), кастомайзер вообще не вызывается. Вы можете иметь любое количество кастомайзеров, а также упорядочить их, используя @Order или Ordered.

1.1.1. Общий

Общий кэш используется, если контекст определяет по крайней мере один бин org.springframework.cache.Cache. Создается бин CacheManager , охватывающий все бины этого типа.

1.1.2. JCache (JSR-107)

JCache инициализируется наличием javax.cache.spi.CachingProvider в classpath (то есть, в classpath присутствует библиотека кэширования, совместимая с JSR-107), а JCacheCacheManager предоставляется spring-boot-starter-cache «Starter». Доступны различные совместимые библиотеки, и Spring Boot предоставляет управление зависимостями для Ehcache 3, Hazelcast и Infinispan. Также можно добавить любые другие совместимые библиотеки.

Возможно, что присутствует более одного поставщика, в этом случае поставщик должен быть указан явно. Даже если стандарт JSR-107 не устанавливает стандартизированный способ определения расположения файла конфигурации, Spring Boot делает всё возможное, чтобы адаптироваться к настройке кэша с реализацией деталей, как показано в следующем примере:

Свойства
# Only necessary if more than one provider is present
spring.cache.jcache.provider=com.example.MyCachingProvider
spring.cache.jcache.config=classpath:example.xml
Yaml
# Only necessary if more than one provider is present
spring:
  cache:
    jcache:
      provider: "com.example.MyCachingProvider"
      config: "classpath:example.xml"
Когда библиотека кэша предлагает как собственную реализацию, так и поддержку JSR-107, Spring Boot отдает предпочтение поддержке JSR-107, чтобы те же возможности были доступны при переходе к другой реализации JSR-107.
Spring Boot имеет общую поддержку Hazelcast. Если доступен единственный HazelcastInstance, он автоматически повторно используется для CacheManager также, если не указано свойство spring.cache.jcache.config.

Существует два способа настройки базовой javax.cache.cacheManager:

  • Кэши могут быть созданы при запуске, задав свойство spring.cache.cache-names. Если определен кастомизированный бин javax.cache.configuration.Configuration, он используется для их настройки.

  • Бины org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer вызываются со ссылкой на CacheManager для полной настройки.

Если определен стандартный бин javax.cache.CacheManager, он автоматически обернётся в реализацию org.springframework.cache.CacheManager, которую ожидает абстракция. Дальнейшая настройка к нему не применяется.

1.1.3. Hazelcast

Spring Boot имеет общую поддержку Hazelcast. Если HazelcastInstance был автоматически настроен и com.hazelcast:hazelcast-spring присутствует в classpath, он автоматически обернётся в CacheManager.

Hazelcast может использоваться как совместимая с JCache кэш или как совместимая с Spring CacheManager кэш. При установке spring.cache.type на hazelcast, Spring Boot будет использовать реализацию, основанную на CacheManager. Если вы хотите использовать Hazelcast как совместимую с JCache кэш, установите spring.cache.type на jcache. Если у вас есть несколько совместимых с JCache поставщиков кэша и вы хотите принудительно использовать Hazelcast, вам необходимо явно указать поставщика JCache.

1.1.4. Infinispan

Infinispan не имеет стандартного расположения файла конфигурации, поэтому оно должно быть указано явно. В противном случае используется стандартная инициализация.

Свойства
spring.cache.infinispan.config=infinispan.xml
Yaml
spring:
  cache:
    infinispan:
      config: "infinispan.xml"

Кэши могут быть созданы при запуске, задав свойство spring.cache.cache-names. Если определен кастомизированный бин ConfigurationBuilder, он используется для настройки кэшей.

Для совместимости с базовой линией Jakarta EE 9 Spring Boot, должны использоваться модули -jakarta Infinispan. Для каждого модуля с вариантом -jakarta, необходимо использовать вариант вместо стандартного модуля. Например, infinispan-core-jakarta и infinispan-commons-jakarta необходимо использовать вместо infinispan-core и infinispan-commons соответственно.

1.1.5. Couchbase

Если Spring Data Couchbase доступен и Couchbase настроен, CouchbaseCacheManager настраивается автоматически. Дополнительные кэши могут быть созданы при запуске, установив свойство spring.cache.cache-names, и значения по умолчанию для кэшей могут быть настроены, используя свойства spring.cache.couchbase.*. Например, следующая конфигурация создает кэши cache1 и cache2 с временем истечения 10 минут:

Свойства
spring.cache.cache-names=cache1,cache2
spring.cache.couchbase.expiration=10m
Yaml
spring:
  cache:
    cache-names: "cache1,cache2"
    couchbase:
      expiration: "10m"

Если вам нужен больший контроль над конфигурацией, рассмотрите регистрацию бина CouchbaseCacheManagerBuilderCustomizer. Следующий пример показывает кастомайзер, который настраивает конкретное время истечения для cache1 и cache2:

Java
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)));

    }

}
Kotlin
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
import java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyCouchbaseCacheManagerConfiguration {

    @Bean
    fun myCouchbaseCacheManagerBuilderCustomizer(): CouchbaseCacheManagerBuilderCustomizer {
        return CouchbaseCacheManagerBuilderCustomizer { 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-names, и настройка параметров кэша с помощью свойств spring.cache.redis.*. Например, следующая конфигурация создаёт кэши cache1 и cache2 со временем жизни 10 минут:

Свойства
spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=10m
Yaml
spring:
  cache:
    cache-names: "cache1,cache2"
    redis:
      time-to-live: "10m"
По умолчанию добавляется префикс ключа, чтобы, если два отдельных кэша используют один и тот же ключ, Redis не имел перекрывающихся ключей и не мог возвращать некорректные значения. Мы настоятельно рекомендуем оставлять эту настройку включенной, если вы создаёте собственные RedisCacheManager.
Вы можете полностью контролировать стандартную конфигурацию, добавив собственный RedisCacheConfiguration @Bean. Это может быть полезно, если вам нужно настроить стратегию сериализации по умолчанию.

Если вам нужен больший контроль над конфигурацией, рассмотрите возможность регистрации bean RedisCacheManagerBuilderCustomizer. Следующий пример демонстрирует кастомайзер, настраивающий конкретное время жизни для cache1 и cache2.

Java
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)));

    }

}
Kotlin
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
import java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyRedisCacheManagerConfiguration {

    @Bean
    fun myRedisCacheManagerBuilderCustomizer(): RedisCacheManagerBuilderCustomizer {
        return RedisCacheManagerBuilderCustomizer { builder ->
            builder
                .withCacheConfiguration(
                    "cache1", RedisCacheConfiguration
                        .defaultCacheConfig().entryTtl(Duration.ofSeconds(10))
                )
                .withCacheConfiguration(
                    "cache2", RedisCacheConfiguration
                        .defaultCacheConfig().entryTtl(Duration.ofMinutes(1))
                )
        }
    }

}

1.1.7. Caffeine

Caffeine — это переписанная на Java 8 версия кэша Guava, которая заменяет поддержку Guava. Если Caffeine присутствует, автоматически настраивается CaffeineCacheManager (предоставленный spring-boot-starter-cache “Starter”). Кэши могут быть созданы при запуске путём установки свойства spring.cache.cache-names и могут быть настраиваемы одним из следующих способов (в указанном порядке):

  1. Спецификация кэша, определённая spring.cache.caffeine.spec

  2. Определён bean com.github.benmanes.caffeine.cache.CaffeineSpec

  3. Определён bean com.github.benmanes.caffeine.cache.Caffeine

Например, следующая конфигурация создаёт кэши cache1 и cache2 с максимальным размером 500 и временем жизни 10 минут.

Свойства
spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
Yaml
spring:
  cache:
    cache-names: "cache1,cache2"
    caffeine:
      spec: "maximumSize=500,expireAfterAccess=600s"

Если определён bean com.github.benmanes.caffeine.cache.CacheLoader, он автоматически ассоциируется с CaffeineCacheManager. Поскольку CacheLoader будет связан со всеми кэшами, управляемыми менеджером кэшей, он должен быть определён как CacheLoader<Object, Object>. Автонастройка игнорирует любой другой общий тип.

1.1.8. Cache2k

Cache2k — кэш в оперативной памяти. Если интегрирование Cache2k с Spring присутствует, автоматически настраивается SpringCache2kCacheManager.

Кэши могут быть созданы при запуске путём установки свойства spring.cache.cache-names Настройка параметров кэша по умолчанию может быть изменена с помощью bean Cache2kBuilderCustomizer. Следующий пример показывает кастомайзер, настраивающий ёмкость кэша на 200 записей со сроком действия 5 минут:

Java
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);
    }

}
Kotlin
import org.springframework.boot.autoconfigure.cache.Cache2kBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.util.concurrent.TimeUnit

@Configuration(proxyBeanMethods = false)
class MyCache2kDefaultsConfiguration {

    @Bean
    fun myCache2kDefaultsCustomizer(): Cache2kBuilderCustomizer {
        return Cache2kBuilderCustomizer { builder ->
            builder.entryCapacity(200)
                .expireAfterWrite(5, TimeUnit.MINUTES)
        }
    }
}

1.1.9. Simple

Если ни один из других поставщиков не найден, настраивается простое решение с использованием ConcurrentHashMap в качестве хранилища кэша. Это значение по умолчанию, если в вашем приложении нет библиотеки кэширования. По умолчанию кэши создаются по мере необходимости, но вы можете ограничить список доступных кэшей, установив свойство cache-names Например, если вам нужны только кэши cache1 и cache2, установите свойство cache-names следующим образом:

Свойства
spring.cache.cache-names=cache1,cache2
Yaml
spring:
  cache:
    cache-names: "cache1,cache2"

Если вы так сделаете, и ваше приложение использует кэш, не указанный в списке, произойдёт ошибка во время выполнения, когда кэш потребуется, но не при запуске. Это аналогично поведению «настоящих» поставщиков кэшей, если вы используете не объявленный кэш.

1.1.10. None

Если @EnableCaching присутствует в вашей конфигурации, ожидается также соответствующая конфигурация кэша. Если у вас есть пользовательский CacheManager, рассмотрите возможность определения его в отдельном классе @Configuration, чтобы можно было переопределить его при необходимости. None использует реализацию no-op, которая полезна в тестах, и тесты slice используют её по умолчанию через @AutoConfigureCache.

Если вам нужно использовать кэш no-op вместо автоматически настроенного менеджера кэша в определённой среде, установите тип кэша на none, как показано в следующем примере:

Свойства
spring.cache.type=none
Yaml
spring:
  cache:
    type: "none"

2. Hazelcast

Если Hazelcast находится в классе и найдена подходящая конфигурация, Spring Boot автоматически настраивает HazelcastInstance, который можно внедрить в ваше приложение.

Spring Boot сначала пытается создать клиента, проверяя следующие параметры конфигурации:

  • Наличие bean com.hazelcast.client.config.ClientConfig.

  • Файл конфигурации, определённый свойством spring.hazelcast.config.

  • Наличие системной переменной hazelcast.client.config.

  • Файл hazelcast-client.xml в рабочей директории или в корне classpath.

  • Файл hazelcast-client.yaml (или hazelcast-client.yml ) в рабочей директории или в корне classpath.

Если клиент не может быть создан, Spring Boot пытается настроить встроенный сервер. Если вы определяете bean com.hazelcast.config.Config , Spring Boot использует его. Если в вашей конфигурации определено имя экземпляра, Spring Boot пытается найти существующий экземпляр вместо создания нового.

Вы также можете указать используемый файл конфигурации Hazelcast через конфигурацию, как показано в следующем примере:

Свойства
spring.hazelcast.config=classpath:config/my-hazelcast.xml
Yaml
spring:
  hazelcast:
    config: "classpath:config/my-hazelcast.xml"

В противном случае Spring Boot пытается найти конфигурацию Hazelcast из стандартных расположений: hazelcast.xml в рабочей директории или в корне classpath, или YAML-аналог в тех же местах. Мы также проверяем, установлена ли системная переменная hazelcast.config. Для получения более подробной информации см. документацию Hazelcast.

По умолчанию поддержка @SpringAware на компонентах Hazelcast включена. Можно переопределить ManagementContext с помощью объявления bean HazelcastConfigCustomizer с @Order выше нуля.
Spring Boot также имеет явную поддержку кэширования для Hazelcast. Если кэширование включено, HazelcastInstance автоматически оборачивается в реализацию CacheManager .

3. Планировщик Quartz

Spring Boot предлагает удобства для работы с планировщиком Quartz, включая модуль spring-boot-starter-quartz. Если Quartz доступен, планировщик Scheduler автоматически настроен (через абстракцию SchedulerFactoryBean).

Компоненты следующих типов автоматически подхватываются и связываются с планировщиком Scheduler:

  • JobDetail: определяет конкретную задачу. Экземпляры JobDetail могут быть созданы с помощью API JobBuilder.

  • Calendar.

  • Trigger: определяет, когда запускается конкретная задача.

По умолчанию используется JobStore в памяти. Однако можно настроить хранилище на основе JDBC, если в приложении доступен компонент DataSource и свойство spring.quartz.job-store-type настроено соответствующим образом, как показано в следующем примере:

Свойства
spring.quartz.job-store-type=jdbc
Yaml
spring:
  quartz:
    job-store-type: "jdbc"

При использовании хранилища JDBC схема может быть инициализирована при запуске, как показано в следующем примере:

Свойства
spring.quartz.jdbc.initialize-schema=always
Yaml
spring:
  quartz:
    jdbc:
      initialize-schema: "always"
По умолчанию база данных обнаруживается и инициализируется с помощью стандартных скриптов, предоставляемых библиотекой Quartz. Эти скрипты удаляют существующие таблицы, удаляя все триггеры при каждом перезапуске. Также можно предоставить пользовательский скрипт, установив свойство spring.quartz.jdbc.schema.

Чтобы использовать DataSource вместо основного DataSource приложения, объявите компонент DataSource, аннотируя его метод @Bean аннотацией @QuartzDataSource. Это гарантирует, что специфичный для Quartz DataSource используется как для SchedulerFactoryBean, так и для инициализации схемы. Аналогично, для использования TransactionManager вместо основного TransactionManager приложения, объявите компонент TransactionManager, аннотируя его метод @Bean аннотацией @QuartzTransactionManager.

По умолчанию задачи, созданные с помощью конфигурации, не будут перезаписывать уже зарегистрированные задачи, которые были прочитаны из постоянного хранилища задач. Чтобы разрешить перезапись существующих определений задач, установите свойство spring.quartz.overwrite-existing-jobs.

Конфигурацию Quartz Scheduler можно настроить, используя свойства spring.quartz и компоненты SchedulerFactoryBeanCustomizer, которые позволяют программно настраивать SchedulerFactoryBean. Расширенные свойства конфигурации Quartz можно настроить с помощью spring.quartz.properties.*.

В частности, компонент Executor не связан с планировщиком, так как Quartz предлагает способ настройки планировщика через spring.quartz.properties. Если вам нужно настроить исполнителя задач, рассмотрите реализацию SchedulerFactoryBeanCustomizer.

Задачи могут определять сеттеры для ввода свойств карты данных. Регулярные компоненты также могут быть введены аналогичным образом, как показано в следующем примере:

Java
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);
    }

}
Kotlin
import org.quartz.JobExecutionContext
import org.springframework.scheduling.quartz.QuartzJobBean

class MySampleJob : QuartzJobBean() {

    // fields ...

    private var myService: MyService? = null

    private var name: String? = null

    // Inject "MyService" bean
    fun setMyService(myService: MyService?) {
        this.myService = myService
    }

    // Inject the "name" job data property
    fun setName(name: String?) {
        this.name = name
    }

    override fun executeInternal(context: JobExecutionContext) {
        myService!!.someMethod(context.fireTime, name)
    }

}

4. Отправка электронной почты

Spring Framework предоставляет абстракцию для отправки электронной почты, используя интерфейс JavaMailSender, а Spring Boot также предоставляет автоматическую настройку и модуль-стартёр для неё.

См. документацию по справке для подробного объяснения, как использовать JavaMailSender.

Если spring.mail.host и соответствующие библиотеки (как определено spring-boot-starter-mail) доступны, по умолчанию создаётся компонент JavaMailSender, если он отсутствует. Отправитель можно дополнительно настроить с помощью элементов конфигурации из пространства имён spring.mail. См. MailProperties для получения более подробной информации.

В частности, некоторые значения по умолчанию для таймаутов бесконечны, и вы можете их изменить, чтобы избежать блокировки потока нереагирующим сервером электронной почты, как показано в следующем примере:

Свойства
spring.mail.properties[mail.smtp.connectiontimeout]=5000
spring.mail.properties[mail.smtp.timeout]=3000
spring.mail.properties[mail.smtp.writetimeout]=5000
Yaml
spring:
  mail:
    properties:
      "[mail.smtp.connectiontimeout]": 5000
      "[mail.smtp.timeout]": 3000
      "[mail.smtp.writetimeout]": 5000

Также можно настроить JavaMailSender с использованием существующего Session из JNDI:

Свойства
spring.mail.jndi-name=mail/Session
Yaml
spring:
  mail:
    jndi-name: "mail/Session"

Когда задаётся jndi-name, он имеет приоритет над всеми другими настройками, связанными с сеансом.

5. Валидация

Функциональность валидации методов, поддерживаемая Bean Validation 1.1, автоматически включена, если реализация JSR-303 (например, Hibernate validator) находится в пути к классам. Это позволяет аннотировать методы bean ограничениями jakarta.validation для параметров и/или возвращаемого значения. Классы-цели с такими аннотированными методами должны быть аннотированы аннотацией @Validated на уровне типа, чтобы их методы могли быть проверены на наличие встроенных аннотаций ограничений.

Например, следующий сервис запускает валидацию первого аргумента, убеждаясь, что его размер находится в диапазоне от 8 до 10:

Java
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 ...
    }

}
Kotlin
import jakarta.validation.constraints.Size
import org.springframework.stereotype.Service
import org.springframework.validation.annotation.Validated

@Service
@Validated
class MyBean {

    fun findByCodeAndAuthor(code: @Size(min = 8, max = 10) String?, author: Author?): Archive? {
        return null
    }

}

В приложении используется MessageSource при разрешении {parameters} в сообщениях ограничений. Это позволяет использовать файлы messages.properties приложения для сообщений Bean Validation. После разрешения параметров завершается интерполяция сообщений с помощью стандартного интерполятора Bean Validation.

Чтобы настроить Configuration для построения ValidatorFactory, определите компонент ValidationConfigurationCustomizer. Если определено несколько компонентов-настроек, они вызываются в порядке, основанном на аннотации @Order или реализации Ordered.

END_OF_DOCUMENT_MARKER

6. Вызов REST-сервисов

Если ваше приложение обращается к удалённым REST-сервисам, Spring Boot делает это очень удобным с помощью RestTemplate или WebClient.

6.1. RestTemplate

Если вам нужно обращаться к удалённым REST-сервисам из вашего приложения, вы можете использовать класс RestTemplate Spring Framework. Поскольку экземпляры RestTemplate часто требуют настройки перед использованием, Spring Boot не предоставляет единственный автоматически настроенный RestTemplate бин. Однако он автоматически настраивает RestTemplateBuilder, который можно использовать для создания экземпляров RestTemplate при необходимости. Автоматически настроенный RestTemplateBuilder гарантирует, что разумные HttpMessageConverters применяются к экземплярам RestTemplate.

Следующий код показывает типичный пример:

Java
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);
    }

}
Kotlin
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate

@Service
class MyService(restTemplateBuilder: RestTemplateBuilder) {

    private val restTemplate: RestTemplate

    init {
        restTemplate = restTemplateBuilder.build()
    }

    fun someRestCall(name: String): Details {
        return restTemplate.getForObject("/{name}/details", Details::class.java, name)!!
    }

}

RestTemplateBuilder включает в себя ряд полезных методов, которые можно использовать для быстрой настройки RestTemplate. Например, для добавления поддержки аутентификации BASIC вы можете использовать builder.basicAuthentication("user", "password").build().

6.1.1. RestTemplate HTTP-клиент

Spring Boot автоматически определит, какой HTTP-клиент использовать с RestTemplate в зависимости от библиотек, доступных в пути к классам приложения. В порядке приоритета поддерживаются следующие клиенты:

  1. Apache HttpClient

  2. OkHttp

  3. Простой JDK-клиент (HttpURLConnection)

Если на пути к классам доступны несколько клиентов, будет использован наиболее предпочтительный клиент.

6.1.2. Настройка RestTemplate

Существует три основных подхода к настройке RestTemplate, в зависимости от того, насколько широко вы хотите применить настройки.

Чтобы сделать область действия любых настроек максимально узкой, введите автоматически настроенный RestTemplateBuilder и затем вызовите его методы по мере необходимости. Каждый вызов метода возвращает новый экземпляр RestTemplateBuilder, поэтому настройки влияют только на это использование билдера.

Чтобы осуществить прикладную, аддитивную настройку для всего приложения, используйте бин RestTemplateCustomizer. Все такие бины автоматически регистрируются в автоматически настроенном RestTemplateBuilder и применяются к любым шаблонам, которые строятся с его помощью.

Следующий пример показывает кастомайзер, который настраивает использование прокси для всех хостов, кроме 192.168.0.5:

Java
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);
        }

    }

}
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

class MyRestTemplateCustomizer : RestTemplateCustomizer {

    override fun customize(restTemplate: RestTemplate) {
        val routePlanner: HttpRoutePlanner = CustomRoutePlanner(HttpHost("proxy.example.com"))
        val httpClient: HttpClient = HttpClientBuilder.create().setRoutePlanner(routePlanner).build()
        restTemplate.requestFactory = HttpComponentsClientHttpRequestFactory(httpClient)
    }

    internal class CustomRoutePlanner(proxy: HttpHost?) : DefaultProxyRoutePlanner(proxy) {

        @Throws(HttpException::class)
        public override fun determineProxy(target: HttpHost, context: HttpContext): HttpHost? {
            if (target.hostName == "192.168.0.5") {
                return null
            }
            return  super.determineProxy(target, context)
        }

    }

}

Наконец, вы можете определить свой собственный бин RestTemplateBuilder. Это заменит автоматически настроенный билдер. Если вы хотите, чтобы какие-либо бины RestTemplateCustomizer были применены к вашему пользовательскому билдеру, как это сделала бы автоматическая настройка, настройте его с помощью RestTemplateBuilderConfigurer. Следующий пример демонстрирует RestTemplateBuilder bean, соответствующий тому, что сделала бы автоматическая настройка Spring Boot, за исключением того, что также указаны пользовательские таймауты подключения и чтения:

Java
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));
    }

}
Kotlin
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
import java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyRestTemplateBuilderConfiguration {

    @Bean
    fun restTemplateBuilder(configurer: RestTemplateBuilderConfigurer): RestTemplateBuilder {
        return configurer.configure(RestTemplateBuilder()).setConnectTimeout(Duration.ofSeconds(5))
            .setReadTimeout(Duration.ofSeconds(2))
    }

}

Самый экстремальный (и редко используемый) вариант — создать свой собственный бин RestTemplateBuilder без использования конфигуратора. Помимо замены автоматически настроенного билдера, это также предотвращает использование любых бинов RestTemplateCustomizer.

6.1.3. Поддержка SSL в RestTemplate

Если вам нужна настройка SSL в RestTemplate, вы можете применить SSL-пакет SSL-пакет к RestTemplateBuilder как показано в этом примере:

Java
import org.springframework.boot.docs.io.restclient.resttemplate.Details;
import org.springframework.boot.ssl.SslBundles;
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, SslBundles sslBundles) {
        this.restTemplate = restTemplateBuilder.setSslBundle(sslBundles.getBundle("mybundle")).build();
    }

    public Details someRestCall(String name) {
        return this.restTemplate.getForObject("/{name}/details", Details.class, name);
    }

}
Kotlin
import org.springframework.boot.docs.io.restclient.resttemplate.Details
import org.springframework.boot.ssl.SslBundles
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate

@Service
class MyService(restTemplateBuilder: RestTemplateBuilder, sslBundles: SslBundles) {

    private val restTemplate: RestTemplate

    init {
        restTemplate = restTemplateBuilder.setSslBundle(sslBundles.getBundle("mybundle")).build()
    }

    fun someRestCall(name: String): Details {
        return restTemplate.getForObject("/{name}/details", Details::class.java, name)!!
    }

}

6.2. WebClient

Если у вас Spring WebFlux присутствует в пути к классам, вы также можете использовать WebClient для вызова удалённых REST-сервисов. По сравнению с RestTemplate, этот клиент имеет более функциональный вид и полностью реактивен. Вы можете узнать больше о WebClient в посвященном разделе документации Spring Framework.

Spring Boot создаёт и предварительно настраивает WebClient.Builder для вас. Настоятельно рекомендуется вводить его в компоненты и использовать для создания экземпляров WebClient. Spring Boot настраивает этот билдер для совместного использования HTTP-ресурсов, отражения настроек кодировщиков таким же образом, как и серверные (см. автонастройку WebFlux HTTP-кодировщиков), и многое другое.

Следующий код показывает типичный пример:

Java
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);
    }

}
Kotlin
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Mono

@Service
class MyService(webClientBuilder: WebClient.Builder) {

    private val webClient: WebClient

    init {
        webClient = webClientBuilder.baseUrl("https://example.org").build()
    }

    fun someRestCall(name: String?): Mono<Details> {
        return webClient.get().uri("/{name}/details", name)
                .retrieve().bodyToMono(Details::class.java)
    }

}

6.2.1. WebClient Runtime

Spring Boot автоматически определит, какой ClientHttpConnector использовать для управления WebClient в зависимости от библиотек, доступных в пути к классам приложения. В порядке приоритета поддерживаются следующие клиенты:

  1. Reactor Netty

  2. Клиент Jetty RS

  3. Apache HttpClient

  4. JDK HttpClient

Если на пути к классам доступны несколько клиентов, будет использован наиболее предпочтительный клиент.

Инициализатор spring-boot-starter-webflux по умолчанию зависит от io.projectreactor.netty:reactor-netty, что включает в себя как серверные, так и клиентские реализации. Если вы выбираете Jetty в качестве реактивного сервера, вы должны добавить зависимость от библиотеки реактивного HTTP-клиента Jetty, org.eclipse.jetty:jetty-reactive-httpclient. Использование одной и той же технологии для сервера и клиента имеет свои преимущества, так как это позволит автоматически совместно использовать HTTP-ресурсы между клиентом и сервером.

Разработчики могут переопределить конфигурацию ресурсов для Jetty и Reactor Netty, предоставив пользовательский бин ReactorResourceFactory или JettyResourceFactory, — это будет применено как к клиентам, так и к серверам.

Если вы хотите переопределить этот выбор для клиента, вы можете определить свой собственный бин ClientHttpConnector и иметь полный контроль над конфигурацией клиента.

Вы можете узнать больше о WebClient параметрах конфигурации в справочной документации Spring Framework.

6.2.2. Настройка WebClient

Существует три основных подхода к WebClient настройке, в зависимости от того, насколько широко вы хотите применить настройки.

Чтобы сделать область действия любых настроек максимально узкой, введите автоматически настроенный WebClient.Builder и затем вызовите его методы по мере необходимости. Экземпляры WebClient.Builder являются состоятельными: любые изменения в билдере отражаются во всех клиентах, созданных с ним. Если вы хотите создать несколько клиентов с одним и тем же билдером, вы также можете рассмотреть клонирование билдера с помощью WebClient.Builder other = builder.clone();.

Чтобы осуществить прикладную, аддитивную настройку для всех WebClient.Builder экземпляров, вы можете объявить бины WebClientCustomizer и изменить WebClient.Builder локально в точке ввода.

Наконец, вы можете вернуться к исходному API и использовать WebClient.create(). В этом случае ни автоматическая настройка, ни WebClientCustomizer не применяются.

6.2.3. Поддержка SSL в WebClient

Если вам нужна настройка SSL для ClientHttpConnector используемого WebClient, вы можете ввести экземпляр WebClientSsl, который можно использовать с методом билдера apply.

Интерфейс WebClientSsl предоставляет доступ к любым SSL-пакетам, которые вы определили в вашем файле application.properties или application.yaml.

Следующий код показывает типичный пример:

Java
import reactor.core.publisher.Mono;

import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientSsl;
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, WebClientSsl ssl) {
        this.webClient = webClientBuilder.baseUrl("https://example.org").apply(ssl.fromBundle("mybundle")).build();
    }

    public Mono<Details> someRestCall(String name) {
        return this.webClient.get().uri("/{name}/details", name).retrieve().bodyToMono(Details.class);
    }

}
Kotlin
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientSsl
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Mono

@Service
class MyService(webClientBuilder: WebClient.Builder, ssl: WebClientSsl) {

    private val webClient: WebClient

    init {
        webClient = webClientBuilder.baseUrl("https://example.org")
                .apply(ssl.fromBundle("mybundle")).build()
    }

    fun someRestCall(name: String?): Mono<Details> {
        return webClient.get().uri("/{name}/details", name)
                .retrieve().bodyToMono(Details::class.java)
    }

}

7. Веб-сервисы

Spring Boot предоставляет автоматическую настройку веб-сервисов, так что вам нужно только определить ваши Endpoints.

Функции Spring Web Services могут быть легко доступны с помощью модуля spring-boot-starter-webservices.

SimpleWsdl11Definition и SimpleXsdSchema бин могут быть автоматически созданы для ваших WSDL и XSD соответственно. Для этого настройте их расположение, как показано в следующем примере:

Свойства
spring.webservices.wsdl-locations=classpath:/wsdl
Yaml
spring:
  webservices:
    wsdl-locations: "classpath:/wsdl"

7.1. Вызов веб-сервисов с помощью WebServiceTemplate

Если вам нужно вызывать удаленные веб-сервисы из вашего приложения, вы можете использовать класс WebServiceTemplate. Поскольку экземпляры WebServiceTemplate часто требуют настройки перед использованием, Spring Boot не предоставляет ни одного автоматически настроенного бинa WebServiceTemplate. Однако он автоматически настраивает бин WebServiceTemplateBuilder, который может использоваться для создания экземпляров WebServiceTemplate по мере необходимости.

Следующий код демонстрирует типичный пример:

Java
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"));
    }

}
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
class MyService(webServiceTemplateBuilder: WebServiceTemplateBuilder) {

    private val webServiceTemplate: WebServiceTemplate

    init {
        webServiceTemplate = webServiceTemplateBuilder.build()
    }

    fun someWsCall(detailsReq: SomeRequest?): SomeResponse {
        return webServiceTemplate.marshalSendAndReceive(
            detailsReq,
            SoapActionCallback("https://ws.example.com/action")
        ) as SomeResponse
    }

}

По умолчанию WebServiceTemplateBuilder определяет подходящий HTTP-сервис WebServiceMessageSender с помощью доступных библиотек HTTP в классе. Вы также можете настроить таймауты чтения и подключения следующим образом:

Java
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();
    }

}
Kotlin
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 java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyWebServiceTemplateConfiguration {

    @Bean
    fun webServiceTemplate(builder: WebServiceTemplateBuilder): WebServiceTemplate {
        val sender = HttpWebServiceMessageSenderBuilder()
            .setConnectTimeout(Duration.ofSeconds(5))
            .setReadTimeout(Duration.ofSeconds(2))
            .build()
        return builder.messageSenders(sender).build()
    }

}

8. Распределенные транзакции с JTA

Spring Boot поддерживает распределенные транзакции JTA по нескольким ресурсам XA, используя менеджер транзакций, полученный из JNDI.

Когда среда JTA обнаружена, Spring использует свой JtaTransactionManager для управления транзакциями. Автоматически настроенные бин JMS, DataSource и JPA обновляются для поддержки XA транзакций. Вы можете использовать стандартные выражения Spring, такие как @Transactional, чтобы участвовать в распределенной транзакции. Если вы находитесь в среде JTA и всё ещё хотите использовать локальные транзакции, вы можете установить свойство spring.jta.enabled в значение false для отключения автоматической настройки JTA.

8.1. Использование управляемого менеджера транзакций Jakarta EE

Если вы упаковываете своё приложение Spring Boot в файл war или ear и развертываете его на сервере приложений Jakarta EE, вы можете использовать встроенный менеджер транзакций сервера приложений. Spring Boot пытается автоматически настроить менеджер транзакций, просматривая общие расположения JNDI (java:comp/UserTransaction, java:comp/TransactionManager, и так далее). При использовании сервиса транзакций, предоставляемого сервером приложений, вам также необходимо убедиться, что все ресурсы управляются сервером и доступны через JNDI. Spring Boot пытается автоматически настроить JMS, ища ConnectionFactory по пути JNDI (java:/JmsXA или java:/XAConnectionFactory), и вы можете использовать свойство spring.datasource.jndi-name для настройки вашего DataSource.

8.2. Смешивание XA и не-XA подключений JMS

При использовании JTA основной бин JMS ConnectionFactory понимает XA и участвует в распределенных транзакциях. Вы можете вводить его в свой бин без необходимости использовать любые @Qualifier:

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

В некоторых ситуациях вы можете захотеть обработать определённые сообщения JMS с помощью не-XA ConnectionFactory. Например, ваша логика обработки JMS может занимать больше времени, чем таймаут XA.

Если вы хотите использовать не-XA ConnectionFactory, вы можете использовать бин nonXaJmsConnectionFactory:

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

Для согласованности также предоставляется бин jmsConnectionFactory с псевдонимом бинa xaJmsConnectionFactory:

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

8.3. Поддержка встроенного менеджера транзакций

Интерфейсы XAConnectionFactoryWrapper и XADataSourceWrapper могут использоваться для поддержки встроенных менеджеров транзакций. Интерфейсы отвечают за обёртку бинa XAConnectionFactory и XADataSource и выставление их как обычных бинa ConnectionFactory и DataSource, которые прозрачно регистрируются в распределённой транзакции. Автоматическая настройка DataSource и JMS использует варианты JTA при наличии бинa JtaTransactionManager и соответствующих бинa-обёрток XA, зарегистрированных в вашем ApplicationContext.

9. Что читать дальше

Теперь у вас должно быть хорошее понимание основных функций Spring Boot и различных технологий, которые Spring Boot поддерживает с помощью автоматической настройки.

Следующие несколько разделов подробно рассказывают о развертывании приложений на облачных платформах. Вы можете узнать о создании образов контейнеров в следующем разделе или перейти к разделу готовых к производству функций.

Copyright © 2012-2023 VMware, Inc.
Licensed under the Apache License, Version 2.0.
https://docs.spring.io/spring-boot/docs/3.1.3/reference/html/io.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API