Веб-приложение для просмотра текущей погоды. Проект позволяет пользователям регистрироваться, искать локации по всему миру и формировать персональный дашборд с метеорологическими сводками. Реализовано на базе многослойной архитектуры с использованием Spring MVC.
Проект разработан в рамках учебного курса Java Backend Learning Course. Приложение интегрировано с внешним сервисом OpenWeatherMap API для получения актуальных погодных данных. В проекте реализована ручная система авторизации на базе сессий и cookies (без использования Spring Security).
Проект развернут и доступен по адресу: Weather Viewer
- login: reviewer
- password: qwerty123
- Интеграция с OpenWeather API: Поиск населенных пунктов по названию (Geocoding API) и получение детальной погодной сводки по координатам.
- Персональные коллекции локаций: Добавление и удаление городов из персонального списка мониторинга для каждого авторизованного пользователя.
- Ручная система аутентификации: Управление жизненным циклом сессий и безопасное хеширование паролей (BCrypt) с сохранением состояния через cookies.
- Защита от дубликатов локаций: Отображение координат (Lat/Lon) для точной идентификации городов с одинаковыми названиями на уровне UI.
- Глобальная обработка исключений: Единый
GlobalExceptionHandler(@ControllerAdvice) для перехвата бизнес-ошибок (например, недоступность внешнего API) и корректной маршрутизации. - Контейнеризация и Деплой: Оптимизированная Multi-stage сборка Docker-образа и оркестрация базы данных, кэша и приложения через
docker-compose.
В проекте старался соблюдать принципы Clean Architecture:
- Изоляция DTO и Сущностей: Строгое разделение между Hibernate Entities и Data Transfer Objects (с использованием MapStruct) для предотвращения утечки бизнес-логики на слой представления.
- Паттерн PRG (Post-Redirect-Get): Исключено дублирование действий пользователя (например, повторное добавление локации) при обновлении страницы.
- Изоляция Context Path: Настроена корректная передача путей между Tomcat и Nginx без использования хардкода, что позволяет приложению прозрачно работать как локально, так и на VPS.
- Слой UI (Thymeleaf & Bootstrap 5): Динамический рендеринг HTML на стороне сервера с использованием утилит форматирования чисел и условного отображения (conditional rendering).
- Слой доступа к данным (Repository): Использование Spring Data JPA для инкапсуляции логики управления EntityManager при взаимодействии с PostgreSQL.
- Кэширование статики на уровне Web-сервера: Nginx настроен на долгосрочное кэширование статических ресурсов (CSS, JS, изображения) для снижения нагрузки на сервер и ускорения загрузки UI.
- Кэширование сетевых ответов через Redis: Внедрение in-memory кэша для кратковременного сохранения ответов от OpenWeather API с целью минимизации задержек и лимитирования внешних запросов.
- Фоновые задачи (Scheduler): Настройка планировщика для автоматической очистки просроченных сессий, срабатывающего по умолчанию один раз в час.
- Контроль доступа (Interceptor): Внедрение перехватчика HTTP-запросов для защиты внутренних эндпоинтов приложения и API-вызовов от неавторизованного доступа.
- Комплексная валидация данных: Применение стандартных аннотаций JSR-380 (@Size, @NotBlank) в связке с кастомными валидаторами для проверки кросс-полевых условий (например, совпадения введенных паролей при регистрации).
- Java 17
- Spring MVC
- Thymeleaf
- Hibernate (JPA) & Hibernate Validator
- PostgreSQL 15
- Redis
- MapStruct & Jackson
- SLF4J & Logback
- Docker & Docker Compose
- JUnit 5 & Mockito
- TestContainers
- WireMock
- Lombok
- Nginx & Apache Tomcat 10+ (среда деплоя)
Проект упакован в контейнеры, что избавляет от необходимости локальной установки JRE, Tomcat или баз данных.
Перед запуском создайте файл .env в корне проекта со следующими переменными:
OPENWEATHER_API_KEY— (Обязательно) Ваш персональный ключ доступа к OpenWeather API.DB_USERNAME— (Обязательно) Логин для PostgreSQL (например,postgres).DB_PASSWORD— (Обязательно) Пароль для PostgreSQL.REDIS_PASSWORD— (Обязательно) Пароль для Redis.
- Клонируйте репозиторий:
git clone https://github.com/XanderGI/WeatherViewer.git
cd WeatherViewer- Убедитесь, что файл .env заполнен корректно.
- Запустите сборку и старт контейнеров в фоновом режиме:
docker compose up --build -d- Приложение будет доступно по адресу:
http://localhost:8080/
Самый простой способ запустить проект локально без установки Tomcat — использовать встроенный плагин Gretty, настроенный в build.gradle:
- Клонируйте репозиторий:
git clone https://github.com/XanderGI/WeatherViewer.git
cd WeatherViewer- Убедитесь, что файл .env заполнен корректно.
- Запустите проект через Gradle:
./gradlew appRun- Приложение будет доступно по адресу:
http://localhost:8080/
├───main
│ ├───java
│ │ └───io.github.XanderGI
│ │ ├───config // Конфигурационные классы Spring (Web, App)
│ │ ├───controller // HTTP маршрутизация (Spring MVC Controllers)
│ │ │ └───advice // Глобальный обработчик ошибок
│ │ │ └───interceptor // Обработчик неавторизированных запросов
│ │ ├───dto // Объекты передачи данных
│ │ ├───entity // Hibernate JPA сущности (User, Location, Session)
│ │ ├───exception // Классы ислкючений
│ │ ├───mapper // MapStruct (Конвертация Entity <-> DTO)
│ │ ├───repository // Слой доступа к данным (Spring Data JPA / Hibernate)
│ │ ├───scheduler // Scheduler для очисти сессий
│ │ ├───security // Менеджер для управления Cookies
│ │ ├───service // Бизнес-логика и интеграция с внешним API
│ │ └───validation // Валидация(Hibernate Validator)
│ ├───resources
│ │ ├───db/migration // SQL-скрипты миграций (Flyway)
│ │ ├───application.properties // Файл конфигурации приложения
│ │ └───logback.xml // Файл настройки логирования
│ ├───webapp // HTML шаблоны Thymeleaf, Статические файлы(CSS, Изображения)
├───test // Интеграционные тесты сервисов и Mocking HTTP-клиента, тесты для Controller layer
├───Dockerfile // Multi-stage сборка приложения
└───docker-compose.yaml // Оркестрация инфраструктуры (App, Postgres, Redis)
- Работа со Spring MVC: Конфигурация контекста (XML и Java Config), настройка DispatcherServlet, маршрутизация HTTP-запросов, биндинг параметров и применение AOP-подходов для централизованной обработки исключений
- Интеграция REST API: Использование встроенных HTTP-клиентов для выполнения сетевых запросов к внешним сервисам и покрытие данного функционала тестами с использованием WireMock.
- Работа с сессиями и cookies: Проектирование механизма сессий и работы с cookies с нуля (отказ от стандартного JSESSIONID и Spring Security), включая создание Interceptor для защиты маршрутов.
- Многопоточность и фоновые задачи: Конфигурация ThreadPool для изолированной обработки фоновых задач и реализация планировщика (Scheduler) для очистки просроченных сессий.
- Реализациия Repository слоя с помощью Spring Data JPA: получил базовое представление как работать со Spring Data JPA, в ходе его практического использования узнал о его преимуществах и недостатках.
- Асинхронное сетевое взаимодействие: Проведение рефакторинга синхронных вызовов в асинхронные с применением пула потоков и
CompletableFutureдля повышения пропускной способности приложения. - Оптимизация производительности с Redis: Внедрение и конфигурация in-memory кэша для сохранения ранее запрошенных локаций (снижение нагрузки на API), с полным покрытием логики кэширования интеграционными тестами.
- Комплексная валидация: Применение стандарта Hibernate Validator для базовых проверок полей и реализация собственных аннотаций для кросс-полевой валидации DTO.
- Интеграционное тестирование с TestContainers: Создание абстрактного тестового класса для автоматического поднятия изолированного контекста с контейнерами PostgreSQL и Redis на этапе прогона тестов.
- Продвинутая контейнеризация: Разработка оптимизированного Dockerfile с разбиением на этапы (multi-stage: резолв зависимостей и упаковка .war артефакта) и установкой лимитов потребления RAM (512MB)