Учебные материалы

Конвертация Spring Boot JAR приложения в WAR с Maven

В этом уроке освещается процесс конвертации исполяемого JAR приложения, которое было собрано с Spring Boot, в WAR файл, который вы можете запустить на любом стандартном контейнере сервлетов.

Что вы создадите

Вы возьмете простое Spring MVC приложение и соберете WAR файл, используя Spring Boot.

Что вам потребуется

  • Примерно 15 минут свободного времени
  • Любимый текстовый редактор или IDE
  • JDK 6 и выше
  • Gradle 1.11+ или Maven 3.0+
  • Вы также можете импортировать код этого урока, а также просматривать web-страницы прямо из Spring Tool Suite (STS), собственно как и работать дальше из него.

Как проходить этот урок

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

Чтобы начать с нуля, перейдите в Настройка проекта.

Чтобы пропустить базовые шаги, выполните следующее:

Когда вы закончите, можете сравнить получившийся результат с образцом в gs-convert-jar-to-war-maven/complete.

Настройка проекта

Для начала вам необходимо настроить базовый скрипт сборки. Вы можете использовать любую систему сборки, которая вам нравится для сборки проетов Spring, но в этом уроке рассмотрим код для работы с Maven. Если вы не знакомы с Maven, ознакомьтесь с соответсвующим уроком Сборка Java-проекта с использованием Maven.

Создание структуры каталогов

В выбранном вами каталоге проекта создайте следующую структуру каталогов; к примеру, командой mkdir -p src/main/java/hello для *nix систем:

└── src
    └── main
        └── java
            └── hello

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-convert-jar-to-war-maven</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.5.RELEASE</version>
    </parent>

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

    <properties>
        <start-class>hello.Application</start-class>
    </properties>

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

    <repositories>
        <repository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>http://repo.spring.io/libs-release</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>http://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>

</project>

Spring Boot Maven plugin предоставляет множество удобных возможностей:

  • Он собирает все jar'ы в classpath и собирает единое, исполняемое "über-jar", что делает более удобным выполнение и доставку вашего сервиса
  • Он ищет public static void main() метод, как признак исполняемого класса
  • Он предоставляет встроенное разрешение зависимостей, с определенными номерами версий для соответсвующих Spring Boot зависимостей. Вы можете переопределить на любые версии, какие захотите, но он будет по умолчанию для Boot выбранным набором версий

Создание базового web-приложения

Теперь, когда вы настроили проект, вы можете создать Spring MVC приложение. Вам оно необходимо для запуска встроенного в Spring Boot контейнера сервлетов. Затем измените его немного, чтобы собрать WAR файл, который вы сможете запустить на любом контейнере сервлетов 3.0.

Spring MVC позволяет вам быстро создавать контроллеры для вашего web-сайта.

src/main/java/hello/HelloController.java

package hello;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HelloController {

    @RequestMapping(value="/", method=RequestMethod.GET)
    public String index() {
        return "index";
    }
}

Контроллер лаконичен и прост, но в нем происходит много чего интересного. Давайте подробнее его рассмотрим шаг за шагом.

Аннотация @Controller сигнализирует о том, что этот класс содержит web-адреса приложения.

Аннотация @RequestMapping гарантирует, что HTTP запросы к / приведут к выполнению метода index().

В этом примере приложение обрабатывает только GET.

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

Web контроллер возвращает строку index когда кто-то делает GET / к вашему сайту. Spring Boot автоматически добавляет Thymeleaf бины в контекст приложения для конвертации в запрос шаблона Thymeleaf, расположенного в src/main/resources/templates/index.html.

src/main/resources/templates/index.html

<html>
    <body>
        Hello, world!
    </body>
</html>

Этот шаблон имеет несколько очень простых HTML элементов и не имеет Thymeleaf кода. Вы можете расширить его по мере необходимости.

Создание приложения исполняемым

Несмотря на то, что пакет этого сервиса может быть в составе web-приложения и WAR файлов, более простой подход, продемонстрированный ниже создает отдельное самостоятельное приложение. Вы упаковываете все в единый, исполняемый JAR-файл, который запускается через хорошо знакомый старый main() Java-метод. Попутно, вы используете поддержку Spring для встроенного Tomcat контейнера сервлетов как HTTP среду выполнения вместо развертывания на сторонний экземпляр.

src/main/java/hello/Application.java

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Метод main() передает управление вспомогательному классу SpringApplication, предоставляя Application.class как аргумент его run() методу. Это говорит Spring о том, чтобы прочитать аннотацию метаданных из Application и управлять им как компонентом в Spring Application Context.

Аннотация @ComponentScan сообщает Spring о запуске рекурсивного поиска в пакете hello и потомках классов, отмеченных прямо или косвенно Spring аннотацией @Component. При этом гарантируется, что Spring найдет и зарегистрирует HelloController, потому что он отмечен @Controller, что в свою очередь является своего рода @Component аннотацией.

@EnableAutoConfiguration аннотация переключает на доступные по умолчанию настройки, основанные на содержимом вашего classpath. К примеру, т.к. приложение зависит от встраиваемой версии Tomcat(tomcat-embed-core.jar), то Tomcat сервер установлен и настроен по умолчанию от вашего имени. И также, т.к. приложение зависит от Spring MVC (spring-webmvc.jar), Spring MVC DispatcherServlet настроен и зарегистрирован за вас - web.xml не нужен! Автонастройка является мощным и гибким механизмом. Более подробно вы можете ознакомиться в API документации.

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

mvn clean package

Запуск сервиса

Запустите ваш сервис из командной строки:

mvn spring-boot:run

Выходные данные отображены. Сервис должен быть поднят и запущен через несколько секунд. В вашем браузере перейдите по адресу http://localhost:8080. Вы должны увидеть текст "Hello, world!", отрендеренный шаблоном.

Создание WAR файла

Приложение, собранное вами на данном этапе настроено на генерацию JAR артефакта. Для переключения на WAR файл, вам необходимо добавить другой плагин в ваш pom.xml:

<packaging>war</packaging>

Если вы хотите разворачивать WAR файл внешнего контейнера, добавьте зависимость встроеннного контейнера как "provided":

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

Ниже представлена новая версия pom.xml, которая включает эти изменения:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-convert-jar-to-war-maven</artifactId>
    <version>0.1.0</version>
    <packaging>war</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <properties>
        <start-class>hello.Application</start-class>
    </properties>

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

    <repositories>
        <repository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>http://repo.spring.io/libs-release</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>http://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>

</project>

Теперь, когда вы запустите mvn clean package, WAR файл будет создан.

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

Ранее приложение содержало метод public static void main(), который запускался плагином spring-boot-maven-plugin, когда использовалась команда java -jar.

Используя конвертацию в WAR файл без XMl файлов, вам необходим другой сигнал сервлет контейнеру о том, как запускать приложение.

src/main/java/hello/WebInitializer.java

package hello;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

public class WebInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

}

WebInitializer является чистым Java классом, который предоставляет альтернативу созданию web.xml. Он расширяет класс SpringServletInitializer. Это расширение предлагает множество конфигурируемых настроек путем переопределения методов. И только один метод configure() обязателен для переопределения.

configure() предоставляет средства для регистрации классов, которые необходимы для запуска приложения. Это то место, где вы передаете для обработки вашу Application конфигурацию. Запомните: Application содержит @ComponentScan, поэтому он будет находить web контроллеры автоматически.

Даже если public static void main() больше не нужен, вы можете оставить его код на месте.

Если вы не используете @ComponentScan, то вы должно быть добавляете все остальные компоненты вручную как @Bean`s or include the other components inside `configure().

Запуск WAR файла

Как только Application загрузится, он инициализирует Spring Boot для автоматического конфигурирования других бинов. в этом примере он добавляет Spring MVC и Thymeleaf бины. Но Spring Boot добавляет и другие бины, исходя из совокупности факторов, таких как ваш classpath и других настроек контекста приложения.

На данном этапе вы готовы к сборке WAR файла:

mvn clean package

Эта команда создает развертываемый артефакт target/gs-convert-jar-to-war-maven-0.1.0.war.

Вы можете загрузить Tomcat, Jetty или любой другой контейнер, который поддерживает сервлеты 3.0 версии. Распакуйте его и поместите WAR файл в правильную директорию. Затем запустите сервер.

В вашем браузере перейдите по адресу http://localhost:8080/gs-convert-jar-to-war-maven-0.1.0/. Вы должны увидеть текст "Hello, world!", отрендеренный шаблоном.

Итог

Поздравляем! Вы только что конвертировали исполняемый JAR в WAR файл приложения, который можно будет запустить на любом сервлет 3.0+ контейнере.

С оригинальным текстом урока вы можете ознакомиться на spring.io.

comments powered by Disqus