Зміст
У першій частині статті розглянемо створення контролерів, використовуючи Spring Framework 3-ї версії і Spring MVC зокрема.
Абревіатура MVC в назві Spring MVC розшифровується як Model-view-controller. Моде́ль-вид-контро́лер (або Модель-вигляд-контролер, англ. Model-view-controller, MVC) — архітектурний шаблон, який використовується під час проектування та розробки програмного забезпечення.
Цей шаблон поділяє систему на три частини: модель даних, вигляд даних та керування. Застосовується для відокремлення даних (модель) від інтерфейсу користувача (вигляду) так, щоб зміни інтерфейсу користувача мінімально впливали на роботу з даними, а зміни в моделі даних могли здійснюватися без змін інтерфейсу користувача.
Мета шаблону — гнучкий дизайн програмного забезпечення, який повинен полегшувати подальші зміни чи розширення програм, а також надавати можливість повторного використання окремих компонент програми. Крім того використання цього шаблону у великих системах призводить до певної впорядкованості їх структури і робить їх зрозумілішими завдяки зменшенню складності.
Парадигрма програмування MVC не буде докладно описуватися в даній статті.
Отже, контролер в Spring MVC виконує роль (як не дивно :)) контролера в парадигмі програмування Model-View-Controller. Кожен запит перехоплюється глобальним Front-контролером, який за специфічними параметрами (URI, метод і/або заголовки запиту) визначає, якому з контролерів передати отриманий запит. Контролер обробляє запит і створює модель. Front-контролер заповнює відображення даними моделі і повертає отриманий результат браузеру. Нижче представлена схема обробки запиту у Spring.
Рис 1. Обробка запиту в Spring Web MVC
Найпростіший контролер виглядає наступним чином:
@Controller
public class SimpleController {
@RequestMapping(value = "/simple1")
public String simple1() {
return "simple";
}
}
Анотація @Controller служить для повідомлення Spring'у про те, що даний клас є bean'ом і його необхідно завантажити при старті програми. Анотацією @RequestMapping (value="/simple1") повідомляємо, що даний контролер буде обробляти запит, URI якого "/simple1".
return "simple";
- повідомляємо Front-контролеру, що ім'я відображення "simple" (за замовчуванням, це файл / WEB-INF/views/simple.jsp).
Ці ж операції можна зробити з використанням класу ModelAndView, який агрегує всі параметри моделі та ім'я відображення:
@Controller
public class SimpleController {
@RequestMapping(value = "/simple2")
public ModelAndView simple2() {
ModelAndView mav = new ModelAndView();
mav.setViewName("simple");
return mav;
}
}
jsp-файл і в першому, і в другому випадку може виглядати, наприклад, наступним чином:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page pageEncoding="UTF-8"%>
<%@ page session="false"%>
<html>
<head>
<title>SimpleController</title>
</head>
<body>
<h1>SimpleController</h1>
<P>Just text</P>
<a href="${pageContext.request.contextPath}/" title="Back">Back</a>
</body>
</html>
У двох наведених вище прикладах контролери не передають ніяких даних відображенням, що буває дуже рідко. Тому розглянемо варіант з передачею даних від контролера відображенню за допомогою моделі.
Дані від контролера до відображення можуть передатися двома способами:
@RequestMapping(value = "/simplemodel1")
public String simpleModel1(Model model) {
model.addAttribute("name", "John");
model.addAttribute("path", "/simplemodel1");
return SIMPLE_MODEL_VIEW_NAME;
}
або
@RequestMapping(value = "/simplemodel2")
public ModelAndView simpleModel2() {
ModelAndView mav = new ModelAndView();
mav.setViewName(SIMPLE_MODEL_VIEW_NAME);
mav.addObject("name", "John");
mav.addObject("path", "/simplemodel2");
return mav;
}
У першому випадку модель передається методу у вигляді параметра. Метод повинен повернути назву відображення. У другому випадку метод сам створює об'єкт ModelAndView, який містить і модель, і ім'я відображення. Контролер повинен повернути цей об'єкт.
jsp-файл буде виглядати наступним чином:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page pageEncoding="UTF-8"%>
<%@ page session="false"%>
<html>
<head>
<title>${path} - SimpleModelController</title>
</head>
<body>
<h1>${path} - SimpleModelController</h1>
<P>Hi ${name}!</P>
<a href="${pageContext.request.contextPath}/" title="Back">Back</a>
</body>
</html>
У даному прикладі контролер передає 2 параметра відображенню - name і path. Вони відображаються за допомогою конструкції ${_param_name_}. Наприклад:
<P>Hi ${name}!</P>
В даному випадку користувачеві передається наступний рядок
<P>Hi John!</P>
Тобто, вираз ${name} замінюється на John так як і в першому, і в другому методі контролера змінна моделі name заповнюється рядком John.
@RequestMapping(value = "/simplemodel1")
public String simpleModel1(Model model) {
// ...
model.addAttribute("name", "John");
// ...
}
@RequestMapping(value = "/simplemodel2")
public ModelAndView simpleModel2() {
// ...
mav.addObject("name", "John");
// ...
}
Раніше ми розглядали тільки методи, які були помічені анотацією @RequestMapping. Також є можливість позначити клас за допомогою анотації @RequestMapping. Тоді всі методи будуть отримувати запити з URI, що буде починатись з рядка, вказаного в анотації @ RequestMapping перед оголошенням класу контролера. Наприклад:
package com.seostella.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/rmc")
public class RequestMappedClassController {
public static final String REQUEST_MAPPED_CLASS_VIEW_NAME = "request_mapped_class";
@RequestMapping(value = "/test")
public String requestMapped() {
return REQUEST_MAPPED_CLASS_VIEW_NAME;
}
}
Щоб метод requestMapped отримав управління, необхідно виконати запит виду "/rmc/test".
Як і в більшості http-фреймворків, в Spring є можливість розподіляти запити за різними методами не тільки по параметрам, зазначеним у URI, але і використовуючи різні методи запиту. Наприклад:
@Controller
public class RequestMethodController {
public static final String REQUEST_METHOD_VIEW_NAME = "request_method";
@RequestMapping(value = "/requestmethod", method = RequestMethod.GET)
public String requestMethodGet(Model model) {
model.addAttribute("method", "get");
return REQUEST_METHOD_VIEW_NAME;
}
@RequestMapping(value = "/requestmethod", method = RequestMethod.POST)
public String requestMethodPost(Model model) {
model.addAttribute("method", "post");
return REQUEST_METHOD_VIEW_NAME;
}
}
Щоб виконався метод requestMethodGet, достатньо в браузері звернеться за адресою /requestmethod. Для цього методу необхідною умовою є метод GET в HTTP-запиті. Саме GET-метод передається серверу, коли Ви переходите на сторінку, набираючи адресу в браузері.
Для того, щоб виконався другий метод requestMethodPost, необхідно передати йому POST-запит, а для цього необхідно скористатися, наприклад, наступною формою:
<form action="${pageContext.request.contextPath}/requestmethod"
method="post">
<input type="submit" value="requestmethod (post)">
</form>
В Spring є також можливість автозаповнення змінної, використовуючи адресу запиту. Розглянемо на прикладі:
@RequestMapping(value = "/pathvariable/{category}/{product}")
public String pathVariable(@PathVariable String category, @PathVariable("product") String productName, Model model) {
model.addAttribute("categoryName", category);
model.addAttribute("productName", productName);
return "view_name";
}
Використовуючи даний код не потрібно піклуватися про те, як дістати рядок, розташований між pathvariable / і наступним слешем. Він буде автоматично поміщений в змінну category, завдяки анотації @PathVariable.
Ви можете замість строкового типу змінної category використовувати цілочисельний або будь-який інший стандартний тип - Spring перетворює рядок до потрібного типу автоматично. Наприклад:
@RequestMapping(value = "/pathvariable/{category}/{product}")
public String pathVariable(@PathVariable int category, @PathVariable("product") String productName, Model model) {
// ...
}
Варто зауважити, що в анотації @PathVariable можна як вказувати назву змінної:
@PathVariable("product") String productName
так і не робити цього. У наступному випадку буде використовуватися назва змінної category:
@PathVariable String category
Також змінна може бути в анотації перед оголошенням класу. Тоді її можна отримати в будь-якому з методів контролера. Наприклад:
@Controller
@RequestMapping(value = "/category/{categoryName}")
public class ClassPathVariableController {
public static final String PATH_VARIABLE_VIEW_NAME = "class_path_variable";
@RequestMapping(value = "/product/{productName}")
public String classPathVariable(@PathVariable String productName,
@PathVariable String categoryName,
Model model) {
model.addAttribute("categoryName", categoryName);
model.addAttribute("productName", productName);
return PATH_VARIABLE_VIEW_NAME;
}
}
Spring 3 і @Controller. Частина 2 | > |