2. Основи веб-програмування
Основна мета цього розділу — ознайомити читача з основними принципами веб-програмування, які не залежать від конкретної технології, що використовується для їх реалізації. У ньому наведено чимало прикладів, які рекомендується випробувати, щоб поступово «зануритися» у філософію веб-розробки. Читач, який вже володіє цими знаннями, може перейти безпосередньо до розділу 3.
Компоненти веб-додатку такі:

Номер | Роль | Поширені приклади |
1 | OS Сервер | Unix, Linux, Windows |
2 | Веб-сервер | Apache (Unix, Linux, Windows) IIS (Windows + платформа .NET) Node.js (Unix, Linux, Windows) |
3 | Код, що виконується на стороні сервера. Він може виконуватися модулями сервера або програмами, зовнішніми щодо сервера (CGI). | JAVASCRIPT (Node.js) PHP (Apache, IIS) JAVA (Tomcat, Websphere, JBoss, Weblogic, ...) C#, VB.NET (IIS) |
4 | База даних — вона може розміщуватися на тому самому комп’ютері, що й програма, яка її використовує, або на іншому комп’ютері через Інтернет. | Oracle (Linux, Windows) MySQL (Linux, Windows) Postgres (Linux, Windows) SQL Server (Windows) |
5 | OS Клієнт | Unix, Linux, Windows |
6 | Веб-браузер | Chrome, Internet Explorer, Firefox, Opera, Safari, ... |
7 | Скрипти, що виконуються на стороні клієнта в браузері. Ці скрипти не мають доступу до дисків клієнтського комп'ютера. | JavaScript (усі браузери) |
2.1. Обмін даними у веб-додатку з використанням форми

