JavaRush /مدونة جافا /Random-AR /التمهيد الربيع الفتح
Surplus
مستوى
Москва

التمهيد الربيع الفتح

نشرت في المجموعة
يوم جيد عزيزي القارئ! ومن الجميل أن ألتقي بكم، حتى لو كان الاسم أبهى هو السبب الرئيسي للنظر في الموضوع المتواضع حول التعارف الأول مع تطوير Spring Boot. أود أن أشارك تجربتي في إكمال المهمة التمهيدية للتدريب الداخلي على بوابة JavaRush، وتقديم نظرة عامة من جانب طالب جامعي تقني عادي تمامًا يريد اختبار قوة معرفته المتراكمة. حذاء الربيع الفتح - 1لا أنكر بأي حال من الأحوال احتمال وجود وقاحة في الكود المرفق أو طريقة التفكير، وأرحب بالنقد البناء، لأنه بفضل "الصدمات والكدمات" يمكن التطور في الاتجاه المهني. علاوة على ذلك، أنا لا أتظاهر على الإطلاق بأنني "علاج سحري" في حل هذه الظروف وأحذف بشكل متعمد الأجزاء الفردية من البرنامج، مما يترك الأهمية الأساسية للدخول في موضوع معقد نسبيًا دون أدنى عواقب على الجهاز العصبي. هذا صحيح، من التهور إنكار ما هو واضح: لقد كان الأمر صعبًا بالنسبة لي ولم يكن هناك شيء واضح على الإطلاق حتى لحظة معينة. وإذا شعرت بمشاعر مماثلة منذ أول لقاء مع المهمة، فعندئذٍ "مرحبًا!" دعنا نكتب تطبيق ويب في Spring Boot باستخدام تشبيه مبسط لاختبار القبول في التدريب الداخلي باستخدام محرك القالب Thymeleafوالاستعلامات queryإلى خادم MySQL محلي لتصفية مجموعة المعلومات الواردة. اذا هيا بنا نبدأ!

التمهيد الربيع. ما هو نوع الحيوان وكيفية طبخه؟

باختصار وإيجاز، إنها أداة ممتازة من Pivotel لتوفير الوقت الثمين في عملية إنشاء تطبيق، مما يلغي الحاجة إلى الاتصال مباشرة بمكتبات الطرف الثالث، وكتابة لوحة رسم خرائط رائعة وServlets. يكفي استخدام أداة إنشاء Spring Initializr ، المدمجة في IntelliJ IDEA Ultimate Edition (ملف - جديد - مشروع... - Spring Initializr) أو الموجودة على خدمة الويب start.spring.io ، مع تحديد الحزم المراد تضمينها من مجموعة واسعة من عروض.
حذاء الربيع الفتح - 2
باتباع المواصفات الفنية المطروحة، سنستخدم مجموعة السادة، القياسية لإنشاء تطبيق ويب بسيط باستخدام قاعدة بيانات MySQL :
  • WEB هو المكون الرئيسي لتطوير تطبيق ويب، بما في ذلك خادم Apache Tomcat المحلي على العنوان القياسي localhost:8080 وإطار عمل Spring MVC العالمي.

  • DevTools - يُستخدم لإعادة تشغيل التطبيق بسرعة في JVM الساخن عند اكتشاف تغييرات في التعليمات البرمجية أو القوالب المجمعة؛ علاوة على ذلك، فإنه يحرر Thymeleaf من مسح ذاكرة التخزين المؤقت إذا تم تضمين المحرك المحدد في المشروع.

  • JPA هي تقنية مطلوبة للعمل مع قواعد البيانات وتوفر تعيينًا علائقيًا للكائنات لكائنات Java، وتوفر واجهة برمجة التطبيقات ( الإسبات في حالتنا) لإدارة الكيانات وحفظها واسترجاعها.

  • Thymeleaf (Moustache، AngularJS، Vaadin وما بعدها) - محرك قالب لتصور التطبيق؛ بفضل معرفتي النسبية بمبادئ لغة HTML، اخترت Thymeleaf، الذي دفع اللغة إلى حجر الزاوية في العالم.

  • MySQL - يربط برامج تشغيل Java Database Connectivity لتنفيذ استعلامات SQL على قاعدة البيانات.
