Pull to refresh

Ускоренная разработка с помощью Spring Boot DevTools

Reading time 8 min
Views 34K
Original author: Vojtech Ruzicka
Как ускорить разработку на Spring Boot с DevTools и сделать этот процесс более приятным и продуктивным?

Настройка


Как обычно при разработке на Spring Boot, настройка достаточно проста. Все, что вам нужно сделать, это добавить правильную зависимость, и готово. Spring Boot находит ее и автоматически настраивает DevTools соответственно.

Если вы используете Maven:

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

Если используется Gradle:

configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }
}
dependencies {
    developmentOnly("org.springframework.boot:spring-boot-devtools")
}

Обратите внимание, что зависимость объявлена ​​как необязательная. Это важно, так как такое объявление зависимости предотвращает транзитивное применение DevTools зависимости к другим модулям, зависящим от вашего проекта.

Автоматический перезапуск


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

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

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

Под капотом Spring DevTools используются два загрузчика классов — base и restart. Классы, которые не изменяются, загружаются базовым загрузчиком base. Классы, с которыми вы работаете, загружаются при помощи загрузчика restart. При каждом перезапуске загрузчик restart создается заново. Таким образом, перезапуск приложения происходит намного быстрее, чем обычно, и может стать реальной альтернативой перезагрузке динамического класса с помощью таких инструментов, как JRebel.

Инициализация рестарта в IDE


Перезапуск срабатывает при каждом изменении файлов в вашем classpath. Однако этот процесс зависит от вашей IDE. Это означает, что недостаточно просто изменить ваши java файлы. Важно то, когда ваша IDE фактически обновляет файлы типа .class в вашем classpath.

При использовании IntelliJ IDEA вам необходимо запустить команду build в своем проекте (Ctrl + F9 или Build → Build Project). Вы также можете настроить автоматический запуск команды build в IDEA. Кроме того, вы можете открыть конфигурацию запуска Spring Boot и определить, что происходит при запуске обновления приложения (Ctrl + F10):



В первом поле со списком вы можете выбрать Update trigger file для запуска рестарта DevTools при каждом выполнении действия Update. В качестве альтернативы, вы даже можете выбрать опцию Hot Swap и попробовать перезапустить приложение, используя DevTools, только если выполнение Hot Swap не удалась.

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

В Eclipse достаточно просто сохранить ваши файлы.

Только разработка


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

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

java -jar devtools-example-1.0.0.jar

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

Напротив, когда вы запускаете распакованные артефакты (например, в вашей IDE), ваше приложение рассматривается в режиме разработки. То же самое относится и к использованию spring-boot-plugin для запуска приложения:

Maven:

mvn spring-boot:run

Gradle:

gradle bootRun

LiveReload


LiveReload — это полезный инструмент, который позволяет мгновенно обновлять страницу в браузере всякий раз, когда вы вносите изменения в файлы, такие как HTML, CSS, изображения и многое другое. Он даже предварительно обрабатывает файлы по мере необходимости — это означает автоматическую компиляцию файлов SASS или LESS.



Spring DevTools автоматически запускает локальный экземпляр сервера LiveReload, который отслеживает ваши файлы. Все, что вам нужно сделать, это установить расширение для браузера, и готово. Он не только полезен для разработки внешнего интерфейса вашего приложения (в случае, если вы распространяете его как часть артефакта приложения Spring), но также может использоваться для мониторинга и перезагрузки вывода вашего REST API.

Переопределение свойств


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

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

spring.thymeleaf.cache=false
spring.freemarker.cache=false
spring.groovy.template.cache=false
spring.mustache.cache=false
server.servlet.session.persistent=true
spring.h2.console.enabled=true
spring.resources.cache.period=0
spring.resources.chain.cache=false
spring.template.provider.cache=false
spring.mvc.log-resolved-exception=true
server.servlet.jsp.init-parameters.development=true
spring.reactor.stacktrace-mode.enabled=true

Вы можете найти список всех свойств в классе DevToolsPropertyDefaultsPostProcessor.

Удаленное подключение


Помимо локальной разработки, вы также можете подключиться к удаленному приложению под управлением DevTools. Этот инструмент не предназначен для производственных сред, поскольку может представлять серьезную угрозу безопасности. Однако он может быть очень полезным в пред производственной (pre-production) среде.

Включение удаленного подключения


Удаленное подключение по умолчанию не включено. Вам необходимо явно включить его, изменив файл pom:

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

Или с gradle, вам нужно установить excludeDevtools = false:

bootWar {
    excludeDevtools = false
}

Затем вам нужно установить пароль, который будет использоваться для аутентификации при подключении к удаленному приложению:

spring.devtools.remote.secret=somesecret

