Статьи

Spring MVC Form Tutorial

Этот туториал покажет, как обрабатывать отправку форм в Spring MVC. Мы определим контроллер для обработки загрузки страницы и отправки формы. Вы можете получить код на GitHub .

Предпосылки:

У вас должно быть рабочее Spring MVC Application. Если у вас еще нет настроенного рабочего приложения Spring MVC, следуйте этому руководству . Для этого урока мы создадим простую форму для подписки на рассылку. Форма будет иметь следующие поля:

  • имя — поле ввода
  • возраст — поле ввода
  • электронная почта — поле ввода
  • пол — выберите раскрывающийся список
  • receiveNewsletter — флажок
  • newsletterFrequency — выберите раскрывающийся список

Требования:

  • receiveNewsletter список receiveNewsletter должен быть активным, только если receiveNewsletter флажок receiveNewsletter
  • Мы не будем выполнять никаких проверок в этом примере (следите за обновлениями для будущего урока)
  • Когда пользователь отправит форму, та же страница перезагрузится
  • На перезагруженной странице должно отображаться сообщение о том, что отправка прошла успешно, и отображаются сохраненные значения

Когда мы закончим, у нас будет страница, которая выглядит следующим образом:

Скриншот формы Spring MVC

Во-первых, давайте настроим объект, который мы будем использовать для хранения информации подписчика. Создайте класс Subscriber в пакете com.codetutr.form . Это базовый Java-бин. Обратите внимание, что мы используем перечисления для хранения полей пола и частоты рассылки. Для простоты я определил перечисления в одном классе. Также обратите внимание, что мы определяем toString . Это просто, чтобы мы могли легко получить значения для печати после отправки.

Subscriber.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package com.codetutr.form;
 
public class Subscriber {
 
    private String name;
    private String email;
    private Integer age;
    private Gender gender;
    private Frequency newsletterFrequency;
    private Boolean receiveNewsletter;
 
    public enum Frequency {
        HOURLY, DAILY, WEEKLY, MONTHLY, ANNUALLY
    }
 
    public enum Gender {
        MALE, FEMALE
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getEmail() {
        return email;
    }
 
    public void setEmail(String email) {
        this.email = email;
    }
 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer age) {
        this.age = age;
    }
 
    public Gender getGender() {
        return gender;
    }
 
    public void setGender(Gender gender) {
        this.gender = gender;
    }
 
    public Frequency getNewsletterFrequency() {
        return newsletterFrequency;
    }
 
    public void setNewsletterFrequency(Frequency newsletterFrequency) {
        this.newsletterFrequency = newsletterFrequency;
    }
 
    public Boolean getReceiveNewsletter() {
        return receiveNewsletter;
    }
 
    public void setReceiveNewsletter(Boolean receiveNewsletter) {
        this.receiveNewsletter = receiveNewsletter;
    }
 
    @Override
    public String toString() {
        return "Subscriber [name=" + name + ", age=" + age + ", gender=" + gender
                + ", newsletterFrequency=" + newsletterFrequency
                + ", receiveNewsletter=" + receiveNewsletter + "]";
    }
 
}

Теперь давайте создадим контроллер. Создайте класс FormController в пакете com.codetutr.controller :

FormController.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.codetutr.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.codetutr.form.Subscriber;
import com.codetutr.form.Subscriber.Frequency;
 
@Controller
public class FormController {
 
    @ModelAttribute("frequencies")
    public Frequency[] frequencies() {
        return Frequency.values();
    }
 
    @RequestMapping(value="form", method=RequestMethod.GET)
    public String loadFormPage(Model m) {
        m.addAttribute("subscriber", new Subscriber());
        return "formPage";
    }
 
    @RequestMapping(value="form", method=RequestMethod.POST)
    public String submitForm(@ModelAttribute Subscriber subscriber, Model m) {
        m.addAttribute("message", "Successfully saved person: " + subscriber.toString());
        return "formPage";
    }
}

Давайте посмотрим на несколько вещей в коде выше. Во-первых, обратите внимание, что оба обработчика запросов (методы, аннотированные @RequestMapping ) отображаются на один и тот же URL — «форму». Единственное отличие в сопоставлении состоит в том, что один обрабатывает HTTP-запрос GET, а другой — POST. Первый обработчик (для запроса GET) будет вызван, когда пользователь перейдет на страницу «формы», потому что он получит доступ к странице с помощью запроса GET. Обработчик POST вызывается при отправке формы (поскольку она будет отправлена ​​через HTTP POST на URL-адрес «формы»). Конечно, вы можете отправить свою форму по любому URL-адресу, используя любой метод HTTP — просто убедитесь, что ваш обработчик соответствующим образом сопоставлен здесь.

Давайте посмотрим на обработчик GET. Требуется Model , которую мы заполняем пустым объектом Subscriber . Этот объект — то, что мы будем использовать для заполнения нашей формы. Здесь мы не устанавливаем никаких значений, но если мы хотим, скажем, установить по умолчанию флажок receiveNewsletter на true и установить частоту рассылки по умолчанию на почасовую, мы можем сделать:

1
2
3
4
Subscriber subscriber = new Subscriber();
subscriber.setReceiveNewsletter(true);
subscriber.setNewsletterFrequency(Frequency.HOURLY);
m.addAttribute("subscriber", subscriber);

Также обратите внимание, что если мы не добавим объект с именем «подписчик» в модель, Spring будет жаловаться, когда мы пытаемся получить доступ к JSP, потому что мы настроим JSP для привязки формы к атрибуту модели «подписчик». Вы увидите ошибку JSP: «Ни BindingResult, ни простой целевой объект для имени компонента« подписчик »недоступны в качестве атрибута запроса», и JSP не будет отображаться.