بعد الاختيار النهائي للمكونات والإنشاء، نحصل على بنية تطبيق ويب عادية مع أدلة جاهزة لمزيد من التعبئة. أجزاء التفاعل مع الجزء المرئي، سواء كانت أنماط رسومية CSS أو صفحات HTML القياسية أو وظائف JavaScript، يجب أن تكون موجودة في "الموارد"، وبالتالي، من المفترض أن يتم وضع مكون الواجهة الخلفية في "Java". يجب علينا أيضًا الانتباه إلى ملف pom.xml الموجود في النطاق الجذر، والذي يخزن بنية المشروع والتبعيات بين المكونات. إذا كنت ترغب في توسيع الوظيفة بشكل أكبر باستخدام حزم إضافية أو إزالة الأشياء غير الضرورية، فيجب عليك إجراء عمليات معالجة بين العلامات <dependencies></dependencies>بطريقة مماثلة.
حذاء الربيع الفتح - 3

الخطوات الأولى لمستقبل عظيم

بعد ذلك، يطرح سؤال مثير للاهتمام ومنطقي تمامًا: "ماذا تفعل الآن؟ كيف سيعمل هذا؟ تم بناء البرنامج على مبادئ Model-View-Controller: فهو ينظم قراءة الكيانات من قاعدة البيانات المتصلة (Model) ويتم عرضها في واجهة المستخدم مع عناصر التحكم (View)؛ يتم التواصل بين المكونات وتنفيذ الإجراءات وفقًا للطلبات المرسلة بفضل وحدة التحكم. إن إنشاء العناصر الأساسية هو بمثابة النقطة المرجعية للتطوير المستمر. لتجنب المنحدر الزلق والحفاظ على احترام رفاقك في مجال العمل، يجب عليك وضع المكونات في الدلائل المناسبة (على سبيل المثال، وضع ملف وحدة التحكم في مجلد وحدات التحكم في فرع "جافا") والاحتفاظ بها بعناية النظام في مكان العمل.

الجوهر جزء صغير في آلية كبيرة

أو بمعنى آخر نموذجنا حسب الشروط المحددة في المشكلة. وبعيدًا عن موضوع المناقشة والعودة إلى المشروع التمهيدي، يمكننا أن نؤكد بثقة أن هناك حدًا أدنى من الاختلافات بين المهام والالتزام بالمفهوم المتوسط ​​في مزيد من المراجعة. لنفترض أن هناك ملاحظات في دفتر ملاحظات، بما في ذلك:
  • رقم التعريف لتحديد الموقع في التدفق العام؛
  • رسالة نصية تحتوي على عدد معين من الأحرف؛
  • تاريخ إضافة المستخدم إلى القائمة العامة؛
  • متغير منطقي لتحديد "تم أو لم يتم" ("اقرأ أو لم أقرأ").
لذلك، دعونا ننشئ فئة Note في دليل يسمى "الكيان" ونضيف الحقول المناسبة:
@Entity
public class Note {

   @Id
   @GeneratedValue
   private int id;
   private String message;
   private Date date;
   private boolean done;

   public Note() {
   }

