Основная задача проекта: Разработать приложение для управления коворкинг-пространством. Приложение должно позволять пользователям бронировать рабочие места, конференц-залы, а также управлять бронированиями и просматривать доступность ресурсов.
Т.е. все то, что было описано и проделано на предыдущих шагах:
Снова нужно переписать, но уже с применением Spring (nonBoot).
- Java конфигурация приложения (простой пример, того, как в принципе можно конфигурировать приложения см. SpringWebAppConfig);
- Взаимодействие с внешними потребителями (пользователями, сторонними сервисами) реализовать с применением REST-контроллеров;
- Интегрировать систему документирования Swagger с приложением (описание и варианты интеграции);
- Текущие аспекты адаптировать под Spring AOP, краткую реализацию мы сделали на прошлом мини шаге - SpringAOPAndCo;
- Приложение полностью управляется Spring-ом, контроллеры покрыты тестами;
- Функциональные требования выполнены полностью.
- Технические требования выполнены полностью.
- Тестами (только интеграционные) покрыто более 87% кода.
Данная версия приложения взаимодействует с пользователем (сервисом или другим приложением) по средствам HTTP-запросов и использует в своей реализации Spring (nonBoot). Приложение развертывается в контейнере сервлетов (TomCat).
Скрипты Liquibase при первичном старте создадут необходимые таблицы и предзаполнят их.
Структура проекта (это не Spring проект, но слоистую структуру можно применять где угодно, отсюда и названия):
- annotation - аннотации для аудирования и логирования;
- aspects - аспектные классы (аудит и логирование);
- config:
- data_source - настройка источника данных (связь в БД и т.д.)
- jwt_config - файлы отвечающие за работу аутентификации с применением JWT токена (фильтр и генератор токена);
- main_config - папка с основным конфигурационным файлом;
- security_config - папка с настройкой системы безопасности Spring - SecurityFilterChain;
- security_details - кастомные UserDetails и UserDetailsService;
- swagger - настройка Swagger-a;
- yaml_read_adapter - адаптер для чтения yaml(yml) файлов;
- controllers - классы управляющие сущностями на 'верхнем' уровне приложения;
- dto - классы для передачи данных со слоя на слой;
- exception - исключения и обработчики ошибок;
- mapper - классы сопоставители;
- models - рабочие сущности приложения;
- repository - классы для взаимодействия с БД;
- services - теоретически, данные классы должны аккумулировать основную "бизнес" логику приложения, но, у нас приложение не большое и логика ровненько размазана по всем слоям;
- resources:
- db/changelog - файлы миграции Liquibase;
- application.yml - файл настроек (см. комментарии);
- log4j.xml - конфигурация логера;
Используя наработки сделанные в предыдущем разделе - SpringAndSwagger подключаем Swagger.
Естественно, на сразу доступны две важные точки доступа:
Что значительно упрощает и ускоряет описание (документирование) основных элементов текущего приложения.
Адрес хоста стандартный для локальной машины (порт исходя из настроек TomCat): http://localhost:8080
Естественно при развертке приложения в контейнере, или в локальном TomCat, в полном адресе запроса может появиться имя приложения (папки где оно развернуто), например cw и тогда между адресом хоста и endpoint-ом появится дополнение, например:
http://localhost:8080/cw/api/v1/places/
Не забываем про это!
| Тип запроса | Endpoint | Полный запрос (пример) | Тело запроса | Описание запроса |
|---|---|---|---|---|
| POST | /api/admin/places/update | http://localhost:8080/api/admin/places/update | {"placeId": 1, "species": "WORKPLACE", "placeNumber": 2} | Обновить выбранный Place (Место/Зал) |
| POST | /api/admin/places/delete | http://localhost:8080/api/admin/places/delete | {"species": "HALL", "placeNumber": 5} | Удаление Place (Место/Зал) |
| POST | /api/admin/places/create | http://localhost:8080/api/admin/places/create | {"species": "HALL", "placeNumber": 5} | Создать Place с заданными параметрами |
| GET | /api/places | http://localhost:8080/api/places | Получить список всех Place-ов (залов/рабочих мест) | |
| GET | /api/places/{placeId} | http://localhost:8080/api/places/1 | Посмотреть данные на Place (Место/Зал) по ID | |
| GET | /api/places/species/{species}/number/{placeNumber} | http://localhost:8080/api/places/species/HALL/number/3 | Посмотреть данные Place (Место/Зал) по виду и номеру |
| Тип запроса | Endpoint | Полный запрос (пример) | Тело запроса | Описание запроса |
|---|---|---|---|---|
| POST | /api/admin/slots/update | http://localhost:8080/api/admin/slots/update | {"slotId":"19", "slotNumber":"20", "timeStart":"20:10", "timeFinish":"20:30"} | Обновить выбранный Slot |
| POST | /api/admin/slots/delete | http://localhost:8080/api/admin/slots/delete | {"slotNumber":"20", "timeStart":"20:00", "timeFinish":"21:00"} | Удаление Slot-а |
| POST | /api/admin/slots/create | http://localhost:8080/api/admin/slots/create | {"slotNumber":"20", "timeStart":"20:00", "timeFinish":"21:00"} | Создать Slot с заданными параметрами |
| GET | /api/slots | http://localhost:8080/api/slots | Получить список всех Slot-ов | |
| GET | /api/slots/number/{slotNumber} | http://localhost:8080/api/slots/number/3 | Посмотреть данные Slot-a по его номеру | |
| GET | /api/slots/id/{slotId} | http://localhost:8080/api/slots/id/2 | Посмотреть данные Slot-a по ID |
| Тип запроса | Endpoint | Полный запрос (пример) | Тело запроса | Описание запроса |
|---|---|---|---|---|
| POST | /api/registration | http://localhost:8080/api/registration | {"login":"nameOf", "password":"passOf", "role":"ADMIN"} | Регистрация пользователя |
| POST | /api/login | http://localhost:8080/api/login | {"login":"nameOf", "password":"passOf"} | Аутентификация пользователя в системе |
| POST | /api/admin/users/update | http://localhost:8080/api/admin/users/update | {"userId":"1", "login":"UserUpdate", "password":"4321End", "role":"ADMIN"} | Обновить данные по User-у |
| POST | /api/admin/users/delete | http://localhost:8080/api/admin/users/delete | {"userId":"4", "login":"UserTwo", "password":"1234", "role":"USER"} | Удалить User-a |
| GET | /api/admin/users/all | http://localhost:8080/api/admin/users/all | Получить список всех User-ов |
| Тип запроса | Endpoint | Полный запрос (пример) | Тело запроса | Описание запроса |
|---|---|---|---|---|
| POST | /api/reservations/update | http://localhost:8080/api/reservations/update | {"reservationId": 16, "reservationDate":"2048-03-10", "userId": 2, "placeId": 3, "slotId": 3} | Обновить данные по брони |
| POST | /api/reservations/delete | http://localhost:8080/api/reservations/delete | {"reservationId": 10, "reservationDate":"2027-06-12", "userId": 3, "placeId": 8, "slotId": 4} | Удалить бронь |
| POST | /api/reservations/create | http://localhost:8080/api/reservations/create | {"reservationDate": "2047-08-11", "userId": "3", "placeId": "5", "slotId": "4"} | Создание новой брони |
| GET | /api/reservations | http://localhost:8080/api/reservations | Посмотреть все существующие брони | |
| GET | /api/reservations/free/date/{date} | http://localhost:8080/api/reservations/free/date/{date} | Посмотреть свободные слоты на конкретную дату | |
| GET | /api/reservations/booked | http://localhost:8080/api/reservations/booked | Посмотреть выборку броней по пользователю, дате и месту |
Для тестирования доступа можно использовать, как Postman, так и Swagger.
Приложение для аутентификации используем JWT ключ, посему не забываем его применять. После авторизации сервис (пользователь) получает его в ответ, пример:
Далее при формировании запроса через Postman выбираем тип аутентификации и добавляем полученный JWT ключ в соответствующее поле:
В Swagger нужно проделать ту же операцию - вводим логин и пароль, получаем ответ:
И вводим в специальное поле, после нажатия кнопки Authorize - все защищенные endpoints теперь доступны для изучения:



