
Фреймворк Spring MVC обеспечивает архитектуру паттерна Model — View — Controller (Модель — Отображение (далее — Вид) — Контроллер) при помощи слабо связанных готовых компонентов. Паттерн MVC разделяет аспекты приложения (логику ввода, бизнес-логику и логику UI), обеспечивая при этом свободную связь между ними.
- Model (Модель) инкапсулирует (объединяет) данные приложения, в целом они будут состоять из POJO («Старых добрых Java-объектов», или бинов).
- View (Отображение, Вид) отвечает за отображение данных Модели, — как правило, генерируя HTML, которые мы видим в своём браузере.
- Controller (Контроллер) обрабатывает запрос пользователя, создаёт соответствующую Модель и передаёт её для отображения в Вид.
DispatcherServlet
Вся логика работы Spring MVC построена вокруг DispatcherServlet, который принимает и обрабатывает все HTTP-запросы (из UI) и ответы на них. Рабочий процесс обработки запроса DispatcherServlet'ом проиллюстрирован на следующей диаграмме:

Ниже приведена последовательность событий, соответствующая входящему HTTP-запросу:
- После получения HTTP-запроса DispatcherServlet обращается к интерфейсу HandlerMapping, который определяет, какой Контроллер должен быть вызван, после чего, отправляет запрос в нужный Контроллер.
- Контроллер принимает запрос и вызывает соответствующий служебный метод, основанный на GET или POST. Вызванный метод определяет данные Модели, основанные на определённой бизнес-логике и возвращает в DispatcherServlet имя Вида (View).
- При помощи интерфейса ViewResolver DispatcherServlet определяет, какой Вид нужно использовать на основании полученного имени.
- После того, как Вид (View) создан, DispatcherServlet отправляет данные Модели в виде атрибутов в Вид, который в конечном итоге отображается в браузере.
Все вышеупомянутые компоненты, а именно, HandlerMapping, Controller и ViewResolver, являются частями интерфейса WebApplicationContext extends ApplicationContext, с некоторыми дополнительными особенностями, необходимыми для создания web-приложений.
Конфигурирование
Вам будет необходимо связать (замапить) запросы, которые Вы хотите обработать при помощи DispatcherServlet, используя мапинг URL в файле web.xml. Ниже приведён пример объявления и мапинга DispatcherServlet'а HelloWeb:
<web-app id = "WebApp_ID" version = "2.4" xmlns = "http://java.sun.com/xml/ns/j2ee" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Spring MVC Application</display-name> <servlet> <servlet-name>HelloWeb</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>HelloWeb</servlet-name> <url-pattern>*.jsp</url-pattern> </servlet-mapping> </web-app>
Файл web.xml будет находиться в каталоге WebContent/WEB-INF. После инициализации HelloWeb, фреймворк попытается загрузить контекст приложения из файла с именем [servlet-name]-servlet.xml, находящегося в каталоге WebContent/WEB-INF. В нашем случае, это будет HelloWeb-servlet.xml.
Далее, тэг <servlet-mapping> указывает, какие веб-адреса обрабатываются каким DispatcherServlet'ом. В нашем случае, все HTTP-запросы, заканчивающиеся на ".jsp", будут обработаны HelloWeb.
Если Вы не хотите использовать [servlet-name]-servlet.xml / WebContent/WEB-INF в качестве файла и директории по умолчанию, Вы можете настроить имя файла и директорию, добавив слушатель сервлета (servlet listener) ContextLoaderListener в web.xml, как показано ниже:
<web-app...> <!-------- DispatcherServlet definition goes here-----> .... <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/HelloWeb-servlet.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> </web-app>
Теперь давайте проверим конфигурацию для HelloWeb-servlet.xml, размещённую в каталоге WebContent/WEB-INF:
<beans xmlns = "http://www.springframework.org/schema/beans" xmlns:context = "http://www.springframework.org/schema/context" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package = "com.tutorialspoint" /> <bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name = "prefix" value = "/WEB-INF/jsp/" /> <property name = "suffix" value = ".jsp" /> </bean> </beans>
Ниже приведены важные моменты в HelloWeb-servlet.xml:
- Файл [servlet-name]-servlet.xml будет использоваться для создания обозначенных бинов, с переопределением определений каждого бина, определённых с тем же именем в глобальной области.
- Тэг <context:component-scan...> будет использован для для активации функции сканирования аннотаций Spring MVC, позволяющей использовать аннотации, такие как Controller, @RequestMapping и проч.
- Имена Видов (View) будут определяться при помощи InternalResourceViewResolver. В соответствии с указанным выше правилом, Вид с именем hello будет реализован по адресу /WEB-INF/jsp/hello.jsp
В следующем разделе будет показано, как создавать Controller, Model и View.
Определение Контроллера
DispatcherServlet отправляет запрос контроллерам для выполнения определённых функций. Аннотация @Controllerannotation указывает, что конкретный класс является контроллером. Аннотация @RequestMapping используется для мапинга (связывания) с URL для всего класса или для конкретного метода обработчика.
@Controller @RequestMapping("/hello") public class HelloController { @RequestMapping(method = RequestMethod.GET) public String printHello(ModelMap model) { model.addAttribute("message", "Hello Spring MVC Framework!"); return "hello"; } }
Аннотация Controller определяет класс как Контроллер Spring MVC. В первом случае, @RequestMapping указывает, что все методы в данном Контроллере относятся к URL-адресу "/hello". Следующая аннотация @RequestMapping(method = RequestMethod.GET) используется для объявления метода printHello() как дефолтного метода для обработки HTTP-запросов GET (в данном Контроллере). Вы можете определить любой другой метод как обработчик всех POST-запросов по данному URL-адресу.
Вы можете написать вышеуказанный Контроллер по-другому, указав дополнительные атрибуты для аннотации @RequestMapping следующим образом:
@Controller public class HelloController { @RequestMapping(value = "/hello", method = RequestMethod.GET) public String printHello(ModelMap model) { model.addAttribute("message", "Hello Spring MVC Framework!"); return "hello"; } }
Атрибут «value» указывает URL, с которым мы связываем данный метод (value = "/hello"), далее указывается, что этот метод будет обрабатывать GET-запросы (method = RequestMethod.GET). Также, нужно отметить важные моменты в отношении приведённого выше контроллера:
- Вы определяете бизнес-логику внутри связанного таким образом служебного метода. Из него Вы можете вызывать любые другие методы.
- Основываясь на заданной бизнес-логике, в рамках этого метода Вы создаёте Модель (Model). Вы можете добавлять аттрибуты Модели, которые будут добавлены в Вид (View). В примере выше мы создаём Модель с атрибутом «message».
- Данный служебный метод возвращает имя Вида в виде строки String. В данном случае, запрашиваемый Вид имеет имя «hello».
Создание Вида (JSP)
Spring MVC поддерживает множество типов Видов для различных технологий отображения страницы. В том числе — JSP, HTML, PDF, Excel, XML, Velocity templates, XSLT, JSON, каналы Atom и RSS, JasperReports и проч. Но чаще всего используются шаблоны JSP, написанные при помощи JSTL.
Давайте напишем простой Вид «hello» в /WEB-INF/hello/hello.jsp:
<html> <head> <title>Hello Spring MVC</title> </head> <body> <h2>${message}</h2> </body> </html>
В данном случае, переменная ${message} выводит тот самый атрибут, установленный нами в Контроллере. Внутри Вида Вы можете отобразить любое количество атрибутов.
Примеры реализации фреймворка Spring MVC
Основываясь на приведённых выше концепциях, предлагаю выполнить несколько важных уроков, которые в дальнейшем помогут нам создавать приложения Spring Web:
Spring MVC Hello World Example
Пример, разъясняющий написание простейшего приложения Hello World.
Spring MVC Form Handling Example
В этом примере объясняется, как написать приложение Spring Web с помощью форм HTML, отправить данные контроллеру и отобразить обработанный результат.
Spring Page Redirection Example
Используем функцию редиректа страниц.
Spring Static Pages Example
Получаем доступ к статическим страницам вместе с динамическими.
Spring Exception Handling Example
Обработка исключений.
