← Назад к вопросам
Как создать обработчик HTTP запросов в Spring?
1.0 Junior🔥 221 комментариев
#REST API и микросервисы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Создание обработчика HTTP запросов в Spring
Spring предоставляет мощный инструмент для обработки HTTP запросов через контроллеры. Рассмотрим несколько подходов от простого к сложному.
1. Простой контроллер с аннотациями
Самый распространенный и рекомендуемый подход — использование @RestController или @Controller с @ResponseBody:
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// GET запрос
@GetMapping("/{id}")
public ResponseEntity<UserDto> getUserById(@PathVariable Long id) {
UserDto user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
// POST запрос
@PostMapping
public ResponseEntity<UserDto> createUser(@RequestBody CreateUserRequest request) {
UserDto newUser = userService.createUser(request);
return ResponseEntity
.status(HttpStatus.CREATED)
.body(newUser);
}
// PUT запрос
@PutMapping("/{id}")
public ResponseEntity<UserDto> updateUser(
@PathVariable Long id,
@RequestBody UpdateUserRequest request) {
UserDto updated = userService.updateUser(id, request);
return ResponseEntity.ok(updated);
}
// DELETE запрос
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
// GET с query параметрами
@GetMapping
public ResponseEntity<List<UserDto>> getAllUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int pageSize,
@RequestParam(required = false) String email) {
List<UserDto> users = userService.getUsers(page, pageSize, email);
return ResponseEntity.ok(users);
}
}
2. Использование @Controller с ResponseBody
Это более явный способ:
@Controller
@RequestMapping("/api/v1/products")
public class ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
@GetMapping("/{id}")
@ResponseBody
public ProductDto getProduct(@PathVariable Long id) {
return productService.getProductById(id);
}
@PostMapping
@ResponseBody
public ResponseEntity<ProductDto> createProduct(@RequestBody CreateProductRequest request) {
ProductDto product = productService.createProduct(request);
return new ResponseEntity<>(product, HttpStatus.CREATED);
}
}
3. Обработка различных типов параметров
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
// Path variable — часть URL
@GetMapping("/{orderId}/items/{itemId}")
public ResponseEntity<OrderItemDto> getOrderItem(
@PathVariable Long orderId,
@PathVariable Long itemId) {
OrderItemDto item = orderService.getOrderItem(orderId, itemId);
return ResponseEntity.ok(item);
}
// Request body — JSON в теле запроса
@PostMapping
public ResponseEntity<OrderDto> createOrder(@RequestBody CreateOrderRequest request) {
OrderDto order = orderService.createOrder(request);
return ResponseEntity.status(HttpStatus.CREATED).body(order);
}
// Query параметры — ?param=value
@GetMapping
public ResponseEntity<Page<OrderDto>> getOrders(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(required = false) String status,
@RequestParam(required = false) LocalDate fromDate) {
Page<OrderDto> orders = orderService.getOrders(page, size, status, fromDate);
return ResponseEntity.ok(orders);
}
// Headers
@PostMapping("/callback")
public ResponseEntity<Void> handleCallback(
@RequestBody String payload,
@RequestHeader("X-Signature") String signature,
@RequestHeader("X-Timestamp") Long timestamp) {
orderService.processCallback(payload, signature, timestamp);
return ResponseEntity.ok().build();
}
}
4. Правильное обеспечение зависимостей
@RestController
@RequestMapping("/api/v1/auth")
public class AuthController {
private final AuthService authService;
private final JwtTokenProvider jwtTokenProvider;
// Конструктор для инъекции зависимостей (рекомендуется)
public AuthController(AuthService authService, JwtTokenProvider jwtTokenProvider) {
this.authService = authService;
this.jwtTokenProvider = jwtTokenProvider;
}
@PostMapping("/login")
public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest request) {
User user = authService.authenticate(request.getEmail(), request.getPassword());
String token = jwtTokenProvider.generateToken(user);
return ResponseEntity.ok(new LoginResponse(token));
}
}
5. Обработка исключений
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public ResponseEntity<UserDto> getUser(@PathVariable Long id) {
try {
UserDto user = userService.getUserById(id);
return ResponseEntity.ok(user);
} catch (UserNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
}
}
// Лучший подход — глобальный обработчик ошибок
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException e) {
ErrorResponse error = new ErrorResponse("USER_NOT_FOUND", e.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(ValidationException.class)
public ResponseEntity<ErrorResponse> handleValidation(ValidationException e) {
ErrorResponse error = new ErrorResponse("VALIDATION_ERROR", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGenericException(Exception e) {
ErrorResponse error = new ErrorResponse("INTERNAL_ERROR", "Внутренняя ошибка сервера");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
6. Настройка в application.properties
# Сканирование компонентов
spring.application.name=my-api
spring.profiles.active=dev
# Контекст приложения
server.servlet.context-path=/api
server.port=8080
# MVC конфигурация
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false
7. Конфигурация Spring Boot приложения
@SpringBootApplication
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
// Настройка WebMvcConfigurer для кастомизации MVC
@Configuration
public static class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor());
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE");
}
}
}
Рекомендации
- Используй @RestController для REST API (вместо @Controller + @ResponseBody)
- Инъекция через конструктор — это чище и безопаснее, чем @Autowired
- Возвращай ResponseEntity для полного контроля над статус кодом и headers
- Группируй endpoints по ресурсам с @RequestMapping на уровне класса
- Обрабатывай исключения глобально через @RestControllerAdvice
- Валидируй входные данные через @Valid и Validator
- Документируй API через Swagger/OpenAPI аннотации
Этот подход позволяет создавать чистые, масштабируемые REST API с Spring.