OtryadWebsite

Сайт и система управления контентом для детской организации: новости, фото- и видеогалереи, админ-панель, SEO с разметкой Schema.org. Spring Boot 4 и PostgreSQL, без единой строчки фронтенд-сборки.

подготовка к продакшену 26 июля 2026
Java 17Spring Boot 4.0Spring SecuritySpring Data JPAPostgreSQLThymeleafCaffeineBucket4jAspectJnginx

OtryadWebsite — это сайт-визитка и полноценная CMS, написанные для Разновозрастного отряда «Надежда». Организация публикует новости, отчёты о поездках, фотоальбомы и видео; всё это нужно было отдать в руки людям, которые не открывают редактор кода.

Поэтому проект состоит из двух половин:

  • публичная часть — лента новостей, галереи, статические страницы, SEO, короткие ссылки, sitemap.xml;
  • админ-панель (/dashboard) — менеджеры постов, медиа, авторов, тегов и пользователей, редактор SEO, журнал аудита, настройки сайта.

Ключевая идея архитектуры: контент живёт в PostgreSQL, файлы — на диске, настройки сайта — в JSON рядом с приложением. Ничего из этого не требует пересборки: добавили пост через панель — он появился на сайте.

Как это выглядит целиком#

Браузер / поисковый робот nginx — TLS, сжатие, отдача файлов, проксирование всё остальное /media/** Spring Boot — вся логика файлы с диска, минуя Java PostgreSQL properties.json каталог медиафайлов
Три источника состояния: база — контент, диск — файлы, JSON — настройки сайта.

Что внутри интересного#

Двухфазная пагинация. spring.jpa.open-in-view=false, а списки нужно показывать вместе с авторами и тегами. Сначала запрашивается страница идентификаторов, затем каждая сущность достаётся по id из кеша Caffeine. Это обходит известную проблему «пагинация + fetch join» и заодно делает вторую страницу почти бесплатной.

SEO как данные, а не как код. Заголовки, описания и тип Schema.org для каждой страницы лежат в properties.json и правятся из панели. Для динамических страниц там же хранятся шаблоны с подстановками вроде <title> и <author>. JSON-LD собирается из цепочки родительских страниц, поэтому breadcrumbs получаются автоматически.

Аудит и лимиты на аспектах. Пометили метод @AuditAction("Создание поста") — запись появилась в журнале, вместе с аргументами; пометили параметр @AuditIgnore — вместо значения запишется ******. Ограничение частоты устроено так же: @RateLimit, а ключ можно задать SpEL-выражением.

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

Документация#

  • Установка и развёртка за nginx — от чистого сервера до HTTPS и systemd, с разбором того, какие настройки обязательно менять.
  • Использование — работа в админ-панели: посты, альбомы, авторы, теги, SEO, короткие ссылки, режим защиты, журнал.
  • Как это работает — полное техническое описание: слои, жизненный цикл запроса, модель данных, кеш, безопасность, SEO-конвейер.
  • Справочник — все маршруты, REST-эндпоинты и параметры конфигурации одной таблицей.

Заметка

Код распространяется по лицензии MIT. Тексты, фотографии и товарные знаки принадлежат РВО «Надежда» — при использовании кода как шаблона контент нужно заменить своим.