JavaRush /مدونة جافا /Random-AR /إنشاء تطبيق ويب بسيط باستخدام servlets وjsp (الجزء الأول)...
Стас Пасинков
مستوى
Киев

إنشاء تطبيق ويب بسيط باستخدام servlets وjsp (الجزء الأول)

نشرت في المجموعة
مستوى المعرفة المطلوب لفهم المقالة: لقد فهمت Java Core بشكل أو بآخر وترغب في الاطلاع على تقنيات JavaEE وبرمجة الويب. يكون الأمر أكثر منطقية إذا كنت تدرس حاليًا مهمة Java Collections، والتي تغطي موضوعات قريبة من المقالة. إنشاء تطبيق ويب بسيط باستخدام servlets وjsp (الجزء 1) - 1هذه المادة هي استمرار منطقي لمقالتي إنشاء مشروع ويب بسيط في IntelliJ Idea Enterprise . لقد أوضحت فيه كيفية إنشاء قالب مشروع ويب فعال. سأوضح لك هذه المرة كيفية إنشاء تطبيق ويب بسيط ولكنه جميل باستخدام تقنيات Java Servlet API وJavaServer Pages API. سيكون لتطبيقنا صفحة رئيسية تحتوي على رابطين:
  • إلى صفحة إضافة المستخدم؛
  • إلى صفحة عرض قائمة المستخدمين.
سأظل أستخدم IntelliJ Idea Enterprise Edition وApache Maven (فقط قم بتضمين بعض التبعيات) وApache Tomcat. في النهاية، سنقوم "بتزيين" تطبيقنا باستخدام إطار عمل W3.CSS . سنفترض أنه في الوقت الحالي لديك بالفعل مشروع فارغ سنقوم بتطويره هنا. إذا لم يكن الأمر كذلك، فانتقل إلى المقالة الأولى وقم بذلك. وسوف يستغرق سوى بضع دقائق :)

قليلا عن هيكل التطبيق في المستقبل

ستكون صفحتنا الرئيسية ( / ) هي صفحة html الثابتة الأكثر شيوعًا والتي تحتوي على رأس ورابطين/زرين:
  • إضافة مستخدم جديد (سيتم إرساله إلى /add );
  • عرض قائمة المستخدمين (يرسل إلى /list ).
سيقوم Tomcat بالتقاط الطلبات إلى هذه العناوين وإرسالها إلى أحد الخدمتين اللتين سنقوم بإنشائهما (سنقوم بوصف التعيين في ملف web.xml ). وستقوم servlets بدورها بمعالجة الطلبات وإعداد البيانات (أو حفظها في حالة إضافة مستخدم)، ونقل التحكم إلى ملفات jsp المقابلة، والتي "ستعرض" النتيجة بالفعل. سنقوم بتخزين البيانات في القائمة الأكثر شيوعًا (القائمة).

لنقم بإنشاء صفحة رئيسية ثابتة

إذا كان لديك ملف Index.jsp في مجلد الويب الخاص بك ، فاحذفه. بدلًا من ذلك، في هذا المجلد سنقوم بإنشاء ملف html بسيط يسمى Index.html :
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My super project!</title>
</head>
<body>
    <!-- header -->
    <div>
        <h1>Super app!<//h1>
    </div>

    <div>       <!-- content -->
        <div>    <!-- buttons holder -->
            <button onclick="location.href='/list'">List users<//button>
            <button onclick="location.href='/add'">Add user<//button>
        </div>
    </div>
