Микросервисная платформа для управления школой — расписание, оценки, посещаемость, дз, классы
Проект в разработке, процент закрытых issue до mvp
Backend:
- Spring Boot, Spring Cloud Gateway, Eureka Discovery, OpenFeign
- Resilience4J (circuitbreaker, retry, semaphore bulkhead)
- Spring Data JPA, PostgreSQL, Flyway
- Caffeine Cache
- Spring Security OAuth2 Resource Server, Keycloak
- MapStruct, Lombok, Webclient (Keycloak Admin API)
- Logback, Loki, Grafana, Alloy, Prometheus
- JUnit, Mockito, MockMvc, testcontainers, Wiremock
- Openhtmltopdf + Thymeleaf (PDF Export)
Frontend:
- Vite, React
- React Router
- TanStack Query
- Redux Toolkit
- Axios
- Tailwind CSS, shadcn/ui, Radix UI, lucide-react
- react-hook-form, Zod
- keycloak-js
flowchart LR
Browser["Browser / React frontend"] --> Gateway["api-gateway :8080"]
Gateway -->|lb://user-service| UserService["user-service :9001"]
Gateway -->|lb://academic-service| AcademicService["academic-service :9002"]
UserService --> UserDb[("user_db")]
AcademicService --> AcademicDb[("academic_db")]
UserService -->|Admin REST API| Keycloak["Keycloak :9090"]
UserService <-->|Feign| AcademicService
AcademicService <-->|Feign| UserService
Gateway --> Eureka["eureka-server :8761"]
UserService --> Eureka
AcademicService --> Eureka
UserService --> Logs["/app/logs"]
AcademicService --> Logs
Gateway --> Logs
Logs --> Alloy["Grafana Alloy"]
Alloy --> Loki["Loki :3100"]
Grafana["Grafana :3000"] --> Loki
| Сервис | Порт | Назначение | Основные файлы |
|---|---|---|---|
api-gateway |
8080 |
Единая точка входа, маршрутизация, Swagger aggregation | backend/api-gateway/src/main/resources/application.yml, GatewayConfig.java |
eureka-server |
8761 |
Service discovery (обнаружение сервисов) | backend/eureka-server/src/main/resources/application.yml |
user-service |
9001 |
Пользователи, роли, профили учеников/учителей/родителей, Keycloak admin API | backend/user-service/src/main/java/com/rusobr/user |
academic-service |
9002 |
Учебные годы, периоды, классы, предметы, расписание, уроки, оценки, посещаемость, ДЗ | backend/academic-service/src/main/java/com/rusobr/academic |
frontend |
5173 в Docker, Vite dev port локально |
Внешний интерфейс школьной системы | frontend/src |
.
├── backend/
│ ├── academic-service/
│ │ ├── src/main/java/com/rusobr/academic/
│ │ │ ├── application/ # services, mappers
│ │ │ ├── config/ # security
│ │ │ ├── domain/ # entities, enums
│ │ │ ├── infrastructure/ # Feign clients, repositories, projections
│ │ │ └── web/ # controllers, DTO, exceptions
│ │ └── src/main/resources/db/migration/
│ ├── user-service/
│ │ ├── src/main/java/com/rusobr/user/
│ │ │ ├── application/ # services, user role strategies, mappers
│ │ │ ├── config/ # security, web client, Feign error decoder
│ │ │ ├── domain/ # User, Student, Teacher, Parent
│ │ │ ├── infrastructure/ # Feign, Keycloak WebClient, repositories
│ │ │ └── web/ # controllers, DTO, exceptions
│ │ └── src/main/resources/db/migration/
│ ├── api-gateway/
│ ├── eureka-server/
│ └── settings.gradle
├── frontend/
│ ├── src/
│ │ ├── axios/ # shared Axios client
│ │ ├── components/ # ui, admin, student, teacher, layout
│ │ ├── hooks/ # TanStack Query hooks
│ │ ├── services/ # API clients
│ │ ├── store/ # Redux Toolkit
│ │ └── views/ # route pages
│ └── package.json
├── configs/ # Loki, Alloy, Grafana конфиги
├── docs/ # readme files
├── keycloak/ # Keycloak realm настройки и темы
├── init-db/ # PostgreSQL init db`s
└── docker-compose.yml
sequenceDiagram
participant UI as React frontend
participant GW as api-gateway
participant AC as academic-service
participant US as user-service
participant KC as Keycloak
participant DBU as user_db
participant DBA as academic_db
UI->>GW: HTTP /academic-service/api/v1/journal/by-assignment
GW->>AC: route lb://academic-service
AC->>DBA: lesson_instances, grades, attendances
AC->>US: Feign /api/v1/students/batch
US->>DBU: users, students
US-->>AC: student names
AC-->>GW: journal response
GW-->>UI: JSON
UI->>GW: HTTP /user-service/api/v1/users/students
GW->>US: route lb://user-service
US->>KC: create Keycloak user + assign role
US->>DBU: save user/student profile
US-->>GW: created user
GW-->>UI: JSON
Основные таблицы:
usersuser_rolesstudentsteachersparents
Диаграмма:
Основные таблицы:
academic_years,academic_periodsschool_classes,class_studentsclass_group,class_group_studentssubjects,teacher_subjects,teaching_assignmentsschedule_lessons,lesson_instancesgrades,period_grades,final_gradesattendanceshomeworks
Диаграмма:
Gateway маршрутизирует запросы по префиксам:
| Prefix | Target |
|---|---|
/user-service/** |
lb://user-service |
/academic-service/** |
lb://academic-service |
Swagger UI:
http://localhost:8080/swagger-ui/index.html
Ученик:
/student/home- Главная/student/diary- Дневник/student/grade- Оценки/student/school-class- Школьный класс
Учитель:
/teacher/home- Главная (расписание учителя и привязанные классы)/teacher/journal- Журнал успеваемости/teacher/homework- Домашние задания
Администратор:
/admin/subject- Предметы/admin/period- Учебные периоды/admin/school-class- Классы/admin/user- Пользователи/admin/schedule- Расписание/admin/academic-year- Учебные года
Дополнительно:
/user/:id/info- карточка пользователя
docker compose upПосле запуска:
- Frontend:
http://localhost:5173 - Gateway:
http://localhost:8080 - Swagger:
http://localhost:8080/swagger-ui/index.html - Eureka:
http://localhost:8761 - Keycloak:
http://localhost:9090 - Grafana:
http://localhost:3000
Eureka admin:
- login:
user - password:
password
Keycloak admin:
- login:
admin - password:
password
Grafana:
- login:
admin - password:
admin
Ученик
- login:
ivanov_i - password:
12345678
Учитель
- login:
teacher_soc - password:
12345678
Админ
- login:
director - password:
12345678
Backend:
cd backend
./gradlew :eureka-server:bootRun
./gradlew :api-gateway:bootRun
./gradlew :user-service:bootRun
./gradlew :academic-service:bootRunWindows PowerShell:
cd backend
.\gradlew.bat :eureka-server:bootRun
.\gradlew.bat :api-gateway:bootRun
.\gradlew.bat :user-service:bootRun
.\gradlew.bat :academic-service:bootRunFrontend:
cd frontend
npm install
npm run dev






