Последнее, на что нужно обратить внимание в коде контроллера, — это метод @ModelAttribute . Когда метод аннотируется с помощью @ModelAttribute , Spring запускает его перед каждым методом-обработчиком и добавляет возвращаемое значение в модель. Мы указали в аннотации, чтобы добавить значения частоты в модель как «частоты». Этот объект будет использоваться для заполнения раскрывающегося списка частоты рассылки в форме JSP. Вместо использования метода @ModelAttribute мы могли бы добавить следующую строку в каждый из обработчиков запросов:

1
m.addAttribute("frequencies", Frequency.values())

Наконец, давайте настроим JSP. Создайте файл с именем formPage.jsp в WEB-INF/view (или там, где вы настроили JSP):

formPage.jsp

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
 
<!DOCTYPE HTML>
<html>
  <head>
    <title>Sample Form</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <style>
      body { background-color: #eee; font: helvetica; }
      #container { width: 500px; background-color: #fff; margin: 30px auto; padding: 30px; border-radius: 5px; box-shadow: 5px; }
      .green { font-weight: bold; color: green; }
      .message { margin-bottom: 10px; }
      label {width:70px; display:inline-block;}
      form {line-height: 160%; }
      .hide { display: none; }
    </style>
  </head>
  <body>
 
  <div id="container">
 
    <h2>Subscribe to The Newsletter!</h2>
    <c:if test="${not empty message}"><div class="message green">${message}</div></c:if>
 
    <form:form modelAttribute="subscriber">
      <label for="nameInput">Name: </label>
      <form:input path="name" id="nameInput" />
      <br/>
 
      <label for="ageInput">Age: </label>
      <form:input path="age" id="ageInput" />
      <br/>
 
      <label for="emailInput">Email: </label>
      <form:input path="email" id="emailInput" />
      <br/>
 
      <label for="genderOptions">Gender: </label>
      <form:select path="gender" id="genderOptions">
        <form:option value="">Select Gender</form:option>
        <form:option value="MALE">Male</form:option>
        <form:option value="FEMALE">Female</form:option>
      </form:select>
      <br/>
 
      <label for="newsletterCheckbox">Newsletter? </label>
      <form:checkbox path="receiveNewsletter" id="newsletterCheckbox" />
      <br/>
      <label for="frequencySelect">Freq:</label>
      <form:select path="newsletterFrequency" id="frequencySelect">
        <form:option value="">Select Newsletter Frequency: </form:option>
        <c:forEach items="${frequencies}" var="frequency">
          <form:option value="${frequency}">${frequency}</form:option>
        </c:forEach>
      </form:select>
      <br/>
 
      <br/>
      <input type="submit" value="Submit" />
    </form:form>
  </div>
 
  <script type="text/javascript">
 
    $(document).ready(function() {
 
      toggleFrequencySelectBox(); // show/hide box on page load
 
      $('#newsletterCheckbox').change(function() {
        toggleFrequencySelectBox();
      })
 
    });
 
    function toggleFrequencySelectBox() {
      if(!$('#newsletterCheckbox').is(':checked')) {
        $('#frequencySelect').val('');
        $('#frequencySelect').prop('disabled', true);
      } else {
        $('#frequencySelect').prop('disabled', false);
      }
    }
 
  </script>
 
  </body>
</html>

Давайте пройдемся по тегам формы, которые мы используем. Обратите внимание на строку в верхней части страницы: <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> . Это импортирует теги Spring Form, которые мы будем использовать. Когда мы открываем форму с <form:form> , обратите внимание, что мы указываем атрибут модели. Это говорит Spring, чтобы искать атрибут в модели и связать его с формой. Атрибуты action и method также могут быть указаны. Если не указано (как в этом примере), они по умолчанию используют текущий URL и «POST» соответственно (как обычные формы HTML).

Обратите внимание, что каждое из наших полей ввода использует тег taglib Spring Form (form: prefix). Каждое из этих полей также указывает атрибут path . Это должно соответствовать получателю или установщику атрибута модели (в нашем случае, класса Subscriber) в соответствии со стандартным соглашением Java-бина (get / is, установить префикс с именем поля с заглавной буквой). Когда страница загружена, поля ввода заполняются Spring, который вызывает метод получения каждого поля, связанного с полем ввода. Когда форма отправляется, вызыватели вызывают для сохранения значений формы в объекте.

Теги <form:input> довольно понятны. Обратите внимание на два случая использования <form:select> . В первом раскрывающемся списке выбора для поля пола обратите внимание, что мы вручную перечисляем все параметры. В выпадающем меню выбора частоты в новостном бюллетене мы, однако, перебираем атрибут модели frequencies (помните, что мы добавили его в модель с помощью метода @ModelAttribute -annotated в контроллере) и добавляем каждый элемент в качестве параметра в раскрывающемся списке. Spring будет автоматически связывать значения формы с перечислениями при отправке формы, если значение выбранной опции является допустимым именем перечисления.

Когда форма отправлена, вызывается обработчик POST в контроллере. Форма автоматически связывается с аргументом подписчика, который мы передали. Аннотация @ModelAttribute здесь на самом деле не нужна. Я напишу больше об этом в другом посте.

Вот оно! Я настоятельно рекомендую вам скачать исходный код и запустить код. Оставляйте любые вопросы в комментариях ниже.

Полный исходный код : ZIP , GitHub Чтобы запустить код из этого урока: необходимо установить Gradle . Загрузите ZIP. Extract. Откройте командную строку для извлеченного местоположения. Запустите gradle jettyRunWar. Перейдите в браузере по адресу http: // localhost: 8080 / form.

Ресурсы

Ссылка: Spring MVC Form Tutorial от нашего партнера JCG Стива Хэнсона в блоге CodeTutr .