2. Podstawy programowania internetowego
Głównym celem tego rozdziału jest zapoznanie czytelnika z głównymi zasadami programowania internetowego, które są niezależne od konkretnej technologii wykorzystywanej do ich wdrożenia. Zawiera on liczne przykłady, które warto przetestować, aby stopniowo „wczuć się” w filozofię tworzenia stron internetowych. Czytelnik posiadający już tę wiedzę może przejść bezpośrednio do rozdziału 3.
Elementy składowe aplikacji internetowej są następujące:

Numer | Rola | Typowe przykłady |
1 | OS Serwer | Unix, Linux, Windows |
2 | Serwer WWW | Apache (Unix, Linux, Windows) IIS (Windows + platforma .NET) Node.js (Unix, Linux, Windows) |
3 | Kody wykonywane po stronie serwera. Mogą być one uruchamiane przez moduły serwera lub przez programy zewnętrzne względem serwera (CGI). | JAVASCRIPT (Node.js) PHP (Apache, IIS) JAVA (Tomcat, Websphere, JBoss, Weblogic, ...) C#, VB.NET (IIS) |
4 | Baza danych – może znajdować się na tym samym komputerze co program, który z niej korzysta, lub na innym komputerze, z którym łączy się przez Internet. | Oracle (Linux, Windows) MySQL (Linux, Windows) Postgres (Linux, Windows) SQL Server (Windows) |
5 | OS Klient | Unix, Linux, Windows |
6 | Przeglądarka internetowa | Chrome, Internet Explorer, Firefox, Opera, Safari, ... |
7 | Skrypty wykonywane po stronie klienta w przeglądarce. Skrypty te nie mają dostępu do dysków komputera klienta. | JavaScript (wszystkie przeglądarki) |
2.1. Wymiana danych w aplikacji internetowej z formularzem

