JavaRush /مدونة جافا /Random-AR /إنشاء تطبيق ويب بسيط باستخدام servlets وjsp (الجزء الثاني...
fatfaggy
مستوى
Киев

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

نشرت في المجموعة
أواصل وصف عملية إنشاء تطبيق ويب باستخدام servlets وjsp وMaven وTomcat. بداية المقال إذا لزم الأمر.
نحن نخلق الكيانات.
لنقم بإنشاء فئة مستخدم في حزمة الكيانات، حيث سنقوم بإنشاء اسمين متغيرين لسلسلة خاصة وكلمة المرور. لنقم بإنشاء مُنشئات (افتراضية والتي تقبل كلتا القيمتين)، والحروف/المحددات، وتجاوز طريقة toString() في حالة حدوث ذلك، بالإضافة إلى طريقتي يساوي () وhashCode (). public class User { private String name; private String password; public User() { } public User(String name, String password) { this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (name != null ? !name.equals(user.name) : user.name != null) return false; return password != null ? password.equals(user.password) : user.password == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (password != null ? password.hashCode() : 0); return result; } } يمكننا الآن البدء في إنشاء قائمة بالمستخدمين، حيث سنضيف مستخدمينا، ومن أين سنأخذهم للعرض. لكن هناك مشكلة. نحن لا نقوم بإنشاء كائنات servlet الخاصة بنا، بل يقوم Tomcat بإنشائها لنا. إن الطرق التي نتجاوزها فيها محددة أيضًا بالنسبة لنا ولا يمكننا إضافة معلمة. كيف إذن يمكننا إنشاء قائمة مشتركة يمكن رؤيتها في كل من servlets الخاصة بنا؟ إذا قمنا ببساطة بإنشاء كائن قائمة خاص بنا في كل servlet، فسوف يتبين أننا سنضيف مستخدمين إلى قائمة واحدة، ولكن عرض قائمة المستخدمين باستخدام ListServlet servlet سيكون مختلفًا تمامًا. اتضح أننا بحاجة إلى كائن مشترك بين كل من servlets. بشكل عام، نحن بحاجة إلى كائن يكون مشتركًا بين جميع الفئات في برنامجنا؛ الكائن الوحيد للبرنامج بأكمله. أتمنى أن تكون قد سمعت شيئًا عن أنماط التصميم. وربما بالنسبة للبعض، هذه هي الحاجة الحقيقية الأولى لاستخدام قالب Singleton في برنامجهم. يمكنك الإبداع وإنشاء بعض المفردات الرائعة، مع عمليات التحقق المزدوجة والمزامنة (نعم، لدينا تطبيق متعدد الخيوط، نظرًا لأن Tomcat يقوم بتشغيل servlets في سلاسل رسائل مختلفة)، لكنني سأستخدم الخيار مع التهيئة المبكرة، لأنه في هذه الحالة مناسبة تماما.
إنشاء نموذج.
بعد ذلك، سنقوم بإنشاء فئة (ونقوم بتنفيذ القالب الفردي فيها) في حزمة النموذج، وسنسميها أيضًا بشكل ملون تمامًا Model. لنقم بإنشاء كائن قائمة مستخدمين خاص فيه، ونقوم بطريقتين: واحدة بحيث يمكنك إضافة مستخدم، والثانية - دعها ببساطة تعيد قائمة السلاسل (أسماء المستخدمين). نظرًا لأن كائن المستخدم الخاص بنا يتكون من اسم وكلمة مرور، فإننا لا نرغب في "الكشف" عن كلمات مرور المستخدم، لذلك سنعيد فقط قائمة بأسمائهم. public class Model { private static Model instance = new Model(); private List model; public static Model getInstance() { return instance; } private Model() { model = new ArrayList<>(); } public void add(User user) { model.add(user); } public List list() { return model.stream() .map(User::getName) .collect(Collectors.toList()); } }
قليلا عن MVC.
نظرًا لأنك سمعت عن Singleton، فهذا يعني أنك سمعت على الأرجح عن نمط تصميم آخر - MVC (وحدة تحكم عرض النموذج، أو وحدة تحكم عرض النموذج الروسية، أو تمامًا كما هو الحال في وحدة تحكم عرض النموذج باللغة الإنجليزية). جوهرها هو فصل منطق العمل عن العرض. أي افصل الكود الذي يحدد ما يجب فعله عن الكود الذي يحدد كيفية العرض . يعتبر العرض (العرض أو المشاهدات فقط) هو المسؤول عن الشكل الذي يتم به تقديم بعض البيانات. في حالتنا، المشاهدات هي صفحات JSP الخاصة بنا. لهذا السبب وضعتهم في مجلد يسمى طرق العرض. النموذج هو البيانات الفعلية التي يعمل بها البرنامج. في حالتنا، هؤلاء هم المستخدمون (قائمة المستخدمين). حسنًا، وحدات التحكم هي الرابط بينهما. يأخذون البيانات من النموذج وينقلونها إلى طرق العرض، أو يتلقون بعض البيانات من Tomcat ويعالجونها وينقلونها إلى النموذج. يجب وصف منطق الأعمال (أي ما يجب فعله ) فيها، وليس في النموذج أو في طريقة العرض. وهكذا، كل شخص يفعل ما يريده:
  • نموذج يخزن البيانات
  • وجهات النظر رسم تمثيل جميل للبيانات
  • وحدات التحكم معالجة البيانات
وهذا يتيح لهم جميعًا أن يكونوا بسيطين إلى حد ما وقابلين للصيانة. وليس تفريغًا وحشيًا لجميع الأكواد في فئة واحدة. لا يعد MVC مناسبًا لبرمجة الويب فحسب، ولكنه لا يزال شائعًا جدًا (إن لم يكن دائمًا) في هذا المجال. في حالتنا، ستعمل servlets كوحدات تحكم. نعم، هذا وصف سطحي جدًا وحتى تقريبي لهذا النمط، لكن هذه المقالة لا تتعلق بأنماط التصميم، بل عن كيفية إنشاء تطبيق ويب بسيط :) من يريد معرفة المزيد - جوجل يعرف كل شيء ! :) دعونا نعود إلى وجهات نظرنا.
إنشاء نموذج لإضافة مستخدم.
لنقم بإضافة نموذج إلى ملف add.jsp، يتكون من مدخلين للنص (أحدهما عادي والآخر نوع كلمة المرور) وزر لإرسال البيانات إلى الخادم. يحتوي النموذج هنا على سمة أسلوب مع منشور القيمة. وهذا يعني أنه سيتم إرسال البيانات من هذا النموذج إلى الخادم في شكل طلب POST. لم يتم تحديد سمة الإجراء، مما يعني أن هذا الطلب سيذهب إلى نفس العنوان الذي ذهبنا إليه في هذه الصفحة (/add). وبالتالي، فإن servlet الخاص بنا، المرتبط بهذا العنوان، عند تلقي طلب GET، يقوم بإرجاع jsp هذا مع نموذج إضافة المستخدمين، وإذا تلقى طلب POST، فإن هذا النموذج قد أرسل بياناته هناك (والتي سنسترجعها من كائن الطلب في طريقة doPost() ومعالجته ونقله إلى النموذج لحفظه). تجدر الإشارة إلى أن المدخلات لها معلمة اسم هنا (بالنسبة للحقل الذي يحمل اسمًا، فإنه يحتوي على اسم القيمة، وبالنسبة للحقل الذي يحتوي على كلمة مرور، فإنه يحتوي على تمرير القيمة). هذه نقطة مهمة جدًا. نظرًا لأنه من أجل الحصول على هذه البيانات (الاسم وكلمة المرور التي سيتم إدخالها) من الطلب (الموجود بالفعل داخل servlet)، فسوف نستخدم هذا الاسم والمرور بالضبط. ولكن أكثر عن ذلك لاحقا. يتم إنشاء زر إرسال البيانات نفسه مرة أخرى على شكل زر، وليس إدخالًا، كما هو معتاد عادةً. لا أعرف مدى عالمية هذا الخيار، لكنه يناسبني في Chrome :)
معالجة طلب POST باستخدام servlet.
دعنا نعود إلى AddServlet servlet. نحن نعلم بالفعل أنه لكي يتمكن servlet الخاص بنا من "التقاط" طلبات GET، فإننا نتجاوز طريقة doGet() من فئة HttpServlet. لتعليم servlet الخاص بنا التقاط طلبات POST أيضًا، فإننا أيضًا نتجاوز طريقة doPost(). يتلقى كائنات طلب واستجابة مماثلة من Tomcat، وسنعمل معها. أولاً، دعنا نستخرج من الطلب الاسم ونمرر المعلمات التي أرسلها النموذج (إذا قمت بتسميتها بشكل مختلف في النموذج، فهذه هي الأسماء التي تكتبها). ثم سنقوم بإنشاء كائن المستخدم الخاص بنا باستخدام البيانات المستلمة. بعد ذلك سوف نحصل على كائن النموذج ونضيف المستخدم الذي تم إنشاؤه إلى النموذج. @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); String password = req.getParameter("pass"); User user = new User(name, password); Model model = Model.getInstance(); model.add(user); }
نقل البيانات إلى العرض.
الآن دعنا ننتقل إلى ListServlet servlet. لقد قمنا بالفعل بتنفيذ طريقة doGet()، والتي تنقل التحكم ببساطة إلى عرض list.jsp. إذا لم يكن لديك هذا بعد، قم بذلك عن طريق القياس بنفس الطريقة من AddServlet servlet. الآن سيكون من الجيد الحصول على قائمة بأسماء المستخدمين من النموذج وتمريرها إلى العرض، الذي سيستقبلها هناك ويعرضها بشكل جيد. للقيام بذلك، سوف نستخدم مرة أخرى كائن الطلب الذي تلقيناه من Tomcat. يمكننا إضافة سمة إلى هذا الكائن، وإعطائه اسمًا، وفي الواقع، الكائن نفسه الذي نرغب في نقله إلى العرض. نظرًا لحقيقة أنه عند نقل عملية التنفيذ من servlet إلى طريقة عرض، فإننا نمرر هناك نفس كائنات الطلب والاستجابة التي تلقاها servlet نفسه، ثم عن طريق إضافة قائمة الأسماء الخاصة بنا إلى كائن الطلب، يمكننا بعد ذلك من هذا الطلب الكائن في العرض، قم بإنشاء قائمة بأسماء المستخدمين واحصل على. لقد انتهينا من فئة ListServlet، لذا إليك رمز الفصل بأكمله. package app.servlets; import app.model.Model; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; public class ListServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Model model = Model.getInstance(); List names = model.list(); req.setAttribute("userNames", names); RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp"); requestDispatcher.forward(req, resp); } }
تنفيذ كود جافا في ملفات jsp.
الآن دعنا ننتقل إلى ملف list.jsp. لن يتم تنفيذ هذا الملف إلا عندما يقوم ListServlet بتمرير عملية التنفيذ هنا. بالإضافة إلى ذلك، في هذا servlet قمنا بالفعل بإعداد قائمة بأسماء المستخدمين من النموذج وقمنا بتمريرها هنا في كائن الطلب. بالنظر إلى قائمة الأسماء، يمكننا تشغيل حلقة for خلالها وطباعة كل اسم. كما قلت من قبل، يمكن لملفات jsp تنفيذ تعليمات برمجية Java (من حيث المبدأ، هذا ما يجعلها مختلفة عن صفحات HTML الثابتة). من أجل تنفيذ بعض التعليمات البرمجية، يكفي وضع البناء في المكان الذي نحتاجه، <% // java code %> داخل مثل هذا البناء، يمكننا الوصول إلى عدة متغيرات: الطلب - كائن الطلب الخاص بنا، والذي مررناه من servlet، حيث تم استدعاؤه ببساطة استجابة req - كائن الاستجابة، في servlet كان يسمى resp out - كائن من نوع JspWriter (موروث من الكاتب المعتاد)، والذي يمكننا من خلاله "كتابة" شيء ما مباشرة في صفحة html نفسها. Out.println("Hello World!") يشبه إلى حد كبير System.out.println("Hello World!")، لكن لا تخلط بينهما! out.println() "يكتب" إلى صفحة html، وSystem.out.println - إلى مخرجات النظام. إذا قمت باستدعاء طريقة System.out.println() داخل القسم الذي يحتوي على كود jsp، فسترى النتائج في وحدة تحكم Tomcat، وليس على الصفحة، كما قد تريد :) يمكنك البحث عن كائنات أخرى متاحة داخل jsp هنا . باستخدام كائن الطلب يمكننا الحصول على قائمة الأسماء التي تم تمريرها من servlet (قمنا بإرفاق السمة المقابلة لهذا الكائن)، وباستخدام الكائن out يمكننا عرض هذه الأسماء. لنفعل ذلك الآن ببساطة في شكل قائمة html: إذا أردنا عرض القائمة فقط عند وجود مستخدمين، وبخلاف ذلك عرض تحذير بعدم وجود مستخدمين حتى الآن، يمكننا إعادة كتابة هذا القسم قليلاً: الآن بعد أن قمنا بذلك معرفة كيفية نقل البيانات من servlets إلى طرق العرض - يمكننا تحسين AddServlet الخاص بنا قليلاً بحيث يتم عرض إشعار حول الإضافة الناجحة للمستخدم. للقيام بذلك، في طريقة doPost()، بعد إضافة مستخدم جديد إلى النموذج، يمكننا إضافة اسم هذا المستخدم إلى سمات كائن req وتمرير التحكم مرة أخرى إلى عرض add.jsp. وقم بالفعل بإنشاء قسم به رمز Java، حيث يمكنك التحقق مما إذا كانت هذه السمة موجودة في الطلب، وإذا كان الأمر كذلك، فاعرض رسالة تفيد بأنه تمت إضافة المستخدم بنجاح. بعد هذه التغييرات، سيبدو الكود الكامل لـ AddServlet servlet كما يلي: هنا، في نهاية طريقة doPost()، نقوم بتعيين سمة مع إضافة اسم المستخدم إلى النموذج، ثم نستدعي doGet( ) الطريقة التي نمرر إليها الطلب والاستجابة الحاليين. وتقوم طريقة doGet() بالفعل بنقل التحكم إلى العرض، حيث ترسل كائن طلب مع إرفاق اسم المستخدم المضاف كسمة. يبقى تصحيح add.jsp نفسه بحيث يعرض مثل هذا الإشعار في حالة وجود هذه السمة. الإضافة النهائية.jsp
    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { for (String s : names) { out.println("
  • " + s + "
  • "); } } %>
<% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    package app.servlets; import app.entities.User; import app.model.Model; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class AddServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp"); requestDispatcher.forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); String password = req.getParameter("pass"); User user = new User(name, password); Model model = Model.getInstance(); model.add(user); req.setAttribute("userName", name); doGet(req, resp); } } <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("

    User '" + request.getAttribute("userName") + "' added!

    "); } %>

    Add user

    يتكون نص الصفحة من div برأس، وبعد ذلك توجد حاوية div للمحتوى، حيث تتحقق من وجود سمة باسم المستخدم، ثم div بنموذج لإضافة المستخدمين، وفي النهاية تذييل مع زر للعودة إلى الصفحة الرئيسية. قد يبدو أن هناك عددًا كبيرًا جدًا من divs، لكننا سنستخدمها لاحقًا عندما نضيف الأنماط :) حسنًا، الإصدار النهائي هو list.jsp. وبالتالي ، لدينا تطبيق ويب يعمل بكامل طاقته ويمكنه تخزين المستخدمين وإضافتهم أيضًا كما عرض قائمة بأسمائهم. كل ما تبقى هو تزيينها..:) <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    إضافة الأنماط. نحن نستخدم إطار عمل W3.CSS.
    في الوقت الحالي، يعمل تطبيقنا، ولكنه مجنون تمامًا :) نحتاج إلى إضافة خلفية وألوان للنص والأزرار، وتصميم القوائم، وإجراء المحاذاة، وإضافة مسافات بادئة، وبشكل عام، الكثير من الأشياء. إذا قمت بكتابة الأنماط يدويًا، فقد يستغرق الأمر الكثير من الوقت والأعصاب. لذلك أقترح استخدام إطار عمل CSS W3.CSS . لديها بالفعل فئات جاهزة مع الأنماط، كل ما تبقى هو وضع فئات CSS التي نريد تطبيقها في هذه الأماكن في الأماكن الصحيحة. لإضافتها إلى صفحاتنا، نحتاج أولاً إلى تضمين ملف يحتوي على الأنماط. يمكن القيام بذلك بطريقتين: 1. تصفح صفحاتنا وأدخل رابطًا مباشرًا للملف الذي يحتوي على الأنماط في القسم الرئيسي، وهذا الخيار مناسب إذا كان لديك اتصال دائم بالإنترنت. وبعد ذلك، عندما تفتح صفحاتك على خادم محلي، سيتم سحب الأنماط من الإنترنت. 2. إذا كنت تريد الحصول على جميع الأنماط محليًا وعدم الاعتماد على اتصال بالإنترنت، فيمكنك ببساطة تنزيل الملف بالأنماط ووضعه في مكان ما داخل مجلد الويب (على سبيل المثال web/styles/w3.css)، ثم انتقل إلى جميع صفحاتنا (index.html وadd.jsp وlist.jsp) وأدخل رابطًا لهذا الملف مع الأنماط داخل قسم الرأس. بعد ذلك، ما عليك سوى تصفح العلامات ووضع علامة عليها بالأنماط التي تريدها . لن أتناول هذا بالتفصيل، لكنني سأقدم على الفور نسختي الجاهزة من ملفاتي الثلاثة مع فئات أنماط مرتبة. Index.html add.jsp list.jsp هذا كل شيء :) إذا كان لا يزال لديك أي أسئلة أو لديك أي تعليقات، أو على العكس من ذلك، لا يعمل شيء ما - اترك تعليقًا. حسنًا، سأرفق بضع لقطات شاشة لما خرج من كل ذلك. وأخيرا. إذا كنت ترغب في التدرب على هذا المشروع، يمكنك تجربة: Super app!

    Super app!

    <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("
    \n" + " ×\n" + "
    User '" + request.getAttribute("userName") + "' added!
    \n" + "
    "); } %>

    Add user

    <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users list

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println("
      "); for (String s : names) { out.println("
    • " + s + "
    • "); } out.println("
    "); } else out.println("
    \n" + " ×\n" + "
    There are no users yet!
    \n" + "
    "); %>
    الصفحة الرئيسية للتطبيق إضافة نافذة المستخدم قائمة المستخدمين
    • أنشئ servlet وjsp لحذف مستخدم واثنين آخرين لتغيير/تحرير مستخدم موجود. سوف تحصل على تطبيق ويب CrUD حقيقي :) على servlets))
    • قائمة الاستبدال (قائمة ) للعمل مع قاعدة البيانات حتى لا يختفي المستخدمون المضافون بعد إعادة تشغيل الخادم :)
    حظ سعيد!
    تعليقات
    TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
    GO TO FULL VERSION