«1. Введение

В этом руководстве мы рассмотрим различия между запуском веб-приложения Spring Boot с помощью команды mvn spring-boot:run и запуском его после компиляции в пакет jar/war с помощью java -jar. команда.

Предположим, вы уже знакомы с конфигурацией цели перепаковки Spring Boot. Дополнительные сведения по этой теме см. в статье Создание приложения Fat Jar с помощью Spring Boot.

2. Плагин Spring Boot Maven

При написании приложения Spring Boot плагин Maven Spring Boot является рекомендуемым инструментом для создания, тестирования и упаковки нашего кода.

Этот плагин поставляется с множеством удобных функций, таких как:

    он разрешает правильные версии зависимостей для нас он может упаковать все наши зависимости (включая встроенный сервер приложений, если это необходимо) в один исполняемый файл jar/war а также будет: управлять для нас конфигурацией пути к классам, поэтому мы можем пропустить эту длинную опцию -cp в нашей команде java -jar, реализовать собственный ClassLoader для поиска и загрузки всех внешних библиотек jar, теперь вложенных в пакет, автоматически найти основной ( ) и настройте его в манифесте, поэтому нам не нужно указывать основной класс в нашей команде java -jar

3. Запуск кода с помощью Maven в развернутой форме

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

Нам нужна только одна зависимость, чтобы плагин знал, что мы хотим использовать Tomcat для запуска нашего кода:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency>

Теперь при выполнении команды mvn spring-boot:run в корневой папке нашего проекта плагин читает конфигурация pom и понимает, что нам нужен контейнер веб-приложения.

Выполнение команды mvn spring-boot:run запускает загрузку Apache Tomcat и инициализирует запуск Tomcat.

Давайте попробуем:

$ mvn spring-boot:run
...
...
[INFO] --------------------< com.baeldung:spring-boot-ops >--------------------
[INFO] Building spring-boot-ops 0.0.1-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.1.3.RELEASE:run (default-cli) > test-compile @ spring-boot-ops >>>
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/tomcat/embed/tomcat-embed-core/9.0.16/tomcat-embed-core-9.0.16.pom
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/tomcat/embed/tomcat-embed-core/9.0.16/tomcat-embed-core-9.0.16.pom (1.8 kB at 2.8 kB/s)
...
...
[INFO] --- spring-boot-maven-plugin:2.1.3.RELEASE:run (default-cli) @ spring-boot-ops ---
...
...
11:33:36.648 [main] INFO  o.a.catalina.core.StandardService - Starting service [Tomcat]
11:33:36.649 [main] INFO  o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.16]
...
...
11:33:36.952 [main] INFO  o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
...
...
11:33:48.223 [main] INFO  o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]
11:33:48.289 [main] INFO  o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''
11:33:48.292 [main] INFO  org.baeldung.boot.Application - Started Application in 22.454 seconds (JVM running for 37.692)

Когда в журнале появится строка, содержащая «Запущенное приложение», наше веб-приложение готово для запроса через браузер по адресу http://localhost:8080/ ~ ~~ 4. Запуск кода как отдельного упакованного приложения

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

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

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

Чтобы обойти это ограничение, нам нужно использовать цель переупаковки плагина Maven Spring Boot, чтобы запустить наш jar/war как отдельное приложение.

4.1. Конфигурация

Обычно нам нужно только настроить плагин сборки:

Но наш пример проекта содержит более одного основного класса, поэтому мы должны указать Java, какой класс запускать, либо настроив плагин: ~ ~~

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

или установив свойство start-class:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <configuration>
                <mainClass>com.baeldung.webjar.WebjarsdemoApplication</mainClass>
            </configuration>
        </execution>
    </executions>
</plugin>

4.2. Запуск приложения

<properties>
    <start-class>com.baeldung.webjar.WebjarsdemoApplication</start-class>
</properties>

Теперь мы можем запустить наш пример war с помощью двух простых команд:

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

$ mvn clean package spring-boot:repackage
$ java -jar target/spring-boot-ops.war

4.3. Внутри файла войны

Чтобы лучше понять, как упомянутая выше команда может запустить полноценное серверное приложение, мы можем заглянуть в наш файл spring-boot-ops.war.

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

META-INF с автоматически сгенерированным файлом MANIFEST.MF WEB-INF/classes, содержащим наши скомпилированные классы WEB-INF/lib, который содержит наши военные зависимости и встроенные jar-файлы Tomcat

    Это еще не все, так как есть несколько папок, специфичных для конфигурации нашего толстого пакета:

WEB-INF/lib-provided, содержащие внешние библиотеки, необходимые при запуске встроенного, но не обязательные при развертывании org/springframework/boot/loader, который содержит пользовательский загрузчик классов Spring Boot — эта библиотека отвечает за загрузку наших внешних зависимостей и делает их доступными во время выполнения

    «4.4. Внутри военного манифеста

Как упоминалось ранее, плагин Maven Spring Boot находит основной класс и генерирует конфигурацию, необходимую для запуска команды java.

Результирующий файл MANIFEST.MF содержит несколько дополнительных строк:

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

Start-Class: com.baeldung.webjar.WebjarsdemoApplication
Main-Class: org.springframework.boot.loader.WarLauncher

4.5. Внутри Jar-файла

Из-за стратегии упаковки по умолчанию наш сценарий боевой упаковки не сильно отличается, независимо от того, используем ли мы плагин Spring Boot Maven или нет.

Чтобы лучше оценить преимущества плагина, мы можем попробовать изменить конфигурацию упаковки pom на jar и снова запустить mvn clean package.

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

Все наши папки классов и ресурсов теперь расположены в BOOT-INF/classes BOOT-INF/lib содержит все внешние библиотеки.

    Без плагина папки lib не существовало бы, а все содержимое BOOT-INF/classes находилось бы в корне пакета.

4.6. Внутри манифеста Jar

Также изменился файл MANIFEST.MF, содержащий следующие дополнительные строки:

Spring-Boot-Classes и Spring-Boot-Lib особенно интересны, так как они сообщают нам, где находится загрузчик классов. собирается найти классы и внешние библиотеки.

Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.1.3.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher

5. Как выбрать

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

5.1. Разработка

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

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

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

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

5.2. Производство

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

Запуск кода через Maven на данном этапе является плохой практикой по нескольким причинам:

Во-первых, нам нужно установить Maven Затем, только потому, что нам нужно скомпилировать код, нам нужен полный комплект Java Development Kit ( JDK) Затем мы должны скопировать кодовую базу на наш сервер, оставив весь наш проприетарный код в виде простого текста. Команда mvn должна выполнить все фазы жизненного цикла (найти исходники, скомпилировать и запустить). Благодаря предыдущему пункту мы также будет тратить ЦП и, в случае облачного сервера, деньги. Maven порождает несколько процессов Java, каждый из которых использует память (по умолчанию каждый из них использует тот же объем памяти, что и родительский процесс). Наконец, если у нас есть несколько серверов для развертывания, все вышеперечисленное повторяется для каждого

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

6. Заключение

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

Исходный код, используемый в этой статье, доступен на GitHub.

«