تطوير تطبيقات الويب السريعة على Vaadin و Spring Boot

KPDV


الغرض من هذه المقالة هو تنظيم عملية تطوير تطبيق ويب على Vaadin 14 باستخدام Spring Boot.


قبل قراءة هذه المقالة ، أوصي بقراءة المواد التالية:



الانطباعات


تعد Vaadin 14 أداة ملائمة إلى حد ما لتصميم تطبيقات الويب ، قبل أن تلبيها ، طورت واجهات رسومية فقط على JavaFX و Android وحتى J2ME ، وفي الوقت نفسه تجنب تطوير الواجهة الأمامية (تتوفر المعرفة الأساسية بتنسيق HTML و CSS و JS) لأنها لا تعتقد بلدي.


تنصل


أولئك الذين لم يعملوا بعد مع Spring Boot يوصون بتخطي بداية سريعة باستخدام Spring Initializr ، والعودة إلى المواد الموصى بها ، ومحاولة تكوين كل شيء بنفسك ، بعد أن واجهوا العديد من المشاكل المختلفة ، وإلا فستكون هناك فجوات في المستقبل في فهم الأشياء المختلفة.


بداية سريعة


قم بإنشاء مشروع لتطبيق الويب الخاص بنا باستخدام Spring Initializr ، التبعيات اللازمة لتطبيق الويب الصغير الخاص بنا:


  • Spring Data JPA (للعمل مع قاعدة البيانات)
  • Vaadin (لتطوير تطبيقات الويب)
  • لومبوك (لتقليل كود لوحة الغلاية)
  • MySQL Driver (أستخدم mariadb ، في الربيع initializr ليس كذلك)

إعداد application.properties وقاعدة البيانات


المشروع الذي تم إنشاؤه في Spring Initializr جاهز تقريبًا للتشغيل ، يمكننا فقط تكوين التطبيق. الخصائص من خلال تحديد مسار قاعدة البيانات واسم المستخدم وكلمة المرور


spring.datasource.url = jdbc:mariadb://127.0.0.1:3306/test spring.datasource.username=user spring.datasource.password=password spring.jpa.hibernate.ddl-auto=update 

الحذر: ddl السيارات

لا تستخدم ddl-auto مع قيمة التحديث في قاعدة بيانات مباشرة أو عند تطوير مشروع ، لأنه يقوم تلقائيًا بتحديث مخطط قاعدة البيانات.
الخيارات الحالية لـ ddl-auto:
create - سيقوم بإنشاء جدول في قاعدة البيانات ، بعد حذف الإصدار القديم من الجدول مسبقًا (فقد البيانات في حالة تغيير المخطط)
التحقق من الصحة - التحقق من الجدول في قاعدة البيانات ، إذا كان لا يتطابق مع الكيان ثم الإسبات سوف يلقي استثناء
تحديث - التحقق من الجدول وتحديثه تلقائيًا دون إزالة الحقول غير الموجودة من الكيان
create-drop - يقوم بفحص الجدول أو إنشائه أو تحديثه ، ثم حذفه ، وهو مخصص لاختبار الوحدة


باستخدام ddl-auto: update value set ، يقوم السبات تلقائيًا بإنشاء جدول في قاعدة البيانات استنادًا إلى جوهرنا ، لأن نصنع دفتر عناوين بسيط ثم ننشئ فئة اتصال.


Contact.class
 @Entity(name = "Contacts") @Getter @Setter @EqualsAndHashCode public class Contact { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String firstName; private String secondName; private String fatherName; private String numberPhone; private String email; } 

لنقم بإنشاء واجهة للعمل مع قاعدة البيانات ، وإضافة طريقة تُرجع القائمة منذ ذلك الحين Spring Data JPA بشكل افتراضي بإرجاع Iterable بدلاً من قائمة.

ContactRepository.class
 public interface ContactRepository extends CrudRepository<Contact, Integer> { List<Contact> findAll(); } 

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


ستكون الصفحة الرئيسية لتطبيقنا هي ContactList. سوف نرث جميع كائنات الصفحات التي تم إنشاؤها من AppLayout - هذا تخطيط نموذجي لتطبيق ويب يتكون من:


  • نافبار (رأس)
  • درج (الشريط الجانبي)
  • المحتوى (المضمون)
    في الوقت نفسه ، تتم إضافة المكونات إلى Navbar و Drawer ، ويتم تعيين مكون على Content as Content ، على سبيل المثال ، VerticalLayout حيث سيتم وضع عناصر المستخدم في ترتيب عمودي.