   public Note(String message) {
       this.message = message;
       this.date = new Date();
       this.done = false;
   }
}
انحراف آخر عن موضوع المناقشة لفهم أكبر لما يحدث من الموقف النظري. يتم تحديد الاتصال بين المكونات في الربيع من خلال التعليقات التوضيحية - مؤشرات خاصة أمام الكائنات، كل منها يلعب دورًا محددًا في الآلية ويبدأ بالرمز "@". يشير التعليق التوضيحي @Entity إلى Spring Boot إلى أن بيانات الفئة اللاحقة تنتمي إلى "الكيان"، ويحدد @Id و @GeneratedValue الحقل المحدد كمعرف مع الإنشاء التلقائي للمكرر عند معالجة مجموعة من المعلومات. لقد حذفت عمدًا إضافة Getter وSetter القياسيين لزيادة ضغط التنسيق المرئي. بعد ذلك، مع الأخذ في الاعتبار استخدام قاعدة بيانات لتخزين السجلات، ننتقل إلى الخطوة التالية في تطوير التطبيق: سنقوم بإنشاء واجهة NoteRepository في دليل "المستودع"، وهو عنصر ربط في سلسلة التبادل، ونرث معظم مستودع مناسب لمزيد من العمل، مع الإشارة إلى الكيان المخزن والمكرر الصحيح للوصول إليه.
public interface NoteRepository extends JpaRepository<Note, Integer> {
}
في الواقع، هذا كل شيء. موجزة وموجزة. الآن سيستخدم Spring Boot المكون الذي تم إنشاؤه لتنظيم التفاعلات مع قاعدة البيانات. هناك أنواع كثيرة نسبيًا من المستودعات القديمة ذات إمكانيات مختلفة للعمل. يقع JpaRepository في أعلى السلم ويتمتع بأكبر قدر من الإمكانات، بما في ذلك CrudRepository وPageAndSortingRepository الموجود أسفله. لن نذهب إلى أبعد من ذلك وننحرف عن الموضوع، لأنه يمكن العثور على بعض التفاصيل الدقيقة على موقع Pivotel الإلكتروني في الوثائق الفنية. الآن، بعد تنفيذ صورة البيانات وتحديد طرق الاتصال على جانب التطبيق، عليك الاهتمام بإنشاء قاعدة بيانات MySQL في البيئة الخارجية المناسبة "MySQL Workbench"، المثبتة مسبقًا على منصة سطح المكتب في تجميع من المطور الرسمي مع حزم إضافية لإنشاء خادم محلي:
حذاء الربيع الفتح - 4
بعد ذلك، باتباع تعليمات البيئة بعد الضغط على أيقونة الخادم المحلي الحالي في النافذة الرئيسية، نقوم بإنشاء مخطط جدولي حسب حقول كياننا (ملاحظة) وتعبئته بالبيانات المناسبة. من الضروري توضيح التفاصيل الدقيقة لهجة MySQL بشكل منفصل، والتي تتطلب الاهتمام بشكل عاجل لتحقيق النتيجة المرجوة بنجاح:
  • لا يوجد نوع منطقي منفصل على هذا النحو. ستقوم أي إجراءات معالجة طلب بتحويل "صحيح" أو "خطأ" إلى قيمة البت "1" أو "0"، على التوالي؛
  • يتم تخزين التاريخ بالكامل في نوع الطابع الزمني. إذا كنت تستخدم التاريخ، وهو أمر مألوف بالنسبة لك، فسيتعين عليك أن تقتصر على الموضع في التقويم فقط.
حذاء الربيع الفتح - 5
بعد الانتهاء من الخطوات التحضيرية بشكل نهائي، نشير إلى “MySQL Workbench” لإرسال البيانات إلى الخادم المحلي من خلال النقر على أيقونة “lightning” الموجودة على شريط الأدوات. الآن، إذا اكتملت إضافة المعلومات بشكل صحيح، فيمكننا العودة بثقة إلى IDE الأصلي الخاص بنا لمواصلة التطوير عن طريق إضافة تكوين قاعدة البيانات الحالية إلى application.properties (الموجود عادةً في دليل "resources"):
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
وأخيرًا ربط كيان Note بـ MySQL باستخدام التعليقات التوضيحية. يشير @Table إلى استخدام جدول بالاسم والمخطط المحددين، ويشير @Column إلى أن المتغيرات تنتمي إلى حقل معين.
@Entity
@Table(name = "test", schema = "test", catalog = "")
public class Note {

