Что такое REST
REST не является протоколом, библиотекой или стандартом. Это набор архитектурных принципов и ограничений (constraints), следование которым делает веб-сервисы масштабируемыми, на...
🟢 Junior Level
REST (Representational State Transfer — «передача состояния представления») — это архитектурный стиль взаимодействия компонентов распределенного веб-приложения, сформулированный Роем Филдингом в 2000 году в его докторской диссертации.
REST не является протоколом, библиотекой или стандартом. Это набор архитектурных принципов и ограничений (constraints), следование которым делает веб-сервисы масштабируемыми, надежными, гибкими и производительными.
Ключевые понятия REST
- Ресурс (Resource): Любая сущность в системе, к которой можно обратиться (пользователь, заказ, товар). Ресурс всегда имеет уникальный идентификатор — URI (например,
/api/v1/orders/42). - Представление (Representation): Текущее состояние ресурса, переданное в определенном формате данных (обычно JSON, реже XML).
- Стандартные методы HTTP: Операции над ресурсами выражаются через глаголы протокола HTTP:
GET— чтение ресурса (безопасный и идемпотентный).POST— создание нового ресурса (неидемпотентный).PUT— полная замена ресурса (идемпотентный).PATCH— частичное обновление ресурса (как правило, неидемпотентный).DELETE— удаление ресурса (идемпотентный).
- Статус-коды HTTP: Сервер сообщает о результате операции стандартными трехзначными кодами (
200 OK,201 Created,400 Bad Request,404 Not Found,500 Internal Server Error).
Базовый пример REST-контроллера на Spring Boot 3
package com.example.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// GET /api/v1/users — получить список ресурсов
@GetMapping
public List<UserResponseDto> getAllUsers() {
return userService.findAll();
}
// GET /api/v1/users/{id} — получить конкретный ресурс
@GetMapping("/{id}")
public ResponseEntity<UserResponseDto> getUserById(@PathVariable Long id) {
return ResponseEntity.ok(userService.findById(id));
}
// POST /api/v1/users — создать ресурс
@PostMapping
public ResponseEntity<UserResponseDto> createUser(@RequestBody CreateUserRequest request) {
UserResponseDto created = userService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created); // 201 Created
}
// DELETE /api/v1/users/{id} — удалить ресурс
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT) // 204 No Content
public void deleteUser(@PathVariable Long id) {
userService.deleteById(id);
}
}
🟡 Middle Level
6 архитектурных ограничений REST (Constraints)
Чтобы API считался истинно RESTful, он обязан удовлетворять 6 строгим правилам:
1. Client-Server (Разделение ответственности интерфейса и хранилища)
2. Stateless (Отсутствие состояния сессии клиента на сервере)
3. Cacheable (Явный контроль кэширования ответов клиентом и прокси)
4. Layered System (Многоуровневая система: балансировщики, CDN, шлюзы прозрачны)
5. Uniform Interface (Единообразный интерфейс — фундамент REST)
6. Code on Demand (Опционально: передача исполняемого кода, например JS)
- Client-Server (Клиент-Сервер): Полное разделение интерфейса пользователя (Frontend, Mobile) и бизнес-логики/хранилища (Backend). Они могут эволюционировать и масштабироваться независимо.
- Stateless (Без сохранения состояния): Сервер не хранит контекст сессии клиента между запросами. Каждый запрос обязан содержать абсолютно всю информацию для его авторизации и обработки (например, JWT-токен в заголовке
Authorization). - Cacheable (Кэшируемость): Каждый ответ обязан явно объявлять, можно ли его кэшировать и на какой срок (заголовки
Cache-Control,ETag,Last-Modified), исключая повторные тяжелые запросы. - Layered System (Многоуровневая архитектура): Клиент не знает, общается ли он напрямую с сервером приложений или с промежуточным звеном (Reverse Proxy, Load Balancer, API Gateway, CDN). Промежуточные слои могут обеспечивать безопасность и кэширование без изменения контракта.
- Uniform Interface (Единообразный интерфейс): Самое строгое и главное ограничение REST, состоящее из 4 постулатов:
- Идентификация ресурсов: Ресурсы отделены от их представлений и имеют стабильные URI (
/products/123). - Манипуляция через представления: Клиент передает представление (
JSON) и желаемое действие через HTTP-метод. - Самодостаточные сообщения (Self-descriptive messages): Каждый запрос/ответ содержит метаданные о формате (
Content-Type: application/json), кодировке и кэшировании. - HATEOAS (Hypermedia As The Engine Of Application State): Ответ сервера содержит гиперссылки на доступные последующие действия клиента.
- Идентификация ресурсов: Ресурсы отделены от их представлений и имеют стабильные URI (
- Code on Demand (Код по требованию, опциональное): Сервер может передавать клиенту исполняемый код для временного расширения функциональности (например, JavaScript-сценарии или WebAssembly).
Модель зрелости Ричардсона (Richardson Maturity Model)
Леонард Ричардсон предложил классификацию веб-сервисов по степени их соответствия принципам REST:
Level 3: HATEOAS (Истинный RESTful API)
▲
Level 2: HTTP Verbs & Status Codes (Золотой стандарт индустрии / Pragmatic REST)
▲
Level 1: Ресурсы (Каждый ресурс имеет свой URI: /orders, /users)
▲
Level 0: The Swamp of POX (Один URI, один HTTP-метод, RPC over HTTP, например SOAP или XML-RPC)
- Level 0: Использование HTTP как простого транспорта. Все запросы идут методом
POSTна один эндпоинт/api/service, а действие зашито в тело сообщения. - Level 1 (Resources): Появление уникальных URI для сущностей (
/users/1,/orders), но операции по-прежнему могут выполняться одним методомPOST. - Level 2 (HTTP Verbs & Codes): Корректное использование семантики HTTP: методы
GET,POST,PUT,DELETEи статус-коды200,201,404,500. Это уровень 99% коммерческих «REST API». - Level 3 (HATEOAS): Сервер вместе с данными возвращает ссылки на связанные действия (
_links). Полное соответствие видению Роя Филдинга.
🔴 Senior Level
REST vs Альтернативы: Когда REST является плохим выбором
В современной enterprise-архитектуре REST не является серебряной пулей:
| Технология | Где превосходит REST | Когда выбирать вместо REST |
|---|---|---|
| gRPC (Protocol Buffers) | Межсервисное взаимодействие (East-West traffic). Бинарная сериализация в 5–10 раз быстрее JSON, HTTP/2 multiplexing, строгая кодогенерация. | Высоконагруженная микросервисная сеть с жесткими требованиями к latency (SLA < 10ms). |
| GraphQL | Решает проблемы Over-fetching (лишние поля) и Under-fetching (N+1 HTTP-запросов к разным ресурсам). Клиент сам запрашивает схему. | Сложные клиентские приложения (BFF, Web/Mobile), требующие агрегации сотен разнородных сущностей. |
| WebSockets / RSocket | Двунаправленный постоянный полнодуплексный обмен сообщениями с минимальным оверхедом заголовков. | Real-time чаты, котировки бирж, дашборды с живыми графиками, IoT телеметрия. |
Современный стандарт обработки ошибок: RFC 9457 (Problem Details)
В Spring Boot 3+ стандартизирован универсальный формат сообщений об ошибках REST API:
package com.example.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.net.URI;
import java.time.Instant;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ProblemDetail handleUserNotFound(UserNotFoundException ex) {
// Формирование стандартного Problem Details (RFC 9457)
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(
HttpStatus.NOT_FOUND, ex.getMessage()
);
problemDetail.setTitle("User Not Found");
problemDetail.setType(URI.create("https://api.example.com/errors/not-found"));
problemDetail.setProperty("timestamp", Instant.now());
problemDetail.setProperty("errorCode", "USR-404");
return problemDetail;
}
}
Клиент получает стандартизированный JSON:
{
"type": "https://api.example.com/errors/not-found",
"title": "User Not Found",
"status": 404,
"detail": "User with id 42 does not exist",
"instance": "/api/v1/users/42",
"timestamp": "2026-09-26T12:00:00Z",
"errorCode": "USR-404"
}
Highload-оптимизации REST на Java 21+
- Virtual Threads (Project Loom в Java 21):
- Включение
spring.threads.virtual.enabled=trueпереводит встроенный Tomcat на виртуальные потоки. - Исчезает необходимость переписывать сервисы на реактивный стек (Spring WebFlux) только ради удержания 50 000 параллельных I/O соединений.
- Включение
- HTTP Caching с
ETag(ShallowEtagHeaderFilter):- Сервер рассчитывает MD5-хэш тела ответа и отдает заголовок
ETag: "686897696a7c76". - Клиент при повторном запросе отправляет
If-None-Match: "686897696a7c76". - Сервер мгновенно возвращает
304 Not Modifiedс пустым телом, экономя исходящий трафик и время рендеринга.
- Сервер рассчитывает MD5-хэш тела ответа и отдает заголовок
🎯 Шпаргалка для интервью
30-секундный ответ
REST — это архитектурный стиль построения веб-сервисов поверх протокола HTTP, сформулированный Роем Филдингом в 2000 году.
- Базируется на 6 ограничениях: Client-Server, Stateless, Cacheable, Layered System, Uniform Interface и Code on Demand.
- В центре концепции находится Ресурс, идентифицируемый URI. Операции над ресурсами задаются глаголами HTTP (
GET,POST,PUT,PATCH,DELETE), а состояние передается через форматы представлений (JSON/XML).- По модели зрелости Ричардсона большинство production API находятся на Level 2 (использование ресурсов, HTTP-глаголов и статус-кодов). Истинный Level 3 требует поддержки HATEOAS.
4 каверзных вопроса с ответами
-
Является ли REST протоколом или спецификацией? Ответ: Нет, REST — это архитектурный стиль (набор принципов и ограничений). Протоколом является HTTP, поверх которого обычно реализуется REST. Стандартом или спецификацией REST не является, поэтому разработчики могут адаптировать его под свои нужды (Pragmatic REST).
- Что такое Uniform Interface (Единообразный интерфейс) и из каких 4 частей он состоит?
Ответ: Это центральное ограничение REST, отделяющее архитектуру от других стилей (RPC). Оно включает:
- Идентификацию ресурсов через URI.
- Манипуляцию ресурсами через представления (клиент изменяет ресурс, отправляя JSON).
- Самоописываемые сообщения (наличие метаданных:
Content-Type, заголовки кэширования). - HATEOAS (сервер передает гиперссылки на доступные последующие переходы состояния).
-
В чём разница между RESTful API и обычным HTTP API? Ответ: HTTP API просто использует протокол HTTP как транспорт для передачи данных (часто как RPC, Level 0–1 по Ричардсону). RESTful API строго соблюдает все 6 ограничений стиля REST, включая statelessness, семантику HTTP-глаголов, кэширование и гипермедиа (HATEOAS).
- Когда REST архитектурно проигрывает другим подходам?
Ответ:
- В межсервисном взаимодействии микросервисов с высокими нагрузками — gRPC значительно быстрее из-за бинарного формата Protobuf и мультиплексирования HTTP/2.
- При сложной выборке связанных сущностей для мобильных клиентов — GraphQL решает проблемы Over-fetching и множественных запросов.
- Для real-time данных — WebSockets и RSocket превосходят REST, устраняя оверхед на постоянное открытие HTTP-соединений.
Красные флаги (чего категорически нельзя говорить)
- ❌ «REST — это официальный протокол передачи данных W3C» — это архитектурный стиль диссертации, а не протокол.
- ❌ «Метод GET можно использовать для удаления записи из базы» — грубейшее нарушение REST: метод
GETобязан быть безопасным (Safe) и не иметь побочных эффектов. - ❌ «REST требует обязательного использования формата JSON» — REST не привязан к JSON, он работает с любыми представлениями (XML, HTML, Protocol Buffers, MessagePack).
- ❌ «Сервер REST хранит состояние сессии пользователя в оперативной памяти» — ограничение Stateless строго запрещает хранение клиентской сессии на сервере.