</body>
</html>
لا يوجد شيء معقد هنا. في العنوان نشير إلى عنوان صفحتنا. في نص الصفحة لدينا قسمان رئيسيان: الرأس (الرأس) والمحتوى (المحتوى). في المحتوى لدينا حامل للأزرار الخاصة بنا، وفي الواقع زرين يتم إرسالهما، عند النقر عليهما، إلى العناوين المناسبة. يمكنك تشغيل المشروع ومعرفة شكله الآن. إذا نقرت على الأزرار، فسيتم فتح الصفحات التي بها خطأ 404 لأننا لا نمتلكها بعد. ولكن هذا يشير إلى أن الأزرار تعمل. اسمحوا لي أن أشير إلى أن هذا ليس الخيار الأكثر عالمية، لأنه إذا تم تعطيل JavaScript فجأة، فلن تكون هذه الأزرار ذات فائدة في المتصفح. لكننا سنفترض أن لا أحد قام بتعطيل جافا سكريبت :). من الواضح أنه يمكن استخدام روابط بسيطة، لكني أفضل الأزرار. أنت تفعل ما تريد أفضل. ولا تنظر إلى حقيقة أنه في الأمثلة الخاصة بي سيكون هناك الكثير من divs . ثم سنملأها بالأنماط، وسيبدو كل شيء أجمل :).

قم بإنشاء ملفات jsp لعرض النتيجة

في نفس دليل الويب ، سوف نقوم بإنشاء مجلد حيث سنضع ملفات jsp الخاصة بنا . لقد أسميتها "مشاهدات"، ومرة ​​أخرى، يمكنك الارتجال. في هذا المجلد سنقوم بإنشاء ملفين jsp:
  • add.jsp — صفحة لإضافة المستخدمين؛
  • list.jsp - صفحة لعرض قائمة المستخدمين.
دعونا نعطيهم عناوين الصفحات المناسبة. شيء مثل "إضافة مستخدم جديد" و"قائمة المستخدمين"، وسنترك الأمر على هذا النحو في الوقت الحالي.

لنقم بإنشاء سيرفلتين

ستقبل Servlets وتعالج الطلبات التي سيمررها إليها Tomcat. في المجلد src/main/java سنقوم بإنشاء حزمة تطبيق تحتوي على مصادرنا. هناك سيكون لدينا المزيد من الحزم المختلفة. لذلك، حتى لا يتم إنشاء هذه الحزم داخل بعضها البعض، فلنقم بإنشاء فئة معينة في حزمة التطبيق (ثم قم بحذفها). لنقم الآن بإنشاء ثلاث حزم مختلفة في حزمة التطبيق :
  • الكيانات - هذا هو المكان الذي ستكمن فيه كياناتنا (الفئة نفسها التي ستصف كائنات المستخدم)؛
  • النموذج - سيكون نموذجنا هنا (المزيد حول هذا لاحقًا)؛
  • servlets - حسنًا، هنا ستكون servlets الخاصة بنا.
بعد ذلك، يمكنك إزالة تلك الفئة بأمان من حزمة التطبيق (إذا قمت بإنشائها بالطبع). في حزمة servlets سنقوم بإنشاء فئتين:
  • AddServlet - سيعالج الطلبات المستلمة على /add ؛
  • ListServlet - سيعالج الطلبات المستلمة على /list .

ربط التبعيات في Maven

يقوم Tomcat الإصدار 9.* بتطبيق مواصفات الإصدار 4.0 من Servlet وإصدار JavaServer Pages 2.3. هذا مكتوب في التوثيق الرسمي لـ Tomcat 9 في الفقرة الأولى من السطر الثاني. هذا يعني أنه إذا كنت مثلي تستخدم هذا الإصدار من Tomcat، فإن الكود الذي نكتبه ونرسله للتشغيل سيستخدم الإصدارات المحددة بالضبط. لكننا نرغب في الحصول على هذه المواصفات في مشروعنا، بحيث يتم تجميع الكود الذي يستخدمها بنجاح على الأقل. ولهذا نحتاج إلى تحميلها في مشروعنا. هذا هو المكان الذي يأتي فيه مافن للإنقاذ.

القاعدة العامة هي كما يلي: إذا كنت بحاجة إلى توصيل شيء ما بمشروعك باستخدام Maven:

  • انتقل إلى موقع مستودع Maven؛
  • ابحث هناك عن المكتبة التي تحتاجها والإصدار الذي تحتاجه؛
  • تحصل على رمز التبعية الذي يجب إدراجه في ملف pom.xml الخاص بك؛
  • إدراج! :)
لذلك دعونا نبدأ. أولاً، لنقم بإعداد ملف pom . في مكان ما بعد /version ولكن قبل /project ، أدخل ما يلي:
<dependencies>

</dependencies>
وبالتالي، أوضحنا أنه داخل هذه العلامات سندرج التبعيات التي نحتاجها. انتقل الآن إلى mvnrepository.com ، وسيكون هناك حقل بحث في الأعلى. أولاً، أدخل servlet في البحث. النتيجة الأولى، حيث يوجد أكثر من سبعة آلاف استخدام، تناسبنا. نتذكر أننا بحاجة إلى الإصدار 4.0 (بالنسبة لـ Tomcat 9، بالنسبة للإصدارات الأخرى، قد تكون التطبيقات الأقدم مناسبة). هذه نسخة حديثة إلى حد ما، لذلك ليس هناك العديد من الاستخدامات، ولكنها هي النسخة التي نحتاجها. سيتم فتح صفحة حيث يمكنك الحصول على الكود الخاص بهذه التبعية لمديري الحزم المختلفين ويمكنك حتى تنزيله فقط. ولكن بما أننا نريد توصيله باستخدام Maven، فإننا نختار الرمز الموجود في علامة التبويب Maven. نقوم بالنسخ واللصق في ملف pom الخاص بنا داخل قسم التبعيات. إذا ظهر إشعار في الركن الأيمن السفلي من IDEA يسألك عما إذا كنا نريد تمكين الاستيراد التلقائي، فإننا نوافق على ذلك. إذا رفضت عن طريق الخطأ، فانتقل إلى "الإعدادات" وقم بتمكين الاستيراد التلقائي يدويًا: الإعدادات (Ctrl + Alt + S) -> البناء والتنفيذ والنشر -> Maven -> الاستيراد، سيؤدي ذلك إلى الاحتفاظ بملف pom وملفات تكوين IDEA لهذا الغرض. المشروع متزامن. الآن، باستخدام نفس المبدأ، سنجد ونربط JavaServer Pages الإصدار 2.3 (أدخل jsp في البحث). وبما أننا تناولنا بالفعل Maven، فلنخبره على الفور أن مصادرنا تتوافق مع بناء جملة Java 8، وأنها تحتاج إلى تجميعها في كود ثانوي من نفس الإصدار. بعد كل هذه المعالجات، سيبدو 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>ru.javarush.info.fatfaggy</groupId>
    <artifactId>my-super-project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compile.source>
        <maven.compiler.target>1.8</maven.compile.target>
    </properties>

    <dependencies>
        <!-- Servlet API 4.0 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- JavaServer Pages API 2.3 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

جعل servlets لدينا servlets حقيقية

عند هذه النقطة، فإن اثنين من servlets التي قمنا بإنشائها هما في الواقع مجرد فصول عادية. ليس لديهم أي وظيفة. ولكن الآن قمنا بتوصيل Servlet API بمشروعنا، وإذا كان الأمر كذلك، فيمكننا استخدام الفئات من هناك. لجعل servlets الخاصة بنا "حقيقية"، نحتاج ببساطة إلى وراثتها من فئة HttpServlet .

رسم الخرائط أو التقسيم

سيكون من الجيد الآن إخبار Tomcat بطريقة أو بأخرى بحيث تتم معالجة الطلبات الواردة من /add بواسطة AddServlet servlet الخاص بنا ، وبالتالي تتم معالجة الطلبات الواردة من /list بواسطة ListServlet servlet . وتسمى هذه العملية رسم الخرائط . ويتم ذلك في ملف web.xml وفقًا لهذا المبدأ:
  • أولاً نصف servlet (نعطي بعض الاسم ونشير إلى المسار إلى الفئة نفسها)؛
  • ثم نربط هذا servlet بعنوان محدد (نشير إلى اسم servlet الذي قدمناه له للتو ونشير إلى العنوان الذي يجب إرسال الطلبات منه إلى هذا servlet).