   @Id
   @GeneratedValue
   private int id;
   @Column(name = "message")
   private String message;
   @Column(name = "date")
   private Date date;
   @Column(name = "done")
   private boolean done;

   public Note() {
   }

   public Note(String message) {
       this.message = message;
       this.date = new Date();
       this.done = false;
   }
}

عرض أو واجهة المستخدم

للأسف، يمكننا أن نقول بأمان ما يلي: "سيصبح تصور التطبيق حجر العثرة الرئيسي دون أدنى معرفة نظرية أو عملية". لأكون صريحًا، استهلك مكون الواجهة الأمامية قدرًا مذهلاً من إجمالي حجم العمل وأثار أعصابي بثقة على مدى فترة طويلة من الزمن. ولكن بفضل بساطة Thymeleaf المذهلة، كان من الممكن إيجاد حل وسط مناسب بعد سلسلة من الهزائم الساحرة. سيتم إجراء مزيد من المناقشة حول تعقيدات استخدام المحرك المحدد، على الرغم من أن المفهوم العام يلتزم بموقف مماثل. الأسلوب الرئيسي هو القدرة على استخدام أنقى HTML وتجميع العرض النهائي من أجزاء فردية لتجنب التكرار المتعدد للأقسام المتطابقة. لنفترض أن بنية واجهة المستخدم تتكون من صفحة رئيسية تتكون من شريط تنقل به عناصر تحكم (إضافة إدخال جديد، العودة إلى الصفحة الرئيسية) وجدول ديناميكي لعرض الكيانات مرتبة حسب وقت إضافة الملاحظة بشكل تصاعدي (ASC). أو التناقص (DESC) الاتجاه.المعاني. دعونا نأخذ كموضع قياسي عرض جميع السجلات بترتيب تصاعدي. وفقًا للسياسة الهرمية لمحرك القالب المحدد، يجب أن تكون عناصر تصور المكونات موجودة في فرع "القوالب" في دليل "الموارد". وبالتالي، فإن المزيد من التلاعب بالمكونات يأخذ في الاعتبار الشروط المطروحة. لنقم بإنشاء صفحة رئيسية باسم "الفهرس" (أو أي اسم آخر حسب التفضيل الشخصي) في قالب html5. على سبيل المثال:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/head :: head"></head>
<body>
<div class="container">
   <div th:replace="fragments/header :: header"></div>
   <div th:if="${not #lists.isEmpty(notes)}">
       <div th:replace="operations/list :: notebook"></div>
   </div>
   <div th:replace="fragments/footer :: footer"></div>
</div>
</body>
</html>
وهكذا، دعونا نحلل المكونات الرئيسية للتطبيق النهائي. يستخدم Thymeleaf صيغة منفصلة للإشارة إلى استخدام الإجراءات ويبدأ بالكلمة الأساسية "th:"، الرابط إلى المكتبة الذي يتم تضمينه بالضرورة في علامة الافتتاح <html>.
<div th:if="${not #lists.isEmpty(notes)}">
لا تختلف عملية "if" تمامًا عن الطريقة المعتادة للقيام بالأشياء وتتحقق من سمة "الملاحظات" الواردة للتأكد من وجود كائنات لمزيد من العرض. تجدر الإشارة بشكل منفصل إلى تداخل الموضوع مع استخدام وحدة التحكم، مع مراعاة استخدامها لتنظيم تفاعل النموذج والتصور. العديد من اللحظات الغامضة تتشكل في المستقبل، فقط عد إذا أردت.
<head th:replace="operations/list :: notebook"></head>
تشير عملية "الاستبدال" إلى استبدال "كعب الروتين" أو الكتلة النشطة بجزء محدد من الصفحة الحالية أو المنفصلة - وقد لوحظت الحالة الأخيرة بوضوح في المثال. نقوم بنسخ الجزء المسمى "notebook" من "list.html" الخاص بدليل "operations" إلى <div></div> الخاص بملف "index"، مع استبدال المحتوى بالكامل في الوجهة النهائية. يحتوي الإصدار الصادر على المحتوى التالي:
<!DOCTYPE html>
<!--suppress ALL -->
<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:th="http://www.thymeleaf.org">

