application properties что это

А как вы определяете свойства переменными окружения в Spring Boot приложениях?

А что, если я скажу, что подобное

содержит ошибку. Не согласны? Разбор под катом.

Жили и не тужили

Как часто работая с проектом, аккуратно завёрнутым в Docker и CI, вам доводилось видеть нечто такое:

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

Сюрприз

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

Переменные окружения проинициализированны, приложение работает с заданным URL, но наше свойство не проставляется.

Расследование

Оказывается уже с версии 3.1 Spring использует переменные окружения как источник свойств, а чтобы нам их можно было определить в bash привычным образом, любезно учитывает верхний регистр и знак подчёркивания вместо точки.

Выдержка из реализации источника свойств Spring приложений, класса SystemEnvironmentPropertySource, в вольном переводе автора:

Спецификация источника, определяющего свойства из системных переменных среды. Для компенсации ограничений в Bash и других интерпретаторах, которые не допускают переменных, содержащих символ точки и/или символ дефиса. Также допускается вариация имён в верхнем регистре для более идиоматического для оболочки представления.

А чё так можно было что ли?

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

Заключение

Знай свой инструмент и не занимайся суеверным программированием делая так, потому что твои дедысиньёры так делали.

Будет прекрасно работать, без необходимости явно описывать переменные окружения в значениях свойства.

Источник

Настройка состава JUnit5 тестов с помощью application.properties

Представьте себе ситуацию, когда ваш проект должен компилироваться в различных окружениях.

Теперь представьте, что не все тесты должны проходить в этих окружениях — кажому свой набор тестов.

И предпочтительней настроить выбор, какие тесты должны выполняться, в… файле application.properties — кажому тесту свой переключатель «вкл/выкл».

Звучит здорово, не правда ли?

Тогда добро пожаловать под кат, где мы все это и реализуем с помощью SpringBoot 2 и JUnit 5.

Предварительные настройки

Сперва давайте выключим JUnit 4, который поставляется в SpringBoot 2 по-умолчанию, и включим JUnit 5.

Для этого внесем изменения в pom.xml :

Предполагаемое решение

Аннотация

Обработка аннотации

Без обработчика аннотации не обойтись.

Этот метод принимает контекст выполняемого JUnit теста и возвращает условие — должен ли тест быть запущен или нет.

Прочитать подробней по условное выполнение тестов JUnit5 можно в официальной документации.

Но как нам проверить значение свойства, которое прописано в application.properties в таком случае?

Получение доступа к контексту Spring из контекста JUnit

Создадим тесты

Давайте создадим несколько тестов и попробуем управлять их запуском:

Наш application.properties файл при этом выглядит так:

Следующий шаг — отделим префиксы наших свойств в аннотацию класса

Писать перед каждым тестом полные названия свойств из application.properties — утомительное занятие. Поэтому резонно их префикс вынести на уровень класса тестов — в отдельную аннотацию.

Создадим annotation для хранения префиксов — TestEnabledPrefix :

Обработка и использование аннотации TestEnabledPrefix

Приступим к обработке новой аннотации.

Давайте создадим вспомогательный класс AnnotationDescription

С помощью этого класса мы сможем хранить имя свойства из application.properties и его значение.

Нам этот класс пригодится, т.к. мы собираемся использовать lambda-выражения.

Создадим метод, который извлечет нам значение свойства «префикс» из аннотации класса TestEnabledPrefix

И теперь проверим значение свойства из application.properties по имени, указанном в аннотации теста

Использование новой аннотации

Теперь применим нашу аннотацию к тест-классу:

Источник

Spring Boot: от начала до продакшена


В данной статье я попробую расписать все шаги, которые потребуются для создания небольшого проекта на Spring Boot и развертывания его на боевом сервере.

Не будем тянуть долгими прелюдиями о философии java и spring’а, и сразу приступим к делу.

Для начала нам необходимо создать каркас приложения, внедрив туда весь необходимый зоопарк технологий(как минимум Spring, JPA, JDBC). До появления spring boot нужно было потратить на это немало времени, если конечно у вас не было рабочей заготовки в закромах кода. И именно сложность создания подобного каркаса, как мне кажется, останавливает многих от разработки небольших веб-проектов на java. Конечно, когда-то был хромой spring roo, который мог создать подобный каркас в ущерб производительности(привет аспектам), но даже с ним количество и сложность конфигурационных файлов заставляли долго медитировать над ними неподготовленного разработчика. Однако теперь с приходом Boot и Spring 4 жизнь стала немного проще и количество конфигурационных файлов заметно уменьшилось.

