← Назад к вопросам

Какие знаешь характеристики у REST?

1.8 Middle🔥 211 комментариев
#REST API и микросервисы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Характеристики REST архитектуры

REST (Representational State Transfer) — это архитектурный стиль для проектирования сетевых приложений. Разработан Роем Филдингом в 2000 году и основан на принципах веб-стандартов. REST определяет набор ключевых характеристик, которые делают API предсказуемым, масштабируемым и поддерживаемым.

1. Архитектурные ограничения REST

REST состоит из шести ограничений (constraints), которые определяют его суть:

Клиент-сервер (Client-Server)

Архитектура разделена на две независимые части:

  • Клиент отправляет запросы
  • Сервер обрабатывает запросы и отправляет ответы

Это позволяет клиентам и серверам развиваться независимо:

// Клиент отправляет запрос
GET /api/v1/users/123 HTTP/1.1
Host: example.com

// Сервер обрабатывает и возвращает ответ
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 123, "name": "John Doe"}

Statelessness (Отсутствие состояния)

Каждый запрос содержит полную информацию, необходимую серверу для обработки. Сервер не хранит контекст клиента между запросами:

// Запрос 1: сервер создаёт сессию
POST /api/v1/auth/login
{"username": "john", "password": "secret"}
→ Ответ: {"token": "eyJhbGc..."}

// Запрос 2: клиент отправляет токен в каждом запросе
GET /api/v1/users/me
Authorization: Bearer eyJhbGc...

Преимущества:

  • Простая масштабируемость (можно добавлять серверы без синхронизации состояния)
  • Надёжность (сервер может перезагрузиться без потери данных клиента)
  • Предсказуемость

Кэшируемость (Cacheability)

Ответы должны явно помечаться как кэшируемые или не кэшируемые. Это снижает нагрузку на сервер:

// Кэшируемый ответ (например, данные о продукте)
GET /api/v1/products/42
HTTP/1.1 200 OK
Cache-Control: max-age=3600  // кэш на 1 час
ETag: "123abc"
Content-Type: application/json
{"id": 42, "name": "Laptop", "price": 999}

// Не кэшируемый ответ (текущий баланс счета)
GET /api/v1/accounts/balance
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store
{"balance": 5000.00}

Механизмы кэширования:

  • Cache-Control — время жизни кэша
  • ETag — уникальный идентификатор версии ресурса
  • Last-Modified — дата последнего изменения

Единая система интерфейсов (Uniform Interface)

Все компоненты используют единый интерфейс, что упрощает взаимодействие и эволюцию системы. Состоит из четырёх подограничений:

a) Идентификация ресурсов в запросе:

GET /api/v1/users/42
GET /api/v1/posts/abc-def
GET /api/v1/comments/uuid

Каждый ресурс имеет уникальный URI.

b) Манипулирование ресурсами через представление (Representation):

// GET — получить представление ресурса
GET /api/v1/users/42
{"id": 42, "name": "John", "email": "john@example.com"}

// PUT — обновить ресурс через представление
PUT /api/v1/users/42
{"id": 42, "name": "John Smith", "email": "john@example.com"}

// DELETE — удалить ресурс
DELETE /api/v1/users/42

c) Самоописывающиеся сообщения (Self-descriptive Messages): Каждое сообщение содержит достаточно информации для интерпретации:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 234
Cache-Control: max-age=300

{"id": 42, "name": "John", "created_at": "2024-01-15T10:30:00Z"}

// Content-Type говорит формат (JSON)
// Cache-Control говорит как кэшировать
// Status код 200 говорит об успехе

d) HATEOAS (Hypermedia As The Engine Of Application State): Ответы содержат ссылки для выполнения доступных операций:

GET /api/v1/users/42
HTTP/1.1 200 OK
{
  "id": 42,
  "name": "John",
  "_links": {
    "self": {"href": "/api/v1/users/42"},
    "all_users": {"href": "/api/v1/users"},
    "edit": {"href": "/api/v1/users/42", "method": "PUT"},
    "delete": {"href": "/api/v1/users/42", "method": "DELETE"}
  }
}

Это позволяет клиентам обнаруживать доступные операции без знания API заранее.

Слоистая система (Layered System)

Архитектура может быть организована в слои, каждый со своей ответственностью. Клиент не знает, общается ли с прямым сервером или через промежуточные слои (кэш, балансировщик нагрузки, API шлюз):

Клиент → API Gateway → Load Balancer → Сервер 1
                     ↓                 → Сервер 2
                    Кэш               → Сервер 3

Код по требованию (Code on Demand) — ОПЦИОНАЛЬНО

Сервер может отправлять исполняемый код (JavaScript, applet) для расширения функциональности клиента. Это опциональное ограничение, редко используется в современных REST API:

// Сервер возвращает JavaScript для обработки на клиенте
GET /api/v1/script
HTTP/1.1 200 OK
Content-Type: application/javascript

function processData(data) { ... }

2. Основные HTTP методы в REST

REST использует стандартные HTTP методы для операций над ресурсами:

// CREATE — создание нового ресурса
POST /api/v1/users
{"name": "Alice", "email": "alice@example.com"}
→ 201 Created
{"id": 99, "name": "Alice", "email": "alice@example.com"}

// READ — получение ресурса
GET /api/v1/users/99200 OK
{"id": 99, "name": "Alice", "email": "alice@example.com"}

// UPDATE — обновление ресурса (полное)
PUT /api/v1/users/99
{"name": "Alice Smith", "email": "alice.smith@example.com"}
→ 200 OK или 204 No Content

// PATCH — частичное обновление
PATCH /api/v1/users/99
{"email": "newemail@example.com"}
→ 200 OK

// DELETE — удаление ресурса
DELETE /api/v1/users/99204 No Content

3. HTTP статус коды

REST использует стандартные HTTP статус коды для передачи результата:

  • 2xx — Успех

    • 200 OK — запрос успешен, возвращены данные
    • 201 Created — ресурс создан
    • 204 No Content — успешно, но нет содержимого для возврата
  • 4xx — Ошибка клиента

    • 400 Bad Request — неверный формат запроса
    • 401 Unauthorized — требуется аутентификация
    • 403 Forbidden — нет прав доступа
    • 404 Not Found — ресурс не найден
    • 409 Conflict — конфликт (например, дублирование)
  • 5xx — Ошибка сервера

    • 500 Internal Server Error
    • 503 Service Unavailable

4. Характеристики хорошего REST API

  • Ориентирован на ресурсы: имена существительные, а не глаголы (/users/42, не /getUser/42)
  • Версионирование: /api/v1/, /api/v2/ для совместимости
  • Представлении агностичен: JSON, XML, YAML — формат зависит от Content-Type
  • Предсказуемость: URL структура логична и консистентна
  • Безопасность: HTTPS, аутентификация, авторизация
  • Пагинация: GET /api/v1/users?page=1&limit=20
  • Фильтрация: GET /api/v1/users?status=active&role=admin
  • Сортировка: GET /api/v1/users?sort=name&order=asc

5. Примеры на Java (Spring Boot)

@RestController
@RequestMapping("/api/v1/users")
public class UserController {
    
    // GET — получение всех пользователей (с фильтрацией и пагинацией)
    @GetMapping
    public ResponseEntity<List<User>> getAllUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int limit) {
        // Ресурс кэшируется на 5 минут
        return ResponseEntity.ok()
                .cacheControl(CacheControl.maxAge(5, TimeUnit.MINUTES))
                .body(userService.findAll(page, limit));
    }
    
    // GET — получение конкретного пользователя
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userService.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User not found"));
        return ResponseEntity.ok(user);
    }
    
    // POST — создание нового пользователя
    @PostMapping
    public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
        User created = userService.save(user);
        return ResponseEntity
                .created(URI.create("/api/v1/users/" + created.getId()))
                .body(created);
    }
    
    // PUT — полное обновление пользователя
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(
            @PathVariable Long id,
            @Valid @RequestBody User user) {
        User updated = userService.update(id, user);
        return ResponseEntity.ok(updated);
    }
    
    // PATCH — частичное обновление
    @PatchMapping("/{id}")
    public ResponseEntity<User> patchUser(
            @PathVariable Long id,
            @RequestBody Map<String, Object> updates) {
        User patched = userService.patch(id, updates);
        return ResponseEntity.ok(patched);
    }
    
    // DELETE — удаление пользователя
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.deleteById(id);
        return ResponseEntity.noContent().build();
    }
}

Заключение

REST — это не просто способ создания API, это набор архитектурных принципов, которые обеспечивают:

  • Масштабируемость
  • Простоту понимания
  • Надёжность
  • Гибкость
  • Совместимость со стандартами веба

Понимание этих характеристик критично для разработки профессиональных и поддерживаемых веб-сервисов на Java.