Skip to content

5. Веб-додаток MVC [personne] — версія 1

5.1. Види додатка

Додаток використовує ту саму форму, що й у попередніх прикладах. Перша сторінка додатка виглядає так:

Image

Цю сторінку ми назвемо [formulaire]. Якщо ввести правильні дані, вони відображаються на сторінці, яку ми назвемо [réponse]:

Image

Якщо дані введені неправильно, помилки відображаються у вікні з назвою [erreurs]:

Image

5.2. Архітектура додатка

Веб-додаток [personne1] матиме таку архітектуру:

Image

Ця архітектура є однорівневою: немає шарів [métier] або [dao], є лише один шар [web]. [ServletPersonne] — це контролер додатка, який обробляє всі запити клієнтів. Для відповіді на них він використовує один із трьох виглядів [formulaire, réponse, erreurs].

Нам потрібно з’ясувати, як контролер [ServletPersonne] визначає дію, яку він повинен виконати після отримання запиту від користувача. Запит клієнта — це потік HTTP, який відрізняється залежно від того, чи зроблено його за допомогою команди GET чи POST.

Запит GET

У цьому випадку потік HTTP виглядає наступним чином:

GET /URL HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0,5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
[ligne vide]

У рядку 1 вказано URL-адресу запиту, наприклад:

GET /personne1/ HTTP/1.1

Цю URL-адресу можна використовувати для визначення дії, яку потрібно виконати. Для цього можна використовувати різні методи:

  1. параметр URL-адреси визначає дію, наприклад [/appli?action=ajouter&id=4]. У цьому випадку параметр [action] вказує контролеру, яку дію від нього вимагають.
  2. останній елемент URL-адреси визначає дію, наприклад [/appli/ajouter?id=4]. У цьому випадку останній елемент URL-адреси [/ajouter] використовується контролером для визначення дії, яку він повинен виконати.

Можливі й інші варіанти. Два попередні є найпоширенішими.

Запит POST

У цьому випадку потік HTTP виглядає наступним чином:

POST /URL HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost:8080/personne1/main
Cookie: JSESSIONID=9F5E5BFA29643FC6B1601EEED907E1F9
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
[ligne vide]
txtNom=&txtAge=&action=validationFormulaire

У рядку 1 вказано запитуваний URL-адресу, наприклад:

POST /personne1/main HTTP/1.1

Цю URL-адресу можна використовувати для визначення дії, яку потрібно виконати, як у випадку з GET. У випадку з GET параметр [action] був інтегрований у URL. Це може бути також і в даному випадку, як-от:

POST /appli?action=ajouter&id=4 HTTP/1.1

Але параметр [action] також може бути включений до надісланих параметрів (рядок 15 вище), як у:

POST /appli HTTP/1.1
...
[ligne vide]
action=ajouter&id=4

Далі ми використаємо ці різні методи, щоб вказати контролеру, що він повинен робити:

  • включити параметр action у запитуваний URL-адресу:
POST /appli?action=ajouter&id=4 HTTP/1.1
  • відправити параметр action:
POST /appli HTTP/1.1
...
[ligne vide]
action=ajouter&id=4
  • використовувати останній елемент URL-адреси як ім'я дії:
POST /appli/ajouter?id=4 HTTP/1.1

5.3. Проєкт Eclipse

Щоб створити проект Eclipse [mvc-personne-01] для веб-додатка [personne1], слід дотримуватися покрокової інструкції, описаної в розділі 3.1.

Image

Не слід залишати контекст [mvc-personne-01], запропонований за замовчуванням. Слід вибрати [personne1], як показано нижче:

Image

Отриманий результат такий:

Image

Якщо раптом знадобиться змінити контекст веб-додатку, слід використати опцію [clic droit sur projet -> Properties -> J2EE]:

Image

У [1] вказується новий контекст.

Ми створимо підпапку [vues] у папці [WEB-INF]: [clic droit sur WEB-INF -> New -> Folder]:

Новий проект тепер виглядає так:

Image

Після завершення проект матиме такий вигляд:

Image

  • контролер [ServletPersonne] знаходиться у папці [src]
  • сторінки JSP з переглядів [formulaire, réponse, erreurs] знаходяться у папці [WEB-INF/vues], що не дозволяє користувачеві безпосередньо їх викликати, як показано у прикладі нижче:

Image

Тепер ми опишемо різні компоненти веб-додатку [/personne1]. Читачеві пропонується створювати їх у міру читання.

5.4. Налаштування веб-додатку [personne1]

Файл web.xml додатка /personne1 матиме такий вигляд:


<?xml version="1.0" encoding="UTF-8"?>
<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>mvc-personne-01</display-name>
    <!--  ServletPersonne -->
    <servlet>
        <servlet-name>personne</servlet-name>
        <servlet-class>
            istia.st.servlets.personne.ServletPersonne
        </servlet-class>
        <init-param>
            <param-name>urlReponse</param-name>
            <param-value>
                /WEB-INF/vues/reponse.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlErreurs</param-name>
            <param-value>
                /WEB-INF/vues/erreurs.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlFormulaire</param-name>
            <param-value>
                /WEB-INF/vues/formulaire.jsp
            </param-value>
        </init-param>
    </servlet>
    <!--  Мапування ServletPersonne-->
    <servlet-mapping>
        <servlet-name>personne</servlet-name>
        <url-pattern>/main</url-pattern>
    </servlet-mapping>
    <!--  файли головних сторінок -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Що міститься в цьому файлі конфігурації?

  • рядки 34–37: URL /main обробляється сервлетом з назвою «person»
  • рядки 10–13: сервлет з назвою «personne» є екземпляром класу [ServletPersonne]
  • рядки 14–19: визначають параметр конфігурації з назвою [urlReponse]. Це URL-адреса подання [réponse].
  • рядки 20–25: визначають параметр конфігурації з іменем [urlErreurs]. Це URL-адреса подання [erreurs].
  • рядки 26–31: визначають параметр конфігурації з назвою [urlFormulaire]. Це URL-адреса подання [formulaire].
  • рядок 40: [index.jsp] буде головною сторінкою додатка.

URL-адреси сторінок JSP та переглядів [formulaire, réponse, erreurs] окремо задаються конфігураційними параметрами. Це дозволяє переміщувати їх без необхідності перекомпіляції додатка.

Коли користувач звернеться за URL-адресою [/personne1], відповідь надішле файл [index.jsp] (файл-початкова сторінка, рядок 40). Цей файл знаходиться в кореневій папці [WebContent]:

Image

Його вміст такий:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
  response.sendRedirect("/personne1/main");
%>

Сторінка [index.jsp] просто перенаправляє клієнта на URL-адресу [/personne1/main]. Отже, коли браузер запитує URL-адресу [/personne1], [index.jsp] надсилає йому таку відповідь HTTP:

1
2
3
4
5
6
7
HTTP/1.x 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=9F5E5BFA29643FC6B1601EEED907E1F9; Path=/personne1
Location: http://localhost:8080/personne1/main
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 0
Date: Thu, 18 May 2006 15:45:23 GMT
  • рядок 1: відповідь HTTP/1.1, щоб вказати серверу перенаправити запит на інший URL
  • рядок 4: URL, на яку має перенаправитися браузер

Після отримання цієї відповіді браузер, відповідно до вказівки (рядок 4), надішле запит на URL-адресу [/personne1/main]. Файл [web.xml] додатка [/personne1] вказує, що цей запит буде оброблено контролером [ServletPersonne] (рядки 35–36).

5.5. Код подання

Ми розпочинаємо розробку веб-додатку з написання його представлень. Вони дозволяють визначити потреби користувача щодо графічного інтерфейсу та можуть бути протестовані без контролера.

5.5.1. Вигляд [formulaire]

Цей вигляд відповідає формі для введення імені та віку:

Image