ستكون صفحة تحرير وإنشاء جهات الاتصال هي ManageContact ، وسننفذ واجهة HasUrlParameter فيها لنقل معرف جهة الاتصال ، عند تشغيل هذه الواجهة ، يجب تمرير المعلمة إلى الصفحة.
من أجل ربط صفحة بعنوان URL معين ، يتم استخدام تعليق الطريق:


 @Route("contacts") public class ContactList extends AppLayout {} @Route("manageContact") public class ManageContact extends AppLayout implements HasUrlParameter<Integer> {} 

إنشاء قائمة الاتصال


في مُنشئ كائن ContactList ، حدد المكونات المستخدمة عن طريق جعلها أولاً حقول الكائن. نظرًا لأن البيانات ستؤخذ من قاعدة البيانات ، فمن الضروري توصيل المستودع بحقل الكائن.


 @Route("contacts") public class ContactList extends AppLayout { VerticalLayout layout; Grid<Contact> grid; RouterLink linkCreate; @Autowired ContactRepository contactRepository; public ContactList(){ layout = new VerticalLayout(); grid = new Grid<>(); linkCreate = new RouterLink(" ",ManageContact.class,0); layout.add(linkCreate); layout.add(grid); addToNavbar(new H3(" ")); setContent(layout); } } 

حول Autowired (محدثة)