<div th:fragment="notebook">
   <table class="table table-bordered table-hover horizontal-align">
       <thead>
       <tr>
           <th style="width: 5%">#</th>
           <th style="width: 60%">Message</th>
           <th class="dropdown" style="width: 20%">Date
               <a th:href="@{'/sort/{sortDate}' (sortDate = 'ASC')}"><i class="fa fa-chevron-circle-up"></i></a>
               <a th:href="@{'/sort/{sortDate}' (sortDate = 'DESC')}"><i class="fa fa-chevron-circle-down"></i></a>
           </th>
           <th style="width: 5%">Done</th>
           <th style="width: 5%">Edit</th>
           <th style="width: 5%">Delete</th>
       </tr>
       </thead>
       <tbody>
       <tr th:each="note : ${notes}">
           <td th:text="${note.id}" style="text-align: center">#</td>
           <td th:text="${note.message}">Message</td>
           <td th:text="${#dates.format(note.date, 'EEE, d MMM yyyy HH:mm')}" style="text-align: center">Date</td>
           <td style="text-align: center">
               <i th:if="${note.done} == true" class="fa fa-plus-square-o" style="font-size:20px;color:#337ab7"></i>
               <i th:if="${note.done} == false" class="fa fa-minus-square-o" style="font-size:20px;color:#337ab7"></i>
           </td>
           <td style="text-align: center"><a th:href="@{'/edit/{id}'(id=${note.id})}"><i class="fa fa-edit" style="font-size:20px"></i></a></td>
           <td style="text-align: center"><a th:href="@{'/delete/{id}'(id=${note.id})}"><i class="fa fa-trash" style="font-size:20px"></i></a></td>
       </tr>
       </tbody>
   </table>
</div>
</html>
دعنا نعود إلى النظرة العامة البناءة ونستعرض وظائف Thymeleaf المستخدمة بالترتيب، مع حذف بناء جملة HTML القياسي أو أنماط الرسوم المستخدمة، والتركيز بشكل خاص على فهم آلية محرك القالب.
<div th:fragment="notebook">
تحدد عملية "الجزء" اسم الجزء وتجعل من الممكن استخدام محتويات الكتلة لأمر "الاستبدال". علاوة على ذلك! لا يتم استبعاد الاستخدامات المتعددة داخل صفحة واحدة بأي حال من الأحوال، مما يؤدي مرة أخرى إلى التشابه مع الإجراءات أو الوظائف في لغات البرمجة.
<a th:href="@{'/sort/{sortDate}' (sortDate = 'ASC')}">
يتم استخدام استدعاء التعليق التوضيحيPostMapping في وحدة التحكم مع التعيين "/sort/{sortDate}"، حيث يكون {sortDate} هو سمة اتجاه الفرز الصادر. يمكن رؤية شيء مشابه في الكتلة التالية، والتي تضيف تغييرًا ديناميكيًا اعتمادًا على موضع العنصر المحدد من قبل المستخدم في حلقة التكرار:
<a th:href="@{'/edit/{id}'(id=${note.id})}">
<tr th:each="note : ${notes}">
تعداد القيم يشبه إلى حد كبير الاستخدام المألوف للكتلة for في بناء جملة Java: يأخذ المتغير "note" العنصر الحالي من مصفوفة سمة الإدخال ${notes} - مصفوفة من الكيانات - ويستخدم لتغيير القيم لاحقا. لنكون صريحين، يمكننا تخصيص مقال منفصل لسرد مجموعة واسعة من إمكانيات Thymeleaf مع أمثلة للتطبيق العملي - محرك القالب بسيط للغاية ولا يتطلب تعلم كمية كبيرة من بناء الجملة الإضافي على الإطلاق. تم توضيح الوظائف الموضحة أعلاه في الوثائق الفنية الموجودة على الموقع الرسمي للمطورين وهي ذات أهمية أساسية في تنظيم الاتصال مع الواجهة الخلفية. لذلك، يمكنك الانتقال بثقة إلى الجزء التالي والأخير. طبعاً من خلال إرفاق باقي مكونات التصور في رابط للتطبيق النهائي في نهاية المقال.

مراقب، مسؤول في شركة صغيرة

"حجر الزاوية في بنية تطبيق الويب" - ربما لا توجد طريقة للعثور على وصف أكثر دقة لأهمية عنصر التحكم في تنظيم عمل البرنامج: يتم تنفيذ معظم العمليات بدقة عن طريق عنصر الربط بين عنصر التحكم نموذج ووجهة نظر. بفضل آليات العمل في Spring Boot، يمكنك بثقة استخدام أساليب التعيين وطلب GET/POST دون أدنى مشكلة، وتوصيل مستودع البيانات تلقائيًا. لنقم بإنشاء فئة NoteController في ملف منفصل في دليل "وحدات التحكم"، مع الإشارة مرة أخرى إلى استخدام التعليق التوضيحي المناسب:
@Controller
public class NoteController {

   private NoteService service;

   @Autowired
   public void setNoteService(NoteService service) {
       this.service = service;
   }

   @GetMapping("/")
   public String list(Model model) {
       return "index";
   }
}
قد تلاحظ العين المتأنية تغييرًا مهمًا في تصميم بنية التطبيق المرتبطة بإضافة خدمة لعزل منطق الأعمال عن العمل مع خدمة إدارة قاعدة البيانات. الإجراءات المكتملة مطلوبة لزيادة تنوع المنتج النهائي وتوفير نطاق واسع لتغيير وظائف واجهة المستخدم دون الحاجة إلى تغييرات في طرق الاتصال بقاعدة البيانات. لا يبرز التمثيل القياسي بأي حال من الأحوال عن حشد التمثيلات المشابهة: تقع الواجهة في دليل منفصل ويتم تنفيذها بواسطة فئة مع التعليق التوضيحي @Service لاكتشاف Spring Boot:
public interface NoteService {
   Note getNoteById(Integer id);
   void saveNote(Note note);
   void updateNote(Integer id, String message, boolean done);
   void deleteNote(Integer id);
   List<Note> findAll();
}

@Service
public class NoteServiceImpl implements NoteService{

   private NoteRepository repository;

   @Autowired
   public void setProductRepository(NoteRepository repository) {
       this.repository = repository;
   }

   @Override
   public Note getNoteById(Integer id) {
       return repository.findOne(id);
   }

   @Override
   public void saveNote(Note note) {
       repository.save(note);
   }

   @Override
   public void updateNote(Integer id, String message, boolean done) {
       Note updated = repository.findOne(id);
       updated.setDone(done);
       updated.setMessage(message);
       repository.save(updated);
   }

   @Override
   public void deleteNote(Integer id) {
       repository.delete(id);
   }