тип HTML
ім'я
роль
1
<input type= "text ">
txtNom
введення імені
2
<input type= "text ">
txtAge
введення віку
3
<input type= "submit ">
 
відправлення введених значень на сервер за адресою /personne1/main
4
<input type= "reset ">
 
для повернення сторінки до стану, в якому вона була спочатку отримана браузером
5
<input type= "button ">
 
для очищення вмісту полів введення [1] та [2]

Вона генерується сторінкою JSP [formulaire.jsp]. Її шаблон складається з таких елементів:

  • [nom]: ім’я (String), знайдене в атрибутах сесії, пов’язаних із ключем «nom»
  • [age]: вік (String), знайдений у атрибутах сесії, пов’язаних із ключем «age»

Вигляд [formulaire] отримується, коли користувач запитує URL-адресу [/personne1/main], c.a.d. URL-адреса контролера [ServletPersonne]. Код сторінки JSP [formulaire.jsp], який генерує вигляд [formulaire], є таким:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
    // отримуємо дані з моделі
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
    
<html>
    <head>
      <title>Personne - formulaire</title>
  </head>
  <body>
      <center>
        <h2>Personne - formulaire</h2>
      <hr>
      <form method="post">
          <table>
            <tr>
              <td>Nom</td>
            <td><input name="txtNom" value="<%= nom %>" type="text" size="20"></td>
          </tr>
          <tr>
              <td>Age</td>
            <td><input name="txtAge" value="<%= age %>" type="text" size="3"></td>
          </tr>
            <tr>
        </table>
        <table>
            <tr>
              <td><input type="submit" value="Envoyer"></td>
            <td><input type="reset" value="Rétablir"></td>
            <td><input type="button" value="Effacer"></td>
          </tr>
        </table>
        <input type="hidden" name="action" value="validationFormulaire"> 
      </form>
    </center>
  </body>
</html>

  • рядки 6–7: сторінка JSP спочатку отримує з запиту [request] елементи [nom, age] своєї моделі. Під час нормальної роботи додатка цю модель створюватиме контролер [ServletPersonne].
  • рядки 18–38: сторінка JSP згенерує форму HTML (тег <form>)
  • рядок 18: тег <form> не має атрибута action для вказівки URL-адреси, яка має обробляти значення, надіслані кнопкою [Envoyer] типу submit (рядок 32). Тоді значення форми будуть відправлені на URL-адресу, з якої була отримана форма, тобто на URL-адресу контролера [ServletPersonne]. Таким чином, цей контролер використовується як для генерації порожньої форми, яка спочатку запитувалася за допомогою GET, так і для обробки введених даних, які будуть надіслані йому за допомогою кнопки [Envoyer].
  • Передані значення відповідають полям HTML, [txtNom] (рядок 22), [txtAge] (рядок 26) та [action] (рядок 37). Цей останній параметр дозволить контролеру зрозуміти, що йому потрібно зробити.
  • Під час початкового відображення форми поля введення [txtNom, txtAge] ініціалізуються відповідно змінними [nom] (рядок 22) та [age] (рядок 26). Ці змінні отримують значення своїх атрибутів із запиту (рядки 6–7), які, як відомо, ініціалізуються сервлетом. Отже, саме сервлет визначає початковий вміст полів введення форми.
  • рядок 33: кнопка [Rétablir] типу [reset] дозволяє повернути форму до того стану, в якому вона перебувала, коли браузер її отримав.
  • рядок 34: кнопка [Effacer] типу [reset] наразі не виконує жодної функції.

Надалі ми будемо називати цей вигляд «[formulaire(nom, age)]», коли захочемо вказати одночасно назву виду та його модель. Крім того, слід пам’ятати, що коли користувач натискає на кнопку [Envoyer], параметри [txtNom, txtAge] надсилаються на URL-адресу [/personne1/main].

5.5.2. Вигляд [reponse]

Цей вигляд відображає значення, введені у форму, якщо вони є дійсними:

Image

Вона генерується сторінкою JSP [reponse.jsp]. Її шаблон складається з таких елементів:

  • [nom]: ім’я (String), яке буде знайдено в атрибутах сесії, пов’язане з ключем «nom»
  • [age]: вік (String), який буде знайдено в атрибутах сесії, пов’язаний із ключем «age»

Код сторінки JSP [reponse.jsp] такий:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
    // отримуємо дані з моделі
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Personne - réponse</h2>
    <hr>
    <table>
        <tr>
          <td>Nom</td>
        <td><%= nom %>
      </tr>
        <tr>
          <td>Age</td>
        <td><%= age %>
      </tr>
    </table>      
  </body>
</html>

  • рядки 6–7: сторінка JSP спочатку отримує із запиту [request] елементи [nom, age] своєї моделі. Під час нормальної роботи додатка саме контролер [ServletPersonne] буде формувати цю модель.
  • Елементи [nom, age] моделі потім відображаються у рядках 20 та 24

Надалі ми називаємо цей вигляд «[réponse(nom, age)]».

5.5.3. Вигляд [erreurs]

Цей вигляд повідомляє про помилки введення даних у формі:

Image

Вона генерується сторінкою JSP [erreurs.jsp]. Її шаблон складається з таких елементів:

  • [erreurs]: список (ArrayList) повідомлень про помилки, який міститься в атрибутах запиту та пов’язаний із ключем «помилки»

Код сторінки JSP [erreurs.jsp] є таким:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ page import="java.util.ArrayList" %>

<%
// отримуємо дані з моделі
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>
    <ul>
        <%
          for(int i=0;i<erreurs.size();i++){
            out.println("<li>" + (String) erreurs.get(i) + "</li>\n");
        }//for
      %>
    </ul>
  </body>
</html>

  • рядок 8: сторінка JSP починається з вилучення із запиту [request] елемента [erreurs] своєї моделі. Цей елемент представляє об’єкт типу ArrayList, що складається з елементів типу String. Ці елементи є повідомленнями про помилки. Під час нормальної роботи додатка саме контролер [ServletPersonne] формуватиме цю модель.
  • рядки 18–22: відображають список повідомлень про помилки. Для цього доводиться писати код Java у тілі HTML сторінки. Слід завжди прагнути звести його до мінімуму, щоб не захаращувати код HTML. Пізніше ми побачимо, що існують рішення, які дозволяють зменшити обсяг коду Java на сторінках JSP.
  • рядок 4: зверніть увагу на тег імпорту пакетів, необхідних для сторінки JSP

Далі ми називаємо цей вигляд «[erreurs(erreurs)]».

5.6. Тестування подання

Можна перевірити правильність роботи сторінок JSP, не написавши контролер. Для цього необхідні дві умови:

  • необхідно мати можливість запитувати їх безпосередньо в додатку, оминаючи контролер
  • сторінка JSP повинна самостійно ініціалізувати модель, яку зазвичай створює контролер

Щоб провести ці тести, ми дублюємо сторінки JSP з поданнями у папці [/WebContent/JSP] проекту Eclipse:

Image

Потім у папці JSP сторінки змінюються наступним чином:

[formulaire.jsp]:


...

<%
  // -- тест: створюємо шаблон сторінки
  request.setAttribute("nom","tintin");
  request.setAttribute("age","30");
%>

<%
    // отримуємо дані з шаблону
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
    
<html>
    <head>
...

Рядки 3–7 було додано для створення шаблону, необхідного для сторінки рядків 11–12.

[reponse.jsp]:


...

<%
  // -- тест: створюємо шаблон сторінки
  request.setAttribute("nom","milou");
  request.setAttribute("age","10");
%>

<%
    // отримуємо дані з шаблону
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>

    
<html>
    <head>
...

Рядки 3–7 було додано для створення шаблону, необхідного для сторінки рядків 11–12.

[erreurs.jsp]:


...

