← Назад к вопросам
Как создать @RestController в Spring?
1.0 Junior🔥 301 комментариев
#Spring Boot и Spring Data
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как создать @RestController в Spring?
@RestController — это аннотация в Spring для создания RESTful веб-сервисов. Она комбинирует @Controller и @ResponseBody, автоматически сериализуя возвращаемые значения в JSON/XML.
1. Базовая структура @RestController
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
@RestController
@RequestMapping("/api/v1/users") // Базовый путь для всех методов
public class UserController {
// GET: http://localhost:8080/api/v1/users
@GetMapping
public List<User> getAllUsers() {
return new ArrayList<>(); // Автоматически сериализуется в JSON
}
// GET: http://localhost:8080/api/v1/users/1
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return new User(id, "John");
}
// POST: http://localhost:8080/api/v1/users
@PostMapping
public User createUser(@RequestBody User user) {
// user автоматически десериализуется из JSON
return user; // Сериализуется обратно в JSON
}
// PUT: http://localhost:8080/api/v1/users/1
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return user;
}
// DELETE: http://localhost:8080/api/v1/users/1
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
// Удаляем пользователя
}
}
// Model
public class User {
private Long id;
private String name;
public User(Long id, String name) {
this.id = id;
this.name = name;
}
// Getters и Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
2. @RestController vs @Controller
@Controller — для обычных MVC приложений:
@Controller
public class WebController {
@GetMapping("/users")
public String getUsers(Model model) {
model.addAttribute("users", userService.getAll());
return "users"; // Возвращает имя HTML шаблона (Thymeleaf, JSP)
}
}
@RestController — для REST API:
@RestController
public class UserRestController {
@GetMapping("/api/v1/users")
public List<User> getUsers() {
return userService.getAll(); // Сериализуется в JSON
}
}
// Эквивалентно:
@Controller
public class UserRestController {
@GetMapping("/api/v1/users")
@ResponseBody
public List<User> getUsers() {
return userService.getAll();
}
}
3. Полный пример с сервисом
// User model
public class User {
private Long id;
private String email;
private String firstName;
private String lastName;
// Конструкторы, getters, setters
public User() {}
public User(Long id, String email, String firstName, String lastName) {
this.id = id;
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
}
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
}
// Service слой
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class UserService {
private final Map<Long, User> users = new HashMap<>();
private Long currentId = 1L;
public UserService() {
// Инициализация тестовых данных
users.put(1L, new User(1L, "john@example.com", "John", "Doe"));
users.put(2L, new User(2L, "jane@example.com", "Jane", "Smith"));
currentId = 3L;
}
public List<User> getAllUsers() {
return new ArrayList<>(users.values());
}
public User getUserById(Long id) {
return users.get(id);
}
public User createUser(User user) {
user.setId(currentId++);
users.put(user.getId(), user);
return user;
}
public User updateUser(Long id, User user) {
if (!users.containsKey(id)) {
return null;
}
user.setId(id);
users.put(id, user);
return user;
}
public boolean deleteUser(Long id) {
return users.remove(id) != null;
}
}
// REST Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@Autowired
private UserService userService;
// GET все пользователи
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
List<User> users = userService.getAllUsers();
return ResponseEntity.ok(users);
}
// GET пользователя по ID
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
if (user == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(user);
}
// POST создание нового пользователя
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User createdUser = userService.createUser(user);
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}
// PUT обновление пользователя
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(
@PathVariable Long id,
@RequestBody User user) {
User updatedUser = userService.updateUser(id, user);
if (updatedUser == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(updatedUser);
}
// DELETE удаление пользователя
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
boolean deleted = userService.deleteUser(id);
if (!deleted) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.noContent().build();
}
}
4. Параметры запроса (@RequestParam, @PathVariable)
@RestController
@RequestMapping("/api/v1/search")
public class SearchController {
// Query параметры: /api/v1/search?name=john&age=30
@GetMapping
public List<User> searchUsers(
@RequestParam(required = false) String name,
@RequestParam(required = false) Integer age) {
// Параметры опциональны (required = false)
return userService.search(name, age);
}
// Path переменные: /api/v1/users/123/orders/456
@GetMapping("/users/{userId}/orders/{orderId}")
public Order getUserOrder(
@PathVariable Long userId,
@PathVariable Long orderId) {
return orderService.getOrder(userId, orderId);
}
// Комбинированные параметры
@GetMapping("/users")
public Page<User> listUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String sort) {
return userService.listUsers(page, size, sort);
}
}
5. ResponseEntity — управление HTTP ответом
@RestController
@RequestMapping("/api/v1/products")
public class ProductController {
// Простой ответ (200 OK)
@GetMapping
public List<Product> getAll() {
return productService.getAll();
}
// С явным статусом
@PostMapping
public ResponseEntity<Product> create(@RequestBody Product product) {
Product created = productService.create(product);
return ResponseEntity
.status(HttpStatus.CREATED)
.body(created);
// Эквивалентно: return new ResponseEntity<>(created, HttpStatus.CREATED);
}
// 204 No Content
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
productService.delete(id);
return ResponseEntity.noContent().build();
}
// 404 Not Found
@GetMapping("/{id}")
public ResponseEntity<Product> getById(@PathVariable Long id) {
Product product = productService.getById(id);
if (product == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(product);
}
// С headers
@GetMapping("/{id}")
public ResponseEntity<Product> getWithHeaders(@PathVariable Long id) {
Product product = productService.getById(id);
return ResponseEntity.ok()
.header("X-Custom-Header", "value")
.body(product);
}
}
6. Обработка ошибок (@ExceptionHandler)
// Custom Exception
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
// Global Exception Handler
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Map<String, String>> handleNotFound(
ResourceNotFoundException ex) {
Map<String, String> error = new HashMap<>();
error.put("error", ex.getMessage());
error.put("status", "404");
return ResponseEntity.notFound().build();
}
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<Map<String, String>> handleBadRequest(
IllegalArgumentException ex) {
Map<String, String> error = new HashMap<>();
error.put("error", ex.getMessage());
error.put("status", "400");
return ResponseEntity.badRequest().body(error);
}
}
// Использование в контроллере
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
User user = userService.getUserById(id);
if (user == null) {
throw new ResourceNotFoundException("User not found: " + id);
}
return user;
}
}
7. Валидация данных (@Valid, @Validated)
// Model с аннотациями валидации
import javax.validation.constraints.*;
public class User {
@NotNull
@Positive
private Long id;
@NotBlank
@Email
private String email;
@NotBlank
@Size(min = 2, max = 50)
private String firstName;
@NotBlank
@Size(min = 2, max = 50)
private String lastName;
// Getters, Setters
}
// RestController с валидацией
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
// @Valid активирует валидацию
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User created = userService.create(user);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
// Если валидация не пройдена:
// 400 Bad Request + детали ошибок
}
// Custom Exception Handler для ошибок валидации
@RestControllerAdvice
public class ValidationExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, Object>> handleValidationException(
MethodArgumentNotValidException ex) {
Map<String, Object> errors = new HashMap<>();
Map<String, String> fieldErrors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
fieldErrors.put(error.getField(), error.getDefaultMessage())
);
errors.put("errors", fieldErrors);
errors.put("status", 400);
return ResponseEntity.badRequest().body(errors);
}
}
8. Пример API с пагинацией
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@Autowired
private UserRepository userRepository;
// GET /api/v1/users?page=0&size=10&sort=name,asc
@GetMapping
public Page<User> listUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(page, size);
return userRepository.findAll(pageable);
}
}
9. Конфигурация Spring Boot Application
// Main Application
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class UserManagementApplication {
public static void main(String[] args) {
SpringApplication.run(UserManagementApplication.class, args);
}
}
// application.properties
spring.application.name=user-api
server.port=8080
server.servlet.context-path=/
# Logging
logging.level.root=INFO
logging.level.com.example=DEBUG
10. Тестирование @RestController
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.hamcrest.Matchers.*;
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testGetAllUsers() throws Exception {
mockMvc.perform(get("/api/v1/users"))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$", hasSize(greaterThanOrEqualTo(0))));
}
@Test
public void testCreateUser() throws Exception {
String newUser = "{\"email\":\"test@example.com\",\"firstName\":\"Test\",\"lastName\":\"User\"}";
mockMvc.perform(post("/api/v1/users")
.contentType("application/json")
.content(newUser))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.id", notNullValue()))
.andExpect(jsonPath("$.email", is("test@example.com")));
}
}
Итоги
Шаги для создания @RestController:
- Аннотируй класс @RestController
- Определи @RequestMapping для базового пути
- Реализуй методы с @GetMapping, @PostMapping и т.д.
- Используй @PathVariable и @RequestBody для параметров
- Возвращай объекты (сериализуются в JSON) или ResponseEntity
- Добавь валидацию через @Valid
- Обработай ошибки через @ExceptionHandler
- Протестируй через MockMvc или RestTemplate
@RestController автоматически сериализует все возвращаемые значения в JSON, делая создание REST API просто и удобно.