Подключение к удаленному приложению


После запуска удаленного приложения вы можете запустить сеанс удаленного подключения. Теперь все, что вам нужно сделать, это запустить org.springframework.boot.devtools.RemoteSpringApplication с URL-адресом вашего удаленного приложения в качестве аргумента. Обратите внимание, что вы должны использовать https, если это возможно.

Запуск удаленного подключения легко выполняется в вашей IDE. В IDEA вам нужно просто создать новую конфигурацию запуска. Перейдите в Run → Edit Configurations ... и создайте новую конфигурацию с иконкой + в левом верхнем углу. Выберите тип приложения.

В качестве класса Main выберите RemoteSpringApplication из модуля DevTools и в качестве аргумента программы передайте URL-адрес вашего удаленного приложения.



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



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

Глобальная конфигурация


Вы можете настроить DevTools, используя свойства конфигурации, как и в любом другом приложении Spring. Обычно это означает редактирование application.properties вашего проекта. Эта конфигурация является отдельной для каждого приложения.

Однако в некоторых сценариях может быть удобно иметь глобальную конфигурацию для ВСЕХ приложений, работающих на одном компьютере. Вы можете создать файл свойств с именем .spring-boot-devtools.properties, расположенный в вашем каталоге $HOME. Декларация, заявленная в этом файле, применяется ко всем приложениям, использующим DevTools.

Ограничения


Live Reload


Приложение Spring с использованием DevTools автоматически запускает сервер LiveReload. К сожалению, только один экземпляр этого сервера может быть запущен одновременно. Точнее, будет работать только первый экземпляр. Это относится не только к нескольким экземплярам приложений Spring с DevTools, но и к любым другим приложениям, которые также используют LiverReload под капотом, таким как Gatsby в режиме разработки.

Если вы хотите настроить приложение Spring так, чтобы оно не запускало сервер LiveReload, то это можно сделать в вашем файле application.properties:

spring.devtools.livereload.enabled=false

Shutdown Hook


DevTools зависят от атрибута shutdown hook класса SpringApplication. Класс не будет работать правильно, если вы вручную отключили атрибута, используя:

springApplication.setRegisterShutdownHook(false);

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

Коллизии со сторонними библиотеками


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

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

spring.devtools.restart.enabled=false

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

public static void main(String[] args) {
    System.setProperty("spring.devtools.restart.enabled", "false");
    SpringApplication.run(MyApp.class, args);
}

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

Включение отложенной инициализации


Вы можете пометить отдельные компоненты как лениво инициализированные с помощью аннотации $@Lazy$. Эта функция доступна уже в течение достаточно долгого времени. Начиная с Spring Boot 2.2, вы можете переключать отложенную инициализацию для всех ваших bean-компонентов, используя spring.main.lazy-initialization = true.

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

DevTools позволяет выполнить горячий перезапуск вашего приложения в той же JVM. Значительным преимуществом горячего перезапуска является то, что он дает JIT больше возможностей для оптимизации кода, используемого при запуске вашего приложения. После нескольких перезапусков исходное время 2500 мс сокращается почти на 80% и приближается к 500 мс. С ленивой инициализацией мы можем доститичь лучших результатов. При установке spring.main.lazy-initialization наше приложение перезапускается через 400 мс непосредственно в IDE.

Использование отложенной инициализации для всех ваших bean-компонентов в производственном приложении сомнительно. Эта процедура обеспечивает превосходное повышение производительности при запуске за счет более длительных первых запросов к отдельным bean-компонентам. Что еще более важно, ваше приложение не перестает работать быстро. Но вместо сбоя сразу же при запуске приложения оно завершится ошибкой только после непосредственного запроса неправильно настроенного компонента. Это может быть очень опасно, так как вы не обнаружите многие ошибки, пока не станет слишком поздно. Тем не менее, массовая отложенная инициализация может быть полезна для ускорения времени разработки, так как при работе с определенной функцией вы обычно работаете только над частью вашего приложения, а остальное не используете. Идеальным компромиссом было бы включение массовой отложенной инициализации только для локальной разработки (скажем, с использованием пружинного профиля) и отключение его для развернутых более высоких сред.

Заключение


DevTools ускоряет и упрощает разработку приложений Spring Boot, обеспечивая автоматический перезапуск и функцию LiveReload. В дополнение к этому, он устанавливает различные свойства для значений, более подходящих для локальной разработки. Кроме того, он позволяет вам удаленно подключаться к вашему приложению и при этом использовать большинство его функций. При запуске приложения в производство DevTools не используются. Для получения подробной информации см. официальную документацию.
Tags:
Hubs:
+11
Comments 1
Comments Comments 1

Articles