Skip to content

2. أساسيات برمجة الويب

يهدف هذا الفصل بشكل أساسي إلى تعريف القارئ بالمبادئ الرئيسية لبرمجة الويب، والتي لا تعتمد على التكنولوجيا المحددة المستخدمة لتنفيذها. ويقدم الفصل العديد من الأمثلة التي يُنصح بتجربتها من أجل «الانغماس» تدريجيًا في فلسفة تطوير الويب. يمكن للقارئ الذي يمتلك هذه المعرفة بالفعل الانتقال مباشرةً إلى الفصل 3.

مكونات تطبيق الويب هي كما يلي:

Image

الرقم
الدور
أمثلة شائعة
1
OS الخادم
Unix، Linux، Windows
2
خادم الويب
أباتشي (يونكس، لينكس، ويندوز)
IIS (ويندوز + منصة .NET)
Node.js (Unix، Linux، Windows)
3
أكواد تُنفَّذ على جانب الخادم. ويمكن تنفيذها بواسطة وحدات الخادم أو بواسطة برامج خارجية (CGI).
JAVASCRIPT (Node.js)
PHP (أباتشي، IIS)
JAVA (Tomcat، Websphere، JBoss، Weblogic، ...)
C#، VB.NET (IIS)
4
قاعدة البيانات - يمكن أن تكون موجودة على نفس الجهاز الذي يعمل عليه البرنامج أو على جهاز آخر عبر الإنترنت.
Oracle (Linux، Windows)
MySQL (Linux، Windows)
Postgres (Linux، Windows)
SQL Server (ويندوز)
5
OS العميل
Unix، Linux، Windows
6
متصفح الويب
Chrome، Internet Explorer، Firefox، Opera، Safari، ...
7
نصوص برمجية تُنفَّذ على جانب العميل داخل المتصفح. لا تتمتع هذه النصوص البرمجية بأي وصول إلى أقراص جهاز العميل.
جافا سكريبت (جميع المتصفحات)

2.1. تبادل البيانات في تطبيق ويب باستخدام نموذج

Image

رقم
الدور
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] بقيمة التعبير:
"'Il est ' + ${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) هي جافا سكريبت. وقد تم إنشاء مئات المكتبات باستخدام هذه اللغة لتسهيل عمل المطور.

لنقم بإنشاء صفحة جديدة باسم [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). عند النقر عليه، يتم تنفيذ دالة جافا سكريبت [réagir] (السمة onclick
  • الأسطر 6-10: نص برمجي جافا سكريبت؛
  • الأسطر 7-9: الدالة [réagir
  • السطر 8: يعرض مربع حوار يحتوي على الرسالة [Vous avez cliqué sur le bouton].

دعونا نعرض الصفحة في متصفح:

  • في [1]، الصفحة المعروضة؛
  • في [2]، مربع الحوار الذي يظهر عند النقر على الزر.

عند النقر على الزر، لا يحدث أي تبادل مع الخادم. يتم تنفيذ كود جافا سكريبت بواسطة المتصفح.

بفضل المكتبات العديدة المتاحة لـ جافا سكريبت، أصبح من الممكن الآن تضمين تطبيقات حقيقية في المتصفح. ومن ثم، فإن الاتجاه يسير نحو البنى التالية:

  • 1-2: الخادم HTML هو خادم للصفحات الثابتة HTML5 / CSS / جافا سكريبت؛
  • 3-4: تتفاعل الصفحات HTML5 / CSS / جافا سكريبت التي يتم عرضها بشكل مباشر مع خادم البيانات. ويقوم هذا الخادم بتقديم البيانات فقط دون تضمين العناصر التصميمية HTML. ويقوم جافا سكريبت بإدراجها في صفحات HTML الموجودة بالفعل على المتصفح.

في هذه البنية، قد يصبح كود جافا سكريبت ثقيلًا. لذا نسعى إلى تنظيمه في طبقات كما نفعل مع الكود الخاص بالجانب الخادمي:

  • الطبقة [UI] هي التي تتفاعل مع المستخدم؛
  • الطبقة [DAO] تتفاعل مع خادم البيانات؛
  • الطبقة [métier] تضم الإجراءات التشغيلية التي لا تتفاعل لا مع المستخدم ولا مع خادم البيانات. وقد لا تكون هذه الطبقة موجودة.

2.4. التفاعلات بين العميل والخادم

لنعد إلى مخططنا الأولي الذي يوضح العناصر الفاعلة في تطبيق ويب:

Image

نركز هنا على التبادلات بين جهاز العميل وجهاز الخادم. تتم هذه التبادلات عبر شبكة، ومن الجيد التذكير بالبنية العامة للتبادلات بين جهازين بعيدين.

2.4.1. نموذج OSI

يصف نموذج الشبكة المفتوحة المسمى OSI (نموذج مرجعي لترابط الأنظمة المفتوحة) الذي حددته المنظمة الدولية للمعايير (ISO) شبكةً مثاليةً يمكن فيها تمثيل الاتصال بين الأجهزة بنموذج مكون من سبع طبقات:

تتلقى كل طبقة الخدمات من الطبقة السفلية وتقدم خدماتها إلى الطبقة العليا. لنفترض أن تطبيقين موجودين على جهازين مختلفين، A و B، يرغبان في التواصل: فيقومان بذلك على مستوى الطبقة Application. ولا يحتاجان إلى معرفة جميع تفاصيل تشغيل الشبكة: فكل تطبيق يسلم المعلومات التي يرغب في إرسالها إلى الطبقة التي تليه، وهي الطبقة Présentation. وبالتالي، لا يتعين على التطبيق سوى معرفة قواعد التفاعل مع الطبقة Présentation. وبمجرد وصول المعلومات إلى الطبقة Présentation، يتم تمريرها وفقًا لقواعد أخرى إلى الطبقة Session وهكذا دواليك، حتى تصل المعلومات إلى الوسيط المادي ويتم إرسالها فعليًّا إلى الجهاز المقصود. وهناك، ستخضع لعملية معالجة عكسية لتلك التي خضعت لها على الجهاز المرسل.

في كل طبقة، تقوم العملية المرسلة المكلفة بإرسال المعلومات بإرسالها إلى عملية مستقبلة على الجهاز الآخر الذي ينتمي إلى نفس الطبقة التي تنتمي إليها. وتقوم بذلك وفقًا لقواعد معينة تُسمى بروتوكول الطبقة. وبذلك نحصل على مخطط الاتصال النهائي التالي:

دور الطبقات المختلفة هو كما يلي:

الطبقة المادية
تضمن نقل البتات عبر وسيط مادي. توجد في هذه الطبقة أجهزة طرفية لمعالجة البيانات (E.T.T.D.) مثل المحطة الطرفية أو الكمبيوتر، بالإضافة إلى أجهزة إنهاء دوائر البيانات (E.T.C.D.) مثل المُعدِّل/المُفكِّك، والمُضاعِف، والمُركِّز. النقاط المهمة في هذا المستوى هي:
  • اختيار طريقة ترميز المعلومات (تناظرية أو رقمية)
  • اختيار طريقة الإرسال (متزامن أو غير متزامن).
وصلة البيانات
يخفي الخصائص المادية للطبقة المادية. يكتشف أخطاء الإرسال ويصححها.
الشبكة
تدير المسار الذي يجب أن تتبعه المعلومات المرسلة عبر الشبكة. ويُطلق على ذلك اسم routage: تحديد المسار الذي يجب أن تتبعه المعلومات حتى تصل إلى مستلمها.
طبقة النقل
يسمح بالاتصال بين تطبيقين، في حين أن الطبقات السابقة كانت تسمح فقط بالاتصال بين الأجهزة. ومن الخدمات التي توفرها هذه الطبقة «التعدد الإرسالي»: حيث يمكن لطبقة النقل استخدام نفس اتصال الشبكة (من جهاز إلى جهاز) لنقل المعلومات الخاصة بعدة تطبيقات.
الجلسة
نجد في هذه الطبقة خدمات تسمح لأحد التطبيقات بفتح جلسة عمل والحفاظ عليها على جهاز بعيد.
التقديم
تهدف هذه الطبقة إلى توحيد عرض البيانات على الأجهزة المختلفة. وبالتالي، فإن البيانات الواردة من الجهاز A سيتم "تنسيقها" بواسطة الطبقة Présentation الخاصة بالجهاز A، وفقًا لتنسيق قياسي قبل إرسالها عبر الشبكة. وعند وصولها إلى الطبقة Présentation في الجهاز المستلم B، الذي سيتعرف عليها بفضل تنسيقها القياسي، سيتم تكييفها بطريقة أخرى حتى يتعرف عليها التطبيق في الجهاز B.
التطبيق
في هذا المستوى، نجد التطبيقات التي عادةً ما تكون قريبة من المستخدم، مثل البريد الإلكتروني أو نقل الملفات.

2.4.2. النموذج TCP/IP

يُعد النموذج OSI نموذجًا مثاليًّا. وتقترب مجموعة البروتوكولات TCP/IP منه بالشكل التالي:

  • تؤدي واجهة الشبكة (بطاقة الشبكة في الكمبيوتر) وظائف الطبقتين 1 و2 من النموذج OSI
  • تؤدي الطبقة IP (بروتوكول الإنترنت) وظائف الطبقة الثالثة (الشبكة)
  • تقوم الطبقة TCP (بروتوكول التحكم في النقل) أو UDP (بروتوكول مخطط بيانات المستخدم) بأداء وظائف الطبقة الرابعة (النقل). يضمن بروتوكول TCP وصول حزم البيانات المتبادلة بين الأجهزة إلى وجهتها بشكل صحيح. وإذا لم يحدث ذلك، فإنه يعيد الحزم التي ضلت طريقها. لا يقوم بروتوكول UDP بهذه المهمة، وبالتالي يقع على عاتق مطور التطبيقات القيام بها. ولهذا السبب، على الإنترنت التي لا تُعد شبكة موثوقة بنسبة 100٪، يُعد بروتوكول TCP هو الأكثر استخدامًا. ونُشير عندئذٍ إلى شبكة TCP-IP.
  • تغطي طبقة التطبيق وظائف المستويات من 5 إلى 7 في نموذج OSI.

توجد تطبيقات الويب في الطبقة Application، وبالتالي فهي تعتمد على بروتوكولات TCP-IP. تتبادل طبقات Application الخاصة بأجهزة العملاء والخادم الرسائل التي تُعهد بها إلى الطبقات من 1 إلى 4 في النموذج لتوجيهها إلى وجهتها. لكي تتفاهم الطبقات التطبيقية في كلا الجهازين، يجب أن «تتحدث» نفس اللغة أو البروتوكول. ويُسمى بروتوكول تطبيقات الويب HTTP (بروتوكول النقل HyperText). وهو بروتوكول نصي، c.a.d، حيث تتبادل الأجهزة أسطر نصية عبر الشبكة للتواصل فيما بينها. هذه التبادلات موحدة، أي أن العميل لديه عدد معين من الرسائل للإشارة بدقة إلى ما يريده من الخادم، كما أن الخادم لديه أيضًا عدد معين من الرسائل لتقديم ردّه إلى العميل. ويأخذ تبادل الرسائل هذا الشكل التالي:

Image

العميل --> الخادم

عندما يوجه العميل طلبه إلى خادم الويب، فإنه يرسل

  1. أسطر نصية بتنسيق HTTP للإشارة إلى ما يريده؛
  2. سطر فارغ؛
  3. وثيقة (اختياري).

الخادم --> العميل

عندما يرد الخادم على العميل، فإنه يرسل

  1. سطور نصية بتنسيق HTTP للإشارة إلى ما يرسله؛
  2. سطر فارغ؛
  3. وثيقة اختيارية.

وبالتالي، تتخذ عمليات التبادل نفس الشكل في كلا الاتجاهين. وفي كلتا الحالتين، قد يتم إرسال مستند، حتى وإن كان من النادر أن يرسل العميل مستندًا إلى الخادم. لكن بروتوكول HTTP ينص على ذلك. وهذا ما يسمح، على سبيل المثال، لمشتركي مزود خدمة الإنترنت بتنزيل مستندات متنوعة على مواقعهم الشخصية المستضافة لدى هذا المزود. ويمكن أن تكون المستندات المتبادلة من أي نوع. لنأخذ مثالاً لمتصفح يطلب صفحة ويب تحتوي على صور:

  1. يتصل المتصفح بخادم الويب ويطلب الصفحة التي يرغب فيها. يتم تحديد الموارد المطلوبة بشكل فريد بواسطة URL (محدد موقع الموارد الموحد). لا يرسل المتصفح سوى رؤوس HTTP ولا يرسل أي مستند.
  2. يرد عليه الخادم. فيقوم أولاً بإرسال رؤوس HTTP تشير إلى نوع الرد الذي يرسله. وقد يكون هذا خطأً إذا كانت الصفحة المطلوبة غير موجودة. وإذا كانت الصفحة موجودة، فسيشير الخادم في رؤوس الاستجابة HTTP إلى أنه سيقوم بعد ذلك بإرسال مستند HTML (لغة الترميز HyperText). هذا المستند عبارة عن سلسلة من أسطر النص بتنسيق HTML. يحتوي النص HTML على علامات (علامات ترميز) تزود المتصفح بتوجيهات حول كيفية عرض النص.
  3. يعرف العميل من خلال رؤوس HTTP الصادرة عن الخادم أنه سيتلقى مستندًا بتنسيق HTML. سيقوم بتحليل هذا المستند وربما يلاحظ أنه يحتوي على إحالات إلى صور. هذه الصور غير موجودة في المستند HTML. لذا، يقوم بإرسال طلب جديد إلى نفس خادم الويب لطلب الصورة الأولى التي يحتاجها. هذا الطلب مطابق للطلب الذي تم إرساله في الخطوة 1، باستثناء أن المورد المطلوب مختلف. سيقوم الخادم بمعالجة هذا الطلب عن طريق إرسال الصورة المطلوبة إلى العميل. هذه المرة، ستوضح رؤوس HTTP في الرد أن المستند المرسل هو صورة وليس مستند HTML.
  4. يستلم العميل الصورة المرسلة. ستتكرر الخطوتان 3 و4 حتى يحصل العميل (وهو متصفح في العادة) على جميع المستندات التي تسمح له بعرض الصفحة بالكامل.

2.4.3. بروتوكول HTTP

لنتعرف على بروتوكول HTTP من خلال أمثلة. ما الذي يتبادله المتصفح وخادم الويب؟

خدمة الويب أو خدمة HTTP هي خدمة TCP-IP تعمل عادةً على المنفذ 80. وقد تعمل على منفذ آخر. في هذه الحالة، سيضطر متصفح العميل إلى تحديد هذا المنفذ في طلب URL الذي يرسله. يكون شكل طلب الويب عمومًا كما يلي:

البروتوكول://جهاز[:port]/المسار/المعلومات

حيث

البروتوكول
http لخدمة الويب. يمكن للمتصفح أيضًا أن يعمل كعميل لخدمات ftp و news و telnet، ...
الجهاز
اسم الجهاز الذي تعمل عليه خدمة الويب
المنفذ
منفذ خدمة الويب. إذا كان الرقم 80، فيمكن حذف رقم المنفذ. وهذا هو الحال الأكثر شيوعًا
المسار
المسار الذي يشير إلى المورد المطلوب
المعلومات
معلومات إضافية تُقدم إلى الخادم لتوضيح طلب العميل

ماذا يفعل المتصفح عندما يطلب المستخدم تحميل ملف URL؟

  1. يفتح اتصالاً TCP-IP مع الجهاز والمنفذ المحددين في الجزء machine[:port] من URL. إن فتح اتصال TCP-IP يعني إنشاء «قناة» اتصال بين جهازين. وبمجرد إنشاء هذه القناة، ستمر جميع المعلومات المتبادلة بين الجهازين عبرها. لا يتطلب إنشاء هذا القناة TCP-IP استخدام بروتوكول الويب HTTP في هذه المرحلة.
  2. بعد إنشاء القناة TCP-IP، سيقوم العميل بتوجيه طلبه إلى خادم الويب عن طريق إرسال أسطر نصية (أوامر) بتنسيق HTTP. سيقوم بإرسال جزء المسار/المعلومات من URL إلى الخادم
  3. سيرد عليه الخادم بنفس الطريقة وعبر نفس القناة
  4. سيتخذ أحد الطرفين قرار إغلاق القناة. ويعتمد ذلك على بروتوكول HTTP المستخدم. مع بروتوكول HTTP 1.0، يقوم الخادم بإغلاق الاتصال بعد كل رد من ردوده. وهذا يجبر العميل الذي يحتاج إلى إرسال عدة طلبات للحصول على المستندات المختلفة المكونة لصفحة ويب على فتح اتصال جديد مع كل طلب، وهو ما ينطوي على تكلفة. مع بروتوكول HTTP/1.1، يمكن للعميل أن يطلب من الخادم إبقاء الاتصال مفتوحًا حتى يطلب منه إغلاقه. وبالتالي، يمكنه استرداد جميع المستندات الخاصة بصفحة ويب عبر اتصال واحد وإغلاق الاتصال بنفسه بمجرد الحصول على آخر مستند. سيكتشف الخادم هذا الإغلاق ويقوم هو أيضًا بإغلاق الاتصال.

لاكتشاف التبادلات بين العميل وخادم الويب، سنستخدم ملحق [Advanced Rest Client] لمتصفح Chrome الذي قمنا بتثبيته في الفقرة 9.6. سنكون في الحالة التالية:

Image

يمكن أن يكون خادم الويب أي خادم. نسعى هنا إلى استكشاف التفاعلات التي ستحدث بين المتصفح وخادم الويب. سبق أن أنشأنا الصفحة الثابتة التالية: 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]، حدد الرابط المطلوب: /intro/exemple-01.html؛
  • في [5]، تُضاف المعلمات المحتملة إلى URL. لا توجد معلمات هنا؛
  • في [6]، نحدد الأمر HTTP المستخدم في الاستعلام، وهو هنا GET.

وينتج عن ذلك الاستعلام التالي:

يتم إرسال الاستعلام المُعدّ بهذه الطريقة [7] إلى الخادم بواسطة [8]. وتكون الإجابة التي يتم الحصول عليها هي التالية:

وقد ذكرنا سابقًا أن التبادلات بين العميل والخادم تتخذ الشكل التالي:

Image

  • في [1]، نرى الرؤوس HTTP التي أرسلها المتصفح في طلبه. لم يكن لديه مستند لإرساله؛
  • في [2]، نرى الرؤوس HTTP التي أرسلها الخادم في الرد. وفي [3]، نرى المستند الذي أرسله.

في [3]، يمكننا التعرف على الصفحة الثابتة HTML التي وضعناها على خادم الويب.

دعونا ندرس الطلب HTTP الصادر عن المتصفح:

GET /intro/exemple-01.html HTTP/1.1
Host: localhost:9000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Content-Type: text/plain; charset=utf-8
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
  • لم يتم عرض السطر 1 بواسطة التطبيق؛
  • السطر 6: يُعرّف المتصفح نفسه برأس [User-Agent
  • السطر 7: يشير المتصفح إلى أنه يرسل إلى الخادم مستندًا نصيًا (text/plain) بتنسيق UTF-8. في الواقع، لم يرسل المتصفح هنا أي مستند؛
  • السطر 8: يشير المتصفح إلى أنه يقبل أي نوع من المستندات كرد؛
  • السطر 9: يحدد المتصفح تنسيقات المستندات المقبولة؛
  • السطر 10: يحدد المتصفح اللغات التي يفضلها حسب ترتيب الأفضلية.

رد عليه الخادم بإرسال الرؤوس التالية HTTP:

1
2
3
4
5
6
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Last-Modified: Sat, 29 Nov 2014 07:31:43 GMT
Content-Type: text/html
Content-Length: 255
Date: Sat, 29 Nov 2014 08:20:52 GMT
  • السطر 1: لم يتم عرضه بواسطة التطبيق؛
  • السطر 2: يحدد الخادم هويته، وهو في هذه الحالة خادم Apache-Coyote؛
  • السطر 3: تاريخ آخر تعديل للوثيقة المرسلة؛
  • السطر 4: طبيعة المستند المرسل من الخادم. في هذه الحالة مستند HTML؛
  • السطر 5: حجم المستند HTML المرسل بالبايت.
  • السطر 6: تاريخ ووقت الرد؛

2.4.4. الخلاصة

لقد اكتشفنا بنية طلب عميل الويب وبنية الرد الذي يقدمه له خادم الويب من خلال بعض الأمثلة. يتم الحوار باستخدام بروتوكول HTTP، وهو مجموعة من الأوامر بتنسيق نصي يتم تبادلها بين الطرفين. يتبع كل من طلب العميل ورد الخادم نفس البنية التالية:

Image

الأمران الشائعان لطلب مورد هما GET و POST. لا يصاحب الأمر GET أي مستند. أما الأمر POST، فيصاحبه مستند يكون في الغالب سلسلة أحرف تجمع جميع القيم التي تم إدخالها في نموذج. يسمح الأمر HEAD بطلب الرؤوس HTTP فقط ولا يكون مصحوبًا بوثيقة.

استجابةً لطلب العميل، يرسل الخادم ردًا له نفس البنية. يتم إرسال المورد المطلوب في الجزء [Document] ما لم يكن الأمر المرسَل من العميل هو HEAD، وفي هذه الحالة يتم إرسال الرؤوس HTTP فقط.

2.5. أساسيات لغة HTML

يمكن لمتصفح الويب عرض مستندات متنوعة، وأكثرها شيوعًا هو المستند HTML (لغة الترميز HyperText). وهو عبارة عن نص منسق بعلامات على شكل <balise>texte</balise>. وبالتالي، فإن النص <B>important</B> سيعرض النص المهم بخط عريض. وهناك علامات منفردة مثل العلامة <hr/> التي تعرض خطًا أفقيًّا. ولن نستعرض العلامات التي يمكن العثور عليها في نص HTML. توجد العديد من برامج WYSIWYG التي تتيح إنشاء صفحة ويب دون كتابة سطر واحد من كود HTML. تقوم هذه الأدوات تلقائيًا بإنشاء كود HTML لتصميم الصفحة الذي يتم إجراؤه باستخدام الماوس وعناصر التحكم المحددة مسبقًا. وبالتالي، يمكن إدراج (باستخدام الماوس) جدول في الصفحة، ثم الاطلاع على كود HTML الذي أنشأه البرنامج لمعرفة العلامات التي يجب استخدامها لتعريف جدول في صفحة ويب. الأمر ليس أكثر تعقيدًا من ذلك. من ناحية أخرى، فإن معرفة لغة HTML أمر لا غنى عنه، حيث يتعين على تطبيقات الويب الديناميكية أن تولد بنفسها الكود HTML لإرساله إلى عملاء الويب. يتم إنشاء هذا الكود برمجيًا، ومن الضروري بالطبع معرفة ما يجب إنشاؤه حتى يحصل العميل على صفحة الويب التي يرغب فيها.

باختصار، ليس هناك حاجة لمعرفة لغة HTML بالكامل لبدء البرمجة على الويب. ومع ذلك، فإن هذه المعرفة ضرورية ويمكن اكتسابها من خلال استخدام برامج WYSIWYG لإنشاء صفحات الويب مثل DreamWeaver وعشرات البرامج الأخرى. وهناك طريقة أخرى لاكتشاف خفايا لغة HTML، وهي تصفح الويب وعرض الكود المصدري للصفحات التي تتميز بخصائص مثيرة للاهتمام وما زالت غير معروفة بالنسبة لك.

2.5.1. مثال

لنأخذ المثال التالي الذي يعرض بعض العناصر التي يمكن العثور عليها في مستند ويب مثل:

  • جدول؛
  • صورة؛
  • رابط.

يكون المستند HTML بالشكل العام التالي:

<html>
    <head>
        <title>Un titre</title>
        ...
    </head>
    <body attributs>
        ...
    </body>
</html>

يُحاط المستند بأكمله بعلامات <html>...</html>. ويتكون من جزأين:

  1. <head>...</head>: هذا هو الجزء غير القابل للعرض من المستند. وهو يوفر معلومات للمتصفح الذي سيقوم بعرض المستند. وغالبًا ما نجد فيه العلامة <title>...</title> التي تحدد النص الذي سيظهر في شريط عنوان المتصفح. وقد نجد فيه علامات أخرى، لا سيما العلامات التي تحدد الكلمات المفتاحية للمستند، وهي الكلمات المفتاحية التي تستخدمها محركات البحث لاحقًا. كما يمكن العثور في هذا الجزء على نصوص برمجية، مكتوبة في الغالب بلغة جافا سكريبت أو في بي سكريبت، والتي سيتم تنفيذها بواسطة المتصفح.
  1. <body attributs>...</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 attributes>....</table>: لتعريف الجدول (السطران 11 و31)
<thead>...</thead>: لتحديد عناوين الأعمدة (السطران 12 و18)
<tbody>...</tbody>: لتحديد محتوى الجدول (السطر 19، 30)
<tr attributs>...</tr>: لتعريف صف (السطران 20 و24)
<td سمات>...</td>: لتعريف خلية (السطر 21)
أمثلة:
<table border="1">...</table>: تحدد السمة border سماكة حدود الجدول
<td style="width: 150px; text-align: center;">خلية(1,2)</td>: تحدد خلية سيكون محتواها هو «خلية(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 بمثابة رابط إلى http://istia.univ-angers.fr.
خلفية الصفحة
<body style="height:400px;width:400px;background-image:url(images/standard.jpg)"> (السطر 8): يشير إلى أن الصورة التي ستُستخدم كخلفية للصفحة موجودة في ملف URL [images/standard.jpg] على خادم الويب. في سياق مثالنا هذا، سيطلب المتصفح العنوان http://localhost:port/intro/images/standard.jpg للحصول على صورة الخلفية هذه. كما سيتم عرض نص المستند داخل مستطيل يبلغ ارتفاعه 400 بكسل وعرضه 400 بكسل.

يتضح من هذا المثال البسيط أنه لإنشاء المستند بالكامل، يتعين على المتصفح إرسال ثلاث طلبات إلى الخادم:

  1. http://localhost:port/intro/exemple-04.html للحصول على المصدر HTML للوثيقة
  2. http://localhost:port/intro/images/cerisier.jpg للحصول على الصورة cerisier.jpg
  3. 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" />
زر من نوع إعادة الضبط
<input type="reset" value="إعادة الضبط" name="cmdRétablir" />
زر من نوع button
<input type="button" value="مسح" name="cmdEffacer" onclick="effacer()" />

دعونا نستعرض هذه العلامات المختلفة:

2.5.2.1. النموذج

نموذج

<form method="post" action="postFormulaire">
علامة HTML
<form name="..." method="..." action="...">...</form>
السمات
name="frmexemple": اسم النموذج
method="..." : الطريقة التي يستخدمها المتصفح لإرسال القيم التي تم جمعها في النموذج إلى خادم الويب
action="..." : URL التي سيتم إرسال القيم التي تم جمعها في النموذج إليها.
يُحاط النموذج الإلكتروني بعلامتي <form>...</form>. يمكن أن يكون للنموذج اسم (name="xx"). وينطبق ذلك على جميع عناصر التحكم الموجودة في النموذج. الغرض من النموذج هو جمع المعلومات التي يدخلها المستخدم عبر لوحة المفاتيح/الماوس وإرسالها إلى عنوان URL لخادم الويب. أي عنوان؟ هو العنوان المشار إليه في السمة action="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="لا" checked="checked" />لا
 
علامة HTML
<input type="radio" attribut2="valeur2" ..../>نص
يعرض زر اختيار مع نص بجانبه.
السمات
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" attribut2="valeur2" ....>نص
يعرض مربع اختيار مع نص بجانبه.
السمات
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="fonction()" : يسمح بتعريف دالة يتم تنفيذها عندما ينقر المستخدم على الزر. هذه الدالة جزء من البرامج النصية المحددة في المستند الويب المعروض. الصيغة السابقة هي صيغة javascript. إذا كانت البرامج النصية مكتوبة بلغة vbscript، فيجب كتابة onclick="fonction" بدون الأقواس. وتصبح الصيغة مماثلة إذا كان من الضروري تمرير معلمات إلى الدالة: onclick="دالة(val1, val2,...)"
في مثالنا، يؤدي النقر على الزر Effacer إلى استدعاء دالة جافا سكريبت effacer التالية:
<script type="text/javascript">
function effacer() {
alert("لقد نقرت على زر "Effacer"");
}
</script>
تعرض الدالة effacer رسالة:

2.5.2.10. زر من نوع «إرسال»

زر من نوع "إرسال"
<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

لنقم باختبار أولي، حيث يتم تعريف العلامة <form> في كود HTML الخاص بالوثيقة على النحو التالي:


<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 (حرف Shift كبير) [3]:

نظرًا لأننا مهتمون بالتبادل الشبكي بين المتصفح وخادم الويب، فإننا نقوم أعلاه بتنشيط علامة التبويب [Network] ثم نضغط على الزر [Envoyer] في النموذج. وهذا الزر من النوع [submit] داخل علامة [form]. يستجيب المتصفح للنقر بطلب URL [/intro/doNothing] المحدد في السمة [action] لعلامة [form]، باستخدام الطريقة GET المحددة في السمة [method]. وبذلك نحصل على المعلومات التالية:

تُظهر لنا لقطة الشاشة أعلاه العنصر URL الذي طلبه المتصفح بعد النقر على الزر [envoyer]. وهو يطلب بالفعل الرمز URL المتوقع [/intro/doNothing]، لكنه يضيف في الخلف معلومات تمثل القيم التي تم إدخالها في النموذج. للحصول على مزيد من المعلومات، نضغط على الرابط أعلاه:

في الرابط أعلاه [1, 2]، نرى رؤوس القسم HTTP التي أرسلها المتصفح. وقد تم تنسيقها هنا. للاطلاع على النص الخام لهذه الرؤوس، نتابع الرابط [view source] [3, 4]. والنص الكامل هو كما يلي:

GET /intro/doNothing?R1=non&C2=deux&txtSaisie=qqs+mots&txtMdp=unMotDePasse&areaSaisie=ligne1%0D%0Aligne2%0D%0Aligne3%0D%0A&cmbValeurs=2&lst1=1&lst2=1&lst2=3&cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1
Host: localhost:9000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Referer: http://localhost:9000/intro/exemple-05.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4

نجد هنا عناصر سبق أن صادفناها من قبل. وتظهر عناصر أخرى للمرة الأولى:

الاتصال: keep-alive
يطلب العميل من الخادم عدم إغلاق الاتصال بعد إرساله للرد. وهذا سيسمح له باستخدام نفس الاتصال لطلب لاحق. لا يبقى الاتصال مفتوحًا إلى الأبد. سيقوم الخادم بإغلاقه بعد فترة طويلة من عدم الاستخدام.
Referer
الرمز URL الذي كان معروضًا في المتصفح عند إرسال الطلب الجديد.

المعلومات الجديدة موجودة في السطر 1 ضمن المعلومات التي تلي URL. نلاحظ أن الخيارات التي تم تحديدها في النموذج موجودة في URL. تم تمرير القيم التي أدخلها المستخدم في النموذج إلى الأمر GET URL?param1=القيمة1&param2=القيمة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=أساسيات+البرمجة%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]. وكما تم في الفقرة السابقة في الصفحة 63، يمكننا في متصفح Chrome الوصول إلى رؤوس الطلب HTTP المرسلة من المتصفح:

POST /intro/doNothing HTTP/1.1
Host: localhost:9000
Connection: keep-alive
Content-Length: 172
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://localhost:9000
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:9000/intro/exemple-05.html
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4

R1=non&C2=deux&txtSaisie=qqs+mots&txtMdp=unMotDePasse&areaSaisie=ligne1%0D%0Aligne2%0D%0Aligne3%0D%0A&cmbValeurs=2&lst1=1&lst2=1&lst2=3&cmdRenvoyer=Envoyer&secret=uneValeur

تظهر عناصر جديدة في طلب العميل 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&param2=val2&.... ويمكن النظر إلى ذلك على أنه ميزة أو عيب:

  • ميزة إذا أردنا السماح للمستخدم بإضافة هذا الرابط URL المُعدّ في قائمة الروابط المفضلة لديه؛
  • عيب إذا كنا لا نرغب في أن يتمكن المستخدم من الوصول إلى بعض المعلومات الواردة في النموذج، مثل الحقول المخفية على سبيل المثال.

وبالتالي، سنستخدم طريقة POST بشكل حصري تقريبًا في نماذجنا.

2.6. Conclusion

عرض هذا الفصل مفاهيم أساسية مختلفة لتطوير الويب:

  • التبادل بين العميل والخادم عبر بروتوكول HTTP؛
  • تصميم مستند باستخدام لغة HTML؛
  • تصميم نماذج الإدخال.

وقد رأينا من خلال مثال كيف يمكن للعميل إرسال المعلومات إلى خادم الويب. ولم نتطرق إلى كيفية قيام الخادم

  • استرداد هذه المعلومات؛
  • معالجتها؛
  • إرسال استجابة ديناميكية إلى العميل بناءً على نتيجة المعالجة.

هذا هو مجال برمجة الويب، وهو مجال سنتناوله في الفصل التالي مع عرض تقنية Spring MVC.