Введение в Spring Frameworks: Spring MVC

в 12:13, , рубрики: idea, java, mvc, spring, Песочница, метки: , , ,

Привет.

Это моя первая статья.Прошу сильно молотком не бить.

Сегодня, этим сообщением начнется мой цикл статей о фреймворках 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.

Скриншот

image

Проект создан и должен иметь такую структуру.

Скриншот

image

Это шаблонный проект, который использует xml-конфигурацию. Но ведь мы хотим использовать аннотации. Значит удалим лишнее.
Удаляем файл mvc-dispatcher-servlet.xml и папку test (тесты в ней используют файл mvc-dispatcher-servlet.xml).
Лишний раз приведу скрин того, что должно быть на этом шаге.

Скриншот

image

Теперь необходимо создать тот самый dispatcher-servlet, только с помощью обычного java-класса. Я считаю, что программа всегда должна быть хорошо структурированна и, думаю, многие меня поддержат. Для начала создадим новый пакет «config», который будет хранить всю конфигурацию Spring. Для этого выбираем папку java и нажимаем «ALT-INSERT». Вводим имя пакета (com.springapp.config) и жмакаем «ОК».

Скриншот

image
image

Пакет создан. Добавим в него новый класс. Для этого, все также — 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».

Скриншот

image

Раз все работает, как надо, можно приступить к реализации просчета суммы двух чисел.

Для начала изменим нашу 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»), видим, что наша форма есть.

Скриншот

image

Ну и считаем сумму.

Скриншот

image

Собственно, на этом все.

В следующий раз мы разберем, что такое Spring Data JPA и как с ним работать.

Вся информация, которую я привел является сугубо моим опытом или мнением и не претендует на эталон или стандарт. Я показываю способы как МОЖНО сделать, а не как НЕОБХОДИМО.

Буду рад конструктивной критике, так как опыт в сфере «статьестроя» у меня не большой.

Всем пока, верней до встречи.

Автор: StMechanus

Источник


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js