Какие использовали методы в @RestController
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
HTTP методы в @RestController
@RestController в Spring Framework позволяет создавать REST API с использованием различных HTTP методов. Каждый метод имеет свою семантику и применяется в определённых сценариях.
REST контроллер
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@Autowired
private UserService userService;
// HTTP методы будут рассмотрены ниже
}
1. GET - Получение ресурсов
GET — безопасный и идемпотентный метод для получения данных БЕЗ изменения состояния сервера.
// Получение всех пользователей
@GetMapping
public ResponseEntity<List<UserDTO>> getAllUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
return ResponseEntity.ok(userService.getUsers(page, size));
}
// Получение по ID
@GetMapping("/{id}")
public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) {
return userService.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
// С query параметрами
@GetMapping("/search")
public ResponseEntity<List<UserDTO>> searchUsers(
@RequestParam String email,
@RequestParam(required = false) String name) {
return ResponseEntity.ok(userService.search(email, name));
}
// Несколько path параметров
@GetMapping("/organizations/{orgId}/users/{userId}")
public ResponseEntity<UserDTO> getUserFromOrganization(
@PathVariable Long orgId,
@PathVariable Long userId) {
return ResponseEntity.ok(userService.getByIdInOrg(orgId, userId));
}
Характеристики GET:
- Безопасен: не изменяет состояние
- Идемпотентен: несколько запросов = один запрос
- Кешируется: браузеры и прокси кешируют GET запросы
- HTTP коды: 200 OK, 404 Not Found, 400 Bad Request
- Нет body: параметры в URL
2. POST - Создание ресурсов
POST — создаёт новый ресурс на сервере. НЕ идемпотентен (каждый запрос создаёт новый ресурс).
// Создание пользователя
@PostMapping
public ResponseEntity<UserDTO> createUser(@RequestBody CreateUserRequest request) {
UserDTO user = userService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}
// Или с URI нового ресурса
@PostMapping
public ResponseEntity<UserDTO> createUserWithLocation(@RequestBody CreateUserRequest request) {
UserDTO user = userService.create(request);
return ResponseEntity
.created(URI.create("/api/v1/users/" + user.getId()))
.body(user);
}
// С валидацией
@PostMapping
public ResponseEntity<UserDTO> createValidatedUser(
@Valid @RequestBody CreateUserRequest request) {
UserDTO user = userService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}
// Batch операция
@PostMapping("/batch")
public ResponseEntity<List<UserDTO>> createUsers(
@RequestBody List<CreateUserRequest> requests) {
List<UserDTO> users = userService.createBatch(requests);
return ResponseEntity.status(HttpStatus.CREATED).body(users);
}
Характеристики POST:
- Не идемпотентен: каждый запрос может создать новый ресурс
- Имеет body: данные в теле запроса (JSON, XML, etc.)
- HTTP коды: 201 Created, 400 Bad Request, 409 Conflict
- Может иметь Location header: указывает URI нового ресурса
- Используется для: создание, отправка форм, запуск операций
3. PUT - Полное обновление ресурса
PUT — полностью заменяет ресурс. Идемпотентен (несколько запросов = один запрос).
// Полное обновление пользователя
@PutMapping("/{id}")
public ResponseEntity<UserDTO> updateUser(
@PathVariable Long id,
@RequestBody UpdateUserRequest request) {
UserDTO updated = userService.updateFully(id, request);
return ResponseEntity.ok(updated);
}
// С проверкой существования
@PutMapping("/{id}")
public ResponseEntity<UserDTO> updateUserIfExists(
@PathVariable Long id,
@RequestBody UpdateUserRequest request) {
try {
UserDTO updated = userService.updateFully(id, request);
return ResponseEntity.ok(updated);
} catch (UserNotFoundException e) {
// PUT может также создать ресурс, если его нет
UserDTO created = userService.createWithId(id, request);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
}
// Обновление с предусловием (ETag)
@PutMapping("/{id}")
public ResponseEntity<UserDTO> updateUserWithETag(
@PathVariable Long id,
@RequestBody UpdateUserRequest request,
@RequestHeader("If-Match") String etag) {
UserDTO updated = userService.updateIfMatch(id, request, etag);
return ResponseEntity.ok(updated);
}
Характеристики PUT:
- Идемпотентен: несколько запросов = один запрос
- Полное обновление: заменяет весь ресурс
- Имеет body: полные данные ресурса
- HTTP коды: 200 OK, 201 Created, 204 No Content, 400 Bad Request
- Может создать: если ресурс не существует
4. PATCH - Частичное обновление ресурса
PATCH — частично обновляет ресурс. Обновляет только переданные поля.
// Частичное обновление
@PatchMapping("/{id}")
public ResponseEntity<UserDTO> partialUpdate(
@PathVariable Long id,
@RequestBody Map<String, Object> updates) {
UserDTO updated = userService.updatePartially(id, updates);
return ResponseEntity.ok(updated);
}
// С DTO для частичного обновления
@PatchMapping("/{id}")
public ResponseEntity<UserDTO> partialUpdateWithDTO(
@PathVariable Long id,
@RequestBody PatchUserRequest request) {
UserDTO updated = userService.patchUser(id, request);
return ResponseEntity.ok(updated);
}
// Пример DTO с Optional полями
public class PatchUserRequest {
private Optional<String> name;
private Optional<String> email;
private Optional<String> phone;
// getters, setters, constructors
}
// Использование
public UserDTO patchUser(Long id, PatchUserRequest request) {
User user = userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found"));
request.getName().ifPresent(user::setName);
request.getEmail().ifPresent(user::setEmail);
request.getPhone().ifPresent(user::setPhone);
return userRepository.save(user);
}
Характеристики PATCH:
- Частичное обновление: только переданные поля
- Менее строгий чем PUT: можно обновить один field
- Имеет body: только измененные данные
- HTTP коды: 200 OK, 204 No Content, 400 Bad Request
- JSON Patch стандарт: RFC 6902 для стандартизации
5. DELETE - Удаление ресурса
DELETE — удаляет ресурс. Идемпотентен.
// Простое удаление
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
// С проверкой существования
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteUserIfExists(@PathVariable Long id) {
try {
userService.delete(id);
return ResponseEntity.noContent().build();
} catch (UserNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
// Мягкое удаление (soft delete)
@DeleteMapping("/{id}")
public ResponseEntity<Void> softDeleteUser(@PathVariable Long id) {
userService.softDelete(id); // Отмечает как удалённый
return ResponseEntity.noContent().build();
}
// Batch удаление
@DeleteMapping
public ResponseEntity<Void> deleteUsers(@RequestBody List<Long> ids) {
userService.deleteAll(ids);
return ResponseEntity.noContent().build();
}
Характеристики DELETE:
- Идемпотентен: несколько удалений = одно удаление
- Может вернуть 404: если ресурс уже удалён
- HTTP коды: 200 OK, 204 No Content, 404 Not Found
- Нет гарантий: сервер может не удалить физически
- Обычно возвращает: 204 No Content
6. HEAD - Как GET, но без тела
HEAD — как GET, но возвращает только заголовки БЕЗ тела ответа.
// Проверка существования ресурса
@HeadMapping("/{id}")
public ResponseEntity<Void> userExists(@PathVariable Long id) {
return userService.exists(id)
? ResponseEntity.ok().build()
: ResponseEntity.notFound().build();
}
// Проверка последнего изменения
@HeadMapping("/{id}")
public ResponseEntity<Void> getUserHeaders(@PathVariable Long id) {
UserDTO user = userService.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found"));
return ResponseEntity.ok()
.lastModified(user.getLastModified())
.eTag(calculateETag(user))
.build();
}
Характеристики HEAD:
- Как GET: но без тела ответа
- Быстрее: меньше передачи данных
- Проверка: существует ли ресурс
- Заголовки: возвращаются полностью (Content-Length, ETag, etc.)
7. OPTIONS - Информация о методах
OPTIONS — возвращает информацию о допустимых методах для ресурса.
// Spring обычно генерирует автоматически
@OptionsMapping("/")
public ResponseEntity<Void> describeOptions() {
return ResponseEntity.ok()
.allow(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT,
HttpMethod.PATCH, HttpMethod.DELETE, HttpMethod.OPTIONS)
.build();
}
// CORS preflight запросы
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
.allowedHeaders("*")
.maxAge(3600);
}
}
Сравнительная таблица
| Метод | Безопасен | Идемпотентен | Body | Кеш | Используется для |
|---|---|---|---|---|---|
| GET | Да | Да | Нет | Да | Получение данных |
| POST | Нет | Нет | Да | Нет | Создание ресурса |
| PUT | Нет | Да | Да | Нет | Полное обновление |
| PATCH | Нет | Нет* | Да | Нет | Частичное обновление |
| DELETE | Нет | Да | Нет | Нет | Удаление ресурса |
| HEAD | Да | Да | Нет | Да | Проверка метаданных |
| OPTIONS | Да | Да | Нет | Нет | Описание методов |
*PATCH может быть идемпотентен в зависимости от реализации
HTTP коды ответов
@GetMapping("/{id}")
public ResponseEntity<?> handleRequest(@PathVariable Long id) {
// 2xx Success
return ResponseEntity.ok(data); // 200 OK
return ResponseEntity.status(HttpStatus.CREATED) // 201 Created
.body(data);
return ResponseEntity.noContent().build(); // 204 No Content
// 3xx Redirection
return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY) // 301
.location(URI.create("/new-url"))
.build();
// 4xx Client Error
return ResponseEntity.badRequest().body(error); // 400
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();// 401
return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); // 403
return ResponseEntity.notFound().build(); // 404
// 5xx Server Error
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) // 500
.body(error);
}
Лучшие практики
- Используй правильный метод: GET для чтения, POST для создания, PUT/PATCH для обновления, DELETE для удаления
- Возвращай правильные коды: 201 при создании, 204 при удалении, 400 при ошибке
- Идемпотентность: PUT и DELETE должны быть идемпотентны
- URL как существительные:
/users, не/getUsersили/deleteUser - Версионирование API:
/api/v1/users - Валидация: используй @Valid для DTO
- Обработка ошибок: ControllerAdvice для глобальной обработки
- CORS: настрой правильно для cross-origin запросов
Правильное использование HTTP методов — это основа хорошего REST API дизайна.