Первое приложение: структура проекта и Spring Initializr
Любой проект Spring Boot начинается одинаково: Spring Initializr собирает скелет, а вы добавляете код. Разберём структуру и первый запуск.
Суть: start.spring.io генерирует проект с правильными версиями. Внутри — главный класс, файл конфигурации application.yml и сборщик Maven или Gradle.
Не создавайте проект Spring Boot вручную — это путь к конфликтам версий. Зайдите на start.spring.io, выберите Maven или Gradle, язык Java, версию Boot 3.x и Java 21, добавьте зависимости (как минимум Spring Web) — и скачайте архив. Внутри будет готовый, запускаемый проект.
Структура проекта
Типичный проект на Maven выглядит так:
myapp/
├── pom.xml файл сборки: зависимости и плагины
├── mvnw, mvnw.cmd Maven Wrapper (запуск без установки Maven)
└── src/
├── main/
│ ├── java/
│ │ └── com/example/myapp/
│ │ ├── MyAppApplication.java главный класс (main)
│ │ ├── controller/
│ │ ├── service/
│ │ └── repository/
│ └── resources/
│ ├── application.yml конфигурация приложения
│ └── static/ статические файлы
└── test/
└── java/ тесты
Ключевые элементы: pom.xml описывает зависимости и подключает spring-boot-maven-plugin для сборки исполняемого JAR. MyAppApplication.java содержит метод main. Папка resources хранит application.yml — главный файл настроек.
Конфигурация в application.yml
Spring Boot читает настройки из application.properties или application.yml. YAML удобнее за счёт вложенности:
server:
port: 8080 # порт встроенного сервера
spring:
application:
name: myapp
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: postgres
password: secret
jpa:
hibernate:
ddl-auto: update # обновлять схему по сущностям
Первый эндпоинт
Добавим простейший контроллер, который отвечает на GET-запрос:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Привет, Spring Boot!";
}
}
Как работает под капотом
При запуске SpringApplication.run() происходит цепочка: создаётся контекст приложения, срабатывает автоконфигурация (Boot видит spring-web → поднимает Tomcat), @ComponentScan находит HelloController и регистрирует его как бин, DispatcherServlet строит карту маршрутов. После этого по адресу http://localhost:8080/hello уже отвечает ваш метод.
# Запуск в режиме разработки
./mvnw spring-boot:run
# Проверка эндпоинта
curl http://localhost:8080/hello
# -> Привет, Spring Boot!
Частые ошибки
- Контроллер вне пакета главного класса. Если положить его в пакет выше
MyAppApplication, сканирование его не найдёт, и эндпоинт вернёт 404. - Занятый порт 8080. Если порт занят, приложение упадёт при старте — поменяйте
server.portв конфиге. - Смешивать .properties и .yml. Выберите один формат, иначе настройки могут переопределять друг друга непредсказуемо.
Best practices
- Используйте Maven/Gradle Wrapper (
mvnw) — тогда у всех в команде одна версия сборщика. - Храните секреты (пароли) не в
application.yml, а в переменных окружения. - Разбивайте конфиги на профили:
application-dev.yml,application-prod.yml.
Итог: проект Spring Boot — это скелет от Initializr с главным классом, конфигом и сборщиком. Запустили, добавили контроллер с @GetMapping — и первый эндпоинт готов. Дальше углубимся в контроллеры.
Закрепим главное
Запомните последовательность первого запуска как ритуал: сгенерировать скелет в Initializr, открыть проект в IDE, убедиться, что главный класс лежит в корневом пакете, добавить контроллер, поднять приложение и проверить эндпоинт через браузер или curl. Эти шаги вы будете повторять в начале каждого проекта, и доведение их до автоматизма экономит много времени.
Полезно с самого начала приучить себя к аккуратной структуре пакетов: controller, service, repository, dto, entity, config. Когда проект маленький, это кажется избыточным, но через несколько месяцев именно понятная раскладка по слоям спасает от хаоса. И сразу заведите профили окружений: даже простому учебному приложению полезно иметь отдельную конфигурацию для разработки и для прода, чтобы потом не переписывать настройки в спешке перед релизом.