دعونا نصف servlet:
<servlet>
    <servlet-name>add</servlet-name>
    <servlet-class>app.servlets.AddServlet</servlet-class>
</servlet>
الآن نربطه بالعنوان:
<servlet-mapping>
    <servlet-name>add</servlet-name>
    <url-pattern>/add</url-pattern>
</servlet-mapping>
كما ترون، اسم servlet هو نفسه في كلتا الحالتين. بفضل هذا، يعرف Tomcat أنه إذا وصل الطلب إلى عنوان /add ، فيجب تمريره إلى app.servlets.AddServlet servlet . نحن نفعل الشيء نفسه مع servlet الثاني. ونتيجة لذلك، يحتوي ملف web.xml الخاص بنا على المحتوى التالي تقريبًا:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- add servlet -->
    <servlet>
        <servlet-name>add</servlet-name>
        <servlet-class>app.servlets.AddServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>add</servlet-name>
        <url-pattern>/add</url-pattern>
    </servlet-mapping>

    <!-- list servlet -->
    <servlet>
        <servlet-name>list</servlet-name>
        <servlet-class>app.servlets.ListServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>list</servlet-name>
        <url-pattern>/list</url-pattern>
    </servlet-mapping>
</web-app>
بالمناسبة، لم نقم بإنشاء علامة للصفحة الرئيسية هنا (في / ). والحقيقة هي أننا في هذه الحالة لا نحتاج إليها. صفحتنا الرئيسية عبارة عن ملف html بسيط يعرض زرين فقط. لا يوجد محتوى ديناميكي، لذلك ليس من المنطقي بالنسبة لنا إنشاء servlet منفصل له، والذي سيتم إرسال الطلبات من العنوان / إليه ، والذي لن يفعل شيئًا سوى نقل التنفيذ إلى بعض jsp (والذي يجب أيضًا أن يكون تم إنشاؤه)، والذي من شأنه أن يرسم لو كان لدينا زرين فقط. نحن لسنا بحاجة إلى هذا؛ نحن سعداء بمورد ثابت. عندما يتلقى Tomcat طلبًا، سيتحقق من عدم وجود servlet واحد يمكنه معالجة الطلب على مثل هذا العنوان، ثم سيرى أنه يوجد بالفعل ملف html جاهز في هذا العنوان ، وسيرسله بنجاح . يمكننا تشغيل تطبيقنا مرة أخرى (إعادة تشغيل الخادم أو إعادة النشر، كما تريد) والتأكد من عرض الصفحة الرئيسية، ولم يتم كسر أي شيء، وعندما نضغط على الأزرار، تحدث التحولات، ولكن في الوقت الحالي يوجد خطأ أيضًا مكتوب. بالمناسبة، إذا كان لدينا خطأ 404 من قبل، لدينا الآن خطأ 405. وهذا يعني أن التعيين نجح، وتم العثور على servlets، لكن لم يكن لديهم أي طرق مناسبة لمعالجة الطلب. إذا كنت لا تزال تتلقى الخطأ 404 في هذه المرحلة، على الرغم من أن كل شيء قد تم بشكل صحيح، فربما يتعين عليك تصحيح تكوين النشر في الفكرة. للقيام بذلك، تحتاج إلى الانتقال إلى تحرير التكوينات (في الجزء العلوي بالقرب من زر البداية)، والانتقال إلى علامة التبويب "النشر" على الجانب الأيمن من النافذة والتأكد من الإشارة إليه ببساطة في سياق التطبيق /

استطراد غنائي قصير: ماذا يحدث "تحت الغطاء"؟