<%
  // -- тест: створюємо шаблон сторінки
  ArrayList<String> erreurs1=new ArrayList<String>();
  erreurs1.add("erreur1");
  erreurs1.add("erreur2");
  request.setAttribute("erreurs",erreurs1);
%>

<%
// отримуємо дані з шаблону
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>

    
<html>
    <head>
...

Рядки 3–9 було додано для створення шаблону, необхідного для сторінки, зазначеної в рядку 13.

Запустіть Tomcat, якщо це ще не зроблено, а потім завантажте такі URL-адреси:

 

Ми отримуємо очікувані результати. Тепер, коли ми маємо достатню впевненість у сторінках JSP додатка, можемо перейти до написання його контролера [ServletPersonne].

5.7. Контролер [ServletPersonne]

Залишилося написати серце нашого веб-додатку — контролер. Його роль полягає в тому, щоб:

  • отримувати запит від клієнта,
  • обробити запитувану ним дію,
  • відправити у відповідь відповідний вигляд.

Контролер [ServletPersonne] оброблятиме такі дії:

запит
джерело
обробка
1
[GET /personne1/main]
URL-адреса, введена користувачем
- надіслати порожній вигляд [formulaire]
2
[POST /personne1/main]
з параметрами [txtNom,
txtAge, дія] опубліковано
натискання на кнопку
[Envoyer] у вікні
[formulaire]
- перевірити значення параметрів [txtNom, txtAge]
- якщо вони неправильні, надіслати вигляд [erreurs(erreurs)]
- якщо вони правильні, надіслати вигляд [reponse(nom,age)]

Додаток запускається, коли користувач надсилає запит на URL-адресу [/personne1/main]. Згідно з файлом [web.xml] додатка (див. розділ 5.4), цей запит обробляється екземпляром типу ServletPersonne, який ми зараз опишемо.

5.7.1. Структура контролера

Код контролера [ServletPersonne] має такий вигляд:

package istia.st.servlets.personne;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
...

     // ініціалізація
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
    }

    @SuppressWarnings("unchecked")
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
...
    }

     // відображення початкового виду
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
...
    }

     // перевірка форми
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
...
    }

     // відправка
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
         // передача управління до GET
        doGet(request, response);
    }
}
  • рядки 20–22: метод [init], що виконується під час початкового завантаження сервлета
  • рядки 25–28: метод [doGet], який викликається веб-сервером, коли до додатка надходить запит типу GET
  • рядки 42–46: метод [doPost], що викликається веб-сервером, коли до додатка надходить запит типу POST. Як показано, цей запит також оброблятиметься методом [doGet] (рядок 45).
  • рядки 31–33: метод [doInit] обробляє дію № 1 [GET /personne1/main]
  • рядки 36–39: метод [doValidationFormulaire] обробляє дію № 2 [POST /personne1/main] із переданими параметрами [txtNom, txtAge, action].

Тепер опишемо різні методи контролера

5.7.2. Ініціалізація контролера

Коли клас контролера завантажується контейнером сервлетів, виконується його метод [init]. Це відбудеться лише один раз. Після завантаження в пам'ять контролер залишатиметься там і оброблятиме запити різних клієнтів. Для кожного клієнта створюється окремий потік виконання, і таким чином методи контролера виконуються одночасно різними потоками. Нагадаємо, що з цієї причини контролер не повинен мати полів, які його методи могли б змінювати. Його поля повинні бути доступними лише для читання. Вони ініціалізуються методом [init], що є його основною функцією. Цей метод має особливість: він виконується лише один раз одним потоком. Отже, у цьому методі не виникає проблем з паралельним доступом до полів контролера. Метод [init] призначений для ініціалізації об’єктів, необхідних для веб-додатка, які будуть спільними для всіх клієнтських потоків у режимі «тільки для читання». Ці спільні об’єкти можна розмістити у двох місцях:

  • у приватних полях контролера
  • контекст виконання додатка (ServletContext)

Код методу [init] контролера [ServletPersonne] має такий вигляд:

