CodeGym /مدونة جافا /Random-AR /إنشاء تطبيق ويب بسيط باستخدام servlets وJSPs (الجزء الأول...
John Squirrels
مستوى
San Francisco

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

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

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

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

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

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

قم بإنشاء خدمتين

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

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

يقوم Tomcat 9 .* بتنفيذ مواصفات Servlet 4.0 و 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>cc.codegym.info.fatfaggy</groupId>
    <artifactId>my-super-project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compile.source>1.8</maven.compile.source>
        <maven.compile.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 حقيقية

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

رسم الخرائط أو العلامات

الآن سيكون من الجيد إخبار Tomcat بطريقة أو بأخرى أن طلبات عنوان / add تتم معالجتها بواسطة AddServlet الخاص بنا، ويتم معالجة طلبات عنوان / list بواسطة ListServlet . تسمى هذه العملية رسم الخرائط (الترميز). ويتم ذلك في 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 الثاني. في النهاية، يحتوي ملف 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، لكن لم يكن لديهم طريقة مناسبة للتعامل مع الطلب.

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

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

استخدم servlets للتعرف على طرق GET وإرسال استجابات بسيطة للغاية

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

}
كما ترون، تأخذ هذه الطريقة وسيطتين: req (طلب) وresp (استجابة). هذه هي نفس الكائنات التي ينشئها Tomcat ويملأها لنا عندما يستدعي الطريقة المناسبة في servlet. للبدء، سنقوم بإنشاء أبسط الردود. للقيام بذلك، سنأخذ كائن resp ونحصل منه على كائن PrintWriter. يتم استخدام هذا النوع من الكائنات لإنشاء استجابة. سوف نستخدمها لإخراج سلسلة بسيطة.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();
    writer.println("GET method from AddServlet");
}
سنفعل شيئًا مشابهًا في ListServlet، ثم سنقوم بإعادة تشغيل الخادم الخاص بنا. كما ترون، كل شيء يعمل! عند النقر فوق الأزرار، تحصل على صفحات تحتوي على النص الذي "كتبناه" باستخدام PrintWriter. لكن ملفات JSP التي أعددناها لإنشاء الصفحات ذات الاستجابات لا يتم استخدامها. هذا ببساطة لأنهم لم يتم إعدامهم أبدًا. يقوم servlet الخاص بنا بإنشاء الاستجابة نفسها وينتهي من التشغيل، مما يشير إلى 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، والتي يتم عرضها الآن. هذا كل شئ حتى الان. في الجزء التالي من هذه المقالة، سنعمل على وظيفة تطبيقنا.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION