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

Как создать обработчик 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");
        }
    }
}

Рекомендации

  1. Используй @RestController для REST API (вместо @Controller + @ResponseBody)
  2. Инъекция через конструктор — это чище и безопаснее, чем @Autowired
  3. Возвращай ResponseEntity для полного контроля над статус кодом и headers
  4. Группируй endpoints по ресурсам с @RequestMapping на уровне класса
  5. Обрабатывай исключения глобально через @RestControllerAdvice
  6. Валидируй входные данные через @Valid и Validator
  7. Документируй API через Swagger/OpenAPI аннотации

Этот подход позволяет создавать чистые, масштабируемые REST API с Spring.

Как создать обработчик HTTP запросов в Spring? | PrepBro