Add OpenAPI spec and Swagger UI docs for Vehicle collection and shop services

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fe9ZVw7Q7JrMz1hgS2rwna
This commit is contained in:
DopleZZ 2026-09-07 15:56:27 +03:00
commit dfd1f365de
2 changed files with 535 additions and 0 deletions

511
openapi/openapi.yaml Normal file
View File

@ -0,0 +1,511 @@
openapi: 3.0.3
info:
title: Vehicle Collection API
version: "1.0.0"
description: >
Набор из двух веб-сервисов: сервис управления коллекцией объектов Vehicle
и сервис /shop, реализующий дополнительные операции над этой коллекцией
через вызовы API первого сервиса.
license:
name: Учебный материал (лабораторная работа по курсу СОА)
servers:
- url: http://127.0.0.1:8080
description: Сервер для разработки и тестирования
tags:
- name: Vehicles
description: Первый веб-сервис — управление коллекцией объектов Vehicle
- name: Shop
description: Второй веб-сервис (/shop) — дополнительные операции над Vehicle
security: []
paths:
/api/vehicles:
post:
tags: [Vehicles]
operationId: createVehicle
summary: Добавить новый элемент в коллекцию
description: >
Создаёт новый объект Vehicle. Поля id и creationDate генерируются
сервисом автоматически и в теле запроса не передаются.
requestBody:
required: true
content:
application/xml:
schema:
$ref: '#/components/schemas/VehicleInput'
responses:
'201':
description: Объект успешно создан
headers:
Location:
description: URL созданного объекта
schema:
type: string
content:
application/xml:
schema:
$ref: '#/components/schemas/Vehicle'
'400':
$ref: '#/components/responses/BadRequest'
get:
tags: [Vehicles]
operationId: getVehicles
summary: Получить массив элементов коллекции
description: >
Возвращает элементы коллекции постранично. Поддерживает сортировку
по любой комбинации полей (параметр sort) и фильтрацию по любой
комбинации полей (параметр filter). Все параметры операции
передаются в URL запроса (query-параметры).
parameters:
- $ref: '#/components/parameters/PageNumber'
- $ref: '#/components/parameters/PageSize'
- $ref: '#/components/parameters/Sort'
- $ref: '#/components/parameters/Filter'
responses:
'200':
description: Страница результатов выборки
content:
application/xml:
schema:
$ref: '#/components/schemas/VehiclePage'
'400':
$ref: '#/components/responses/BadRequest'
/api/vehicles/{id}:
parameters:
- $ref: '#/components/parameters/VehicleId'
get:
tags: [Vehicles]
operationId: getVehicleById
summary: Получить элемент коллекции по ИД
responses:
'200':
description: Найденный объект
content:
application/xml:
schema:
$ref: '#/components/schemas/Vehicle'
'404':
$ref: '#/components/responses/NotFound'
put:
tags: [Vehicles]
operationId: updateVehicle
summary: Обновить элемент коллекции
requestBody:
required: true
content:
application/xml:
schema:
$ref: '#/components/schemas/VehicleInput'
responses:
'200':
description: Объект обновлён
content:
application/xml:
schema:
$ref: '#/components/schemas/Vehicle'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
delete:
tags: [Vehicles]
operationId: deleteVehicle
summary: Удалить элемент коллекции
responses:
'204':
description: Объект удалён
'404':
$ref: '#/components/responses/NotFound'
/api/vehicles/by-type/{type}:
delete:
tags: [Vehicles]
operationId: deleteVehiclesByType
summary: Удалить все объекты с заданным значением поля type
parameters:
- $ref: '#/components/parameters/VehicleTypePath'
responses:
'200':
description: Результат удаления
content:
application/xml:
schema:
$ref: '#/components/schemas/DeletionResult'
'400':
$ref: '#/components/responses/BadRequest'
/api/vehicles/by-type/{type}/any:
delete:
tags: [Vehicles]
operationId: deleteOneVehicleByType
summary: Удалить один (любой) объект с заданным значением поля type
parameters:
- $ref: '#/components/parameters/VehicleTypePath'
responses:
'200':
description: Удалённый объект
content:
application/xml:
schema:
$ref: '#/components/schemas/Vehicle'
'404':
description: Объектов с указанным значением type не найдено
content:
application/xml:
schema:
$ref: '#/components/schemas/Error'
/api/vehicles/count/fuel-type-less-than/{fuelType}:
get:
tags: [Vehicles]
operationId: countVehiclesByFuelTypeLessThan
summary: Вернуть количество объектов, у которых fuelType меньше заданного
description: >
Значения FuelType сравниваются по порядку их объявления в перечислении
(ALCOHOL < MANPOWER < PLASMA < ANTIMATTER). Объекты с fuelType = null
в сравнении не участвуют и не учитываются в результате.
parameters:
- $ref: '#/components/parameters/FuelTypePath'
responses:
'200':
description: Количество подходящих объектов
content:
application/xml:
schema:
$ref: '#/components/schemas/CountResult'
'400':
$ref: '#/components/responses/BadRequest'
/shop/fix-distance/{vehicle-id}:
post:
tags: [Shop]
operationId: fixDistance
summary: "\"Скрутить\" счётчик пробега транспортного средства до нуля"
description: >
Обращается к API первого сервиса и обнуляет счётчик пробега
транспортного средства с заданным id.
parameters:
- $ref: '#/components/parameters/ShopVehicleId'
responses:
'200':
description: Счётчик пробега обнулён
content:
application/xml:
schema:
$ref: '#/components/schemas/ActionResult'
'404':
$ref: '#/components/responses/NotFound'
/shop/add-wheels/{vehicle-id}/{number-of-wheels}:
post:
tags: [Shop]
operationId: addWheels
summary: Добавить транспортному средству указанное число колёс
description: >
Обращается к API первого сервиса и увеличивает число колёс
транспортного средства с заданным id на указанное значение.
parameters:
- $ref: '#/components/parameters/ShopVehicleId'
- $ref: '#/components/parameters/NumberOfWheels'
responses:
'200':
description: Колёса добавлены
content:
application/xml:
schema:
$ref: '#/components/schemas/ActionResult'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
components:
parameters:
VehicleId:
name: id
in: path
required: true
description: Идентификатор объекта Vehicle
schema:
type: integer
format: int64
minimum: 1
ShopVehicleId:
name: vehicle-id
in: path
required: true
description: Идентификатор транспортного средства
schema:
type: integer
format: int64
minimum: 1
NumberOfWheels:
name: number-of-wheels
in: path
required: true
description: Число колёс, которое нужно добавить
schema:
type: integer
format: int32
minimum: 1
VehicleTypePath:
name: type
in: path
required: true
description: Значение поля type
schema:
$ref: '#/components/schemas/VehicleType'
FuelTypePath:
name: fuelType
in: path
required: true
description: Значение поля fuelType, с которым сравниваются объекты коллекции
schema:
$ref: '#/components/schemas/FuelType'
PageNumber:
name: pageNumber
in: query
required: false
description: Порядковый номер выводимой страницы, нумерация начинается с 1
schema:
type: integer
format: int32
minimum: 1
default: 1
PageSize:
name: pageSize
in: query
required: false
description: Размер страницы (количество элементов на странице)
schema:
type: integer
format: int32
minimum: 1
default: 10
Sort:
name: sort
in: query
required: false
description: >
Правило сортировки в формате "поле,направление", где направление —
asc или desc (по умолчанию asc). Параметр можно указать несколько
раз, чтобы отсортировать по нескольким полям сразу — порядок
повторений задаёт приоритет полей. Допустимые имена полей: id, name,
coordinates.x, coordinates.y, creationDate, enginePower, type,
fuelType.
style: form
explode: true
schema:
type: array
items:
type: string
pattern: '^(id|name|coordinates\.x|coordinates\.y|creationDate|enginePower|type|fuelType)(,(asc|desc))?$'
example: ["name,asc"]
Filter:
name: filter
in: query
required: false
description: >
Условие фильтрации в формате "поле:оператор:значение". Поддерживаемые
операторы: eq, ne, gt, gte, lt, lte, like (like — только для строковых
полей, подстрока без учёта регистра). Параметр можно указать
несколько раз — все условия объединяются по И (AND), что позволяет
фильтровать по любой комбинации полей. Для проверки на отсутствие
значения используется литерал null, например enginePower:eq:null.
style: form
explode: true
schema:
type: array
items:
type: string
example: ["type:eq:PLANE"]
responses:
NotFound:
description: Объект с указанным идентификатором не найден
content:
application/xml:
schema:
$ref: '#/components/schemas/Error'
BadRequest:
description: >
Переданные данные нарушают ограничения целостности, заданные на
уровне класса, либо параметры запроса имеют неверный формат
content:
application/xml:
schema:
$ref: '#/components/schemas/Error'
schemas:
VehicleType:
type: string
enum: [PLANE, BOAT, SHIP]
xml:
name: VehicleType
FuelType:
type: string
enum: [ALCOHOL, MANPOWER, PLASMA, ANTIMATTER]
xml:
name: FuelType
Coordinates:
type: object
required: [x, y]
properties:
x:
type: integer
format: int32
y:
type: number
format: float
exclusiveMinimum: true
minimum: -27
xml:
name: Coordinates
Vehicle:
type: object
required: [id, name, coordinates, creationDate]
properties:
id:
type: integer
format: int64
minimum: 1
readOnly: true
name:
type: string
minLength: 1
coordinates:
$ref: '#/components/schemas/Coordinates'
creationDate:
type: string
format: date-time
readOnly: true
enginePower:
type: number
format: double
nullable: true
exclusiveMinimum: true
minimum: 0
type:
type: string
nullable: true
allOf:
- $ref: '#/components/schemas/VehicleType'
fuelType:
type: string
nullable: true
allOf:
- $ref: '#/components/schemas/FuelType'
xml:
name: Vehicle
VehicleInput:
type: object
required: [name, coordinates]
properties:
name:
type: string
minLength: 1
coordinates:
$ref: '#/components/schemas/Coordinates'
enginePower:
type: number
format: double
nullable: true
exclusiveMinimum: true
minimum: 0
type:
type: string
nullable: true
allOf:
- $ref: '#/components/schemas/VehicleType'
fuelType:
type: string
nullable: true
allOf:
- $ref: '#/components/schemas/FuelType'
xml:
name: Vehicle
VehiclePage:
type: object
properties:
pageNumber:
type: integer
format: int32
pageSize:
type: integer
format: int32
totalElements:
type: integer
format: int64
totalPages:
type: integer
format: int32
items:
type: array
items:
$ref: '#/components/schemas/Vehicle'
xml:
name: vehicle
wrapped: true
xml:
name: VehiclePage
DeletionResult:
type: object
properties:
deletedCount:
type: integer
format: int64
xml:
name: DeletionResult
CountResult:
type: object
properties:
count:
type: integer
format: int64
xml:
name: CountResult
ActionResult:
type: object
properties:
vehicleId:
type: integer
format: int64
message:
type: string
xml:
name: ActionResult
Error:
type: object
properties:
timestamp:
type: string
format: date-time
status:
type: integer
format: int32
error:
type: string
message:
type: string
path:
type: string
xml:
name: Error

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Vehicle Collection API — документация</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css">
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
<script>
window.onload = function () {
SwaggerUIBundle({
url: "../openapi.yaml",
dom_id: "#swagger-ui",
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
]
});
};
</script>
</body>
</html>