JavaRush /Курсы /JSP & Servlets /Сборка war-проекта

Сборка war-проекта

JSP & Servlets
2 уровень , 2 лекция
Открыта

Отличия war и jar-файлов

Фактически jar-библиотека – это просто zip архив, что напрямую следует из его имени: Java Archive. Чаще всего он содержит просто четыре вещи:

  • скомпилированные классы;
  • ресурсы: properties-файлы и тому подобное;
  • манифест MANIFEST.MF;
  • другие jar-библиотеки (редко).

Типичная структура такого архива имеет вид:

  META-INF/
  	MANIFEST.MF
  com/
  	javarush/
	      MyApplication.class
  application.properties

Теперь давай рассмотрим типичный war-файл. Кстати, war не от слова война, а от Web Archive. Структура war-файла обычно посложнее. Чаще всего он состоит из двух частей:

  • Java-часть
    • скомпилированные классы
    • ресурсы для java-классов: properties-файлы и тому подобное
    • другие jar-библиотеки (часто)
    • манифест MANIFEST.MF
  • Web-часть
    • web-xml – дескриптор развертывания веб-сервиса
    • jsp-сервелеты
    • статические веб-ресурсы: HTML, CSS, JS-файлы

Пример типичного war-файла:

META-INF/
    MANIFEST.MF
WEB-INF/
    web.xml
    jsp/
    	helloWorld.jsp
    classes/
    	static/
    	templates/
    	application.properties
    lib/
    	// *.jar files as libs

Важно! jar-файл может запустить просто java-машина, для запуска же war-файла его нужно загрузить на веб-сервер. Самостоятельно он не запускается.

Плагин создания war-файла с помощью maven-war-plugin

Давайте представим, что у нас есть простой веб-проект. Пусть проект задается такой структурой файлов, как нам его собрать?

|-- pom.xml
 `-- src
 	`-- main
     	|-- java
     	|   `-- com
     	|   	`-- example
     	|       	`-- projects
     	|           	`-- SampleAction.java
     	|-- resources
     	|   `-- images
     	|   	`-- sampleimage.jpg
     	`-- webapp
         	|-- WEB-INF
         	|   `-- web.xml
         	|-- index.jsp
         	`-- jsp
             	`-- websource.jsp

Во-первых, нам нужно указать Maven, собрать все это в виде war-файла, для этого есть тег <package>, пример:

 <project> ... <groupId>com.example.projects</groupId> <artifactId>simple-war</artifactId>
  	<packaging>war</packaging>
      <version>1.0-SNAPSHOT</version> <name>Simple War Project</name> <url>http://javarush.com</url> ... </project>

Во-вторых, нам нужно подключить плагин maven-war-plugin. Пример:

  <build> <plugins> <plugin>
        <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version>
    	<configuration> <webappDirectory>/sample/servlet/container/deploy/directory</webappDirectory> </configuration>
      </plugin> </plugins> </build>

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

Плагину можно задать два режима сборки (два вида goal):

  • war:war
  • war:exploded

В первом случает итоговый war-файл просто кладется в папку target и имеет имя <artifactId>-<version>.war.

Но можно “попросить” плагин, чтобы в итоговую папку содержимое war-файла было помещено в том состоянии, в котором оно будет распаковано веб-сервером у себя внутри. Для этого используется goal war:exploded.

Второй подход используется часто, если ты запускаешь или дебажишь проект прямо из Intellij IDEA.

Кстати, тег webappDirectory в примере выше позволяет переопределить директорию куда будет распакован ваш war-файл при сборке в режиме war:exploded.

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

Сборка web-приложения на основе SpringBoot

Ну и хотелось бы разобрать какой-нибудь реальный пример сборки. Давай не мелочиться и рассмотрим это на примере приложения на основе SpringBoot.

Шаг первый. Создай пустой Maven web-проект с помощью IDEA.

Шаг второй. Добавь в его pom.xml зависимости от Spring.

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

Шаг третий. Создай класс com.javarush.spring.MainController. Его нужно разместить в папке src/main/java:


@Controller
public class MainController {
 
	@GetMapping("/")
    public String viewIndexPage(Model model) {
        model.addAttribute("header", "Maven Generate War");
    	return "index";
	}
}

Тут описаны 3 вещи. Во-первых, аннотация @Controller указывает фреймворку SpringBoot, что этот класс будет использоваться для обслуживания входящих веб-запросов.

Во-вторых, аннотация @GetMapping, указывает, что наш метод будет вызываться для обслуживания GET-запроса на корневой URI - /

В-третьих, метод возвращает строку "index". Это говорит фреймворку SpringBoot, что в качестве ответа нужно отдать содержимое файла index.html.

Шаг четвертый. Нужно добавить в проект файл index.html с таким содержимым:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
    <!-- Bootstrap core CSS -->
    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
</head>
<body>
    <nav class="navbar navbar-light bg-light">
    	<div class="container-fluid">
        	<a class="navbar-brand" href="#">
            	JavaRush Tutorial
        	</a>
    	</div>
    </nav>
    <div class="container">
    	<h1>[[${header}]]</h1>
    </div>
</body>
</html>

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

Красным отображены теги, которые будут обработаны библиотекой Thymeleaf, зеленым – стили CSS-библиотеки Bootstrap.

Шаг пятый. Задаем плагин в pom.xml:

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.3.1</version>
</plugin>

Немного переоценил свои силы. Чтобы полностью разобрать простой пример, нужно много времени. Но ты можешь скачать полный код проекта из GitHub и попробовать разобраться в нем самостоятельно. Кстати, процентов 80% своего рабочего времени ты будешь делать именно это :)

Полный код ты можешь скачать по ссылке в GitHub.

Комментарии (15)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Мая Уровень 82
17 августа 2025
ничего не поняла, но уже привыкла к такой ситуации.
ALEXANDR Уровень 22
22 апреля 2025
Подскажите, а структура проекта, что в начале лекции, в ручную создаётся или ее можно как то автоматически создать?
Борис Уровень 33
29 августа 2024
подскажите пожалуйста почему Idea зависимости выделяет красным? Ошибка: Dependency 'org.springframework.boot:spring-boot-starter-thymeleaf:' not found
Alec Sacreson Уровень 51
10 октября 2024
Нужно версию указать, например <version> 3.3.2</version> В остальных депенденси спринга тоже. А посмотреть доступную версию можно сочетанием cntr + space. <version>cntr + space</version>
Sunat Уровень 49 Expert
5 мая 2024
Здравствуйте. Не дает скачать проект, пишет нет доступа. Подскажите что делать...
Dmitry Tolstov Уровень 7
16 июля 2023
Модификация [[${header}]] библиотекой Thymeleaf по какой то причине не происходит.
Радик Уровень 1 Expert
18 августа 2023
вроде как не нужно квадратные скобки , только так ${header}
Даниил Уровень 92 Expert
5 июля 2023
Продолжение разбора по ссылке. https://www.baeldung.com/maven-generate-war-file
Max Dudin Уровень 6 Expert
28 мая 2023
"Немного переоценил свои силы" 🤣 и это после всего того, через что пришлось пройти... spring dependency не хотели подгружаться reload'иться пока у каждой не указал версию. Нашел две из них на https://mvnrepository.com выбрал версию 2.7.6, они подгрузились. Третьей (spring-boot-starter-thymeleaf) по быстрому не нашел, добавил такую же на дурика, и нормально прошло. Папки java при это варианте сборки изначально не было .. добавил. Класс MainController создал, прямо так как написано "com.javarush.spring.MainController", в папке java создалась папка com.javarush.spring, а в ней уже MainController.
Андрей Уровень 37 Expert
13 июля 2024
Проект на который дали ссылку является многомодульным maven проектом. Pom файл данного проекта ссылается на родительский pom файл. А в этом файле прописаны уже все версии. Кстати этот родительский ссылается на другой родительский pom...
jvatechs Уровень 111 Expert
6 мая 2023
Такое ощущение, что я прочитал незаконченную статью. Оборвалось на самом интересном. Для чего тогда всё это добавлялось? Чтоб показать как добавлять зависимости/плагины в пом-файлы? Для наглядности можно было бы вставить какой-нибудь простой пример, чтоб запустить этот проект.
Pixta Уровень 108 Expert
13 июля 2022
Добавление примера создания war считаю неуместным. В целом не завершенная мысль + использование тем, которые сейчас нет цели рассказать.
Рогов Игорь Уровень 17
17 июня 2022
вот мы делали Чат, например. как его , например, собрать чтоб он без идеи работал или вообще с томката например? не хватает наглядности
Фарид Гулиев Уровень 41
14 июля 2022
надо было добавить в сервер клиентский интерфейс, а потом создать два jar-файла, один для сервера, другой для чата. Инструкций в интернете полно, сам так делал
Anonymous #3322801 Уровень 2 Expert
13 июля 2023
тоже так делала, но ощущение что все равно это не должно выглядеть так... а как то поприличней