Какие знаешь ключевые признаки обычного контроллера?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Ключевые признаки обычного контроллера в Spring
Обычный контроллер (traditional/view controller, не REST) имеет характерные отличия от REST контроллеров. Давайте рассмотрим основные признаки и различия.
1. Аннотация @Controller
Основной признак — использование аннотации @Controller вместо @RestController:
// ✓ Обычный контроллер
@Controller
@RequestMapping("/users")
public class UserController {
// ...
}
// ❌ REST контроллер (другой подход)
@RestController
@RequestMapping("/api/v1/users")
public class UserRestController {
// ...
}
2. Возвращает String (имя View)
Обычный контроллер возвращает логическое имя представления (view), а не объекты данных:
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home"; // Возвращает имя шаблона (home.html, home.jsp)
}
@GetMapping("/about")
public String about() {
return "about"; // about.html или about.jsp
}
@GetMapping("/contact")
public String contact() {
return "contact"; // contact.html
}
}
Spring автоматически ищет шаблон с таким именем в папке templates/ (для Thymeleaf) или WEB-INF/jsp/ (для JSP).
3. Использует Model для передачи данных
Для передачи данных в шаблон используется объект Model:
@Controller
@RequestMapping("/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping
public String listProducts(Model model) {
List<Product> products = productService.getAllProducts();
model.addAttribute("products", products); // Передаём в шаблон
model.addAttribute("title", "All Products");
return "products/list"; // products/list.html
}
@GetMapping("/{id}")
public String showProduct(@PathVariable Long id, Model model) {
Product product = productService.getProductById(id);
model.addAttribute("product", product);
model.addAttribute("relatedProducts", productService.getRelated(id));
return "products/detail"; // products/detail.html
}
@PostMapping
public String createProduct(@ModelAttribute Product product, Model model) {
Product saved = productService.save(product);
model.addAttribute("success", true);
return "products/created"; // products/created.html
}
}
4. Работает с HTML формами
Обычный контроллер часто обрабатывает HTML формы с использованием @ModelAttribute:
@Controller
@RequestMapping("/users")
public class UserFormController {
@Autowired
private UserService userService;
// Показываем форму
@GetMapping("/register")
public String showRegistrationForm(Model model) {
model.addAttribute("user", new User()); // Пустой объект для формы
return "registration"; // registration.html
}
// Обрабатываем отправку формы
@PostMapping("/register")
public String registerUser(
@ModelAttribute User user, // Автоматически заполняется из POST параметров
BindingResult bindingResult,
Model model) {
// Валидация
if (bindingResult.hasErrors()) {
return "registration"; // Повторно показываем форму с ошибками
}
userService.register(user);
model.addAttribute("message", "Registration successful!");
return "registration-success"; // registration-success.html
}
}
5. Использует Template Engine (Thymeleaf, FreeMarker, JSP)
Данные обрабатываются на сервере и вставляются в HTML шаблон:
<!-- templates/products/list.html (Thymeleaf) -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="${title}">Products</title>
</head>
<body>
<h1 th:text="${title}">All Products</h1>
<table>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
<tr th:each="product : ${products}">
<td th:text="${product.name}">Product Name</td>
<td th:text="${product.price}">$0.00</td>
</tr>
</table>
</body>
</html>
// Контроллер передаёт данные
@GetMapping
public String listProducts(Model model) {
List<Product> products = productService.getAllProducts();
model.addAttribute("products", products);
model.addAttribute("title", "All Products");
return "products/list"; // Thymeleaf обработает шаблон
}
6. Редирект вместо JSON
Обычно после обработки формы контроллер выполняет redirect (перенаправление) на другую страницу:
@Controller
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
public String createOrder(@ModelAttribute Order order) {
Order saved = orderService.save(order);
// Редирект на страницу просмотра заказа
return "redirect:/orders/" + saved.getId(); // Редирект
}
@GetMapping("/{id}")
public String viewOrder(@PathVariable Long id, Model model) {
Order order = orderService.findById(id);
model.addAttribute("order", order);
return "orders/view"; // orders/view.html
}
}
7. Не использует @ResponseBody
Обычный контроллер не аннотирует методы с @ResponseBody:
// ❌ Неправильно для обычного контроллера
@Controller
public class BadController {
@GetMapping
@ResponseBody // Не нужна!
public String getData() {
return "{\"data\": \"value\"}"; // Это будет возвращено как text/plain
}
}
// ✓ Правильно
@Controller
public class GoodController {
@GetMapping
public String getData(Model model) {
model.addAttribute("data", "value");
return "mypage"; // mypage.html
}
}
8. Работает с SessionAttributes
Для хранения данных сессии используется аннотация @SessionAttributes:
@Controller
@RequestMapping("/checkout")
@SessionAttributes("cart") // Хранить корзину в сессии
public class CheckoutController {
@GetMapping("/step1")
public String step1(Model model) {
Cart cart = new Cart();
model.addAttribute("cart", cart);
return "checkout/step1"; // checkout/step1.html
}
@PostMapping("/step1")
public String processStep1(
@ModelAttribute Cart cart, // Автоматически из сессии
RedirectAttributes redirectAttributes) {
// Обрабатываем step 1
return "redirect:/checkout/step2"; // Переход на step 2
}
@GetMapping("/step2")
public String step2(@ModelAttribute Cart cart, Model model) { //Cart из сессии
model.addAttribute("cart", cart);
return "checkout/step2"; // checkout/step2.html
}
}
9. Post-Redirect-Get (PRG) паттерн
Обычный контроллер следует паттерну PRG для обработки форм:
@Controller
public class CommentController {
// GET — показываем форму
@GetMapping("/comments/new")
public String showCommentForm(Model model) {
model.addAttribute("comment", new Comment());
return "comment-form"; // comment-form.html
}
// POST — обрабатываем форму
@PostMapping("/comments")
public String saveComment(@ModelAttribute Comment comment) {
commentService.save(comment);
// Редирект (не вернуть шаблон!)
return "redirect:/comments/" + comment.getId();
}
// GET — показываем результат
@GetMapping("/comments/{id}")
public String viewComment(@PathVariable Long id, Model model) {
Comment comment = commentService.findById(id);
model.addAttribute("comment", comment);
return "comment-view"; // comment-view.html
}
}
Сравнение: @Controller vs @RestController
| Признак | @Controller | @RestController |
|---|---|---|
| Возвращает | View name (String) | JSON/XML (объекты) |
| Использует Model | Да | Нет |
| Использует Template Engine | Да | Нет |
| Обрабатывает формы | Да | Редко |
| Content-Type | text/html | application/json |
| Редиректы | Часто | Редко |
| @ResponseBody нужна | Нет | Автоматична |
| SessionAttributes | Часто | Редко |
| Цель | Веб-приложения (MVC) | REST API |
Полный пример обычного контроллера
@Controller
@RequestMapping("/blog")
public class BlogController {
@Autowired
private BlogService blogService;
@Autowired
private CommentService commentService;
// Показать список статей
@GetMapping
public String list(
@RequestParam(defaultValue = "0") int page,
Model model) {
List<Post> posts = blogService.getPostsByPage(page);
model.addAttribute("posts", posts);
model.addAttribute("currentPage", page);
return "blog/list"; // blog/list.html
}
// Показать одну статью
@GetMapping("/{slug}")
public String view(
@PathVariable String slug,
Model model) {
Post post = blogService.getBySlug(slug);
List<Comment> comments = commentService.getByPostId(post.getId());
model.addAttribute("post", post);
model.addAttribute("comments", comments);
model.addAttribute("newComment", new Comment());
return "blog/post-detail"; // blog/post-detail.html
}
// Обработать добавление комментария
@PostMapping("/{slug}/comments")
public String addComment(
@PathVariable String slug,
@ModelAttribute Comment comment) {
Post post = blogService.getBySlug(slug);
comment.setPost(post);
commentService.save(comment);
// PRG паттерн — редирект
return "redirect:/blog/" + slug;
}
}
Когда использовать @Controller
- ✓ Традиционные веб-приложения (MVC)
- ✓ Приложения с шаблонами (Thymeleaf, JSP)
- ✓ Обработка HTML форм
- ✓ Server-side rendering
- ✓ Полные веб-сайты (не API)
В современной разработке обычные контроллеры использую меньше, так как популярны:
- Frontend frameworks (React, Vue, Angular) + REST API
- Single Page Applications (SPA)
- API-first подход
Однако для простых админ-панелей, внутренних систем и traditional веб-приложений обычные контроллеры остаются удобным решением.