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

Какие знаешь аннотации контроллеров с дополнительным словом?

1.7 Middle🔥 181 комментариев
#Spring Framework

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

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

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

Аннотации контроллеров с дополнительным словом в Spring

В Spring Framework существует большое количество аннотаций для работы с контроллерами. Аннотации с дополнительным словом обычно предоставляют более специфичную функциональность. Давайте разберём самые важные из них.

Основные аннотации контроллеров

// @Controller — базовая аннотация для контроллеров (возвращает имя представления)
@Controller
public class UserViewController {
    
    @GetMapping("/users")
    public String showUsers(Model model) {
        model.addAttribute("users", userService.getAll());
        return "users/list"; // имя представления (HTML шаблон)
    }
}

// @RestController — контроллер для REST API (возвращает JSON)
@RestController
@RequestMapping("/api/users")
public class UserRestController {
    
    @GetMapping
    public List<UserDTO> getUsers() {
        return userService.getAll();
    }
}

// @RepositoryRestController — специализированный контроллер для работы с репозиториями
@RepositoryRestController
@RequestMapping("/api/custom-users")
public class CustomUserController {
    
    @Autowired
    private UserRepository userRepository;
    
    @GetMapping("/special")
    public ResponseEntity<List<User>> getSpecialUsers() {
        return ResponseEntity.ok(userRepository.findSpecialUsers());
    }
}

Аннотации для маршрутизации HTTP методов

@RestController
@RequestMapping("/api/products")
public class ProductController {
    
    @Autowired
    private ProductService productService;
    
    // @GetMapping — обработка GET запросов (получение данных)
    @GetMapping
    public List<ProductDTO> getAllProducts() {
        return productService.getAll();
    }
    
    @GetMapping("/{id}")
    public ProductDTO getProduct(@PathVariable Long id) {
        return productService.getById(id);
    }
    
    // @PostMapping — обработка POST запросов (создание данных)
    @PostMapping
    public ResponseEntity<ProductDTO> createProduct(
        @RequestBody CreateProductRequest request
    ) {
        Product product = productService.create(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(new ProductDTO(product));
    }
    
    // @PutMapping — обработка PUT запросов (полное обновление)
    @PutMapping("/{id}")
    public ResponseEntity<ProductDTO> updateProduct(
        @PathVariable Long id,
        @RequestBody UpdateProductRequest request
    ) {
        Product product = productService.update(id, request);
        return ResponseEntity.ok(new ProductDTO(product));
    }
    
    // @PatchMapping — обработка PATCH запросов (частичное обновление)
    @PatchMapping("/{id}/status")
    public ResponseEntity<ProductDTO> updateStatus(
        @PathVariable Long id,
        @RequestBody UpdateStatusRequest request
    ) {
        Product product = productService.updateStatus(id, request.getStatus());
        return ResponseEntity.ok(new ProductDTO(product));
    }
    
    // @DeleteMapping — обработка DELETE запросов (удаление данных)
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
        productService.delete(id);
        return ResponseEntity.noContent().build();
    }
}

Аннотации для параметров запроса

@RestController
@RequestMapping("/api/search")
public class SearchController {
    
    @Autowired
    private SearchService searchService;
    
    // @RequestParam — для параметров строки запроса
    @GetMapping("/users")
    public List<UserDTO> searchUsers(
        @RequestParam(name = "query", required = false) String query,
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "20") int size
    ) {
        return searchService.searchUsers(query, page, size);
    }
    // GET /api/search/users?query=john&page=1&size=50
    
    // @PathVariable — для параметров пути URL
    @GetMapping("/users/{id}/orders/{orderId}")
    public OrderDTO getUserOrder(
        @PathVariable Long id,
        @PathVariable Long orderId
    ) {
        return searchService.getUserOrder(id, orderId);
    }
    // GET /api/search/users/123/orders/456
    
    // @RequestHeader — для заголовков HTTP
    @GetMapping("/protected")
    public ResponseEntity<DataDTO> getProtectedData(
        @RequestHeader("Authorization") String authToken,
        @RequestHeader(value = "X-API-Key", required = false) String apiKey
    ) {
        return ResponseEntity.ok(searchService.getProtectedData(authToken, apiKey));
    }
    
    // @RequestBody — для тела запроса (обычно JSON)
    @PostMapping("/advanced")
    public List<ResultDTO> advancedSearch(
        @RequestBody AdvancedSearchRequest request
    ) {
        return searchService.advancedSearch(request);
    }
    
    // @RequestAttribute — для атрибутов запроса (установленных фильтрами/интерцепторами)
    @GetMapping("/user-data")
    public UserDTO getUserData(
        @RequestAttribute("userId") Long userId
    ) {
        return searchService.getUserData(userId);
    }
    
    // @CookieValue — для значений cookie
    @GetMapping("/user-session")
    public ResponseEntity<SessionDTO> getUserSession(
        @CookieValue("JSESSIONID") String sessionId
    ) {
        return ResponseEntity.ok(searchService.getSession(sessionId));
    }
}

Аннотации для обработки исключений

// @ExceptionHandler — обработчик исключений в контроллере
@RestController
@RequestMapping("/api/items")
public class ItemController {
    
    @Autowired
    private ItemService itemService;
    
    @GetMapping("/{id}")
    public ItemDTO getItem(@PathVariable Long id) {
        return itemService.getById(id);
    }
    
    @ExceptionHandler(ItemNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleItemNotFound(ItemNotFoundException e) {
        ErrorResponse error = new ErrorResponse("Item not found", e.getMessage());
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
    }
    
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<ErrorResponse> handleIllegalArgument(IllegalArgumentException e) {
        ErrorResponse error = new ErrorResponse("Invalid argument", e.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
    }
}

// @ControllerAdvice — глобальный обработчик исключений
@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(EntityNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleEntityNotFound(EntityNotFoundException e) {
        ErrorResponse error = new ErrorResponse("Resource not found", e.getMessage());
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
    }
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGlobalException(Exception e) {
        ErrorResponse error = new ErrorResponse("Internal server error", e.getMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
    }
}

// @RestControllerAdvice — комбинация @ControllerAdvice и @ResponseBody
@RestControllerAdvice
public class RestExceptionHandler {
    
    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<ValidationErrorResponse> handleValidation(
        ValidationException e,
        HttpServletRequest request
    ) {
        ValidationErrorResponse error = new ValidationErrorResponse(
            "Validation failed",
            e.getErrors(),
            request.getRequestURI()
        );
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
    }
}

Аннотации для кросс-доменных запросов

// @CrossOrigin — разрешение CORS для определённых источников
@RestController
@RequestMapping("/api/public")
public class PublicApiController {
    
    @CrossOrigin(origins = "https://example.com", maxAge = 3600)
    @GetMapping("/data")
    public DataDTO getPublicData() {
        return new DataDTO("public");
    }
    
    // Или на уровне класса
}

@RestController
@RequestMapping("/api/shared")
@CrossOrigin(origins = {"https://frontend.com", "https://mobile.com"}, maxAge = 7200)
public class SharedApiController {
    
    @GetMapping("/info")
    public InfoDTO getSharedInfo() {
        return new InfoDTO();
    }
}

Аннотации для валидации

@RestController
@RequestMapping("/api/orders")
public class OrderController {
    
    @PostMapping
    public ResponseEntity<OrderDTO> createOrder(
        @Valid @RequestBody CreateOrderRequest request // @Valid включает валидацию
    ) {
        Order order = orderService.create(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(new OrderDTO(order));
    }
    
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ValidationErrorResponse> handleValidationException(
        MethodArgumentNotValidException e
    ) {
        List<String> errors = e.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(error -> error.getField() + ": " + error.getDefaultMessage())
            .collect(Collectors.toList());
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
            .body(new ValidationErrorResponse("Validation failed", errors));
    }
}

// Класс с валидацией
public class CreateOrderRequest {
    
    @NotBlank(message = "Order number is required")
    private String orderNumber;
    
    @NotNull(message = "Amount is required")
    @Min(value = 1, message = "Amount must be greater than 0")
    private BigDecimal amount;
    
    @Email(message = "Invalid email format")
    private String customerEmail;
    
    // getters and setters
}

Аннотации для документирования API (Swagger/OpenAPI)

@RestController
@RequestMapping("/api/products")
@Tag(name = "Products", description = "API для управления товарами")
public class ProductApiController {
    
    @GetMapping("/{id}")
    @Operation(summary = "Получить товар по ID", description = "Возвращает информацию о товаре")
    @ApiResponse(responseCode = "200", description = "Товар найден")
    @ApiResponse(responseCode = "404", description = "Товар не найден")
    public ProductDTO getProduct(
        @PathVariable @Parameter(description = "ID товара") Long id
    ) {
        return productService.getById(id);
    }
}

Практический пример полного контроллера

@RestController
@RequestMapping("/api/v1/articles")
@CrossOrigin(origins = "*", maxAge = 3600)
@Tag(name = "Articles", description = "API для работы со статьями")
public class ArticleController {
    
    @Autowired
    private ArticleService articleService;
    
    @GetMapping
    @Operation(summary = "Получить все статьи")
    public List<ArticleDTO> getAllArticles(
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "10") int size
    ) {
        return articleService.getAll(page, size);
    }
    
    @GetMapping("/{id}")
    @Operation(summary = "Получить статью по ID")
    public ArticleDTO getArticle(@PathVariable Long id) {
        return articleService.getById(id);
    }
    
    @PostMapping
    @Operation(summary = "Создать новую статью")
    public ResponseEntity<ArticleDTO> createArticle(
        @Valid @RequestBody CreateArticleRequest request
    ) {
        Article article = articleService.create(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(new ArticleDTO(article));
    }
    
    @PutMapping("/{id}")
    @Operation(summary = "Обновить статью")
    public ArticleDTO updateArticle(
        @PathVariable Long id,
        @Valid @RequestBody UpdateArticleRequest request
    ) {
        return articleService.update(id, request);
    }
    
    @DeleteMapping("/{id}")
    @Operation(summary = "Удалить статью")
    public ResponseEntity<Void> deleteArticle(@PathVariable Long id) {
        articleService.delete(id);
        return ResponseEntity.noContent().build();
    }
}

Заключение

Аннотации контроллеров в Spring предоставляют декларативный способ описания функциональности без написания лишнего кода. Знание этих аннотаций и их правильное использование позволяет разработчику создавать чистые, понятные и хорошо задокументированные REST API.