package istia.st.servlets.personne;

...
@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     // параметри екземпляра
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();

     // ініціалізація
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
         // отримуємо параметри ініціалізації сервлета
        ServletConfig config = getServletConfig();
         // обробка інших параметрів ініціалізації
        String valeur=null;
        for(int i=0;i<paramètres.length;i++){
             // значення параметра
            valeur=config.getInitParameter(paramètres[i]);
             // параметр присутній?
            if(valeur==null){
                 // фіксується помилка
                erreursInitialisation.add("Le paramètre ["+paramètres[i]+"] n'a pas été initialisé");
            }else{
                 // зберігаємо значення параметра
                params.put(paramètres[i],valeur);
            }
             // URL-адреса подання [erreurs] обробляється окремо
            urlErreurs = config.getInitParameter("urlErreurs");
            if (urlErreurs == null)
                throw new ServletException(
                        "Le paramètre [urlErreurs] n'a pas été initialisé");
        }
    }
...
}
  • рядок 16: отримується конфігурація веб-додатку c.a.d. Зміст файлу [web.xml]
  • у рядках 19–29 отримуються параметри ініціалізації сервлета, імена яких визначені в таблиці [paramètres] у рядку 9
  • рядок 21: отримується значення параметра
  • рядок 25: якщо параметр відсутній, помилка додається до списку помилок [erreursInitialisation], який спочатку був порожнім (рядок 8).
  • рядок 28: якщо параметр присутній, він зберігається разом зі своїм значенням у словнику [params], який спочатку був порожнім (рядок 10).
  • рядки 31–35: параметр [urlErreurs] має обов’язково бути присутнім, оскільки він вказує URL-адресу подання [erreurs], здатного відображати можливі помилки ініціалізації. Якщо його немає, додаток припиняється шляхом запуску [ServletException] (рядок 33).

5.7.3. Метод [doGet]

Метод [doGet] обробляє як запити GET, так і POST у сервлеті, оскільки метод [doPost] перенаправляє на метод [doGet]. Його код такий:

package istia.st.servlets.personne;

...
@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     // параметри екземпляра
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();

...
    @SuppressWarnings("unchecked")
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

         // перевіряється, як пройшла ініціалізація сервлета
        if (erreursInitialisation.size() != 0) {
             // передаємо управління сторінці помилок
            request.setAttribute("erreurs", erreursInitialisation);
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
             // кінець
            return;
        }

         // отримуємо метод відправлення запиту
        String méthode=request.getMethod().toLowerCase();
         // отримуємо дію, яку потрібно виконати
        String action=request.getParameter("action");
         // дія?
        if(action==null){
            action="init";
        }
         // виконання дії
        if(méthode.equals("get") && action.equals("init")){
             // запуск програми
            doInit(request,response);
            return;
        }
        if(méthode.equals("post") && action.equals("validationFormulaire")){
             // перевірка форми введення даних
            doValidationFormulaire(request,response);
            return;
        }
         // інші випадки
        doInit(request,response);
    }

     // відправлення
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
         // передача управління GET
        doGet(request, response);
    }
}
  • рядки 18–25: перевіряється, чи список помилок ініціалізації порожній. Якщо це не так, відображається представлення [erreurs(erreursInitialisation)], яке повідомить про помилку або помилки.

Щоб зрозуміти цей код, слід згадати шаблон подання [erreurs]:

<%
// отримання даних з моделі
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>

Вигляд [erreurs] очікує на елемент ключа «errors» у запиті. Контролер створює цей елемент у рядку 20.

  • рядок 28: отримується метод [get] або [post], який клієнт використав для формування свого запиту
  • рядок 30: отримується значення параметра [action] із запиту. Нагадаємо, що в нашому додатку лише запит № 2 [POST /personne1/main] має параметр [action]. У цьому запиті він має значення [validationFormulaire].
  • рядки 31–34: якщо параметр [action] відсутній, йому присвоюється значення «init». Це відбудеться під час початкового запиту № 1 [GET /personne1/main].
  • рядки 36–40: обробка запиту № 1 [GET /personne1/main].
  • рядки 41–45: обробка запиту № 2 [POST /personne1/main].
  • рядок 47: якщо ситуація не відповідає жодному з двох попередніх випадків, діють так, ніби це випадок № 1