لا تحاول الوصول إلى contactRepository من مُنشئ كائن ؛ فهذا سيؤدي بالتأكيد إلى NullPointerException أو الوصول إلى أساليب مع شرح توضيحي لـ PostConstruct أو طرق كائن تم إنشاؤه بالفعل.
على تلميح من zesetup : contactRepository ، يمكنك حقنه من خلال المنشئ:


 ContactRepository contactRepository; @Autowired public ContactList(ContactRepository contactRepository){ this.contactRepository = contactRepository; 

كملاحظة من markellg : تجدر الإشارة أيضًا إلى أنه عند استخدام Spring الإصدار 4.3 والإصدارات الأحدث ، يكون التعليق التوضيحي Autowired على المنشئ اختياريًا إذا كان الفصل يحتوي على مُنشئ واحد.


تمت إضافة مكون VerticalLayout إلى فئة ContactList للترتيب العمودي للعناصر الموجودة في المحتوى ، وسوف نضيف RouterLink إليه (للانتقال إلى صفحة إنشاء جهة اتصال) و Grid لعرض الجدول. تتم كتابة الشبكة بواسطة كائن جهة الاتصال حتى نتمكن من تحميل البيانات من القائمة ويتم سحبها تلقائيًا عند استدعاء طريقة setItems () ؛


 Grid<Contact> grid; public ContactList(){ grid = new Grid<>(); //      grid = new Grid<>(Contact.class); //      ,       } 

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


لملء الجدول ، سوف نحصل على البيانات من contactRepository ، لهذا سننشئ طريقة مع شرح PostConstruct


ملء جدول مع fillGrid ()
  @PostConstruct public void fillGrid(){ List<Contact> contacts = contactRepository.findAll(); if (!contacts.isEmpty()){ //     grid.addColumn(Contact::getFirstName).setHeader(""); grid.addColumn(Contact::getSecondName).setHeader(""); grid.addColumn(Contact::getFatherName).setHeader(""); grid.addColumn(Contact::getNumberPhone).setHeader(""); grid.addColumn(Contact::getEmail).setHeader("E-mail"); //     grid.addColumn(new NativeButtonRenderer<Contact>("", contact -> { UI.getCurrent().navigate(ManageContact.class,contact.getId()); })); grid.addColumn(new NativeButtonRenderer<Contact>("", contact -> { Dialog dialog = new Dialog(); Button confirm = new Button(""); Button cancel = new Button(""); dialog.add("     ?"); dialog.add(confirm); dialog.add(cancel); confirm.addClickListener(clickEvent -> { contactRepository.delete(contact); dialog.close(); Notification notification = new Notification(" ",1000); notification.setPosition(Notification.Position.MIDDLE); notification.open(); grid.setItems(contactRepository.findAll()); }); cancel.addClickListener(clickEvent -> { dialog.close(); }); dialog.open(); })); grid.setItems(contacts); } } 

يستخدم NativeButtonRenderer لإضافة أعمدة مع أزرار التحرير والحذف ، ونقوم بتمرير اسم الزر إلى وسيطات المُنشئ ، ومعالج النقر فوق الزر.


 grid.addColumn(new NativeButtonRenderer<Contact>("", contact -> { //DO SOMETHING })); grid.addColumn(new NativeButtonRenderer<Contact>("", new ClickableRenderer.ItemClickListener<Contact>() { @Override public void onItemClicked(Contact contact) { //DO SOMETHING }})); 

يؤدي

قائمة الاتصال


إنشاء صفحة تحرير جهة اتصال


تقبل صفحة تحرير جهة الاتصال المعلمة كمعرف جهة اتصال ، لذلك نحتاج إلى تطبيق طريقة setParameter ():


  @Override public void setParameter(BeforeEvent beforeEvent, Integer contactId) { id = contactId; if (!id.equals(0)){ addToNavbar(new H3(" ")); } else { addToNavbar(new H3(" ")); } fillForm(); //  } 

تشبه إضافة المكونات قائمة ContactList ، فقط في هذه الحالة ، لا نستخدم VerticalLayout ، ولكن نستخدم ترميز FormLayout الخاص لعرض هذه النماذج. نحن نملأ النموذج بالبيانات التي لم تعد تستخدم الطريقة مع التعليق التوضيحي لـ PostConstruct ، ولكن بعد الحصول على رقم الاتصال من URL ، لأن السلسلة: Object constructor ->PostConstruct -> Override


ManageContact.class
 @Route("manageContact") public class ManageContact extends AppLayout implements HasUrlParameter<Integer> { Integer id; FormLayout contactForm; TextField firstName; TextField secondName; TextField fatherName; TextField numberPhone; TextField email; Button saveContact; @Autowired ContactRepository contactRepository; public ManageContact(){ //    contactForm = new FormLayout(); firstName = new TextField(""); secondName = new TextField(""); fatherName = new TextField(""); numberPhone = new TextField(" "); email = new TextField(" "); saveContact = new Button(""); //     contactForm.add(firstName, secondName,fatherName,numberPhone,email,saveContact); setContent(contactForm); } @Override public void setParameter(BeforeEvent beforeEvent, Integer contactId) { id = contactId; if (!id.equals(0)){ addToNavbar(new H3(" ")); } else { addToNavbar(new H3(" ")); } fillForm(); } public void fillForm(){ if (!id.equals(0)){ Optional<Contact> contact = contactRepository.findById(id); contact.ifPresent(x -> { firstName.setValue(x.getFirstName()); secondName.setValue(x.getSecondName()); fatherName.setValue(x.getFatherName()); numberPhone.setValue(x.getNumberPhone()); email.setValue(x.getEmail()); }); } saveContact.addClickListener(clickEvent->{ //       Contact contact = new Contact(); if (!id.equals(0)){ contact.setId(id); } contact.setFirstName(firstName.getValue()); contact.setSecondName(secondName.getValue()); contact.setFatherName(fatherName.getValue()); contact.setEmail(email.getValue()); contact.setNumberPhone(numberPhone.getValue()); contactRepository.save(contact); Notification notification = new Notification(id.equals(0)? "  ":"  ",1000); notification.setPosition(Notification.Position.MIDDLE); notification.addDetachListener(detachEvent -> { UI.getCurrent().navigate(ContactList.class); }); contactForm.setEnabled(false); notification.open(); }); } } 

يؤدي

الاتصال التحرير


النتائج: يعد Vaadin 14 إطارًا مناسبًا إلى حد ما لإنشاء تطبيقات ويب بسيطة ، حيث يمكنك استخدامه بسرعة لإنشاء تطبيق بمعرفة Java فقط في الأمتعة ، وسيعمل بنجاح. لكن لسوء الحظ ، يتم إنشاء الواجهة بأكملها من جانب الخادم والموارد ضرورية أكثر بكثير من استخدام HTML5 + JS. يعد هذا الإطار أكثر ملاءمة للمشاريع الصغيرة التي يجب القيام بها بسرعة دون دراسة التقنيات الأمامية.


يوضح هذا المقال كيف يمكنك إنشاء تطبيق ويب بسرعة وسهولة دون تصميم قاعدة بيانات مسبقًا ، وتجنب تكوينات XML الطويلة ، ومدى سرعة تطوير واجهة الويب. بالنسبة للجزء الأكبر ، يجعل Spring Boot و Spring Data JPA الحياة أسهل للمطورين ويبسط عملية التطوير. لن تكشف المقالة عن أي شيء جديد للمطورين الذين تم تأسيسهم بالفعل ، ولكنها ستساعد المبتدئين على البدء في إتقان إطار Spring.


مستودع مع المشروع


الأخطاء النحوية وعلامات الترقيم ممكنة في المقالة ؛ عند الكشف ، يرجى إرسال رسالة شخصية

Source: https://habr.com/ru/post/ar480852/


All Articles