Если же у вас нет данной IDE, то скачиваем Spring Boot CLI, следуем инструкции в INSTALL.txt. Нужно задать системную переменную SPRING_HOME(путь к папке со Spring Boot, не к папке bin!) и добавить путь к SPRING_HOME/bin в системную переменную PATH на windows.

Итак, консоль спринга настроили, теперь самое время создать проект. Сделать это можно следующей командой:

UPDATE
Кроме того, как написали в комментариях, существует еще веб-конструктор: start.spring.io

Далее импортируем получившийся каркас в любимую IDE и начинаем его модифицировать под наши нужды.

Для начала добавим в каталог src/main папку webapps. Все веб-ресурсы мы будем создавать в ней, а не в папке resources, как хочет того спринг. Дело в том, что если мы будем создавать файлы в папке resources, то тогда мы лишимся возможности видеть изменения, сделанные в наших веб-ресурсах, без перезагрузки сервера. А это может быть неприятно, когда ради того, чтобы посмотреть изменившийся текст на веб-странице приходится перезапускать веб-сервер.

Теперь в папке webapps создаем файл index.html и папки css, js, font, images, в которые будем класть соответствующие ресурсы.

Для примера сделаем самый простой каркас index.html:

Изменим файл pom.xml
Должно получиться что-то подобное:

Из pom-файла мы можем увидеть следующее:
Мы используем java 8(самое время ее попробовать). Наш класс приложения называется com.yourcompany.Application(не забудьте переименовать стандартно сгенерированный класс, который может называться к примеру DemoApplication).

Мы используем postgresql 9.4(тоже неплохо бы установить его локально на свою машину). Connection pool для взаимодействия с базой данных мы берем самый модный и производительный (HikariCP). Кроме того, мы используем специальный плагин, который, когда мы будем генерировать итоговый jar’ник, перенесет все наши данные из webapp в resources/static, как того хочет spring boot. В противном случае вы не сможете увидеть все те веб-страницы, что создадите в папке webapps, когда запустите jar-ник.

Читайте также:  exit poll что это

Добавим пакет config и создадим в нем класс JpaConfig:

Кроме того, добавим в файл application.properties следующие строчки:

И наконец в Application.java меняем строку инициализации на следующую:

Тем самым мы настроили подключение к СУБД PostgreSQL.

Не забываем создать саму базу данных и простенькую таблицу в ней. Сделать это удобнее всего через PgAdmin.
Создав в ней пустую базу yourapp_data, выполняем скрипт создания таблицы:

Теперь настало время немного заняться начинкой нашего проекта. А именно добавить какую-нибудь сущность БД и научиться с ней работать, получая с клиента данные для ее формирования и отправляя клиенту же данные об уже созданных сущностях.

Создаем пакеты controller, entity, repository, service, utils.

В пакете entity создаем интерфейс:

Аннотации JPA и Hibernate в данном примере использовать не будем, так как эти технологии сильно замедляют работу(запрос может выполняться в 10 раз медленнее, чем на чистом jdbc), а так как у нас нет сильно сложных сущностей, для которых реально может потребоваться ORM, то воспользуемся обычным jdbcTemplate.

Создаем интерфейс репозитория:

Вместо уже упомянутого jdbcTemplate, мы, как видите, используем JdbcOperations, который является его интерфейсом. Нам приходится использовать везде интерфейсы, отделяя их от реализации, так как, во-первых это стильно, модно, молодежно, а во-вторых, spring в нашем случае использует стандартный jdk’шный Proxy для наших объектов, поэтому напрямую инжектить реализацию не получиться, пока мы не введем полноценные аспекты и AspectJ compile-time weaving. В нашем случае этого и не требуется, чтобы не перегружать приложение.

Осталось уже немного. Создаем наш сервис(мы же хорошие разработчики и должны отделить бизнес-логику от логики работы с СУБД?).

Отлично. Теперь создаем пару вспомогательных классов, необходимых для реализации контроллера:

Это наша реализация Exception’а. Может пригодиться в будущем, хотя и не обязательна, но на нее завязан следующий класс:

Если мы словили такую ошибку в нашем контроллере, то она будет обработана дополнительно в этом методе.
Наконец напишем небольшой классик, который будет формировать структуру данных для передачи на клиент:

Все, со вспомогательными классами закончили. Осталось написать наш контроллер. Он будет простым, как пробка:

В нем два метода — сохранить полученные данные и выдать порцию случайных данных на клиент. Контроллер унаследован от созданного нами ранее ExceptionHandlerController. Обработка исключений написана только как шаблон и нуждается в соответствующей доработки под себя.

Итак, основная часть серверного кода написана, осталось проверить его работу на клиенте. Для этого нужно доработать наш файл index.html и заодно добавить библиотеку jquery в каталог js.
index.html:

Да, UI получился не бог весть каким красивым, но зато с его помощью мы можем проверить работу приложения.
Запустим наш проект. В Intellij Idea это можно сделать через специальную конфигурацию запуска(Spring Boot).
Если все сделано верно, то по адресу localhost:8080 вы сможете увидеть заголовок Hello World, строку ввода и две кнопки. Попробуйте ввести что-нибудь в строку ввода и нажать на кнопку POST. Если после этого вы увидите аналогичный текст ниже поля ввода, то все работает как надо. Теперь останется модифицировать проект под свои нужды, добавить модный UI(например materializecss.com) и творить разумное, доброе, вечное.

Однако рано или поздно вы сотворите желаемое и встанет вопрос о том, как донести ваше детище в массы. Об этом будет вторая часть статьи.

Начнем с малого, но важного.
Даже если проект небольшой, все равно для него потребуется свой домен. Если вы просто обкатываете какую-нибудь идею и не хотите тратить бешеные деньги для регистрации домена на том же godaddy, то можете воспользоваться бесплатной альтернативой: freenom.com

Далее займемся сервером, где все это будет крутиться. Так как проект у нас небольшой, то и сервер нам сгодится небольшой. В идеале хватит VPS. Достать его можно в разных местах, например www.digitalocean.com
Итак, регистрируемся, создаем самый простой дроплет и ставим на него ubuntu (в моем случае это ubuntu 12.04, дальнейшие инструкции буду описывать для этой системы, но на остальных будет примерно то же)

Отлично, у нас есть сервер, пора залить на него наш проект.

Но не будем унывать, поставим себе новую версию:

Теперь настала очередь postgres’а. До этого мы использовали локальную версию на машине разработчика, теперь пришло время поставить СУБД на сервер.

Для этого сначала выполняем магическую последовательность команд:

Далее выполняем команду входа в psql:

И выходим c помощью команды \q

Редактируем файл /etc/postgresql/9.4/main/postgresql.conf, изменив строчку #listen_addresses = ‘localhost’ на listen_addresses = ‘*’
Тем самым мы сможем подключаться к postgresql извне с помощью pgadmin’а. Хотя, конечно, желательно этого избежать в целях безопасности, и когда все будет настроено и отлажено, отключить эту возможность.

Затем редактируем файл /etc/postgresql/9.4/main/pg_hba.conf
Должны быть добавлены две новых строчки и изменена одна строка для 127.0.0.1 следующим образом:

Я намеренно изменил md5 на trust, так как лично у меня были проблемы с запуском проекта, тем самым отключив проверку пароля для заданных адресов. Возможно у вас их не будет.

Теперь все настроено. Хотя тюнинговать постгрес можно до бесконечности, но ведь у нас всего лишь маленький проект, а значит, пока оставим как есть.

Перезапускаем postgres: и проверяем его работу.

Всё, с настройкой postgres’а закончили, что у нас дальше по сценарию?

В моем случае корневой директорией nginx была /etc/nginx. Там нам в первую очередь потребуется изменить файл /sites_available/default следующим образом:

Однако и это еще не все. Необходимо также модифицировать наш проект, чтобы он поддерживал настроенный нами прокси. Благо сделать это не трудно, достаточно лишь в application.properties добавить строки(не забудьте залить новую версию с изменениями):

Теперь можно запустить nginx командой service nginx start и затем попробовать запустить наш проект. Он будет доступен по ссылке сайта, либо же, если вы еще не приобрели домен, то по его ip-адресу, без указания порта.

Остался еще один небольшой штрих. Немного неудобно всегда стартовать проект тем способом, который был описан выше. Неплохо бы, чтобы при старте проекта консоль ввода на сервере освобождалась, приложение не закрывалось бы после выхода из ssh-сессии и чтобы где-нибудь велись логи приложения. Сделать это можно с помощью команды nohup. Предварительно создаем bash-скрипт, называя его script.sh:

Читайте также:  какой лук посадить под зиму на зелень

Прописываем ему право на исполнение:

И запускаем командой:

Все, приложение запущено.

Теперь, если все сделано правильно, можно открыть сайт нашего проекта в браузере и насладиться результатом.

Источник

Валидация параметров конфигурации Spring Boot при запуске

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

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

Spring Boot предлагает нам удобный способ валидации параметров конфигурации. Мы собираемся связать входные значения со @ConfigurationProperties и использовать Bean Validation для их валидации.

Код примера

Зачем нам нужно проверять параметры конфигурации?

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

Давайте рассмотрим следующий сценарий:

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

В конце концов, мы осознаем причину — это опечатка в адресе электронной почты, который мы определили в конфигурации:

«Разве я не проверил это? А ну понятно. Мне нужно было реализовать вспомогательный класс для чтения и проверки данных конфигурации, но мне было очень лениво в тот момент. Ааа, не важно, это же исправлено сейчас.»

Я жил по такому сценарию, не один раз.

Итак, вот мотивация этой статьи. Давайте попробуем найти практическое решение этой проблемы.

Валидация свойств при запуске

Привязка наших параметров конфигурации к объекту — это простой способ поддерживать их. Таким образом, мы можем извлечь выгоду из безопасности типов и найти ошибки раньше.

Spring Boot имеет аннотацию @ConfigurationProperties для реализации привязки свойств, определенных в файлах application.properties или application.yml.

Однако для их проверки нам нужно выполнить еще пару шагов.

Сначала давайте взглянем на наш файл application.properties:

Затем мы добавляем аннотацию @Validated в наш класс @ConfigurationProperties вместе с некоторыми аннотациями Bean Validation в полях:

Чтобы Spring Boot загрузил наш класс AppProperties, мы аннотируем этот @Configuration класс с помощью @EnableConfigurationProperties:

Если мы сейчас запустим приложение Spring Boot с (недействительным) адресом электронной почты из приведенного выше примера, приложение не запустится:

Зависимость API валидации бинов

Чтобы использовать аннотации для валидации bean-компонентов, мы должны включить зависимость javax.validation.validation-api в classpath нашего приложения.

Кроме того, мы также можем определить некоторые значения по умолчанию, инициализируя поля AppProperties:

Даже если мы не определим значения для свойств send-report-emails и report-type в application.properties, теперь мы получим значения по умолчанию Boolean.FALSE и ReportType.HTML соответственно.

Валидация вложенных объектов конфигурации

Некоторые свойства имеет смысл объединить во вложенный объект.

Итак, давайте создадим ReportProperties для группировки свойств, связанных с нашим очень важным отчетом:

Затем мы выполним рефакторинг наших AppProperties, чтобы включить получившийся вложенный объект ReportProperties вместо отдельных свойств:

Мы должны быть внимательными и не забыть поместить аннотацию Valid перед нашим полем вложенного отчета.

Это сообщает Spring, что необходимо проверить свойства вложенных объектов.

Наконец, мы должны изменить префикс свойств, связанных с отчетом, на report.* и в нашем файле application.properties:

Таким образом, свойства с префиксом app.properties будут по-прежнему привязаны к классу AppProperties, а свойства с префиксом app.properties.report будут привязаны к объекту ReportProperties в поле report.

Валидация с использованием Bean Factory Methods

Мы также можем запустить проверку, связав файл свойств с методом фабрики Bean с помощью аннотации @ConfigurationProperties:

Это особенно полезно, когда мы хотим привязать свойства к компонентам, определенным в сторонних библиотеках или поддерживаемым в отдельных jar файлах.

Использование собственного Spring валидатора

Несмотря на то, что Bean Validation обеспечивает декларативный подход к проверке наших объектов и возможность повторного использования, иногда нам нужно больше для настройки нашей логики проверки.

Для этого случая Spring имеет независимый механизм валидации — интерфейс Validator, который позволятет обеспечить динамическую валидацию ввода.

Давайте расширим нашу проверку, чтобы проверить, что report.email-address содержит определенный домен, например такой как @analysisapp.com:

Затем нам нужно зарегистрировать наш Spring валидатор с помощью специального метода с именем configurationPropertiesValidator():

Только если имя получившегося bean-компонента Spring будет ConfigurationPropertiesValidator, Spring будет запускать этот валидатор для всех bean-компонентов с аннотацией @ConfigurationProperties.

Обратите внимание, что мы должны определить наш метод configurationPropertiesValidator() как статический. Это позволяет Spring создавать bean-компонент на самом раннем этапе, перед классами с аннотацией @Configuration, чтобы избежать каких-либо проблем при создании других bean-компонентов в зависимости от свойств конфигурации.

Валидатор Spring не является частью Bean Validation

Валидатор Spring не связан с Bean Validation и работает независимо после Bean Validation. Его основная цель — инкапсулировать логику проверки от любой инфраструктуры или контекста.

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

Вместо определения метода фабрики бинов мы можем переместить нашу собственную реализацию Validator внутрь классов свойств конфигурации:

Таким образом, мы можем выполнить разные реализации Validator для каждого класса @ConfigurationProperties.

Заключение

Если мы хотим обезопасносить себя от ошибок ввода, проверка нашей конфигурации — это хороший способ. Spring Boot облегчает работу способами, описанными в этой статье.

Источник

Выполнение запланированных заданий в Spring Boot

В этой статье мы покажем, как настраивать и запускать запланированные задания в приложениях Spring Boot.

Пример кода

Эта статья сопровождается примером рабочего кода на GitHub.

Создание приложения Spring Boot для планирования

Для работы некоторых примеров, давайте сначала создадим проект Spring Boot с помощью Spring boot Initializr, а затем откроем проект в нашей любимой среде IDE. Мы не добавляли никаких зависимостей в Maven, pom.xml поскольку планировщик является частью основного модуля платформы Spring.

Включение расписания

По умолчанию планирование отключено. Перед добавлением любых запланированных заданий нам необходимо явно включить планирование, добавив аннотацию @enableScheduling :

Здесь мы добавили аннотацию @enableScheduling к нашему классу приложения, JobschedulingApplication чтобы включить планирование.

Читайте также:  с каким шагом ставить стропила на двухскатную крышу

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

Планирование теперь будет активировано только тогда, когда мы загрузим класс SchedulerConfig приложение, что обеспечит лучшую модуляризацию.

Включение планирования с помощью свойства

Добавление запланированных заданий

Аннотированный метод должен удовлетворять двум условиям:

Метод не должен принимать никаких входных параметров.

В следующих разделах мы рассмотрим различные варианты настройки планировщика для запуска запланированных заданий.

Выполнение задания с фиксированной задержкой

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

Новое задание всегда будет ждать завершения предыдущего задания. Его следует использовать в ситуациях, когда вызовы методов должны происходить последовательно.

В этом примере мы вычисляем цену продукта, выполняя метод в компоненте Spring с фиксированной задержкой:

Здесь мы запланировали выполнение метода computePrice с фиксированной задержкой, установив значение для атрибута fixedDelay в 2000 миллисекунды или 2 секунды.

Мы также переводим метод в режим ожидания на 4 секунды, Thread.sleep() чтобы смоделировать ситуацию, когда выполнение метода занимает больше времени, чем интервал задержки. Следующее выполнение начнется только после того, как предыдущее выполнение завершится, по крайней мере, через 4 секунды, даже если интервал задержки в 2 секунды истек.

Выполнение задания с фиксированной частотой

В этом примере мы обновляем параметры ценообразования, выполняя метод с фиксированной частотой:

Здесь мы аннотировали метод refreshPricingParameters аннотацией @Scheduled и установили для атрибута fixedRate значение 3000 миллисекунды или 3 секунды. Это обеспечит запуск метода каждые 3 секунды.

Аннотация @Async к методу позволяет выполнить его в отдельном потоке. В результате, когда предыдущее выполнение метода занимает больше времени, чем интервал с фиксированной скоростью, последующий вызов метода сработает, даже если предыдущий вызов все еще выполняется.

Это позволит выполнять несколько запусков метода параллельно в течение перекрывающегося временного интервала.

Без применения аннотации @Async метод всегда будет выполняться после завершения предыдущего выполнения, даже если интервал с фиксированной скоростью истек.

Отсрочка первого исполнения с помощью начальной задержки

Здесь мы установили задержку первого выполнения метода initialDelay в 2000 миллисекунды или 2 секунды.

Указание интервалов в формате длительности ISO

До сих пор в наших примерах мы указывали временной интервал в миллисекундах. Указание более высоких значений интервала в часах или днях, что чаще всего имеет место в реальных ситуациях, трудночитаемо.

В аннотации @Scheduler представлены атрибуты интервала fixedRateString и fixedDelayString в формате длительности ISO, как показано в этом примере кода:

Здесь мы установили значение fixedDelayString как, PT02S чтобы указать фиксированную задержку не менее 2 секунд между последовательными вызовами. Точно так же мы можем использовать fixedRateString для указания фиксированной частоты в этом формате.

Вынесение интервала в файл свойств

Мы также можем ссылаться на значение свойства из нашего файла свойств в качестве значения атрибутов fixedDelayString или fixedRateString для экстернализации значений интервала, как показано ниже:

Использование выражений Cron для определения интервала

Мы также можем указать временной интервал в cron-подобном выражении в стиле UNIX для более сложных требований планирования, как показано в этом примере:

Здесь мы указали интервал, используя выражение cron, привязанное к свойству с именем, interval-in-cron, определенным в нашем application.properties файле.

Выражение cron представляет собой строку из шести-семи полей, разделенных пробелом, для представления триггеров на секунду, минуту, час, день месяца, месяц, день недели и, необязательно, год. Однако выражение cron в Spring Scheduler состоит из шести полей, как показано ниже:

Например, выражение cron: 0 15 10 * * * запускается в 10:15 каждый день (каждую 0-ю секунду, 15-ю минуту, 10-й час, каждый день). * указывает, что выражение cron соответствует всем значениям поля. Например, * в поле минут означает каждую минуту.

Такие выражения, как 0 0 * * * *, трудно читать. Чтобы улучшить читаемость, Spring поддерживает макросы для представления часто используемых последовательностей, как в следующем примере кода:

Spring предоставляет следующие макросы:

Развертывание нескольких экземпляров планировщика с помощью ShedLock

Как мы уже видели с помощью Spring Scheduler, очень легко планировать задания, добавляя аннотации @Scheduler к методам в Spring Beans. Однако в распределенных средах, когда мы развертываем несколько экземпляров нашего приложения, оно не может обрабатывать синхронизацию планировщика по нескольким экземплярам. Вместо этого он выполняет задания одновременно на каждом узле.

Для координации ShedLock использует внешнее хранилище данных, совместно используемое несколькими экземплярами. В качестве внешнего хранилища данных может использоваться любая база данных JDBC, такая как Mongo Redis, Hazelcast, ZooKeeper или другие.

ShedLock разработан для использования в ситуациях, когда у нас есть запланированные задачи, которые не готовы к параллельному выполнению, но могут безопасно выполняться повторно. Более того, блокировки основаны на времени, и ShedLock предполагает, что часы на узлах синхронизированы.

Давайте изменим наш пример, добавив зависимости:

Мы добавили зависимости от основного модуля shedlock-spring вместе с зависимостями от shedlock-provider-jdbc-template шаблона jdbc и от базы данных h2, которая будет использоваться в качестве общей базы данных. В производственных сценариях мы должны использовать персистентную базу данных, такую ​​как MySQL, Postgres и т. д.

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

Далее мы создадим таблицу, которая будет использоваться в качестве общей базы данных.

Наконец, мы аннотируем наши запланированные задания, применив аннотацию @SchedulerLock :

Условия использования распределенного планировщика заданий Quartz

Spring Scheduler предпочтительнее, когда мы хотим реализовать простую форму планирования заданий, такую ​​как выполнение методов для bean-компонента каждые X секунд или по расписанию cron, не беспокоясь о каких-либо побочных эффектах перезапуска заданий после сбоев.

Заключение

Краткий обзор основных моментов этой статьи:

Планирование является частью основного модуля, поэтому нам не нужно добавлять какие-либо зависимости.

По умолчанию планирование отключено. Мы явно включаем планирование, добавляя @EnableScheduling аннотацию к классу конфигурации Spring.

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

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

Мы можем использовать распределенный планировщик заданий, такой как Quartz, для решения более сложных сценариев планирования, таких как возобновление невыполненных заданий и создание отчетов.

Вы можете найти весь исходный код, использованный в статье на Github.

Источник

Сказочный портал