Привет.
Это моя первая статья.Прошу сильно молотком не бить.
Сегодня, этим сообщением начнется мой цикл статей о фреймворках Spring.
Я не буду вдаваться в тонкости теории, здесь на хабре достаточно статей об этом. Предпочитаю практику.
Тем не менее, стоит напомнить, что работать со Spring Framework можно как с помощью xml-конфигурации, так и с помощью аннотаций. Также, ничего не мешает комбинировать оба подхода.
Лично я предпочитаю работать с аннотациями, чего и вам советую. Поэтому все примеры, которые я буду приводить, будут использовать аннотации.
Думаю, стоит рассказать, что же мы сегодня будем делать.
Сегодня мы создадим простое веб-приложение, которое будет считать сумму двух чисел и, естественно, отправлять пользователю ответ.
Работать будем в IDE Intellij IDEA 12. Приступим.
Создадим новый проект (File-New Project).
Выбираем «Тип проекта» — Spring MVC. Даем проекту имя (Project name) и жмем Finish. При желании можно указать другой базовый пакет (Base package), так я изменил его на «com.springapp.controllers». Также, если можно указать путь к JDK (Project SDK) и Серверу(Application server), на котором приложение будет развертываться. Как можно заметить я использую 7 версию Java и сервер Glassfish.
Проект создан и должен иметь такую структуру.
Это шаблонный проект, который использует xml-конфигурацию. Но ведь мы хотим использовать аннотации. Значит удалим лишнее.
Удаляем файл mvc-dispatcher-servlet.xml и папку test (тесты в ней используют файл mvc-dispatcher-servlet.xml).
Лишний раз приведу скрин того, что должно быть на этом шаге.
Теперь необходимо создать тот самый dispatcher-servlet, только с помощью обычного java-класса. Я считаю, что программа всегда должна быть хорошо структурированна и, думаю, многие меня поддержат. Для начала создадим новый пакет «config», который будет хранить всю конфигурацию Spring. Для этого выбираем папку java и нажимаем «ALT-INSERT». Вводим имя пакета (com.springapp.config) и жмакаем «ОК».
Пакет создан. Добавим в него новый класс. Для этого, все также — ALT-INSERT и выбираем «Class». Назовем его MvcConfig.
Созданный класс должен иметь приблизительно такой вид.
package com.springapp.config;
/**
* Created with IntelliJ IDEA.
* User: diversant
* Date: 18.06.13
* Time: 13:05
* To change this template use File | Settings | File Templates.
*/
public class MvcConfig {
}
Приступим к созданию конфигурации. Я приведу сразу готовый конфигурационный класс и ниже опишу все необходимые детали.
package com.springapp.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@ComponentScan(basePackages="com.springapp")
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
return resolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
Начнем с самого начала.
@Configuration
— говорим о том, что данный класс является конфигурационным для Spring, тоесть включает конфигурацию бинов.
@ComponentScan
— указываем пакет, к котором будут искаться необходимые директивы для взаимодействия с бинами.
@EnableWebMvc
— указываем, что данный класс является конфигурационным для Spring MVC.
@Bean
— говорим о том, что аннотированный метод является бином.
Аннотацию @Override
думаю знают все, кто хоть немного работал с Java.
Теперь более подробно о самих методах класса.
В методе getViewResolver() мы указываем, на мой взгляд, самый простой просмотрщик страниц, конфигурация которого состоит из добавления префикса и суфикса к странице.
В методе addResourceHandlers(ResourceHandlerRegistry registry) мы указываем расположение всех ресурсов, которые будут использоваться для страниц. Это могут быть и каскадные таблицы стилей, и java-script файлы, изображения и прочее.
Вот такая простая конфигурация.
Теперь необходимо объяснить веб-контейнеру, что мы будем использовать этот класс в качестве диспатчера. Для этого необходимо отредактировать файл web.xml. Идея создала для нас такой шаблонный код.
<web-app 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>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Нам необходимо заменить его этим
<web-app 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</display-name>
<context-param>
<param-name>contextClass</param-name><param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value></context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name><param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value></init-param>
<init-param>
<param-name>contextConfigLocation</param-name><param-value>com.springapp.config</param-value></init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
Детально расписывать не буду, скажу только — мы указываем, что конфигурация контекста и диспатчера выполняется с помощью аннотаций (c помощью параметра contextClass и его значения org.springframework.web.context.support.AnnotationConfigWebApplicationContext). Также указываем, в каком пакете искать конфигурационные классы (параметр contextConfigLocation).
Далее необходимо создать контроллер. Контроллер в Spring выполняет трасляцию адресов (то что мы видим в браузере) и перенаправление на страницы (в нашем случае hello.jsp).
Так как, Идея создала базовый контроллер за нас, нам не прийдется писать его вручную. На всякий случай, я приведу его код и поясню, что там происходит.
package com.springapp.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/")
public class HelloController {
@RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
model.addAttribute("message", "Hello world!");
return "hello";
}
}
Начнем с аннотаций.
@Controller
— собственно говорим о том, что это контроллер. Добавить нечего
@RequestMapping("/")
— с помощью этой аннотации указываем область видимости для этого котроллера (если эта аннотация применина к классу) или конкретный транслируемый адрес (если это метод). Также можно указать при каком конкретном запросе будет транслироваться тот или инной адрес (параметр method). В данной случае мы говорим о том, что данный контроллер будет видеть все адреса (то, что в браузере) и пытаться траслировать их на нужную страницу. Для большей ясности приведу пример.
Допустим есть 2 адреса mydomain.com/info, mydomain.com/about. Если мы указаем в RequestMapping вместо "/" — "/about", то контроллер никогда не будет пытаться траслировать адрес mydomain.com/info, так как просто не будем видеть его.
О том, что делает метод printWelcome(). Данный метод просто передает на страницу сообщение «Hello World» и, естественно, указывает имя самой страницы. Ну а с помощью просмотрщика, который мы описали в классе диспатчера (MvcConfig) это имя транслируется в полнить путь к странице, с помощью добавления префикса и суфикса.
Осталось привести только код самой страницы hello.jsp.
<html>
<body>
<h1>${message}</h1>
</body>
</html>
Собственно, можно приступить к развертке приложения. Для этого используем кнопку запуска.
Ждем пока, запустится сервер, развернется приложение. И вуаля, видим всеми любимый «Hello World».
Раз все работает, как надо, можно приступить к реализации просчета суммы двух чисел.
Для начала изменим нашу jsp страницу, добавив в нее форму для ввода чисел.
<html>
<body>
<h1>${message}</h1>
<form method="post">
<input name="value1" type="text"/>
+
<input name="value2" type="text"/>
<input type="submit"/>
</form>
<h3>Result: ${result}</h3>
</body>
</html>
Ничего сложного. Мы добавили два поля для ввода чисел, кнопку отправки и дериктиву вывода результата. Для простоты, я решил использовать для вывода результата ту же страницу.
И последнее, добавить метод обработки POST-запроса в наш котроллер.
package com.springapp.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/")
public class HelloController {
@RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
model.addAttribute("message", "Hello world!");
return "hello";
}
@RequestMapping(method = RequestMethod.POST)
public String calcSum(Model m,
@RequestParam(value = "value1") Double value1,
@RequestParam(value = "value2") Double value2 ){
m.addAttribute("result", (value1+value2));
return "hello";
}
}
В этом методе мы, с помощью аннотации @RequestMapping
указываем метод обработки POST, а также с помощью аннотации @RequestParam
получает информацию из полей формы (value1, value2).
Запускаем (Идея предложит 4 варианта, выбираем «Redeploy»), видим, что наша форма есть.
Ну и считаем сумму.
Собственно, на этом все.
В следующий раз мы разберем, что такое Spring Data JPA и как с ним работать.
Вся информация, которую я привел является сугубо моим опытом или мнением и не претендует на эталон или стандарт. Я показываю способы как МОЖНО сделать, а не как НЕОБХОДИМО.
Буду рад конструктивной критике, так как опыт в сфере «статьестроя» у меня не большой.
Всем пока, верней до встречи.
Автор: StMechanus