Цель
Создать простое приложение на технологии Spring MVC
Что требуется для начала
- Установленная JDK 6+,
- Maven 2
- Настроенные переменные окружения: JAVA_HOME=<путь к JDK>, M2_HOME=путь к мавен, PATH=JAVA_HOME\bin;M2_HOME\bin;%PATH%;
- Среда разработки, например IntelliJ Idea 11 Ultimate (в Community будет не так удобно работать с Spring и JSP)
Шаг 1: Создание maven проекта
Создайте новую директорию для проекта, например project и выполните команду:
mvn archetype:generate -DgroupId=ru.mai.dep806.mvcapp -DartifactId=webapp -Dversion=1.0-SNAPSHOT -Dpackage=ru.mai.dep806.mvcapp -DarchetypeArtifactId=maven-archetype-webapp -B
Названия groupId, artifactId, version и package можно заменить, если проект будет называться по-другому. Но слово webapp в имени лучше оставить на случай если в проект добавятся другие модули в той же папке project рядом с webapp.
Теперь можно открыть проект в среде разработки, обычно надо выбрать New Project -> Import from External Model -> Maven
Шаг 2: Добавление библиотек Spring в проект
В pom.xml в раздел <dependencies> добавьте следующие зависимости:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>3.1.2.RELEASE</version> </dependency>
Если среда разработки автоматически подхватывает изменения в maven проектах (см. настройку на скриншоте выше), то должно пройти некоторое время, пока мавен выкачает указанные и все зависимые от них библиотеки с исходниками, после чего IDE их проиндексирует для быстрого поиска. Подождите пока процесс завершится.
Также стоит сразу добавить конфигурацию плагина-компилятора в секцию <build> </build>
для того, чтобы указать версию языка java, которую мы будем использовать. Даже если вы используете самую новую jdk 7, версия языка по умолчанию стоит 1.3, а на 1.6.
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.5.1</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins>
Шаг 3: Добавление диспетчера Spring MVC
Для того, чтобы Spring MVC мог обрабатывать HTTP запросы, нужно прописать сервлет-диспетчер. Откройте web.xml и добавьте следующие строки в <web-app>:
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping>
Название сервлета может быть произвольное, но должно совпадать в обеих секциях, а также в имени spring-файла на следующем шаге. Все запросы пользователя, которые будет обрабатывать наше MVC приложение должны удовлетворять url-pattern. Т.е. его лучше выбрать в самом начале (например, *.do или *.action или /app/*), иначе придется потом менять ссылки по всему приложению.
Шаг 4: Создание action-servlet.xml
Корнем конфигурации Spring MVC является файл спринг-контекста, название которого по-умолчанию принимается <имя сервлета-диспетчера>-servlet.xml
В нашем случае - это action-servlet.xml, который требуется положить в WEB-INF
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 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="ru.mai.dep806.mvcapp.controllers"/> </beans>
Основной смысловой строкой тут является <context:component-scan/> - тег, который говорит "собери все Spring-бины в пакете ru.mai.dep806.mvcapp.controllers". Забегая вперед, Spring-бинами являются обычные классы, помеченные Spring-аннотациями. В нашем случае это будут контроллеры, но вообще могут быть и любые другие бины реализующие произвольную логику.
Шаг 5: Создание пакетов общей структуры проекта
Подсвечивая красным имя пакета, IDE нам указывает что такого пакета в проекте нет. Значит нужно его создать. Мало того, у нас в проекте даже нет папки, где должны лежать исходники. Для этого мы в папке main создаем подпапку java. Также заодно можно создать src/test/java и src/test/resources для будущих тестов и тестовых ресурсов. Но IDE пока не знает о назначении этих папок, нужно либо сделать вид, что мы изменили pom.xml (добавив пустую строку), либо сделать Reimport All Maven Projects в правой панели Maven. После этого новые папки окрасятся в синий и зеленый цвета, что означает что среда поняла их назначение (по-умолчанию, в мавене исходники и тесты лежат именно по этим путям).
Дальше, в контекстном меню папки src/main/java, выбрав new package создадим пакет ru.mai.dep806.mvcapp.controllers
Замечание для Idea: по-умолчанию пустые пакеты отображаются в дереве одной строкой компактно, если требуется их развернуть, например, для создания подпакета в середине пути, снимите флаг Compact empty middle package в меню над деревом)
Шаг 6: Добавление контроллера для главной страницы
Наконец то мы можем создать первый класс-контроллер WelcomeController (в пакете controllers):
package ru.mai.dep806.mvcapp.controllers; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; /** * Контроллер для главной страницы приложения. */ @Controller public class WelcomeController { private int visitorCount = 0; @RequestMapping("/index.html") public String index(Model model) { model.addAttribute("visitorCount", visitorCount++); return "WEB-INF/jsp/index.jsp"; } }
Аннотация @Controller говорит component-scan что нужно создать спринг-бин из этого класса (поэтому рекомендуется оставлять в нем конструктор по-умолчанию без параметров). Аннотация @RequestMapping говорит, что метод index будет обрабатывать запросы по URL /index.html от корня приложения (если приложение развернуто на сервере под контекстом /mvc то соответственно полный URL будет http://localhost:8080/mvc/index.html). Посмотрите какие другие параметры есть у этой аннотации, также она может принимать wildcards и использовать в качестве пути переменные, значения которых можно получить в параметре метода - фактически можно добиться практически любой сложности URL.
Далее, метод index (название произвольное, главное чтобы он был public) принимает на вход объект модели, которую может заполнить в теле метода, и возвращает String - имя jsp страницы, которая представляет собой view. Забегая вперед, можно сказать что параметры у метода и возвращаемое значение могут быть самые разнообразные, в зависимости от потребностей конкретной логики контроллера. Никакого интерфейса или жесткой модели тут нет.
Все объекты-бины в спринге по-умолчанию являются синглтонами. Т.е. на все приложение создается один единственный экземпляр нашего контроллера, который обрабатывает все запросы, в том числе может и параллельно. Попробуйте предположить какое значение будет у переменной visitorCount после нескольких обращений к index.html. Что есть плохого в реализации этого метода? Как это можно исправить?
Шаг 7: Добавление JSP-файла (view) для главной страницы
Теперь пока добавить "лицо" нашего приложения - view для главной страницы. Для этого, создадим папку jsp в WEB-INF и в ней файл index.jsp, чтобы наш контроллер нашел ее по полному пути внутри сервера: WEB-INF/jsp/index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Добро пожаловать</title> </head> <body> <h4> Добро пожаловать! </h4> Поздравляем, вы <b>${visitorCount}</b> посетитель и можете выиграть поездку в столицу Java - Джакарту <br/> <a href="http://clck.yandex.ru/redir/dtype=stred/pid=7/cid=1228/*http://pogoda.yandex.ru/jakarta"><img src="http://info.weather.yandex.net/jakarta/2.ru.png" border="0" alt=""/><img width="1" height="1" src="http://clck.yandex.ru/click/dtype=stred/pid=7/cid=1227/*http://img.yandex.ru/i/pix.gif" alt="" border="0"/></a> </body> </html>
Тут кроме HTML из интересного используется синтаксис Expression Language (EL) - ${visitorCount} для вывода значения переменной модели, которую мы установили в контроллере.
Для того, чтобы можно было использовать EL, необходимо установить флаг isELIgnored="false", который по-умолчанию true для совместимости с предыдущими версиями JSP, где EL не интерпретировался.
Шаг 8: Конфигурация проекта для запуска в Tomcat
Теперь мы можем собрать проект с помощью цели maven package, в результате чего получим файл target/webapp.war готовый к развертыванию на любом сервере приложений или web-контейнере java. Но maven предоставляет возможность запускать встроенный web-контейнер Tomcat, который перед запуском надо сконфигурировать в pom.xml:
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat6-maven-plugin</artifactId> <version>2.0</version> </plugin>
Шаг 9: Launch!
Запускаем проект с помощью команды mvn tomcat6:run (из командной строки или IDE).
Если все прошло успешно (в логах есть строка INFO: FrameworkServlet 'action': initialization completed), то можно зайти на страницу по адресу http://localhost/webapp/index.html
Поздравляем с созданием первого MVC приложения!
2 Comments
Alexei Rybalko
Шаг 2
Данный кусок кода следует поместить в pom.xml в раздел <build> ... </build>
Eugene Gavrilov
Исправлено, спасибо!