Numer | Rola |
1 | Przeglądarka wysyła po raz pierwszy żądanie URL dotyczące (http://machine/url). Nie przekazano żadnych parametrów. |
2 | Serwer WWW wysyła jej stronę internetową o nazwie URL. Może to być strona statyczna lub wygenerowana dynamicznie przez skrypt serwera (SA), który mógł wykorzystać zawartość baz danych (SB, SC). W tym przypadku skrypt wykryje, że plik URL został wywołany bez przekazania parametrów i wygeneruje stronę internetową początkową. Przeglądarka odbiera stronę i wyświetla ją (CA). Skrypty po stronie przeglądarki (CB) mogły zmodyfikować stronę początkową wysłaną przez serwer. Następnie, w wyniku interakcji między użytkownikiem (CD) a skryptami (CB), strona internetowa zostanie zmodyfikowana. W szczególności zostaną wypełnione formularze. |
3 | Użytkownik zatwierdza dane z formularza, które następnie muszą zostać wysłane do serwera WWW. Przeglądarka ponownie żąda strony początkowej URL lub innej, w zależności od sytuacji, i jednocześnie przekazuje serwerowi wartości z formularza. W tym celu może wykorzystać dwie metody o nazwach GET i POST. Po otrzymaniu żądania od klienta serwer uruchamia skrypt (SA) powiązany z żądanym URL, który wykrywa parametry i przetwarza je. |
4 | Serwer dostarcza stronę internetową wygenerowaną programowo (SA, SB, SC). Ten etap jest identyczny z poprzednim etapem 2. Wymiana danych odbywa się teraz zgodnie z etapami 2 i 3. |
2.2. Strony internetowe statyczne, strony internetowe dynamiczne
Strona statyczna jest reprezentowana przez plik HTML. Strona dynamiczna to strona HTML generowana „na bieżąco” przez serwer WWW.
2.2.1. Strona statyczna HTML (język znaczników HyperText)
Stwórzmy pierwszy projekt Spring MVC [1-2]:
![]() |
- w [1-2] tworzymy nowy projekt oparty na Spring Boot [http://projects.spring.io/spring-boot/];
![]() |
- informacje [3-7] dotyczą konfiguracji projektu w Maven;
- w [3] podano nazwę projektu Maven;
- w [4] podano grupę Maven, w której zostanie umieszczony wynik kompilacji projektu;
- w [5] – nazwa nadana wynikowi kompilacji;
- w [6] – opis projektu;
- w [7] – pakiet, w którym zostanie umieszczona klasa wykonywalna projektu;
- w [8] – charakter projektu. Jest to projekt internetowy z widokami Thymeleaf. Widoczne są tutaj wszystkie gotowe do użycia zależności Maven oferowane przez projekt Spring Boot;
- w polu [9] określa się, że wynik kompilacji Maven zostanie spakowany do archiwum jar, a nie war. Projekt będzie wówczas korzystał z wbudowanego serwera Tomcat, który znajdzie się wśród jego zależności;
- w [10] przechodzimy do kolejnego etapu kreatora;
![]() |
- w [11] należy wskazać folder projektu;
- w [12] kończymy pracę z kreatorem;
- w pliku [13] znajduje się wygenerowany projekt.
Przyjrzyjmy się wygenerowanemu plikowi [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 /> <!-- wyszukiwanie elementu nadrzędnego z repozytorium -->
</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>
Zawiera on wszystkie informacje podane w kreatorze. W wierszach 26–30 znajdujemy zależność, o której nie wiedzieliśmy. Umożliwia ona integrację testów jednostkowych JUnit ze Springiem.
Zacznijmy od utworzenia statycznej strony HTML w tym projekcie. Domyślnie powinna ona znajdować się w folderze [src / main / resources / static]:
![]() |
- w [1-4] tworzymy plik HTML w folderze [static];
![]() |
- w pliku [6] należy nadać nazwę stronie;
- w pliku [7] strona została dodana.
Treść utworzonej strony jest następująca:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
- wiersze 2–10: kod jest ograniczony tagiem głównym <html>;
- wiersze 3–6: tag <head> wyznacza tzw. nagłówek strony;
- wiersze 7–9: tag <body> wyznacza tzw. treść strony.
Zmodyfikujmy ten kod w następujący sposób:
<!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>
- wiersz 5: określa tytuł strony – zostanie wyświetlony jako tytuł okna przeglądarki wyświetlającej stronę;
- wiersz 8: tekst napisany dużymi literami (<h1>).
Uruchommy aplikację [1-3]:
![]() |
następnie w przeglądarce wywołajmy URL [http://localhost:8080/exemple-01.html]:
![]() |
- w [1], URL wyświetlanej strony;
- w [2] – tytuł okna, który został podany przez tag <title> na stronie;
- w [3] – treść strony – została pobrana z tagu <h1>.
Przyjrzyjmy się kodowi [4-5], który przeglądarka otrzymała jako HTML:
![]() |
- w [5] przeglądarka otrzymała stronę HTML, którą stworzyliśmy. Zinterpretowała ją i wyświetliła w formie graficznej.
2.2.2. Dynamiczna strona Thymeleaf
Stwórzmy teraz stronę Thymeleaf. Jest to klasyczna strona HTML z tagami wzbogaconymi o atrybuty [Thymeleaf] i [http://www.thymeleaf.org/]. Postępujemy analogicznie do tworzenia strony HTML, ale tym razem nową stronę HTML należy umieścić w folderze [templates]:
![]() |
Strona [exemple-02.html] będzie wyglądać następująco:
<!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>
- wiersz 8: tag <p> jest tagiem HTML, który wprowadza akapit na wyświetlanej stronie. [th:text] jest atrybutem [Thymeleaf], który ma dwa różne przeznaczenia w zależności od tego, czy [Thymeleaf] jest aktywny, czy nie:
- jeśli [Thymeleaf] nie interpretuje strony HTML, atrybut [th:text] zostanie zignorowany, ponieważ jest nieznany w HTML. Wyświetlony tekst będzie wówczas brzmiał [Voici l'heure],
- jeśli [Thymeleaf] interpretuje stronę HTML, atrybut [th:text] zostanie oceniony, a jego wartość zastąpi tekst [Voici l'heure]. Jego wartość będzie wyglądać mniej więcej tak: [Il est 17:11:06];
Zobaczmy, jak to działa w praktyce. Duplikujemy stronę [templates / exemple-02.html] w folderze [static]. Strony HTML umieszczone w tym folderze nie są interpretowane przez [Thymeleaf]:
![]() | ![]() | ![]() |
Uruchamiamy aplikację tak, jak robiliśmy to już wielokrotnie, a następnie wywołujemy w przeglądarce pliki URL i [http://localhost:8080/exemple-02.html]:
![]() |
W [1] widzimy, że atrybut [th:text] nie został zinterpretowany, ale nie spowodowało to również żadnego błędu. Kod źródłowy strony otrzymanej w [2] pokazuje, że przeglądarka prawidłowo odebrała całą stronę.
Wróćmy do strony [exemple-02.html] z folderu [templates]:
![]() |
Strony HTML umieszczone w folderze [templates] są interpretowane przez plik [Thymeleaf]. Wróćmy do kodu strony:
<!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>
- wiersz 7: [Thymeleaf] zinterpretuje atrybut [th:text] i zastąpi [Voici l'heure] wartością wyrażenia:
Wyrażenie to wykorzystuje zmienną [${heure}], gdzie [heure] należy do szablonu widoku [exemple-02.html]. Musimy zatem utworzyć ten szablon. W tym celu skorzystamy z przykładu omówionego w punkcie 1.6. Modyfikujemy projekt w następujący sposób:
![]() |
W [1] dodajemy następujący kontroler:
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) {
// format godziny
SimpleDateFormat formater = new SimpleDateFormat("HH:MM:ss");
// aktualna godzina
String heure = formater.format(new Date());
// umieszczamy godzinę w szablonie widoku
model.addAttribute("heure", heure);
// wyświetlanie widoku [exemple-02.html]
return "exemple-02";
}
}
- wiersze 13–14: metoda [heure] przetwarza URL i [/];
- wiersz 14: [Model model] jest pustym szablonem. Akcja [heure] musi umieścić w nim atrybuty, które chce widzieć w szablonie. Wiadomo, że widok [exemple-02.html] oczekuje atrybutu o nazwie [heure];
- wiersze 19–22: realizują to, co właśnie wyjaśniono. Widok [exemple-02.html] zostanie wyświetlony (wiersz 22) z atrybutem o nazwie [heure] w swoim szablonie (wiersz 20);
- wiersz 16: tworzymy formatator daty. Zastosowany format [HH:MM:ss] jest formatem [heures:minutes:secondes], w którym godziny mieszczą się w przedziale [0-24];
- wiersz 18: za pomocą tego formatownika formatuje się datę bieżącego dnia;
- wiersz 20: uzyskana godzina jest przypisywana do atrybutu o nazwie [heure];
Uruchamiamy aplikację i żądamy wartości URL oraz [/]:
![]() |
- w [1] otrzymujemy stronę, a w [2] jej zawartość HTML. Można zauważyć, że pierwotny tekst [Voici l'heure] całkowicie zniknął;
Jeśli teraz odświeżymy stronę [1] (F5), otrzymamy inny widok (nowy czas), podczas gdy URL pozostaje niezmieniony. To właśnie dynamiczny charakter strony: jej zawartość może zmieniać się w miarę upływu czasu.
Z powyższego wynika, że strony dynamiczne i statyczne różnią się zasadniczo.
2.2.3. Konfiguracja aplikacji Spring Boot
Wróćmy do architektury projektu Eclipse:
![]() |
Plik [application.properties] służy do konfiguracji aplikacji Spring Boot. Na razie ten plik jest pusty. Można go wykorzystać do konfiguracji aplikacji na wiele sposobów opisanych w plikach URL i [http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html]. Wykorzystamy plik [application.properties] zgodnie z instrukcją zawartą w pliku [2]:
- wiersz 1: określa port usługi aplikacji internetowej;
- wiersz 2: określa kontekst aplikacji internetowej;
Dzięki tej konfiguracji strona statyczna [exemple-01.html] zostanie wygenerowana przy użyciu plików URL i [http://localhost:9000/intro/exemple-01.html]:
![]() |
2.3. Skrypty po stronie przeglądarki
Strona HTML może zawierać skrypty, które będą wykonywane przez przeglądarkę. Głównym językiem skryptowym po stronie przeglądarki jest obecnie (styczeń 2015 r.) JavaScript. W tym języku stworzono setki bibliotek, aby ułatwić pracę programistom.
Stwórzmy nową stronę [exemple-03.html] w folderze [static] istniejącego projektu:
![]() |
Edytujmy plik [exemple-03.html], wpisując następującą treść:
<!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>
- wiersz 13: definiuje przycisk (atrybut type) z tekstem „Kliknij mnie” (atrybut value). Po kliknięciu uruchamiana jest funkcja JavaScript [réagir] (atrybut onclick);
- wiersze 6–10: skrypt JavaScript;
- wiersze 7–9: funkcja [réagir];
- wiersz 8: wyświetla okno dialogowe z komunikatem [Vous avez cliqué sur le bouton].
Wyświetlmy stronę w przeglądarce:
![]() |
- w [1] – wyświetlana strona;
- w [2] – okno dialogowe wyświetlane po kliknięciu przycisku.
Po kliknięciu przycisku nie dochodzi do wymiany danych z serwerem. Kod JavaScript jest wykonywany przez przeglądarkę.
Dzięki ogromnej liczbie dostępnych bibliotek JavaScript można obecnie wbudowywać w przeglądarkę pełnoprawne aplikacje. W związku z tym dąży się do następujących architektur:
![]() |
- 1-2: serwer HTML jest serwerem stron statycznych HTML5 / CSS / JavaScript;
- 3-4: Strony HTML5 / CSS / JavaScript, które są generowane, współdziałają bezpośrednio z serwerem danych. Serwer ten dostarcza wyłącznie dane bez szablonu HTML. To właśnie kod JavaScript wstawia je do stron HTML już wyświetlanych w przeglądarce.
W tej architekturze kod JavaScript może stać się zbyt rozbudowany. Dlatego staramy się go uporządkować warstwowo, tak jak w przypadku kodu po stronie serwera:
![]() |
- warstwa [UI] odpowiada za interakcję z użytkownikiem;
- warstwa [DAO] współpracuje z serwerem danych;
- warstwa [métier] obejmuje procedury biznesowe, które nie wchodzą w interakcję ani z użytkownikiem, ani z serwerem danych. Warstwa ta może nie istnieć.
2.4. Wymiana danych między klientem a serwerem
Wróćmy do naszego początkowego schematu, który ilustrował elementy składowe aplikacji internetowej:

W tym miejscu skupiamy się na wymianie danych między komputerem klienckim a serwerem. Odbywa się ona za pośrednictwem sieci i warto przypomnieć ogólną strukturę wymiany danych między dwoma odległymi komputerami.
2.4.1. Model OSI
Model otwartej sieci o nazwie OSI (Open Systems Interconnection Reference Model), zdefiniowany przez ISO (Międzynarodową Organizację Normalizacyjną), opisuje idealną sieć, w której komunikację między komputerami można przedstawić za pomocą modelu siedmiowarstwowego:
![]() |
Każda warstwa korzysta z usług warstwy niższej i udostępnia swoje usługi warstwie wyższej. Załóżmy, że dwie aplikacje znajdujące się na różnych maszynach A i B chcą się komunikować: robią to na poziomie warstwy Application. Nie muszą one znać wszystkich szczegółów działania sieci: każda aplikacja przekazuje informacje, które chce przesłać, do warstwy poniżej – warstwy Présentation. Aplikacja musi zatem znać jedynie zasady współpracy z warstwą Présentation. Gdy informacja znajdzie się w warstwie Présentation, jest przekazywana zgodnie z innymi regułami do warstwy Session i tak dalej, aż informacja dotrze do nośnika fizycznego i zostanie fizycznie przesłana do komputera docelowego. Tam zostanie poddana procesowi odwrotnemu do tego, który miała miejsce na komputerze nadawczym.
Na każdej warstwie proces nadawczy odpowiedzialny za wysyłanie informacji przekazuje ją do procesu odbiorczego na innym komputerze należącym do tej samej warstwy co on sam. Odbywa się to zgodnie z określonymi zasadami, zwanymi protokołem warstwy. Otrzymujemy zatem następujący ostateczny schemat komunikacji:
![]() |
Rola poszczególnych warstw jest następująca:
Fizyczna | Zapewnia transmisję bitów za pośrednictwem nośnika fizycznego. W tej warstwie znajdują się urządzenia końcowe do przetwarzania danych (E.T.T.D.), takie jak terminal lub komputer, a także urządzenia końcowe obwodów danych (E.T.C.D.), takie jak modulator/demodulator, multiplekser, koncentrator. Istotne kwestie na tym poziomie to:
|
Łącze danych | Ukrywa specyfikę fizyczną warstwy fizycznej. Wykrywa i koryguje błędy transmisji. |
Sieć | Zarządza ścieżką, którą muszą podążać informacje wysyłane w sieci. Nazywa się to routage: określenie trasy, którą musi podążać informacja, aby dotarła do odbiorcy. |
Transport | Umożliwia komunikację między dwiema aplikacjami, podczas gdy poprzednie warstwy pozwalały jedynie na komunikację między urządzeniami. Usługą świadczoną przez tę warstwę może być multipleksowanie: warstwa transportowa może wykorzystywać to samo połączenie sieciowe (między urządzeniami) do przesyłania informacji należących do kilku aplikacji. |
Sesja | W tej warstwie znajdują się usługi umożliwiające aplikacji otwarcie i utrzymanie sesji roboczej na zdalnym komputerze. |
Prezentacja | Ma ona na celu ujednolicenie sposobu prezentacji danych na różnych maszynach. W ten sposób dane pochodzące z maszyny A zostaną „przetworzone” przez warstwę Présentation maszyny A zgodnie ze standardowym formatem, zanim zostaną wysłane do sieci. Po dotarciu do warstwy Présentation komputera docelowego B, który rozpozna je dzięki standardowemu formatowi, zostaną one przekształcone w inny sposób, aby aplikacja na komputerze B mogła je rozpoznać. |
Aplikacja | Na tym poziomie znajdują się aplikacje zazwyczaj bliskie użytkownikowi, takie jak poczta elektroniczna lub przesyłanie plików. |
2.4.2. Model TCP/IP
Model OSI jest modelem idealnym. Zestaw protokołów TCP/IP zbliża się do niego w następującej postaci:
![]() |
- interfejs sieciowy (karta sieciowa komputera) pełni funkcje warstw 1 i 2 modelu OSI
- warstwa IP (protokół internetowy) pełni funkcje warstwy 3 (sieć)
- Warstwa TCP (Transfer Control Protocol) lub UDP (User Datagram Protocol) pełni funkcje warstwy 4 (transportowej). Protokół TCP gwarantuje, że pakiety danych wymieniane między urządzeniami dotrą do miejsca przeznaczenia. Jeśli tak się nie stanie, protokół ten odsyła zagubione pakiety. Protokół UDP nie wykonuje tej czynności, więc zadanie to spoczywa na programiście aplikacji. Dlatego w Internecie, który nie jest siecią w 100% niezawodną, najczęściej stosowany jest protokół TCP. Mówimy wówczas o sieci TCP-IP.
- Warstwa aplikacji obejmuje funkcje poziomów od 5 do 7 modelu OSI.
Aplikacje internetowe znajdują się w warstwie Application i opierają się zatem na protokołach TCP-IP. Warstwy Application na komputerach klienckich i serwerze wymieniają między sobą komunikaty, które są przekazywane warstwom od 1 do 4 modelu w celu dostarczenia do miejsca przeznaczenia. Aby się porozumieć, warstwy aplikacji obu komputerów muszą „mówić” tym samym językiem lub protokołem. Protokół stosowany w aplikacjach internetowych nosi nazwę HTTP (HyperText Transfer Protocol). Jest to protokół tekstowy, c.a.d, dzięki któremu urządzenia wymieniają między sobą wiersze tekstu w sieci, aby się porozumieć. Wymiana ta jest znormalizowana, tzn. klient dysponuje pewną liczbą komunikatów, aby dokładnie wskazać serwerowi, czego oczekuje, a serwer również dysponuje pewną liczbą komunikatów, aby udzielić klientowi odpowiedzi. Ta wymiana komunikatów ma następującą postać:

Klient --> Serwer
Gdy klient wysyła żądanie do serwera WWW, przesyła
- wiersze tekstu w formacie HTTP, aby wskazać, czego oczekuje;
- pusty wiersz;
- opcjonalnie dokument.
Serwer --> Klient
Gdy serwer wysyła odpowiedź do klienta, przesyła
- wiersze tekstu w formacie HTTP, aby wskazać, co wysyła;
- pusty wiersz;
- opcjonalnie dokument.
Wymiana danych ma zatem tę samą formę w obu kierunkach. W obu przypadkach może nastąpić wysłanie dokumentu, choć rzadko zdarza się, by klient wysyłał dokument do serwera. Jednak protokół HTTP to przewiduje. To właśnie pozwala na przykład abonentom dostawcy usług internetowych na pobieranie różnych dokumentów na swoją stronę osobistą hostowaną u tego dostawcy. Wymieniane dokumenty mogą być dowolne. Weźmy na przykład przeglądarkę żądającą strony internetowej zawierającej obrazy:
- przeglądarka łączy się z serwerem WWW i żąda żądanej strony. Żądane zasoby są jednoznacznie identyfikowane za pomocą URL (Uniform Resource Locator). Przeglądarka wysyła jedynie nagłówki HTTP, a nie sam dokument.
- Serwer odpowiada na to żądanie. Najpierw wysyła nagłówki HTTP, wskazujące, jaki typ odpowiedzi wysyła. Może to być komunikat o błędzie, jeśli żądana strona nie istnieje. Jeśli strona istnieje, serwer poinformuje w nagłówkach HTTP swojej odpowiedzi, że po nich wyśle dokument HTML (HyperText Markup Language). Dokument ten stanowi ciąg wierszy tekstu w formacie HTML. Tekst HTML zawiera znaczniki (tagi), które dostarczają przeglądarce wskazówek dotyczących sposobu wyświetlania tekstu.
- Klient na podstawie nagłówków HTTP wysłanych przez serwer wie, że otrzyma dokument HTML. Przeanalizuje go i być może zauważy, że zawiera odniesienia do obrazów. Obrazy te nie znajdują się w dokumencie HTML. W związku z tym wysyła nowe żądanie do tego samego serwera WWW, prosząc o pierwszy potrzebny mu obraz. Żądanie to jest identyczne z tym wysłanym w punkcie 1, z tą różnicą, że żądany zasób jest inny. Serwer przetworzy to żądanie, wysyłając klientowi żądany obraz. Tym razem w odpowiedzi nagłówki HTTP będą wskazywać, że wysłany dokument to obraz, a nie dokument HTML.
- Klient pobiera przesłany obraz. Kroki 3 i 4 będą powtarzane, dopóki klient (zazwyczaj przeglądarka) nie otrzyma wszystkich dokumentów umożliwiających wyświetlenie całej strony.
2.4.3. Protokół HTTP
Przyjrzyjmy się protokołowi HTTP na przykładach. Jakie dane wymieniają między sobą przeglądarka i serwer WWW?
Serwis internetowy lub serwis HTTP to serwis TCP-IP, który zazwyczaj działa na porcie 80. Może jednak działać na innym porcie. W takim przypadku przeglądarka kliencka musiałaby podać ten port w żądaniu URL. Żądanie URL ma ogólną postać:
protokół://komputer[:port]/ścieżka/informacje
gdzie
protokołu | http dla serwisu internetowego. Przeglądarka może również pełnić rolę klienta usług ftp, news, telnet itp. |
komputer | nazwa komputera, na którym działa usługa internetowa |
port | port serwisu internetowego. Jeśli jest to 80, można pominąć numer portu. Jest to najczęstszy przypadek |
ścieżka | ścieżka wskazująca żądany zasób |
informacje | dodatkowe informacje przekazywane serwerowi w celu doprecyzowania żądania klienta |
Co robi przeglądarka, gdy użytkownik żąda załadowania pliku o nazwie URL?
- otwiera połączenie TCP-IP z maszyną i portem wskazanymi w części machine[:port] pliku URL. Nawiązanie połączenia TCP-IP oznacza utworzenie „kanału” komunikacyjnego między dwoma maszynami. Po utworzeniu tego kanału wszystkie informacje wymieniane między tymi maszynami będą przez niego przepływać. Utworzenie tego kanału TCP-IP nie wiąże się jeszcze z wykorzystaniem protokołu internetowego HTTP.
- Po utworzeniu kanału TCP-IP klient wyśle żądanie do serwera internetowego, wysyłając mu wiersze tekstu (polecenia) w formacie HTTP. Wyśle on do serwera część ścieżki/informacji z URL
- serwer odpowie w ten sam sposób i w tym samym kanale
- jeden z partnerów podejmie decyzję o zamknięciu kanału. Zależy to od używanego protokołu HTTP. W przypadku protokołu HTTP 1.0 serwer zamyka połączenie po każdej swojej odpowiedzi. Zmusza to klienta, który musi wysłać wiele żądań w celu uzyskania różnych dokumentów tworzących stronę internetową, do nawiązywania nowego połączenia przy każdym żądaniu, co wiąże się z pewnymi kosztami. W przypadku protokołu HTTP/1.1 klient może poinstruować serwer, aby utrzymywał połączenie otwarte do momentu, aż klient poleci mu je zamknąć. Dzięki temu może pobrać wszystkie dokumenty strony internetowej za pomocą jednego połączenia i samodzielnie zamknąć połączenie po otrzymaniu ostatniego dokumentu. Serwer wykryje to zamknięcie i również zamknie połączenie.
Aby zapoznać się z wymianą danych między klientem a serwerem WWW, wykorzystamy rozszerzenie [Advanced Rest Client] przeglądarki Chrome, które zainstalowaliśmy w punkcie 9.6. Znajdziemy się w następującej sytuacji:

Serwer WWW może być dowolny. Chcemy tutaj prześledzić komunikację, jaka będzie miała miejsce między przeglądarką a serwerem WWW. Wcześniej utworzyliśmy następującą statyczną stronę o nazwie 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>
którą wyświetlamy w przeglądarce:
![]() |
Widać, że żądana strona URL to: [http://localhost:9000/intro/exemple-01.html]. Serwer usługi internetowej to zatem localhost (=serwer lokalny), a port to 9000. Użyjmy aplikacji [Advanced Rest Client], aby wysłać żądanie dotyczące tego samego URL:
![]() |
- w [1] uruchamiamy aplikację (w zakładce [Applications] w nowej zakładce przeglądarki Chrome);
- w [2] wybieramy opcję [Request];
- w [3] należy podać adres serwera: http://localhost:9000;
- w polu [4] należy podać żądaną stronę: /intro/exemple-01.html;
- w [5] dodaje się ewentualne parametry do URL. Tutaj nie ma żadnych;
- w [6] określa się polecenie HTTP użyte w zapytaniu, w tym przypadku GET.
W rezultacie otrzymujemy następujące zapytanie:
![]() |
Tak przygotowane zapytanie [7] jest wysyłane do serwera przez [8]. Otrzymana odpowiedź wygląda następująco:
![]() |
Jak wspomniano powyżej, komunikacja między klientem a serwerem ma następującą postać:

- w [1] widać nagłówki HTTP wysłane przez przeglądarkę w jej żądaniu. Nie miała ona żadnego dokumentu do wysłania;
- w [2] widać nagłówki HTTP wysłane przez serwer w odpowiedzi. W [3] widać dokument, który serwer wysłał.
W pliku [3] rozpoznajemy statyczną stronę HTML, którą umieściliśmy na serwerze WWW.
Przyjrzyjmy się żądaniu HTTP wysłanemu przez przeglądarkę:
- wiersz 1 nie został wyświetlony przez aplikację;
- wiersz 6: przeglądarka identyfikuje się za pomocą nagłówka [User-Agent];
- wiersz 7: przeglądarka wskazuje, że wysyła do serwera dokument tekstowy (text/plain) w formacie UTF-8. W rzeczywistości przeglądarka nie wysłała tutaj żadnego dokumentu;
- wiersz 8: przeglądarka wskazuje, że akceptuje każdy typ dokumentu w odpowiedzi;
- wiersz 9: przeglądarka określa akceptowane formaty dokumentów;
- wiersz 10: przeglądarka określa preferowane języki w kolejności według preferencji.
Serwer odpowiedział, wysyłając następujące nagłówki HTTP:
- wiersz 1: nie został wyświetlony przez aplikację;
- wiersz 2: serwer identyfikuje się, w tym przypadku jest to serwer Apache-Coyote;
- wiersz 3: data ostatniej modyfikacji wysłanego dokumentu;
- wiersz 4: rodzaj dokumentu wysłanego przez serwer. W tym przypadku jest to dokument HTML;
- wiersz 5: rozmiar w bajtach przesłanego dokumentu HTML.
- wiersz 6: data i godzina odpowiedzi;
2.4.4. Wnioski
Na podstawie kilku przykładów zapoznaliśmy się ze strukturą żądania klienta sieciowego oraz odpowiedzi udzielanej mu przez serwer sieciowy. Komunikacja odbywa się za pomocą protokołu HTTP, czyli zestawu poleceń w formacie tekstowym wymienianych między obiema stronami. Żądanie klienta i odpowiedź serwera mają tę samą strukturę:

Dwa typowe polecenia służące do żądania zasobu to GET oraz POST. Polecenie GET nie jest opatrzone dokumentem. Natomiast polecenie POST jest opatrzone dokumentem, który najczęściej stanowi ciąg znaków zawierający wszystkie wartości wprowadzone w formularzu. Polecenie HEAD służy do żądania wyłącznie nagłówków HTTP i nie jest mu dołączony żaden dokument.
Na żądanie klienta serwer wysyła odpowiedź o tej samej strukturze. Żądany zasób jest przekazywany w części [Document], chyba że polecenie klienta brzmiało HEAD – w takim przypadku wysyłane są wyłącznie nagłówki HTTP.
2.5. Podstawy języka HTML
Przeglądarka internetowa może wyświetlać różne dokumenty, z których najpopularniejszym jest dokument HTML (HyperText Markup Language). Jest to tekst sformatowany za pomocą znaczników o postaci <balise>texte</balise>. Na przykład tekst <B>important</B> wyświetli ważny fragment tekstu pogrubioną czcionką. Istnieją również pojedyncze znaczniki, takie jak znacznik <hr/>, który wyświetla poziomą linię. Nie będziemy omawiać znaczników, które można znaleźć w tekście HTML. Istnieje wiele programów WYSIWYG umożliwiających tworzenie stron internetowych bez pisania ani jednej linii kodu HTML. Narzędzia te automatycznie generują kod HTML na podstawie układu strony utworzonego za pomocą myszki i gotowych elementów sterujących. Można więc wstawić (za pomocą myszki) do strony tabelę, a następnie przejrzeć kod HTML wygenerowany przez oprogramowanie, aby dowiedzieć się, jakich tagów należy użyć do zdefiniowania tabeli na stronie internetowej. To naprawdę nie jest skomplikowane. Ponadto znajomość języka HTML jest niezbędna, ponieważ dynamiczne aplikacje internetowe muszą samodzielnie generować kod HTML, który ma zostać wysłany do klientów internetowych. Kod ten jest generowany programowo i oczywiście trzeba wiedzieć, co należy wygenerować, aby klient otrzymał pożądaną stronę internetową.
Podsumowując, nie ma potrzeby znajomości całego języka HTML, aby rozpocząć programowanie internetowe. Jednak znajomość ta jest niezbędna i można ją zdobyć, korzystając z oprogramowania do tworzenia stron internetowych w języku WYSIWYG, takiego jak DreamWeaver i dziesiątek innych. Innym sposobem na poznanie subtelności języka HTML jest przeglądanie sieci i wyświetlanie kodu źródłowego stron, które zawierają interesujące i jeszcze nieznane Ci funkcje.
2.5.1. Przykład
Rozważmy poniższy przykład, który przedstawia kilka elementów, jakie można znaleźć w dokumencie internetowym, takich jak:
- tabela;
- obraz;
- link.
![]() | ![]() |
Dokument HTML ma następującą ogólną postać:
Cały dokument jest ujęty w tagi <html>...</html>. Składa się on z dwóch części:
- <head>...</head>: jest to niewidoczna część dokumentu. Zawiera informacje dla przeglądarki, która wyświetli dokument. Często znajduje się tam tag <title>...</title>, który określa tekst, który zostanie wyświetlony w pasku tytułu przeglądarki. Można tam znaleźć również inne tagi, w szczególności tagi definiujące słowa kluczowe dokumentu, które są następnie wykorzystywane przez wyszukiwarki. W tej części można również znaleźć skrypty, najczęściej napisane w języku JavaScript lub VBScript, które zostaną wykonane przez przeglądarkę.
- <body atrybuty>...</body>: jest to część, która zostanie wyświetlona przez przeglądarkę. Tagi zawarte w tej części wskazują przeglądarce „pożądany” wygląd dokumentu. Każda przeglądarka interpretuje te tagi na swój sposób. W związku z tym dwie przeglądarki mogą wyświetlać ten sam dokument internetowy w różny sposób. Jest to zazwyczaj jeden z problemów, z którymi borykają się projektanci stron internetowych.
Kod HTML naszego przykładowego dokumentu wygląda następująco:
<!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>
Element | tagi i przykłady HTML |
tytuł dokumentu | <title>tagi</title> (wiersz 5) tekst balises pojawi się w pasku tytułu przeglądarki wyświetlającej dokument |
pozioma linia | <hr/>: wyświetla poziomą kreskę (wiersz 10) |
tabela | <table atrybuty>....</table>: do zdefiniowania tabeli (wiersze 11, 31) <thead>...</thead>: w celu zdefiniowania nagłówków kolumn (wiersze 12, 18) <tbody>...</tbody>: służy do zdefiniowania zawartości tabeli (wiersze 19, 30) <tr atrybuty>...</tr>: w celu zdefiniowania wiersza (wiersze 20, 24) <td atrybuty>...</td>: do zdefiniowania komórki (wiersz 21) przykłady: <table border="1">...</table>: atrybut border określa grubość obramowania tabeli <td style="width: 150px; text-align: center;">komórka(1,2)</td>: definiuje komórkę, której zawartością będzie komórka(1,2). Zawartość ta zostanie wyśrodkowana w poziomie (text-align: center). Komórka będzie miała szerokość 150 pikseli (width: 150px) |
obraz | <img border="0" src="/images/cerisier.jpg"/> (wiersz 36): definiuje obraz bez obramowania (border=0"), którego plik źródłowy znajduje się w katalogu /images/cerisier.jpg na serwerze WWW (src="images/cerisier.jpg"). Link ten znajduje się w dokumencie internetowym uzyskanym za pomocą URL http://localhost:port/intro/exemple-04.html. W związku z tym przeglądarka zażąda pliku URL http://localhost:port/intro/images/cerisier.jpg, aby pobrać obraz, do którego odwołuje się ten link. |
link | <a href="http://istia.univ-angers.fr">tutaj</a> (wiersz 40): sprawia, że tekst ici służy jako link do strony URL http://istia.univ-angers.fr. |
na dole strony | <body style="height:400px;width:400px;background-image:url(images/standard.jpg)"> (wiersz 8): wskazuje, że obraz, który ma służyć jako tło strony, znajduje się pod adresem URL [images/standard.jpg] na serwerze WWW. W kontekście naszego przykładu przeglądarka wyśle żądanie do adresu http://localhost:port/intro/images/standard.jpg, aby pobrać ten obraz tła. Ponadto treść dokumentu zostanie wyświetlona w prostokącie o wysokości 400 pikseli i szerokości 400 pikseli. |
Na tym prostym przykładzie widać, że aby zbudować cały dokument, przeglądarka musi wysłać trzy żądania do serwera:
- http://localhost:port/intro/exemple-04.html, aby pobrać plik źródłowy HTML dokumentu
- http://localhost:port/intro/images/cerisier.jpg, aby pobrać obraz cerisier.jpg
- http://localhost:port/intro/images/standard.jpg, aby pobrać obraz tła o numerze standard.jpg
2.5.2. Formularz HTML
Poniższy przykład przedstawia formularz:
![]() | ![]() |
Kod HTML generujący ten wygląd jest następujący:
<!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>
Powiązanie między kontrolą wizualną a tagiem HTML przedstawia się następująco:
Kontrola | tag HTML |
formularz | <form method="post" action="..."> |
pole wprowadzania danych | <input type="text" name="txtSaisie" size="20" value="kilka słów" /> |
ukryte pole wprowadzania danych | <input type="password" name="txtMdp" size="20" value="unMotDePasse" /> |
pole wielowierszowe | <textarea rows="2" name="areaSaisie" cols="20"> wiersz1 wiersz 2 wiersz 3 </textarea> |
przyciski opcji | <input type="radio" value="Tak" name="R1" />Tak <input type="radio" name="R1" value="nie" checked="checked" />Nie |
pola wyboru | <input type="checkbox" name="C1" value="jeden" />1 <input type="checkbox" name="C2" value="dwa" checked="checked" />2 <input type="checkbox" name="C3" value="trzy" />3 |
Lista rozwijana | <select size="1" name="cmbValeurs"> <option value="1">opcja1</option> <option selected="selected" value="2">opcja 2</option> <option value="3">opcja 3</option> </select> |
lista z jednym wyborem | <select size="3" name="lst1"> <option selected="selected" value="1">lista1</option> <option value="2">lista2</option> <option value="3">lista3</option> <option value="4">lista4</option> <option value="5">lista5</option> </select> |
lista z możliwością wyboru wielu pozycji | <select size="3" name="lst2" multiple="multiple"> <option value="1">lista1</option> <option value="2">lista2</option> <option selected="selected" value="3">lista3</option> <option value="4">lista4</option> <option value="5">lista5</option> </select> |
przycisk typu submit | <input type="submit" value="Wyślij" name="cmdRenvoyer" /> |
przycisk typu reset | <input type="reset" value="Przywróć" name="cmdRétablir" /> |
przycisk typu button | <input type="button" value="Usuń" name="cmdEffacer" onclick="effacer()" /> |
Przyjrzyjmy się tym różnym tagom:
2.5.2.1. ulary
formularz | |
tag HTML | <form name="..." method="..." action="...">...</form> |
atrybuty | name="frmexemple": nazwa formularza method="..." : metoda używana przez przeglądarkę do wysyłania do serwera WWW wartości zebranych w formularzu action="..." : adres, na który zostaną wysłane wartości zebrane w formularzu. Formularz internetowy jest otoczony tagami <form>...</form>. Formularz może mieć nazwę (name="xx"). Dotyczy to wszystkich elementów kontrolnych, które można znaleźć w formularzu. Celem formularza jest zebranie informacji podanych przez użytkownika za pomocą klawiatury lub myszy oraz wysłanie ich do adresu URL serwera internetowego. Którego? Tego, który jest podany w atrybucie action="URL". Jeśli ten atrybut nie występuje, informacje zostaną wysłane do serwera dokumentu, w którym znajduje się formularz. Klient sieciowy może wykorzystać dwie różne metody o nazwach POST i GET do wysyłania danych na serwer WWW. Atrybut method="méthode", przy czym method jest równe GET lub POST, w tagu <form> wskazuje przeglądarce metodę, jaką należy zastosować do wysłania informacji zebranych w formularzu do serwera określonego przez atrybut action="URL". Gdy atrybut method nie jest określony, domyślnie stosowana jest metoda GET. |
2.5.2.2. Pola wprowadzania tekstu
pole tekstowe | <input type="text" name="txtSaisie" size="20" value="kilka słów" /> <input type="password" name="txtMdp" size="20" value="unMotDePasse" /> |
![]() |
tag HTML | <input type="..." name="..." size=".." value=".."/> Tag input służy do różnych elementów sterujących. To właśnie atrybut type pozwala odróżnić te różne elementy sterujące od siebie. |
atrybuty | type="text": określa, że jest to pole wprowadzania danych type="password": znaki w polu wprowadzania danych są zastępowane znakami *. Jest to jedyna różnica w stosunku do zwykłego pola wprowadzania danych. Ten typ elementu kontrolnego nadaje się do wprowadzania haseł. size="20": liczba znaków widocznych w polu – nie uniemożliwia wprowadzenia większej liczby znaków name="txtSaisie": nazwa elementu value="kilka słów": tekst, który będzie wyświetlany w polu wprowadzania danych. |
2.5.2.3. Pola wprowadzania danych wielowierszowe
pole wprowadzania wielowierszowe | <textarea rows="2" name="areaSaisie" cols="20"> wiersz1 wiersz 2 wiersz 3 </textarea> |
![]() |
tag HTML | <textarea ...>tekst</textarea> wyświetla wielowierszowe pole wprowadzania tekstu z domyślnym tekstem |
atrybuty | rows="2": liczba wierszy cols="'20" : liczba kolumn name="areaSaisie": nazwa kontrolki |
2.5.2.4. Przyciski opcji
przyciski opcji | <input type="radio" value="Tak" name="R1" />Tak <input type="radio" name="R1" value="nie" checked="checked" />Nie |
tag HTML | <input type="radio" attribut2="valeur2" ..../>tekst wyświetla przycisk opcji z tekstem obok. |
atrybuty | name="radio": nazwa elementu sterującego. Przyciski opcji o tej samej nazwie tworzą grupę przycisków, które wykluczają się wzajemnie: można zaznaczyć tylko jeden z nich. value="wartość": wartość przypisana do przycisku opcji. Nie należy mylić tej wartości z tekstem wyświetlanym obok przycisku opcji. Ten ostatni służy wyłącznie do wyświetlania. checked="checked": jeśli to słowo kluczowe jest obecne, przycisk opcji jest zaznaczony, w przeciwnym razie nie jest. |
2.5.2.5. Pola wyboru
Pola wyboru | <input type="checkbox" name="C1" value="jeden" />1 <input type="checkbox" name="C2" value="dwa" checked="checked" />2 <input type="checkbox" name="C3" value="trzy" />3 |
tag HTML | <input type="checkbox" attribut2="valeur2" ....>tekst wyświetla pole wyboru z tekstem obok. |
atrybuty | name="C1": nazwa elementu sterującego. Pola wyboru mogą, ale nie muszą mieć tę samą nazwę. Pola o tej samej nazwie tworzą grupę powiązanych pól. value="wartość": wartość przypisana do pola wyboru. Nie należy mylić tej wartości z tekstem wyświetlanym obok pola wyboru. Ten ostatni służy wyłącznie do wyświetlania. checked= „checked”: jeśli to słowo kluczowe występuje, pole wyboru jest zaznaczone, w przeciwnym razie nie jest. |
2.5.2.6. Lista rozwijana (combo)
Combo | <select size="1" name="cmbValeurs"> <option value="1">opcja1</option> <option selected="selected" value="2">opcja2</option> <option value="3">opcja 3</option> </select> |
tag HTML | <select size=".." name=".."> <option [selected="selected"] value=”v”>...</option> ... </select> wyświetla na liście teksty zawarte między znacznikami <option>...</option> |
atrybuty | name="cmbValeurs": nazwa kontrolki. size="1": liczba widocznych elementów listy. size="1" sprawia, że lista działa jak pole kombi. selected="selected": jeśli ten atrybut występuje dla elementu listy, element ten pojawia się jako zaznaczony na liście. W naszym powyższym przykładzie element listy choix2 pojawia się jako zaznaczony element listy rozwijanej, gdy jest ona wyświetlana po raz pierwszy. value=”v”: jeśli element zostanie wybrany przez użytkownika, to właśnie ta wartość [v] zostanie przesłana na serwer. W przypadku braku tego atrybutu na serwer zostanie przesłany wyświetlany i zaznaczony tekst. |
2.5.2.7. Lista z jednym wyborem
lista z jednym wyborem | <select size="3" name="lst1"> <option selected="selected" value="1">lista1</option> <option value="2">lista2</option> <option value="3">lista3</option> <option value="4">lista4</option> <option value="5">lista5</option> </select> |
![]() |
tag HTML | <select size=".." name=".."> <option [selected="selected"]>...</option> ... </select> wyświetla na liście teksty zawarte między tagami <option>...</option> |
atrybuty | takie same jak w przypadku listy rozwijanej wyświetlającej tylko jeden element. Ten element sterujący różni się od poprzedniej listy rozwijanej jedynie atrybutem size>1. |
2.5.2.8. Lista z możliwością wielokrotnego wyboru
lista z możliwością wyboru pojedynczego elementu | <select size="3" name="lst2" multiple="multiple"> <option value="1" selected="selected">lista1</option> <option value="2">lista2</option> <option selected="selected" value="3">lista3</option> <option value="4">lista4</option> <option value="5">lista5</option> </select> |
![]() |
tag HTML | <select size=".." name=".." multiple="multiple"> <option [selected="selected"]>...</option> ... </select> wyświetla na liście teksty zawarte między tagami <option>...</option> |
atrybuty | multiple: umożliwia zaznaczenie wielu elementów z listy. W powyższym przykładzie zaznaczone są oba elementy: liste1 i liste3. |
2.5.2.9. Przycisk typu button
przycisk typu button | <input type="button" value="Usuń" name="cmdEffacer" onclick="effacer()" /> |
tag HTML | <input type="button" value="..." name="..." onclick="effacer()" ..../> |
atrybuty | type="button": definiuje kontrolkę przycisku. Istnieją dwa inne typy przycisków: submit i reset. value="Usuń": tekst wyświetlany na przycisku onclick="funkcja()": pozwala zdefiniować funkcję, która ma zostać wykonana, gdy użytkownik kliknie przycisk. Funkcja ta jest częścią skryptów zdefiniowanych w wyświetlanym dokumencie internetowym. Powyższa składnia jest zgodna ze standardem javascript. Jeśli skrypty są napisane w języku VBScript, należy wpisać onclick="funkcja" bez nawiasów. Składnia pozostaje taka sama, jeśli do funkcji trzeba przekazać parametry: onclick="funkcja(val1, val2,...)" W naszym przykładzie kliknięcie przycisku Effacer wywołuje następującą funkcję JavaScript effacer: <script type="text/javascript"> function effacer() { alert("Kliknąłeś przycisk Usuń"); } </script> Funkcja effacer wyświetla komunikat: ![]() |
2.5.2.10. Przycisk typu „submit”
przycisk typu „submit” | <input type="submit" value="Wyślij" name="cmdRenvoyer" /> |
tag HTML | <input type="submit" value="Wyślij" name="cmdRenvoyer" /> |
atrybuty | type="submit": definiuje przycisk jako przycisk wysyłający dane formularza do serwera WWW. Gdy użytkownik kliknie ten przycisk, przeglądarka wyśle dane formularza do adresu URL zdefiniowanego w atrybucie action tagu <form> zgodnie z metodą określoną przez atrybut method tego samego tagu. value="Wyślij": tekst wyświetlany na przycisku |
2.5.2.11. Przycisk typu reset
Przycisk typu reset | <input type="reset" value="Przywróć" name="cmdRétablir" /> |
tag HTML | <input type="reset" value="Przywróć" name="cmdRétablir"/> |
atrybuty | type="reset": określa przycisk jako przycisk resetowania formularza. Gdy użytkownik kliknie ten przycisk, przeglądarka przywróci formularz do stanu, w jakim go otrzymała. value="Przywróć": tekst wyświetlany na przycisku |
2.5.2.12. Pole ukryte
ukryte pole | <input type="hidden" name="secret" value="uneValeur" /> |
tag HTML | <input type="hidden" name="..." value="..."/> |
atrybuty | type="hidden": określa, że jest to pole ukryte. Pole ukryte stanowi część formularza, ale nie jest widoczne dla użytkownika. Jeśli jednak użytkownik poprosiłby swoją przeglądarkę o wyświetlenie kodu źródłowego, zobaczyłby tag <input type="hidden" value="..."> i tym samym wartość pola ukrytego. value="uneValeur": wartość pola ukrytego. Jaka jest zaleta pola ukrytego? Pozwala to serwerowi internetowemu na przechowywanie informacji w trakcie kolejnych żądań wysyłanych przez klienta. Rozważmy przykład aplikacji do zakupów online. Klient kupuje pierwszy produkt o numerze art1 w ilości q1 na pierwszej stronie katalogu, a następnie przechodzi do kolejnej strony katalogu. Aby zapamiętać, że klient kupił q1 sztuk produktu art1, serwer może umieścić te dwie informacje w ukrytym polu formularza internetowego na nowej stronie. Na tej nowej stronie klient kupuje produkty o numerach q2 i art2. Gdy dane z tego drugiego formularza zostaną wysłane na serwer (submit), serwer otrzyma nie tylko informację (q2,art2), ale także (q1,art1), które również stanowią część formularza jako ukryte pola. Serwer WWW umieści wówczas w nowym ukrytym polu informacje (q1,art1) oraz (q2,art2) i wyśle nową stronę katalogu. I tak dalej. |
2.5.3. Wysyłanie wartości formularza do serwera WWW przez klienta WWW
W poprzednim opracowaniu wspomnieliśmy, że klient internetowy dysponuje dwiema metodami wysyłania do serwera internetowego wartości z wyświetlonego formularza: metodami GET i POST. Przyjrzyjmy się na przykładzie różnicy między tymi dwiema metodami.
2.5.3.1. Metoda GET
Przeprowadźmy pierwszy test, w którym w kodzie HTML dokumentu tag <form> jest zdefiniowany w następujący sposób:
<form method="get" action="doNothing">
![]() |
Gdy użytkownik kliknie przycisk [1], wartości wprowadzone w formularzu zostaną przesłane do kontrolera Spring [2]. Widzieliśmy, że wartości z formularza będą wysyłane do kontrolera URL [doNothing]:
<form method="get" action="doNothing">
Akcja [doNothing] jest zdefiniowana w kontrolerze [MyController] [2] w następujący sposób:
// ----------------------- wyczyszczenie strumienia [Content-Length=0]
@RequestMapping(value = "/doNothing")
@ResponseBody
public void doNothing() {
}
- wiersz 1: akcja przetwarza URL [/doNothing], a więc w rzeczywistości [/context/doNothing], gdzie [context] to kontekst lub nazwa aplikacji internetowej, w tym przypadku [/intro];
- wiersz 3: adnotacja [@ResponseBody] wskazuje, że wynik metody opatrzonej adnotacją musi zostać wysłany bezpośrednio do klienta;
- wiersz 4: metoda nie zwraca żadnej wartości. W związku z tym klient otrzyma od serwera pustą odpowiedź.
Chcemy jedynie dowiedzieć się, w jaki sposób przeglądarka przekazuje wprowadzone wartości do serwera internetowego. W tym celu wykorzystamy narzędzie do debugowania dostępne w przeglądarce Chrome. Aktywuje się je, naciskając klawisze CTRL-Shift-I (wielka litera) [3]:
![]() |
Ponieważ interesuje nas komunikacja sieciowa między przeglądarką a serwerem internetowym, otwieramy powyższą kartę [Network], a następnie klikamy przycisk [Envoyer] w formularzu. Jest to przycisk typu [submit] umieszczony wewnątrz tagu [form]. Przeglądarka reaguje na kliknięcie, wysyłając żądanie o wartości URL [/intro/doNothing] wskazaną w atrybucie [action] tagu [form], przy użyciu metody GET podanej w atrybucie [method]. Otrzymujemy wówczas następujące informacje:
![]() |
Powyższy zrzut ekranu przedstawia kod URL, o który poprosiła przeglądarka po kliknięciu przycisku [envoyer]. Rzeczywiście żąda on pliku URL, przewidzianego jako [/intro/doNothing], ale na końcu dodaje informacje, które są wartościami wprowadzonymi w formularzu. Aby uzyskać więcej informacji, klikamy na powyższy link:
![]() |
Powyżej, w [1, 2], widzimy nagłówki HTTP wysłane przez przeglądarkę. Zostały one tutaj sformatowane. Aby wyświetlić surowy tekst tych nagłówków, klikamy link [view source] [3, 4]. Pełny tekst wygląda następująco:
Znajdujemy tu elementy, które pojawiały się już wcześniej. Inne pojawiają się po raz pierwszy:
Connection: keep-alive | klient prosi serwer, aby nie zamykał połączenia po wysłaniu odpowiedzi. Dzięki temu będzie mógł wykorzystać to samo połączenie do kolejnego żądania. Połączenie nie pozostaje otwarte w nieskończoność. Serwer zamknie je po zbyt długim okresie bezczynności. |
Referer | URL – adres, który był wyświetlany w przeglądarce w momencie wysłania nowego żądania. |
Nowością jest wiersz 1 w informacjach następujących po URL. Widać, że wybory dokonane w formularzu znajdują się w URL. Wartości wprowadzone przez użytkownika w formularzu zostały przekazane w poleceniu GET URL?param1=wartość1¶m2=wartość2&... HTTP/1.1, gdzie parami to nazwy (atrybut name) elementów sterujących formularza internetowego, a valeuri to wartości z nimi powiązane. Poniżej przedstawiamy tabelę składającą się z trzech kolumn:
- kolumna 1: zawiera definicję elementu sterującego HTML z przykładu;
- kolumna 2: przedstawia wygląd tego elementu sterującego w przeglądarce;
- kolumna 3: przedstawia wartość wysyłaną do serwera przez przeglądarkę dla elementu sterującego z kolumny 1 w postaci, jaką ma ona w zapytaniu GET z przykładu.
element sterujący HTML | wygląd | zwracana(-e) wartość(-e) |
<input type="radio" value="Tak" name="R1"/>Tak <input type="radio" name="R1" value="nie" checked="checked"/>Nie | R1=Tak – wartość atrybutu value przycisku opcji zaznaczonego przez użytkownika. | |
<input type="checkbox" name="C1" value="jeden"/>1 <input type="checkbox" name="C2" value="dwa" checked="checked"/>2 <input type="checkbox" name="C3" value="trzy"/>3 | C1=jeden C2=dwa – wartości atrybutów value pól zaznaczonych przez użytkownika | |
<input type="text" name="txtSaisie" size="20" value="kilka słów"/> | txtSaisie=programowanie+Web - tekst wpisany przez użytkownika w polu wprowadzania danych. Spacje zostały zastąpione znakiem + | |
<input type="password" name="txtMdp" size="20" value="unMotDePasse"/> | txtMdp=tojesttajemnica – tekst wpisany przez użytkownika w polu wprowadzania danych | |
<textarea rows="2" name="areaSaisie" cols="20"> wiersz1 wiersz 2 wiersz 3 </textarea> | areaSaisie=podstawy+programowania+%0D%0A programowania+internetowego – tekst wpisany przez użytkownika w polu wprowadzania danych. %OD%OA to znacznik końca linii. Spacje zostały zastąpione znakiem + | |
<select size="1" name="cmbValeurs"> <option value='1'>opcja1</option> <option selected="selected" value='2'>opcja2</option> <option value='3'>opcja3</option> </select> | cmbValeurs=3 - atrybut [value] elementu wybranego przez użytkownika | |
<select size="3" name="lst1"> <option selected="selected" value='1'>lista1</option> <option value='2'>lista2</option> <option value='3'>lista3</option> <option value='4'>lista4</option> <option value='5'>lista5</option> </select> | ![]() | lst1=3 - atrybut [value] elementu wybranego przez użytkownika |
<select size="3" name="lst2" multiple="multiple"> <option selected="selected" value='1'>lista1</option> <option value='2'>lista2</option> <option selected="selected" value='3'>lista3</option> <option value='4'>lista4</option> <option value='5'>lista5</option> </select> | lst2=1 lst2=3 - atrybuty [value] elementów wybranych przez użytkownika | |
<input type="submit" value="Wyślij" name="cmdRenvoyer"/> | cmdRenvoyer=Wyślij - nazwa i atrybut value przycisku, który posłużył do wysłania danych formularza na serwer | |
<input type="hidden" name="secret" value="uneValeur"/> | secret=wartość - atrybut value ukrytego pola |
2.5.3.2. Metoda POST
Modyfikujemy dokument HTML tak, aby przeglądarka korzystała teraz z metody POST do wysyłania wartości formularza na serwer WWW:
<form method="post" action="doNothing">
Wypełniamy formularz tak samo jak w przypadku metody GET i przesyłamy parametry na serwer za pomocą przycisku [Envoyer]. Tak jak opisano w poprzednim akapicie na stronie 62, w przeglądarce Chrome mamy dostęp do nagłówków HTTP żądania wysłanego przez przeglądarkę:
W żądaniu HTTP od klienta pojawiają się nowe elementy:
POST URL HTTP/1.1 | Zapytanie GET zostało zastąpione zapytaniem POST. Parametry nie występują już w pierwszym wierszu zapytania. Można zauważyć, że znajdują się one teraz (wiersz 15) za zapytaniem HTTP, po pustym wierszu. Ich kodowanie jest identyczne jak w zapytaniu GET. |
Content-Length | liczba „wysłanych” znaków, c.a.d. Liczba znaków, które serwer WWW będzie musiał odczytać po otrzymaniu nagłówków HTTP, aby pobrać dokument wysłany przez klienta. Dokumentem tym jest w tym przypadku lista wartości z formularza. |
Content-type | określa typ dokumentu, który klient wyśle po nagłówkach HTTP. Typ [application/x-www-form-urlencoded] wskazuje, że jest to dokument zawierający wartości z formularza. |
Istnieją dwie metody przesyłania danych do serwera WWW: GET i POST. Czy jedna z tych metod jest lepsza od drugiej? Widzieliśmy, że jeśli wartości formularza były wysyłane przez przeglądarkę metodą GET, przeglądarka wyświetlała w polu Adresse żądaną wartość URL w postaci URL?param1=val1¶m2=val2&.... Można to postrzegać jako zaletę lub wadę:
- zaletą, jeśli chcemy umożliwić użytkownikowi dodanie tego skonfigurowanego adresu URL do ulubionych;
- wadą, jeśli nie chcemy, aby użytkownik miał dostęp do niektórych informacji zawartych w formularzu, takich jak na przykład pola ukryte.
W dalszej części będziemy stosować w naszych formularzach niemal wyłącznie metodę POST.
2.6. Conclusion
W niniejszym rozdziale przedstawiono różne podstawowe pojęcia związane z tworzeniem stron internetowych:
- wymianę danych między klientem a serwerem za pośrednictwem protokołu HTTP;
- tworzenie dokumentu przy użyciu języka HTML;
- tworzenie formularzy do wprowadzania danych.
Na przykładzie mogliśmy zobaczyć, w jaki sposób klient może wysyłać informacje do serwera internetowego. Nie omówiliśmy jednak, w jaki sposób serwer może
- pobierać te informacje;
- przetwarzać je;
- wysłać do klienta dynamiczną odpowiedź zależną od wyniku przetwarzania.
Jest to dziedzina programowania internetowego, którą omówimy w następnym rozdziale wraz z prezentacją technologii Spring MVC.










