5.7.4. Метод [doInit]

Цей метод обробляє запит № 1 [GET /personne1/main]. Для цього запиту він повинен надіслати порожній вигляд [formulaire(nom,age)]. Його код такий:

package istia.st.servlets.personne;
...

@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     // параметри екземпляра
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();

...    
     // відображення початкового виду
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // надсилаємо порожню форму
        request.setAttribute("nom", "");
        request.setAttribute("age", "");
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }
...
}
  • рядки 18–19: відображається представлення [formulaire]. Нагадаємо, який шаблон очікується для цього представлення:

<%
    // отримуємо дані з моделі
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
  • рядки 16–17: шаблон [nom,age] з подання [formulaire] ініціалізується порожніми рядками.

5.7.5. Метод [doValidationFormulaire]

Цей метод обробляє запит № 2 [POST /personne1/main], у якому передані параметри — [action, txtNom, txtAge]. Його код такий:

package istia.st.servlets.personne;

...
@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     // параметри екземпляра
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();
...
     // перевірка форми
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
         // отримання параметрів
        String nom = request.getParameter("txtNom");
        String age = request.getParameter("txtAge");
         // перевірка параметрів
        ArrayList<String> erreursAppel = new ArrayList<String>();
         // ім'я не може бути порожнім
        nom = nom.trim();
        if (nom.equals(""))
            erreursAppel.add("Le champ [nom] n'a pas été rempli");
         // вік має бути цілим числом >=0
        if (!age.matches("^\\s*\\d+\\s*$"))
            erreursAppel.add("Le champ [age] est erroné");
         // чи є помилки в параметрах?
        if (erreursAppel.size() != 0) {
             // відправляємо сторінку з повідомленням про помилки
            request.setAttribute("erreurs", erreursAppel);
            getServletContext().getRequestDispatcher(urlErreurs).forward(request, response);
            return;
        }
         // параметри правильні — надсилається сторінка відповіді
        request.setAttribute("nom", nom);
        request.setAttribute("age", age);
        getServletContext().getRequestDispatcher((String)params.get("urlReponse")).forward(request,
                response);
        return;
    }
...
}
  • рядки 16–17: із запиту клієнта отримуються значення параметрів «txtNom» та «txtAge».
  • рядки 19–26: перевіряється правильність цих двох параметрів
  • рядки 28–33: якщо один із параметрів є помилковим, відображається подання [erreurs(erreursAppel)]. Нагадаємо модель цього подання:

<%
// отримуємо дані з шаблону
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>
  • рядки 35–38: якщо обидва отримані параметри «txtNom» та «txtAge» мають допустимі значення, відображається погляд [reponse(nom,age)]. Слід згадати шаблон подання [reponse]:

<%
    // отримуємо дані з моделі
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>

5.8. Tests

Додамо проект [mvc-personne-01] до додатків Tomcat, дотримуючись процедури, описаної в розділі 3.3:

Image

Запустіть Tomcat. Після цього можна продовжити тестування, наведене як приклад у розділі 5.1. Можна додати й інші тести. Наприклад, можна видалити один із параметрів конфігурації urlXXX у web.xml і подивитися на результат. Так, як показано нижче, один із параметрів виведено у коментарі в [web.xml]:


        <!-- 
            <init-param>
              <param-name>urlFormulaire</param-name>
              <param-value>
                /WEB-INF/vues/formulaire.jsp
              </param-value>
            </init-param>
        -->

Запускаємо / перезапускаємо Tomcat і звертаємося за URL-адресою [http://localhost:8080/personne1/main]. Отримуємо таку відповідь:

Image