Реактивный backend для чат‑приложения на базе Spring Boot 3 / WebFlux / GraphQL, с поддержкой JWT‑аутентификации, Postgres (R2DBC), Redis и «умных» обновлений через GraphQL Subscriptions.
Проект разделён на несколько Gradle‑модулей по принципам DDD / Hexagonal / Clean Architecture:
- core — доменная модель и порты:
- сущности:
User,ChatRoom,Message,Participant,RefreshTokenи т.д.; - общие абстракции:
CreateUseCase,FindUseCase,UpdateUseCase,DeleteUseCase, критерии поиска, пагинация; - порты (
ports.inbound/ports.outbound) для пользователей, сообщений, комнат, безопасности, токенов.
- сущности:
- application — прикладные use‑cases:
CreateUserUseCase,CreateMessageUseCase,FindMessagesUseCase,CreateChatRoomUseCase,AddReactionUseCaseи пр.;AuthenticationServiceImplреализуетAuthenticationUseCase(login / refresh / logout).
- infrastructure — адаптеры и интеграции:
- Persistence: R2DBC‑репозитории, сущности и мапперы (
UserRepositoryImpl,MessageRepositoryImpl,ChatRoomRepositoryImpl,ParticipantRepositoryPortImplи др.); - Security: JWT‑генерация и валидация, адаптеры к
AuthenticationPort,SecurityUtilsPort,PasswordEncoderPort, blacklist refresh‑токенов и access‑токенов; - GraphQL: резолверы (
UserResolver,MessageResolver,ChatRoomResolver) + DTO; - Redis / Smart updates:
RedisConfig+SmartUpdateAdapter, который хранит контекст клиента и пушит «умные» обновления через ReactorSinks.
- Persistence: R2DBC‑репозитории, сущности и мапперы (
- boot — точка входа Spring Boot:
OnlineChatApplicationсо@SpringBootApplication(scanBasePackages = "com.metarash.onlinechat");- подключает модули
core,application,infrastructure, конфигурацию GraphQL, безопасности и БД.
- Язык / платформа: Java 21
- Сборка: Gradle (многомодульный проект)
- Web / Reactive:
- Spring Boot 3.3.x
- Spring WebFlux
- Project Reactor
- API:
- Spring for GraphQL (
/graphql) - GraphQL Subscriptions (
/subscriptions) для «умных» обновлений
- Spring for GraphQL (
- БД:
- PostgreSQL (R2DBC драйвер + Flyway миграции)
- Кеш / брокер:
- Redis (ReactiveRedisTemplate, хранение клиентского контекста)
- Безопасность:
- Spring Security (reactive)
- JWT (jjwt)
- Инфраструктура и утилиты:
- MapStruct (мапперы DTO ↔ домен)
- Lombok
Основная конфигурация находится в boot/src/main/resources/application.yml:
- PostgreSQL (R2DBC + Flyway):
- URL:
r2dbc:postgresql://localhost:5432/OnlineChat - JDBC для Flyway:
jdbc:postgresql://localhost:5432/OnlineChat - схема:
onlinechat - пользователь:
postgres - пароль:
12345
- URL:
- Redis:
- host:
localhost - port:
6379
- host:
- GraphQL:
- endpoint:
/graphql - GraphiQL UI: включен (
/graphiql?path=/graphql) - WebSocket для подписок:
/subscriptions
- endpoint:
- JWT:
- заданы
access-secret,refresh-secret, TTL для access/refresh токенов.
- заданы
- Java 21 (JDK)
- Docker (желательно) или локально установленные:
- PostgreSQL
- Redis
# PostgreSQL
docker run --name onlinechat-postgres -e POSTGRES_PASSWORD=12345 \
-e POSTGRES_DB=OnlineChat -p 5432:5432 -d postgres:16
# Redis
docker run --name onlinechat-redis -p 6379:6379 -d redis:7Убедитесь, что схема onlinechat создаётся миграциями Flyway (это делает приложение при старте).
Из корня проекта:
# Windows (PowerShell / cmd)
gradlew.bat :boot:bootRun
# Linux / macOS
./gradlew :boot:bootRunПосле старта приложение будет доступно по адресу:
- HTTP:
http://localhost:8080/graphql - GraphiQL:
http://localhost:8080/graphiql?path=/graphql - WebSocket Subscriptions:
ws://localhost:8080/subscriptions
./gradlew :boot:bootJar
java -jar boot/build/libs/boot-*.jarСхема определена в infrastructure/src/main/resources/graphql/schema.graphqls.
Основные операции:
- Query
getMessages(input: GetMessagesInput!): [Message!]!getUser(id: UUID!): User!getCurrentUser: User!getChatRoom(id: UUID!): ChatRoomResponse!getUserChatRooms: [ChatRoom!]!
- Mutation
login(input: LoginInput!): AuthResponse!register(input: RegisterInput!): AuthResponse!refreshToken(refreshToken: String!): AuthResponse!logout: String!createChatRoom,sendMessage,editMessage,deleteMessage,addReaction,removeReaction
- Subscription
userSmartUpdates(userId: UUID!): UserUpdate!— смарт‑обновления (новые сообщения / обновление списка комнат)
- Регистрация / логин
mutation {
register(input: { username: "test", password: "secret" }) {
userId
accessToken
refreshToken
}
}-
Использование accessToken
- Отправлять в заголовке
Authorization: Bearer <accessToken>при запросах к/graphql.
- Отправлять в заголовке
-
Обновление токена
mutation {
refreshToken(refreshToken: "<refresh-token>") {
accessToken
refreshToken
}
}- Подписка на обновления
- открыть WebSocket‑подключение к
/subscriptionsи вызвать
- открыть WebSocket‑подключение к
subscription {
userSmartUpdates(userId: "<uuid>") {
type
data {
... on Message { id content }
... on RoomListUpdate { roomId lastMessage { id content } }
}
}
}В целом проект выглядит архитектурно зрелым и хорошо структурированным, но требует доработки инфраструктуры (секреты, контейнеризация) и покрытия тестами перед продакшеном.