   @Override
   public List<Note> findAll() {
       return repository.findAll();
   }
}
دعنا نعود إلى مراجعة وحدة التحكم وننظر إلى تعقيدات تنظيم العمل باستخدام أساليب Spring Boot. يشير التعليق التوضيحي @Autowired إلى الحاجة إلى ربط الخدمة تلقائيًا بمتغير محدد من النوع المناسب وإنشاء اتصال بقاعدة البيانات. يجب إيلاء المزيد من الاهتمام للطريقة التي يتواصل بها العرض، والمشار إليها بواسطة التعليق التوضيحي @GetMapping("/")، والذي يُرجع صفحة باسم "الفهرس" عند تلقي اتصال بالمضيف المحلي:8080. يمكنك استخدام أسلوب مختلف، وتحديد الوصف الموسع @RequestMapping(value = "/"، الأسلوب = RequestMethod.GET) أو استبدال نوع الإرجاع بـ ModelAndView الجاهز. ومع ذلك، وفقا لحالة الخبرة الحالية في التطبيق العملي، لا ألاحظ أي اختلافات جوهرية في النتيجة النهائية وأستخدم الخيار المعتاد. دعونا نقوم بتوسيع وحدة التحكم عن طريق إضافة عناصر جديدة باستخدام علامة تبويب إضافية. بعد أن ينقر المستخدم على عنصر شريط التنقل، يتم استدعاء @GetMapping("/new") وإعادة توجيهه إلى الصفحة "الجديدة" من دليل "العمليات"، مما يؤدي إلى إرجاع معلمة باسم "رسالة" عند تأكيد البيانات المدخلة باستخدام الزر وإعادة التوجيه إلى الكتلة الرئيسية. إن الحاجة إلى التطابق الكامل لاسم المتغير في نافذة الإدخال مع اسم القيمة المنقولة تتطلب إشارة خاصة.
<input type="text" class="form-control" id="message" th:name="message" placeholder="Enter your note." maxlength="100"/>
@GetMapping("/new")
public String newNote() {
   return "operations/new";
}

@PostMapping("/save")
public String updateNote(@RequestParam String message) {
   service.saveNote(new Note(message));
   return "redirect:/";
}
يتم استخدام أسلوب مماثل لتحديث السجل. بعد النقر على عنصر التحكم، يتم استدعاء تعيين @GetMapping("/edit/{id}") ويتم نقل المعرف من سلسلة URL، وتتم إضافة سمة "note" مع إدخال لمزيد من التحرير. @RequestParam(القيمة = "done"، مطلوب = false) boolean تم) يلعب تحديد قيمة معينة دورًا رئيسيًا في استخدام مربع الاختيار عند استخدام محرك قالب Thymeleaf ويتم ضبطه على "خطأ" افتراضيًا.
@GetMapping("/edit/{id}")
public String edit(@PathVariable Integer id, Model model) {
   Note note = service.getNoteById(id);
   model.addAttribute("note", note);
   return "operations/edit";
}

@PostMapping("/update")
public String saveNote(@RequestParam Integer id, @RequestParam String message,
                      @RequestParam(value = "done", required = false) boolean done) {
   service.updateNote(id, message, done);
   return "redirect:/";
}
تعد إزالة العناصر من قاعدة البيانات أمرًا بسيطًا للغاية ولا تتطلب أي معالجة كبيرة عن طريق استدعاء وظيفة الخدمة المناسبة باستخدام القيمة التي تم تمريرها:
@GetMapping("/delete/{id}")
public String delete(@PathVariable Integer id) {
   service.deleteNote(id);
   return "redirect:/";
}
الآن دعونا نجري تعديلات صغيرة على الأجزاء النهائية وننتقل إلى التواصل المثير مع MySQL باستخدام استعلامات الاستعلام في Spring Data JPA، ونضيف بشكل منفصل وظيفة لإدارة التصفية البسيطة قبل إغلاق وحدة التحكم.
@Controller
public class NoteController {

   private String sortDateMethod = "ASC";

   @GetMapping("/")
   public String list(Model model) {
       List<Note> notebook = filterAndSort();
       model.addAttribute("notes", notebook);
       model.addAttribute("sort", sortDateMethod);
       return "index";
   }

private List<Note> filterAndSort() {
   List<Note> notebook = null;
   switch (sortDateMethod) {
       case "ASC":
           notebook = service.findAllByOrderByDateAsc();
           break;
       case "DESC":
           notebook = service.findAllByOrderByDateDesc();
           break;
   }
   return notebook;
}

استفسار صغير جدًا ولكنه مهم جدًا.

من المحرج الاعتراف بأن تصفية القيم، على عكس التوقعات، تحولت إلى حجر عثرة آخر في تنفيذ المهمة الفنية، والتغلب بثقة على عتبة التعقيد التي حددها ترقيم الصفحات - تقسيم مجموعة البيانات إلى صفحات منفصلة بحجم معين لمزيد من العرض. على الأرجح، كان التعب المتراكم يؤثر سلبًا، ولكن... جاء الإلهام بعد مواجهة عرضية تمامًا مع استعلامات الاستعلام.
public interface NoteRepository extends JpaRepository<Note, Integer> {
   List<Note> findAllByOrderByDateAsc();
   List<Note> findAllByOrderByDateDesc();
}
يوفر Spring Data JPA القدرة على إنشاء استعلامات قاعدة بيانات عالية الدقة مما يلغي الحاجة إلى فرز المعلومات بمجرد استلامها ولها نطاق واسع من إمكانات التطبيق. على سبيل المثال:
List<Note> findAllByOrderByDateAsc();
سيتم تحويل الطريقة إلى استعلام SQL وعرض جميع السجلات (findAll) مرتبة (حسب الطلب) حسب التاريخ (حسب التاريخ) بترتيب تصاعدي (تصاعدي). علاوة على ذلك، يمكنك إنشاء مجموعات معقدة وعينات عبر العديد من المجالات بمتطلب واحد. لنفترض، حدد جميع السجلات (findAll) المكتملة (byDoneTrue) بالترتيب (byOrder) المتناقص (Decs) حسب قيمة التاريخ (byDate):
Page<Note> findAllByDoneTrueOrderByDateDesc(Pageable pageable);

استنتاج أو اعتراف آخر لمبرمج مبتدئ

الجميع! يمكنك تشغيل تطبيق الويب بأمان باستخدام مجموعة Shift+F10 أو من خلال النقر على الأيقونة المقابلة. سيقوم Spring Boot ببناء البرنامج على Apache Maven وتثبيت خادم Apache Tomcat المحلي على المضيف المحلي: 8080. الآن تحتاج فقط إلى اتباع الرابط في أي متصفح.
حذاء الربيع الفتح - 6
وبطبيعة الحال، تطوير منهجية لتلبية متطلبات العمل الأخرى. إمكانات التطبيق محدودة بجهد المطور وسعة الحيلة وخياله.
حذاء الربيع الفتح - 7
لكي أكون صريحًا وأهتم بالمسار الذي سلكته، فأنا مقتنع مرارًا وتكرارًا بصحة الاتجاه المختار وأدرك فوائد الدراسة على بوابة JavaRush التعليمية. بفضل مجموعة متنوعة من المهام العملية، كان من الممكن إرجاع الاهتمام المغري بتعلم البرمجة، والذي تم قمعه بالكامل في البرنامج القديم والممل بشكل مدهش لمؤسسة التعليم العالي في اتجاه مماثل. أربعة أشهر من الدراسة النشطة للمواد في مجموعة التكنولوجيا الخلفية استثمرت معرفة أكبر بكثير مقارنة بسنوات كاملة من حضور المحاضرات والفصول المعملية. صدق او لا تصدق. أتمنى ألا تستسلم لصعوبات إدخال المواد المعقدة، لأنه من خلال التغلب على العقبات نصبح أفضل ونتطور على المستوى المهني والشخصي. آمل أن تكون هذه القصة الصغيرة قد ساعدتني في اكتشاف بعض الأفكار الجديدة لاستخدام الأداة المذهلة التي تسمى SpringBoot. ملاحظة جيثب .
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION