Содержание
В этой статье рассмотрим создание контроллеров при использовании Spring Framework 3-й версии и Spring MVC в частности.
Аббревиатура MVC в названии Spring MVC расшифровывается как 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
так и не делать этого. В следующем случае будет использоваться название, совпадающее с названием переменной:
@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 | > |