Номер | Роль |
1 | Браузер вперше надсилає запит URL на (http://machine/url). Параметри не передаються. |
2 | Веб-сервер надсилає їй веб-сторінку з кодом URL. Вона може бути статичною або динамічно згенерованою серверним скриптом (SA), який міг використовувати вміст баз даних (SB, SC). У цьому випадку скрипт виявить, що запит на URL надійшов без передачі параметрів, і згенерує початкову веб-сторінку. Браузер отримує сторінку та відображає її (CA). Скрипти на стороні браузера (CB) могли змінити початкову сторінку, надіслану сервером. Потім у результаті взаємодії між користувачем (CD) та скриптами (CB) веб-сторінка буде змінена. Зокрема, будуть заповнені форми. |
3 | Користувач підтверджує дані форми, які потім мають бути надіслані на веб-сервер. Браузер повторно запитує початкову сторінку URL або іншу, залежно від обставин, і одночасно передає серверу значення з форми. Для цього він може використовувати два методи, що називаються GET та POST. Отримавши запит від клієнта, сервер запускає скрипт (SA), пов’язаний із запитаним URL, який виявляє параметри та обробляє їх. |
4 | Сервер видає веб-сторінку, сформовану програмно (SA, SB, SC). Цей етап ідентичний попередньому етапу 2. Обмін даними відтепер відбувається відповідно до етапів 2 та 3. |
2.2. Статичні веб-сторінки, динамічні веб-сторінки
Статична сторінка представлена файлом HTML. Динамічна сторінка — це сторінка HTML, яка генерується «на льоту» веб-сервером.
2.2.1. Статична сторінка HTML (мова розмітки HyperText)
Створимо перший проект Spring MVC [1-2]:
![]() |
- у [1-2] ми створюємо новий проєкт на базі Spring Boot [http://projects.spring.io/spring-boot/];
![]() |
- інформація [3-7] стосується налаштування Maven для проєкту;
- у [3] вказано назву проекту Maven;
- у [4] вказано групу Maven, до якої буде розміщено результат компіляції проєкту;
- у [5] — назва продукту компіляції;
- у [6] — опис проекту;
- [7] — пакет, у який буде розміщено виконуваний клас проекту;
- у [8] — тип проекту. Це веб-проект із Thymeleaf-шаблонами. Тут можна побачити всі готові до використання залежності Maven, що надаються проектом Spring Boot;
- у полі [9] вказується, що результат збірки Maven буде упаковано в архів jar, а не war. Проект використовуватиме вбудований сервер Tomcat, який буде серед його залежностей;
- у [10] ми переходимо до наступного кроку майстра;
![]() |
- у [11] вказується папка проекту;
- у [12] завершуємо роботу майстра;
- у [13] — згенерований проект.
Розглянемо згенерований файл [pom.xml]:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st.springmvc</groupId>
<artifactId>intro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springmvc-intro</name>
<description>Les bases de la programmation web</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.9.RELEASE</version>
<relativePath /> <!-- пошук батьківського елемента в репозиторії -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>istia.st.springmvc.Application</start-class>
<java.version>1.7</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Він містить усю інформацію, вказану в майстрі. У рядках 26–30 ми бачимо залежність, про яку раніше не знали. Вона дозволяє інтегрувати модульні тести JUnit із Spring.
Почнемо зі створення статичної сторінки HTML у цьому проєкті. За замовчуванням її слід розмістити в папці [src / main / resources / static]:
![]() |
- у [1-4] створюємо файл HTML у папці [static];
![]() |
- в [6], надайте назву сторінці;
- у [7] — сторінка додана.
Вміст створеної сторінки такий:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
- рядки 2–10: код обмежується кореневим тегом <html>;
- рядки 3–6: тег <head> обмежує так званий заголовок сторінки;
- рядки 7–9: тег <body> обмежує так званий основний вміст сторінки.
Змінимо цей код наступним чином:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>essai 1 : une page statique</title>
</head>
<body>
<h1>Une page statique...</h1>
</body>
</html>
- рядок 5: визначає заголовок сторінки — він відображатиметься як заголовок вікна браузера, у якому відкрито сторінку;
- рядок 8: текст, набраний великими літерами (<h1>).
Запустимо додаток [1-3]:
![]() |
потім за допомогою браузера відкриємо URL [http://localhost:8080/exemple-01.html]:
![]() |
- у [1] — URL переглянутої сторінки;
- в [2] — заголовок вікна, який було отримано з тегу <title> сторінки;
- в [3] — основний текст сторінки, який було отримано з тегу <h1>.
Розглянемо [4-5] — код HTML, отриманий браузером:
![]() |
- у [5] браузер отримав сторінку HTML, яку ми створили. Він її проаналізував і перетворив на графічне зображення.
2.2.2. Динамічна сторінка Thymeleaf
Тепер створимо сторінку Thymeleaf. Це класична сторінка HTML з тегами, розширеними атрибутами [Thymeleaf] та [http://www.thymeleaf.org/]. Ми дотримуємося підходу, аналогічного тому, що використовувався при створенні сторінки HTML, але цього разу нову сторінку HTML потрібно розмістити в папці [templates]:
![]() |
Сторінка [exemple-02.html] матиме такий вигляд:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>spring mvc intro</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Il est ' + ${heure}">Voici l'heure</p>
</body>
</html>
- рядок 8: тег <p> є тегом HTML, який вводить абзац на відображуваній сторінці. [th:text] — це атрибут [Thymeleaf], який має два різних призначення залежно від того, чи діє [Thymeleaf]:
- якщо [Thymeleaf] не інтерпретує сторінку HTML, атрибут [th:text] буде проігноровано, оскільки він невідомий у HTML. У цьому випадку відображатиметься текст [Voici l'heure],
- якщо [Thymeleaf] інтерпретує сторінку HTML, атрибут [th:text] буде обчислено, і його значення замінить текст [Voici l'heure]. Його значення буде виглядати приблизно так: [Il est 17:11:06];
Давайте подивимося, як це працює на практиці. Ми дублюємо сторінку [templates / exemple-02.html] у папці [static]. Сторінки HTML, розміщені в цій папці, не інтерпретуються [Thymeleaf]:
![]() | ![]() | ![]() |
Ми запускаємо програму, як це вже робили кілька разів, а потім за допомогою браузера запитуємо файли URL та [http://localhost:8080/exemple-02.html]:
![]() |
У [1] ми бачимо, що атрибут [th:text] не був інтерпретований, але й не спричинив помилки. Вихідний код сторінки, отриманий у [2], показує, що браузер успішно отримав повну сторінку.
Повернемося до сторінки [exemple-02.html] у папці [templates]:
![]() |
Сторінки HTML, розміщені в папці [templates], інтерпретуються файлом [Thymeleaf]. Повернемося до коду сторінки:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>spring mvc intro</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Il est ' + ${heure}">Voici l'heure</p>
</body>
</html>
- рядок 7: [Thymeleaf] інтерпретує атрибут [th:text] і замінить [Voici l'heure] на значення виразу:
Цей вираз використовує змінну [${heure}], де [heure] належить до моделі подання [exemple-02.html]. Отже, нам потрібно створити цю модель. Для цього ми скористаємося прикладом, розглянутим у розділі 1.6. Ми змінюємо проект наступним чином:
![]() |
У [1] додаємо такий контролер:
package istia.st.springmvc;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MyController {
@RequestMapping("/")
public String heure(Model model) {
// формат часу
SimpleDateFormat formater = new SimpleDateFormat("HH:MM:ss");
// поточний час
String heure = formater.format(new Date());
// встановлюємо час у шаблоні подання
model.addAttribute("heure", heure);
// відображення подання [exemple-02.html]
return "exemple-02";
}
}
- рядки 13–14: метод [heure] обробляє URL та [/];
- рядок 14: [Model model] — це порожня модель. Дія [heure] повинна додати до неї атрибути, які вона хоче бачити в моделі. Відомо, що представлення [exemple-02.html] очікує атрибут із назвою [heure];
- рядки 19–22: реалізують те, що щойно було пояснено. Вигляд [exemple-02.html] буде відображено (рядок 22) із атрибутом у його шаблоні, що має назву [heure] (рядок 20);
- рядок 16: створюється форматувач дати. Використовуваний формат [HH:MM:ss] є форматом [heures:minutes:secondes], у якому години знаходяться в діапазоні [0-24];
- рядок 18: за допомогою цього форматувальника форматується сьогоднішня дата;
- рядок 20: отриманий час прив’язується до атрибута з назвою [heure];
Запускаємо додаток і запитуємо URL [/]:
![]() |
- в [1] — отримана сторінка, а в [2] — її вміст HTML. Можна помітити, що початковий текст [Voici l'heure] повністю зник;
Якщо тепер оновити сторінку [1] (F5), ми отримаємо інше відображення (новий час), тоді як URL не змінюється. У цьому полягає динамічний характер сторінки: її вміст може змінюватися з плином часу.
З вищесказаного слід винести, що динамічні та статичні сторінки мають принципово різну природу.
2.2.3. Налаштування додатка Spring Boot
Повернемося до архітектури проекту Eclipse:
![]() |
Файл [application.properties] дозволяє налаштувати додаток Spring Boot. Наразі цей файл порожній. Його можна використовувати для налаштування додатка різними способами, описаними в URL та [http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html]. Ми будемо використовувати файл [application.properties] відповідно до [2]:
- рядок 1: встановлює порт служби веб-додатка;
- рядок 2: встановлює контекст веб-додатка;
Завдяки цій конфігурації статична сторінка [exemple-01.html] буде отримана за допомогою URL та [http://localhost:9000/intro/exemple-01.html]:
![]() |
2.3. Скрипти на стороні браузера
Сторінка HTML може містити скрипти, які виконуватимуться браузером. Наразі (січень 2015 р.) основною мовою скриптів на стороні браузера є JavaScript. Для полегшення роботи розробника на цій мові створено сотні бібліотек.
Створимо нову сторінку [exemple-03.html] у папці [static] існуючого проєкту:
![]() |
Відредагуємо файл [exemple-03.html], додавши до нього такий вміст:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>exemple Javascript</title>
<script type="text/javascript">
function réagir() {
alert("Vous avez cliqué sur le bouton !");
}
</script>
</head>
<body>
<input type="button" value="Cliquez-moi" onclick="réagir()" />
</body>
</html>
- рядок 13: визначає кнопку (атрибут type) з текстом «Натисніть мене» (атрибут value). При натисканні на неї виконується функція JavaScript [réagir] (атрибут onclick);
- рядки 6–10: скрипт JavaScript;
- рядки 7–9: функція [réagir];
- рядок 8: відображає діалогове вікно з повідомленням [Vous avez cliqué sur le bouton].
Переглянемо сторінку в браузері:
![]() |
- у [1] — відображена сторінка;
- на [2] — діалогове вікно, що з’являється при натисканні кнопки.
При натисканні на кнопку обмін даними з сервером не відбувається. Код JavaScript виконується браузером.
Завдяки величезній кількості доступних бібліотек JavaScript тепер можна вбудовувати у браузер повноцінні додатки. Тому спостерігається тенденція до використання таких архітектур:
![]() |
- 1-2: сервер HTML — це сервер статичних сторінок HTML5 / CSS / JavaScript;
- 3-4: Сторінки HTML5 / CSS / Javascript, що генеруються, безпосередньо взаємодіють із сервером даних. Цей сервер надає виключно дані без оформлення HTML. Саме Javascript вставляє їх у сторінки HTML, які вже відкриті в браузері.
У такій архітектурі код JavaScript може стати об’ємним. Тому його намагаються структурувати за рівнями, як це робиться для серверного коду:
![]() |
- шар [UI] взаємодіє з користувачем;
- шар [DAO] взаємодіє з сервером даних;
- шар [métier] об’єднує бізнес-процедури, які не взаємодіють ані з користувачем, ані з сервером даних. Цей шар може бути відсутнім.
2.4. Взаємодія «клієнт-сервер»
Повернімося до нашої початкової схеми, яка ілюструвала учасників веб-додатку:

Тут нас цікавить обмін даними між клієнтським і серверним комп’ютерами. Він відбувається через мережу, і варто нагадати загальну структуру обміну даними між двома віддаленими комп’ютерами.
2.4.1. Модель OSI
Модель відкритої мережі, що називається OSI (Open Systems Interconnection Reference Model) і визначена ISO (Міжнародною організацією зі стандартизації), описує ідеальну мережу, де зв’язок між машинами можна представити за допомогою семирівневої моделі:
![]() |
Кожен рівень отримує послуги від нижчого рівня та надає свої послуги вищому рівню. Припустимо, що два додатки, розташовані на різних машинах A та B, хочуть встановити зв’язок: вони роблять це на рівні Application. Їм не потрібно знати всіх деталей функціонування мережі: кожна програма передає інформацію, яку вона хоче надіслати, на нижній рівень — рівень Présentation. Отже, програмі потрібно знати лише правила взаємодії з рівнем Présentation. Як тільки інформація потрапляє на рівень Présentation, вона за іншими правилами передається на рівень Session і так далі, доки інформація не потрапить на фізичний носій і не буде фізично передана на машину-адресата. Там вона пройде обробку, зворотну до тієї, яку вона пройшла на комп’ютері-відправнику.
На кожному рівні процес-відправник, відповідальний за надсилання інформації, надсилає її процесу-одержувачу на іншому комп’ютері, що належить до того самого рівня. Це відбувається за певними правилами, які називаються протоколом рівня. Отже, маємо таку кінцеву схему зв’язку:
![]() |
Роль різних рівнів така:
Фізичний | Забезпечує передачу бітів по фізичному носію. На цьому рівні знаходяться кінцеві пристрої обробки даних (E.T.T.D.), такі як термінал або комп’ютер, а також пристрої завершення каналів передачі даних (E.T.C.D.), такі як модулятор/демодулятор, мультиплексор, концентратор. Ключовими моментами на цьому рівні є:
|
Канал передачі даних | Приховує фізичні особливості фізичного рівня. Виявляє та виправляє помилки передачі. |
Мережа | Керує маршрутом, яким має пройти інформація, що надсилається в мережі. Це називається routage: визначення маршруту, яким має пройти інформація, щоб дістатися до адресата. |
Транспортний рівень | Забезпечує зв’язок між двома додатками, тоді як попередні рівні дозволяли лише зв’язок між машинами. Однією зі служб, що надаються цим рівнем, може бути мультиплексування: транспортний рівень може використовувати одне й те саме мережеве з’єднання (від машини до машини) для передачі інформації, що належить кільком додаткам. |
Сесія | У цьому рівні містяться послуги, що дозволяють додатку відкривати та підтримувати робочу сесію на віддаленому комп’ютері. |
Представлення | Вона спрямована на уніфікацію представлення даних на різних машинах. Таким чином, дані, що надходять з машини А, будуть «оформлені» шаром Présentation машини А відповідно до стандартного формату перед відправкою в мережу. Потрапивши на рівень Présentation комп’ютера-одержувача B, який розпізнає їх завдяки стандартному формату, дані будуть «оформлені» іншим чином, щоб програма на комп’ютері B могла їх розпізнати. |
Застосування | На цьому рівні знаходяться додатки, які зазвичай знаходяться найближче до користувача, такі як електронна пошта або передача файлів. |
2.4.2. Модель TCP/IP
Модель OSI є ідеальною моделлю. Набір протоколів TCP/IP наближається до неї у такому вигляді:
![]() |
- мережевий інтерфейс (мережева карта комп’ютера) виконує функції рівнів 1 і 2 моделі OSI
- рівень IP (Інтернет-протокол) виконує функції 3-го рівня (мережа)
- Рівень TCP (Протокол управління передачею) або UDP (Протокол користувацьких датаграм) виконує функції 4-го рівня (транспортного). Протокол TCP гарантує, що пакети даних, якими обмінюються комп’ютери, надійно доходять до місця призначення. Якщо це не відбувається, він повертає пакети, що загубилися. Протокол UDP не виконує цю функцію, і тоді це завдання лягає на розробника додатків. Саме тому в Інтернеті, який не є на 100 % надійною мережею, найчастіше використовується протокол TCP. У цьому випадку йдеться про мережу TCP-IP.
- Рівень додатків охоплює функції рівнів 5–7 моделі OSI.
Веб-додатки знаходяться в шарі Application і, отже, базуються на протоколах TCP-IP. Рівні Application клієнтських машин та сервера обмінюються повідомленнями, які передаються рівням 1–4 моделі для подальшої доставки до місця призначення. Щоб зрозуміти один одного, рівні додатків обох машин повинні «говорити» однією мовою або протоколом. Протокол веб-додатків називається HTTP (HyperText Transfer Protocol). Це протокол текстового типу, c.a.d, за допомогою якого машини обмінюються рядками тексту в мережі для взаєморозуміння. Цей обмін стандартизований, тобто клієнт має у своєму розпорядженні певну кількість повідомлень, щоб точно вказати серверу, чого він хоче, а сервер також має певну кількість повідомлень, щоб надати клієнту відповідь. Цей обмін повідомленнями має такий вигляд:

Клієнт --> Сервер
Коли клієнт надсилає запит до веб-сервера, він надсилає
- рядки тексту у форматі HTTP, щоб вказати, чого він хоче;
- порожній рядок;
- за бажанням — документ.
Сервер --> Клієнт
Коли сервер надсилає відповідь клієнту, він надсилає
- рядки тексту у форматі HTTP, щоб вказати, що саме він надсилає;
- порожній рядок;
- опціонально — документ.
Отже, обмін даними має однакову форму в обох напрямках. В обох випадках можливе надсилання документа, хоча клієнт рідко надсилає документ на сервер. Але протокол HTTP це передбачає. Саме це дозволяє, наприклад, абонентам інтернет-провайдера завантажувати різноманітні документи на свій особистий сайт, розміщений у цього провайдера. Обмінювані документи можуть бути будь-якими. Розглянемо браузер, який запитує веб-сторінку, що містить зображення:
- браузер підключається до веб-сервера та запитує потрібну сторінку. Запитані ресурси однозначно позначаються за допомогою URL (Uniform Resource Locator). Браузер надсилає лише заголовки HTTP, а не сам документ.
- Сервер відповідає йому. Спочатку він надсилає заголовки HTTP, що вказують, який тип відповіді він надсилає. Це може бути повідомлення про помилку, якщо запитувана сторінка не існує. Якщо сторінка існує, сервер у заголовках HTTP своєї відповіді вкаже, що після них він надішле документ HTML (HyperText Markup Language). Цей документ — це послідовність рядків тексту у форматі HTML. Текст у форматі HTML містить теги (маркери), які надають браузеру вказівки щодо способу відображення тексту.
- Клієнт, виходячи з заголовків HTTP сервера, знає, що отримає документ HTML. Він проаналізує його і, можливо, виявить, що той містить посилання на зображення. Цих зображень немає в документі HTML. Тому він надсилає новий запит на той самий веб-сервер, щоб отримати перше зображення, яке йому потрібно. Цей запит ідентичний тому, що був зроблений у пункті 1, за винятком того, що запитуваний ресурс інший. Сервер обробить цей запит, надіславши клієнту запитане зображення. Цього разу у відповіді заголовки HTTP вкажуть, що надісланий документ є зображенням, а не документом HTML.
- Клієнт отримує надіслане зображення. Етапи 3 і 4 повторюватимуться доти, доки клієнт (зазвичай веб-браузер) не отримає всі документи, необхідні для відображення сторінки в повному обсязі.
2.4.3. Протокол HTTP
Розглянемо протокол HTTP на прикладах. Які дані обмінюються браузер і веб-сервер?
Веб-сервіс або сервіс HTTP — це сервіс TCP-IP, який зазвичай працює на порту 80. Він може працювати й на іншому порту. У цьому випадку браузер-клієнт буде змушений вказати цей порт у запиті URL. Запит URL має такий загальний вигляд:
протокол://комп'ютер[:port]/шлях/інформація
де
протокол | http для веб-сервісу. Браузер також може виступати клієнтом для сервісів ftp, news, telnet тощо. |
машина | ім'я машини, на якій працює веб-сервіс |
порт | порт веб-сервісу. Якщо це 80, номер порту можна опустити. Це найпоширеніший випадок |
шлях | шлях до запитуваного ресурсу |
додаткова інформація | додаткова інформація, що надається серверу для уточнення запиту клієнта |
Що робить браузер, коли користувач запитує завантаження URL?
- він відкриває канал зв'язку TCP-IP із машиною та портом, вказаними в частині machine[:port] файлу URL. Встановити з'єднання TCP-IP означає створити «канал» зв'язку між двома машинами. Після створення цього каналу вся інформація, що обмінюється між двома машинами, буде проходити через нього. Створення цього каналу TCP-IP ще не передбачає використання веб-протоколу HTTP.
- Після створення каналу TCP-IP клієнт надсилає запит до веб-сервера, відправляючи йому рядки тексту (команди) у форматі HTTP. Він надсилає серверу частину «шлях/інформація» з URL
- сервер відповість йому таким самим чином і через той самий канал
- один із двох учасників приймає рішення про закриття каналу. Це залежить від використовуваного протоколу HTTP. З протоколом HTTP 1.0 сервер закриває з’єднання після кожної своєї відповіді. Це змушує клієнта, який повинен зробити кілька запитів для отримання різних документів, що складають веб-сторінку, відкривати нове з’єднання для кожного запиту, що пов’язано з витратами. З протоколом HTTP/1.1 клієнт може вказати серверу залишити з’єднання відкритим, доки він не дасть команду його закрити. Таким чином, він може завантажити всі документи веб-сторінки за допомогою одного з’єднання та самостійно закрити його після отримання останнього документа. Сервер виявить це закриття та також закриє з’єднання.
Щоб дослідити обмін даними між клієнтом і веб-сервером, ми скористаємося розширенням [Advanced Rest Client] для браузера Chrome, яке ми встановили в розділі 9.6. Ми опинимося в такій ситуації:

Веб-сервер може бути будь-яким. Нам цікаво з’ясувати, який обмін даними відбуватиметься між браузером і веб-сервером. Раніше ми створили таку статичну сторінку HTML:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>essai 1 : une page statique</title>
</head>
<body>
<h1>Une page statique...</h1>
</body>
</html>
яку ми переглядаємо у браузері:
![]() |
Бачимо, що запитувана сторінка URL має адресу: [http://localhost:9000/intro/exemple-01.html]. Отже, сервер веб-служби — це localhost (=локальний сервер), а порт — 9000. Скористаємося додатком [Advanced Rest Client], щоб надіслати запит на той самий URL:
![]() |
- у [1] запускаємо додаток (у вкладці [Applications] нової вкладки Chrome);
- у [2] вибираємо опцію [Request];
- у [3] вказуємо сервер, до якого звертаємося: http://localhost:9000;
- у [4] вкажіть запитуваний URL: /intro/exemple-01.html;
- у [5] додаються можливі параметри до запиту URL. Тут їх немає;
- у [6] вказується команда HTTP, яка використовується для запиту, у даному випадку GET.
У результаті отримуємо такий запит:
![]() |
Підготовлений таким чином запит [7] надсилається на сервер за допомогою [8]. Отримана відповідь має такий вигляд:
![]() |
Вище ми зазначали, що обмін даними між клієнтом і сервером має такий вигляд:

- у [1] ми бачимо заголовки HTTP, надіслані браузером у його запиті. У нього не було документа для надсилання;
- у [2] ми бачимо заголовки HTTP, надіслані сервером у відповіді. У [3] ми бачимо документ, який він надіслав.
У [3] можна впізнати статичну сторінку HTML, яку ми розмістили на веб-сервері.
Розглянемо запит HTTP від браузера:
- 1-й рядок не відображався додатком;
- рядок 6: браузер ідентифікується за допомогою заголовка [User-Agent];
- рядок 7: браузер вказує, що надсилає серверу текстовий документ (text/plain) у форматі UTF-8. Насправді тут браузер не надіслав жодного документа;
- рядок 8: браузер вказує, що приймає у відповідь будь-який тип документа;
- рядок 9: браузер вказує формати документів, які він приймає;
- рядок 10: браузер вказує бажані мови в порядку пріоритетності.
Сервер відповів йому, надіславши такі заголовки HTTP:
- рядок 1: не відображається додатком;
- рядок 2: сервер ідентифікує себе, у даному випадку це сервер Apache-Coyote;
- рядок 3: дата останньої зміни надісланого документа;
- рядок 4: тип документа, надісланого сервером. У даному випадку — документ HTML;
- рядок 5: розмір у байтах надісланого документа HTML.
- рядок 6: дата та час відповіді;
2.4.4. Висновок
На кількох прикладах ми розглянули структуру запиту веб-клієнта та відповіді, яку йому надає веб-сервер. Діалог відбувається за допомогою протоколу HTTP — набору команд у текстовому форматі, якими обмінюються обидва учасники. Запит клієнта та відповідь сервера мають однакову структуру:

Дві типові команди для запиту ресурсу — це GET та POST. Команда GET не супроводжується документом. Команда POST, у свою чергу, супроводжується документом, який найчастіше є рядком символів, що об’єднує всі значення, введені у форму. Команда HEAD дозволяє запитувати лише заголовки HTTP і не супроводжується документом.
На запит клієнта сервер надсилає відповідь, яка має таку саму структуру. Запитаний ресурс передається у частині [Document], за винятком випадків, коли команда клієнта була HEAD — у такому разі надсилаються лише заголовки HTTP.
2.5. Основи мови HTML
Веб-браузер може відображати різні документи, найпоширенішим з яких є документ HTML (HyperText Markup Language). Це текст, відформатований за допомогою тегів у формі <balise>texte</balise>. Так, тег <B>important</B> відображатиме важливий текст жирним шрифтом. Існують окремі теги, такі як тег <hr/>, який відображає горизонтальну лінію. Ми не будемо розглядати теги, які можна знайти в тексті HTML. Існує чимало програм WYSIWYG, що дозволяють створювати веб-сторінки без написання жодного рядка коду HTML. Ці інструменти автоматично генерують код HTML на основі макета, створеного за допомогою миші та попередньо визначених елементів управління. Таким чином, можна (за допомогою миші) вставити на сторінку таблицю, а потім переглянути код HTML, згенерований програмою, щоб дізнатися, які теги слід використовувати для визначення таблиці на веб-сторінці. Все дуже просто. Крім того, знання мови HTML є необхідним, оскільки динамічні веб-додатки повинні самостійно генерувати код HTML для надсилання веб-клієнтам. Цей код генерується програмно, і, звісно, потрібно знати, що саме слід згенерувати, щоб клієнт отримав бажану веб-сторінку.
Підсумовуючи, для початку веб-програмування зовсім не обов’язково знати мову HTML у повному обсязі. Однак ці знання є необхідними і їх можна здобути завдяки використанню програмного забезпечення WYSIWYG для створення веб-сторінок, такого як DreamWeaver та десятків інших. Інший спосіб ознайомитися з тонкощами мови HTML — це переглядати веб-сторінки та вивчати їхній вихідний код, який містить цікаві та ще невідомі вам особливості.
2.5.1. Приклад
Розглянемо наступний приклад, який містить деякі елементи, що можуть зустрічатися у веб-документі, такі як:
- таблиця;
- зображення;
- посилання.
![]() | ![]() |
Документ HTML має такий загальний вигляд:
Весь документ обмежений тегами <html>...</html>. Він складається з двох частин:
- <head>...</head>: це невидима частина документа. Вона надає інформацію браузеру, який буде відображати документ. У ній часто зустрічається тег <title>...</title>, який визначає текст, що буде відображатися в рядку заголовка браузера. Також тут можуть бути інші теги, зокрема ті, що визначають ключові слова документа, які потім використовуються пошуковими системами. У цій частині також можуть міститися скрипти, найчастіше написані на JavaScript або VBScript, які будуть виконуватися браузером.
- <body атрибути>...</body>: це частина, яка відображатиметься браузером. Теги HTML, що містяться в цій частині, вказують браузеру «бажаний» візуальний вигляд документа. Кожен браузер інтерпретує ці теги по-своєму. Тому два браузери можуть по-різному відображати один і той самий веб-документ. Зазвичай це є однією з головних проблем веб-дизайнерів.
Код HTML нашого прикладу документа виглядає так:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>balises</title>
</head>
<body style="height: 400px; width: 400px; background-image: url(images/standard.jpg)">
<h1 style="text-align: center">Les balises HTML</h1>
<hr />
<table border="1">
<thead>
<tr>
<th>Colonne 1</th>
<th>Colonne 2</th>
<th>Colonne 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>cellule(1,1)</td>
<td style="width: 150px; text-align: center;">cellule(1,2)</td>
<td>cellule(1,3)</td>
</tr>
<tr>
<td>cellule(2,1)</td>
<td>cellule(2,2)</td>
<td>cellule(2,3</td>
</tr>
</tbody>
</table>
<table>
<tr>
<td>Une image</td>
<td><img border="0" src="images/cerisier.jpg" /></td>
</tr>
<tr>
<td>le site de l'ISTIA</td>
<td><a href="http://istia.univ-angers.fr">ici</a></td>
</tr>
</table>
</body>
</html>
Елемент | теги та приклади HTML |
заголовок документа | <title>теги</title> (рядок 5) текст balises з’явиться у рядку заголовка браузера, який відображатиме документ |
горизонтальна смуга | <hr/>: відображає горизонтальну лінію (рядок 10) |
таблиця | <table атрибути>....</table> : для визначення таблиці (рядки 11, 31) <thead>...</thead>: для визначення заголовків стовпців (рядки 12, 18) <tbody>...</tbody>: для визначення вмісту таблиці (рядки 19, 30) <tr атрибути>...</tr>: для визначення рядка (рядки 20, 24) <td атрибути>...</td>: для визначення комірки (рядок 21) приклади: <table border="1">...</table>: атрибут border визначає товщину межі таблиці <td style="width: 150px; text-align: center;">cellule(1,2)</td>: визначає комірку, вміст якої буде cellule(1,2). Цей вміст буде вирівняно по горизонталі (text-align: center). Ширина комірки становитиме 150 пікселів (width: 150px) |
зображення | <img border="0" src="/images/cerisier.jpg"/> (рядок 36): визначає зображення без рамки (border=0"), вихідний файл якого знаходиться за адресою /images/cerisier.jpg на веб-сервері (src="images/cerisier.jpg"). Це посилання міститься у веб-документі, отриманому за допомогою URL http://localhost:port/intro/exemple-04.html. Отже, браузер завантажить файл URL http://localhost:port/intro/images/cerisier.jpg, щоб отримати зображення, на яке тут є посилання. |
посилання | <a href="http://istia.univ-angers.fr">тут</a> (рядок 40): робить текст ici посиланням на URL http://istia.univ-angers.fr. |
нижній колонтитул | <body style="height:400px;width:400px;background-image:url(images/standard.jpg)"> (рядок 8): вказує, що зображення, яке має слугувати фоном сторінки, знаходиться за адресою URL [images/standard.jpg] на веб-сервері. У контексті нашого прикладу браузер надішле запит на URL http://localhost:port/intro/images/standard.jpg, щоб отримати це фонове зображення. Крім того, основний текст документа буде відображатися у прямокутнику висотою 400 пікселів і шириною 400 пікселів. |
З цього простого прикладу видно, що для побудови всього документа браузер повинен надіслати три запити до сервера:
- http://localhost:port/intro/exemple-04.html, щоб отримати вихідний код документа HTML
- http://localhost:port/intro/images/cerisier.jpg — для отримання зображення cerisier.jpg
- http://localhost:port/intro/images/standard.jpg, щоб отримати фонове зображення standard.jpg
2.5.2. Форма HTML
У наступному прикладі наведено форму:
![]() | ![]() |
Код HTML, що створює це зображення, виглядає так:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>formulaire</title>
<script type="text/javascript">
function effacer() {
alert("Vous avez cliqué sur le bouton Effacer");
}
</script>
</head>
<body style="height: 400px; width: 400px; background-image: url(images/standard.jpg)">
<h1 style="text-align: center">Formulaire HTML</h1>
<form method="post" action="postFormulaire">
<table>
<tr>
<td>Etes-vous marié(e)</td>
<td>
<input type="radio" value="Oui" name="R1" />Oui
<input type="radio" name="R1" value="non" checked="checked" />Non
</td>
</tr>
<tr>
<td>Cases à cocher</td>
<td>
<input type="checkbox" name="C1" value="un" />1
<input type="checkbox" name="C2" value="deux" checked="checked" />2
<input type="checkbox" name="C3" value="trois" />3
</td>
</tr>
<tr>
<td>Champ de saisie</td>
<td>
<input type="text" name="txtSaisie" size="20" value="qqs mots" />
</td>
</tr>
<tr>
<td>Mot de passe</td>
<td>
<input type="password" name="txtMdp" size="20" value="unMotDePasse" />
</td>
</tr>
<tr>
<td>Boîte de saisie</td>
<td>
<textarea rows="2" name="areaSaisie" cols="20">
ligne1
ligne2
ligne3
</textarea>
</td>
</tr>
<tr>
<td>combo</td>
<td>
<select size="1" name="cmbValeurs">
<option value="1">choix1</option>
<option selected="selected" value="2">choix2</option>
<option value="3">choix3</option>
</select>
</td>
</tr>
<tr>
<td>liste à choix simple</td>
<td>
<select size="3" name="lst1">
<option selected="selected" value="1">liste1</option>
<option value="2">liste2</option>
<option value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</td>
</tr>
<tr>
<td>liste à choix multiple</td>
<td>
<select size="3" name="lst2" multiple="multiple">
<option value="1" selected="selected">liste1</option>
<option value="2">liste2</option>
<option selected="selected" value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</td>
</tr>
<tr>
<td>bouton</td>
<td>
<input type="button" value="Effacer" name="cmdEffacer" onclick="effacer()" />
</td>
</tr>
<tr>
<td>envoyer</td>
<td>
<input type="submit" value="Envoyer" name="cmdRenvoyer" />
</td>
</tr>
<tr>
<td>rétablir</td>
<td>
<input type="reset" value="Rétablir" name="cmdRétablir" />
</td>
</tr>
</table>
<input type="hidden" name="secret" value="uneValeur" />
</form>
</body>
</html>
Зв’язок між візуальним елементом <--> тегом HTML такий:
Перевірка | тег HTML |
форма | <form method="post" action="..."> |
поле введення | <input type="text" name="txtSaisie" size="20" value="кілька слів" /> |
приховане поле введення | <input type="password" name="txtMdp" size="20" value="unMotDePasse" /> |
багаторядкове поле введення | <textarea rows="2" name="areaSaisie" cols="20"> рядок1 рядок 2 рядок 3 </textarea> |
перемикачі | <input type="radio" value="Так" name="R1" />Так <input type="radio" name="R1" value="ні" checked="checked" />Ні |
поля для позначення | <input type="checkbox" name="C1" value="один" />1 <input type="checkbox" name="C2" value="два" checked="checked" />2 <input type="checkbox" name="C3" value="три" />3 |
Список | <select size="1" name="cmbValeurs"> <option value="1">варіант 1</option> <option selected="selected" value="2">варіант 2</option> <option value="3">варіант 3</option> </select> |
список з одним варіантом вибору | <select size="3" name="lst1"> <option selected="selected" value="1">список1</option> <option value="2">список2</option> <option value="3">список3</option> <option value="4">список4</option> <option value="5">список5</option> </select> |
список із можливістю вибору декількох елементів | <select size="3" name="lst2" multiple="multiple"> <option value="1">список1</option> <option value="2">список2</option> <option selected="selected" value="3">список3</option> <option value="4">список4</option> <option value="5">список5</option> </select> |
кнопка типу «submit» | <input type="submit" value="Відправити" name="cmdRenvoyer" /> |
кнопка типу «reset» | <input type="reset" value="Скинути" name="cmdRétablir" /> |
кнопка типу button | <input type="button" value="Стерти" name="cmdEffacer" onclick="effacer()" /> |
Давайте розглянемо ці різні теги:
2.5.2.1. Форма « »
форма | |
тег HTML | <form name="..." method="..." action="...">...</form> |
атрибути | name="frmexemple": ім'я форми method="..." : метод, який використовує браузер для надсилання на веб-сервер значень, зібраних у формі action="..." : URL, на яку будуть надіслані значення, зібрані у формі. Веб-форма оточена тегами <form>...</form>. Форма може мати ім’я (name="xx"). Це стосується всіх елементів управління, які можна знайти у формі. Мета форми — зібрати інформацію, введену користувачем за допомогою клавіатури/миші, та надіслати її на URL веб-сервера. Який саме? Той, що вказаний в атрибуті action="URL". Якщо цей атрибут відсутній, інформація буде надіслана на URL документа, в якому знаходиться форма. Веб-клієнт може використовувати два різні методи, що називаються POST та GET, для надсилання даних на веб-сервер. Атрибут method="méthode", причому method дорівнює GET або POST, у тезі <form> вказує браузеру, який метод слід використовувати для надсилання інформації, зібраної у формі, на URL, вказаний атрибутом action="URL". Якщо атрибут method не вказано, за замовчуванням використовується метод GET. |
2.5.2.2. Поля для введення тексту
поле введення | <input type="text" name="txtSaisie" size="20" value="кілька слів" /> <input type="password" name="txtMdp" size="20" value="unMotDePasse" /> |
![]() |
тег HTML | <input type="..." name="..." size=".." value=".."/> Тег input використовується для різних елементів управління. Саме атрибут type дозволяє розрізняти ці різні елементи управління між собою. |
атрибути | type="text": вказує, що це поле введення type="password": символи у полі введення замінюються на символи *. Це єдина відмінність від звичайного поля введення. Цей тип елемента управління підходить для введення паролів. size="20": кількість символів, що відображаються у полі — не обмежує введення більшої кількості символів name="txtSaisie": ім’я елемента управління value="кілька слів" : текст, який відображатиметься у полі введення. |
2.5.2.3. Багаторядкові поля введення
багаторядкове поле введення | <textarea rows="2" name="areaSaisie" cols="20"> рядок1 рядок 2 рядок 3 </textarea> |
![]() |
тег HTML | <textarea ...>текст</textarea> відображає багаторядкове поле введення, яке спочатку містить текст |
атрибути | rows="2": кількість рядків cols="'20" : кількість стовпців name="areaSaisie": ім'я елемента управління |
2.5.2.4. Радіо-кнопки
радіо-кнопки | <input type="radio" value="Так" name="R1" />Так <input type="radio" name="R1" value="no" checked="checked" />Ні |
тег HTML | <input type="radio" атрибут2="значення2" ..../>текст відображає перемикач із текстом поруч. |
атрибути | name="radio": ім'я елемента управління. Перемикачі з однаковим ім'ям утворюють групу, елементи якої взаємовиключні: можна вибрати лише один із них. value="значення": значення, присвоєне радіо-кнопці. Не слід плутати це значення з текстом, що відображається поруч із радіо-кнопкою. Останній призначений лише для відображення. checked="checked": якщо цей ключовий атрибут присутній, перемикач позначений як вибраний, інакше — ні. |
2.5.2.5. Поля для позначення
поля для позначення | <input type="checkbox" name="C1" value="один" />1 <input type="checkbox" name="C2" value="два" checked="checked" />2 <input type="checkbox" name="C3" value="три" />3 |
тег HTML | <input type="checkbox" атрибут2="значення2" ....>текст відображає прапорець із текстом поруч. |
атрибути | name="C1": ім'я елемента управління. Поля для позначення можуть мати однакове ім'я або ні. Поля з однаковим ім'ям утворюють групу пов'язаних полів. value="значення": значення, присвоєне прапорцю. Не слід плутати це значення з текстом, що відображається поруч із перемикачем. Останній призначений лише для відображення. checked= "checked": якщо цей ключовий параметр присутній, прапорець встановлено; інакше — ні. |
2.5.2.6. Список, що розгортається (комбо)
Комбо | <select size="1" name="cmbValeurs"> <option value="1">варіант1</option> <option selected="selected" value="2">варіант 2</option> <option value="3">варіант 3</option> </select> |
тег HTML | <select size=".." name=".."> <option [selected="selected"] value=”v”>...</option> ... </select> відображає у списку тексти, що містяться між тегами <option>...</option> |
атрибути | name="cmbValeurs": ім'я елемента управління. size="1": кількість видимих елементів списку. size="1" перетворює список на комбінований список. selected="selected": якщо це ключове слово вказано для елемента списку, він відображається у списку як вибраний. У нашому прикладі вище елемент списку choix2 відображається як вибраний елемент комбобокса, коли той з’являється вперше. value=”v”: якщо елемент вибрано користувачем, саме це значення [v] надсилається на сервер. За відсутності цього атрибута на сервер надсилається текст, що відображається та вибрано. |
2.5.2.7. Список з одним вибором
список з одним вибором | <select size="3" name="lst1"> <option selected="selected" value="1">список1</option> <option value="2">список2</option> <option value="3">список3</option> <option value="4">список4</option> <option value="5">список5</option> </select> |
![]() |
тег HTML | <select size=".." name=".."> <option [selected="selected"]>...</option> ... </select> відображає у списку тексти, що містяться між тегами <option>...</option> |
атрибути | такі самі, як і для випадаючого списку, що відображає лише один елемент. Цей елемент управління відрізняється від попереднього випадаючого списку лише атрибутом size>1. |
2.5.2.8. Список із можливістю множинного вибору
Список з одним вибором | <select size="3" name="lst2" multiple="multiple"> <option value="1" selected="selected">список1</option> <option value="2">список2</option> <option selected="selected" value="3">список3</option> <option value="4">список4</option> <option value="5">список5</option> </select> |
![]() |
тег HTML | <select size=".." name=".." multiple="multiple"> <option [selected="selected"]>...</option> ... </select> відображає у списку тексти, що містяться між тегами <option>...</option> |
атрибути | multiple: дозволяє вибрати кілька елементів зі списку. У наведеному вище прикладі вибрано обидва елементи: liste1 та liste3. |
2.5.2.9. Кнопка типу button
кнопка типу button | <input type="button" value="Очистити" name="cmdEffacer" onclick="effacer()" /> |
тег HTML | <input type="button" value="..." name="..." onclick="effacer()" ..../> |
атрибути | type="button": визначає елемент управління «кнопка». Існують ще два типи кнопок: submit та reset. value="Очистити": текст, що відображається на кнопці onclick="функція()" : дозволяє визначити функцію, яка має виконуватися, коли користувач натискає на кнопку. Ця функція є частиною скриптів, визначених у відображеному веб-документі. Наведений вище синтаксис відповідає синтаксису javascript. Якщо скрипти написані на VBScript, слід вказати onclick="функція" без дужок. Синтаксис залишається незмінним, якщо потрібно передати параметри до функції: onclick="функція(val1, val2,...)" У нашому прикладі клік на кнопку Effacer викликає таку функцію JavaScript effacer: <script type="text/javascript"> function effacer() { alert("Ви натиснули кнопку «Очистити»"); } </script> Функція effacer відображає повідомлення: ![]() |
2.5.2.10. Кнопка типу «submit»
кнопка типу «submit» | <input type="submit" value="Надіслати" name="cmdRenvoyer" /> |
тег HTML | <input type="submit" value="Надіслати" name="cmdRenvoyer" /> |
атрибути | type="submit": визначає кнопку як кнопку відправки даних форми на веб-сервер. Коли клієнт натисне на цю кнопку, браузер надішле дані форми на URL, визначений в атрибуті action тегу <form>, відповідно до методу, визначеного атрибутом method цього ж тегу. value="Відправити": текст, що відображається на кнопці |
2.5.2.11. Кнопка типу «reset»
кнопка типу «reset» | <input type="reset" value="Відновити" name="cmdRétablir" /> |
тег HTML | <input type="reset" value="Скинути" name="cmdRétablir"/> |
атрибути | type="reset": визначає кнопку як кнопку скидання форми. Коли користувач натисне цю кнопку, браузер поверне форму до того стану, в якому він її отримав. value="Скинути": текст, що відображається на кнопці |
2.5.2.12. Приховане поле
приховане поле | <input type="hidden" name="secret" value="uneValeur" /> |
тег HTML | <input type="hidden" name="..." value="..."/> |
атрибути | type="hidden": вказує, що це приховане поле. Приховане поле є частиною форми, але не відображається користувачеві. Однак, якщо користувач попросить свій браузер показати вихідний код, він побачить тег <input type="hidden" value="..."> і, отже, значення прихованого поля. value="uneValeur": значення прихованого поля. У чому полягає користь прихованого поля? Воно дозволяє веб-серверу зберігати інформацію під час послідовних запитів клієнта. Розглянемо приклад веб-додатку для покупок. Клієнт купує перший товар art1 у кількості q1 на першій сторінці каталогу, а потім переходить на нову сторінку каталогу. Щоб запам’ятати, що клієнт придбав q1 товарів у кількості art1, сервер може помістити ці дві інформації в приховане поле веб-форми на новій сторінці. На цій новій сторінці клієнт купує товари q2 та art2. Коли дані цієї другої форми будуть надіслані на сервер (submit), сервер отримає не тільки інформацію (q2,art2), а й (q1,art1), які також є частиною форми як приховані поля. Потім веб-сервер помістить у нове приховане поле дані (q1,art1) та (q2,art2) і надішле нову сторінку каталогу. І так далі. |
2.5.3. Відправлення веб-клієнтом значень форми на веб-сервер
У попередньому розділі ми зазначили, що веб-клієнт має два методи для надсилання на веб-сервер значень форми, яку він відобразив: методи GET та POST. Розглянемо на прикладі різницю між цими двома методами.
2.5.3.1. Метод GET
Проведемо перший тест, у якому в коді HTML документа тег <form> визначено таким чином:
<form method="get" action="doNothing">
![]() |
Коли користувач натисне на кнопку [1], значення, введені у форму, будуть надіслані до контролера Spring [2]. Ми бачили, що значення з форми будуть надіслані до контролера URL [doNothing]:
<form method="get" action="doNothing">
Дія [doNothing] визначена у контролері [MyController] [2] наступним чином:
// ----------------------- очищення потоку [Content-Length=0]
@RequestMapping(value = "/doNothing")
@ResponseBody
public void doNothing() {
}
- рядок 1: дія обробляє URL [/doNothing], тобто фактично [/context/doNothing], де [context] — це контекст або назва веб-додатка, тут — [/intro];
- рядок 3: анотація [@ResponseBody] вказує, що результат анотованого методу має бути надісланий безпосередньо клієнту;
- рядок 4: метод не повертає ніякого значення. Отже, клієнт отримає порожню відповідь від сервера.
Нам потрібно лише з’ясувати, як браузер передає введені значення на веб-сервер. Для цього ми скористаємося інструментом налагодження, доступним у Chrome. Його можна активувати, натиснувши CTRL-Shift-I (велика літера) [3]:
![]() |
Оскільки нас цікавить обмін даними між браузером і веб-сервером, ми відкриваємо вкладку [Network], а потім натискаємо кнопку [Envoyer] у формі. Ця кнопка є елементом типу [submit], розміщеним усередині тегу [form]. Браузер реагує на клік, запитуючи URL [/intro/doNothing], вказані в атрибуті [action] тегу [form], за допомогою методу GET, вказаного в атрибуті [method]. У результаті ми отримуємо таку інформацію:
![]() |
На наведеному вище знімку екрана показано код URL, який браузер запитує після натискання кнопки [envoyer]. Він дійсно запитує URL, передбачений [/intro/doNothing], але додає до нього інформацію, яка складається зі значень, введених у форму. Щоб отримати додаткову інформацію, натискаємо на посилання вище:
![]() |
Вище, у [1, 2], ми бачимо заголовки HTTP, надіслані браузером. Тут вони були відформатовані. Щоб переглянути необроблений текст цих заголовків, переходимо за посиланням [view source] [3, 4]. Повний текст виглядає так:
Ми бачимо елементи, з якими вже стикалися раніше. Інші з’являються вперше:
Connection: keep-alive | клієнт просить сервер не закривати з’єднання після його відповіді. Це дозволить йому використовувати те саме з’єднання для наступного запиту. З’єднання не залишається відкритим нескінченно. Сервер закриє його після занадто тривалого періоду бездіяльності. |
Referer | URL — це URL-адреса, яка відображалася в браузері під час надсилання нового запиту. |
Новим елементом є рядок 1 у інформації, що йде за URL. Можна помітити, що вибір, зроблений у формі, відображається в URL. Значення, введені користувачем у форму, були передані в запиті GET URL?param1=значення1¶m2=значення2&... HTTP/1.1, де parami — це імена (атрибут name) елементів управління веб-форми, а valeuri — значення, пов’язані з ними. Нижче наведено таблицю з трьома стовпцями:
- 1-й стовпець: містить визначення елемента управління HTML із прикладу;
- 2-й стовпець: відображення цього елемента управління в браузері;
- стовпець 3: містить значення, яке браузер надсилає на сервер для елемента управління зі стовпця 1 у тому вигляді, в якому воно міститься у запиті GET з прикладу.
елемент управління HTML | візуальне представлення | повернуте значення (значення) |
<input type="radio" value="Так" name="R1"/>Так <input type="radio" name="R1" value="ні" checked="checked"/>Ні | R1=Так - значення атрибута value радіо-кнопки, яку користувач позначив. | |
<input type="checkbox" name="C1" value="один"/>1 <input type="checkbox" name="C2" value="два" checked="checked"/>2 <input type="checkbox" name="C3" value="три"/>3 | C1=один C2=два - значення атрибутів value полів, позначених користувачем | |
<input type="text" name="txtSaisie" size="20" value="кілька слів"/> | txtSaisie=програмування+Веб - текст, введений користувачем у поле введення. Пробіли замінено на знак + | |
<input type="password" name="txtMdp" size="20" value="unMotDePasse"/> | txtMdp=цесекрет - текст, введений користувачем у поле введення | |
<textarea rows="2" name="areaSaisie" cols="20"> рядок1 рядок 2 рядок3 </textarea> | areaSaisie=основи+програмування+Web%0D%0A веб-програмування+ - текст, введений користувачем у поле введення. %OD%OA — це позначка кінця рядка. Пробіли замінено на знак + | |
<select size="1" name="cmbValeurs"> <option value='1'>варіант1</option> <option selected="selected" value='2'>варіант2</option> <option value='3'>варіант3</option> </select> | cmbValeurs=3 - атрибут [value] елемента, вибраного користувачем | |
<select size="3" name="lst1"> <option selected="selected" value='1'>список1</option> <option value='2'>список2</option> <option value='3'>список3</option> <option value='4'>список4</option> <option value='5'>список5</option> </select> | ![]() | lst1=3 - атрибут [value] елемента, вибраного користувачем |
<select size="3" name="lst2" multiple="multiple"> <option selected="selected" value='1'>список1</option> <option value='2'>список2</option> <option selected="selected" value='3'>список3</option> <option value='4'>список4</option> <option value='5'>список5</option> </select> | lst2=1 lst2=3 - атрибути [value] елементів, вибраних користувачем | |
<input type="submit" value="Надіслати" name="cmdRenvoyer"/> | cmdRenvoyer=Надіслати - ім'я та атрибут value кнопки, яка використовувалася для надсилання даних форми на сервер | |
<input type="hidden" name="secret" value="uneValeur"/> | secret=значення - атрибут value прихованого поля |
2.5.3.2. Метод POST
Ми змінюємо документ HTML, щоб браузер тепер використовував метод POST для надсилання значень форми на веб-сервер:
<form method="post" action="doNothing">
Ми заповнюємо форму так само, як для методу GET, і надсилаємо параметри на сервер за допомогою кнопки [Envoyer]. Як і в попередньому абзаці на сторінці 62, у Chrome ми маємо доступ до заголовків HTTP запиту, надісланого браузером:
У запиті HTTP від клієнта з’являються нові елементи:
POST URL HTTP/1.1 | запит GET замінено на запит POST. Параметри більше не містяться в першому рядку запиту. Можна помітити, що тепер вони розміщені (рядок 15) після запиту HTTP, після порожнього рядка. Їхнє кодування ідентичне тому, яке вони мали в запиті GET. |
Content-Length | кількість «відправлених» символів, c.a.d. Кількість символів, яку повинен прочитати веб-сервер після отримання заголовків HTTP, щоб отримати документ, який надсилає йому клієнт. У даному випадку цим документом є список значень форми. |
Content-type | вказує тип документа, який клієнт надішле після заголовків HTTP. Тип [application/x-www-form-urlencoded] вказує, що це документ, який містить значення форми. |
Існує два методи передачі даних на веб-сервер: GET та POST. Чи є один із цих методів кращим за інший? Ми бачили, що якщо значення форми надсилалися браузером за допомогою методу GET, браузер відображав у своєму полі Adresse запитуване значення URL у формі URL?param1=val1¶m2=val2&.... Це можна розглядати як перевагу або недолік:
- перевагою, якщо потрібно дозволити користувачеві додати цей налаштований URL до своїх улюблених посилань;
- недоліком — якщо не хочемо, щоб користувач мав доступ до певної інформації у формі, наприклад, до прихованих полів.
Надалі ми будемо використовувати у своїх формах майже виключно метод POST.
2.6. Conclusion
У цьому розділі було представлено різні базові концепції веб-розробки:
- обмін даними між клієнтом і сервером за допомогою протоколу HTTP;
- створення документа за допомогою мови HTML;
- створення форм для введення даних.
На прикладі ми побачили, як клієнт може надсилати інформацію на веб-сервер. Ми не розглядали, як сервер може
- отримувати цю інформацію;
- обробляти її;
- надіслати клієнту динамічну відповідь залежно від результату обробки.
Це сфера веб-програмування, яку ми розглянемо в наступному розділі, де буде представлено технологію Spring MVC.










