ربما تساءلت بالفعل عن كيفية عمل تطبيقنا في Tomcat؟ ما الذي يحدث هناك؟ وأين هي الطريقة الرئيسية () ؟ بمجرد كتابة localhost:8080 في متصفحك والانتقال إلى هذا العنوان، يرسل المتصفح طلبًا إلى هذا العنوان عبر بروتوكول http . أتمنى أن تكون على علم بالفعل بأن الطلبات يمكن أن تكون من "أنواع" مختلفة، وأكثرها شيوعًا GET و POST . كل طلب يجب أن يكون له إجابة. يتوقع طلب GET أنه سيتم إعطاؤه رمز HTML جاهزًا ردًا على ذلك ، والذي سيتم إعادته إلى المتصفح، وسيقوم المتصفح باستبدال هذا الرمز بشكل جميل بجميع أنواع الحروف والأزرار والنماذج. يعد طلب POST أكثر إثارة للاهتمام، لأنه يحمل أيضًا بعض المعلومات معه. على سبيل المثال، في نموذج تسجيل المستخدم أو التفويض، قمت بإدخال بياناتك والنقر فوق "إرسال". في هذه اللحظة، تم إرسال طلب POST إلى الخادم مع معلوماتك الشخصية بداخله. قبل الخادم هذه المعلومات وعالجها وأعاد نوعًا من الاستجابة (على سبيل المثال، صفحة html مع ملفك الشخصي). الفرق الأساسي بينهما هو أن طلبات GET تهدف فقط إلى تلقي البيانات من الخادم، بينما تحمل طلبات POST بعض المعلومات معها، وقد تتغير البيانات الموجودة على الخادم (على سبيل المثال، عندما تقوم بتحميل صورتك إلى الخادم، فإنه سوف يطير في طلب POST وسيقوم الخادم بإضافته إلى قاعدة البيانات، أي أنه سيحدث بعض التغيير. الآن دعنا نعود إلى Tomcat. عندما يتلقى بعض الطلبات من العميل، فإنه ينظر إلى العنوان. يبحث في بياناته إلى معرفة ما إذا كان هناك servlet مناسب يمكنه معالجة الطلبات إلى مثل هذا العنوان (أو مورد جاهز يمكن إعادته على الفور). إذا لم يجد أي شيء للعودة، فإنه لا يستجيب بصفحة html، ولكن مع استجابة 404. إذا عثر على servlet مناسب، والذي "يقع" على هذا العنوان، فإنه ينظر في نوع الطلب الذي تلقاه (GET، POST، أو أي شيء آخر)، ثم يسأل servlet عما إذا كان لديه طريقة يمكنه التعامل مع هذا النوع من الطلبات، إذا قال servlet أنه لا يمكنه معالجة هذا النوع، فإن Tomcat يستجيب للعميل بالرمز 405. وهذا ما حدث لنا للتو. ولكن إذا تم العثور على servlet مناسب، وله طريقة مناسبة، يقوم Tomcat بإنشاء كائن من هذا servlet، وتشغيله في مؤشر ترابط جديد ( مؤشر ترابط )، مما يسمح لـ servlet بالعمل في مؤشر ترابط منفصل، ويستمر Tomcat في العمل بشكل أكبر في حد ذاتها، واستقبال وإرسال الطلبات. بالإضافة إلى ذلك، يقوم Tomcat بإنشاء كائنين آخرين: أحدهما من النوع HttpServletRequest (سأسميه باختصار طلبًا في المستقبل)، والثاني من النوع HttpServletResponse(سأسميها الجواب). في الكائن الأول، يقوم بوضع جميع البيانات التي تلقاها في طلب من العميل، بحيث يمكن سحب جميع تلك البيانات من هذا الكائن. حسنًا، بعد كل هذا، يقوم بتمرير هذين الكائنين إلى الطريقة المناسبة لـ servlet الذي يعمل في موضوع منفصل. بمجرد أن ينتهي servlet من عمله ويكون لديه استجابة جاهزة لإرسالها إلى العميل، فإنه يرفع إشارة إلى Tomcat قائلاً: "لقد انتهيت، كل شيء جاهز." يقبل Tomcat الرد ويرسله إلى العميل. يسمح هذا لـ Tomcat بقبول الطلبات وإرسال الاستجابات دون انقطاع، بينما يتم تنفيذ كل العمل بواسطة servlets التي تعمل في سلاسل رسائل منفصلة. وبناء على ذلك، عندما نكتب كود servlet، فإننا نحدد العمل الذي سيتم تنفيذه. ونعم، يمكنك التفكير في الطريقة main() على أنها موجودة في Tomcat نفسها (نعم، إنها مكتوبة بلغة Java)، وعندما "نبدأ" Tomcat، سيظهر ملف main().

نحن نلتقط طرق GET باستخدام servlets ونرسل استجابات بسيطة

في الوقت الحالي، لا تحتوي servlets الخاصة بنا على طرق مناسبة (GET)، لذا يُرجع لنا Tomcat خطأ 405. فلنقم بإنشائها! تحدد فئة HttpServlet ، التي نرث منها servlets، طرقًا مختلفة. من أجل تعيين بعض التعليمات البرمجية للطرق، فإننا ببساطة نتجاوزها. في هذه الحالة، نحن بحاجة إلى تجاوز طريقة doGet() في كل من servlets.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}
كما ترى، تقبل هذه الطريقة كائنين: req (الطلب) و resp (الاستجابة). هذه هي نفس الكائنات التي سيقوم Tomcat بإنشائها وملؤها لنا عندما يستدعي الطريقة المناسبة في هذا الخادم. أولاً، دعونا نقوم بأبسط الإجابات. للقيام بذلك، خذ كائن resp واحصل منه على كائن PrintWriter ، والذي يمكن استخدامه لإنشاء الاستجابات. حسنًا، باستخدامه سنطبع بعض السلاسل البسيطة.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();
    writer.println("Method GET from AddServlet");
}
سنفعل شيئًا مشابهًا في ListServlet servlet ، وبعد ذلك سنبدأ تشغيل خادمنا مرة أخرى. كما ترون، كل شيء يعمل! عند النقر على الأزرار، تفتح الصفحات بالنص الذي "سجلناه" باستخدام PrintWriter . إن الأمر مجرد أن jsp الخاص بنا الذي أعددناه لإنشاء صفحات تحتوي على إجابات لا يتم استخدامه بأي شكل من الأشكال. وذلك لأن الإعدام ببساطة لا يصل إليهم. يقوم الخادم الصغير الآن بإنشاء استجابة وينهي عمله، مما يشير إلى Tomcat بأن لديه استجابة جاهزة للعميل. يأخذ Tomcat هذا الرد ببساطة ويرسله مرة أخرى إلى العميل. نقوم بنقل التحكم من servlets إلى jsp. فلنغير كود أساليبنا بهذه الطريقة:
  • نحصل من كائن الطلب على كائن مدير الطلبات، حيث نمرر عنوان jsp الخاص بالصفحة التي نريد نقل التحكم إليها؛
  • باستخدام الكائن المستلم، نقوم بنقل التحكم إلى صفحة jsp المحددة ، ولا تنس إرفاق كائنات الطلب والاستجابة التي تلقيناها من Tomcat هناك.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
    requestDispatcher.forward(req, resp);
}
في نص صفحات jsp (داخل علامة النص) يمكننا كتابة شيء ما حتى نتمكن من رؤية الصفحة التي يتم عرضها بوضوح. بعد ذلك نقوم بإعادة تشغيل الخادم والتحقق. يتم الضغط على الأزرار الموجودة على الصفحة الرئيسية، ويتم فتح الصفحات، مما يعني إرسال الطلبات إلى servlets، وبعد ذلك يتم نقل التحكم إلى صفحات jsp، والتي تم تقديمها بالفعل. هذا كل شئ. في الجزء التالي من المقالة سنتعامل مع وظائف تطبيقنا.

ماذا تقرأ:

إنشاء مشروع ويب بسيط في IntelliJ Idea Enterprise. خطوة بخطوة، مع الصور


الدردشة الخاصة بي
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION