Vaadin和Spring Boot上的快速Web应用开发

气道正压通气


本文的目的是系统化使用Spring Boot在Vaadin 14上开发Web应用程序的过程。


在阅读本文之前,我建议阅读以下材料:



印象数


Vaadin 14是用于设计Web应用程序的相当方便的工具,在满足该要求之前,它仅在JavaFX,Android甚至J2ME上开发了图形界面,并且同时避免了前端开发(可使用HTML,CSS,JS的基本知识),因为它不认为我的


免责声明


那些尚未使用Spring Boot的人建议跳过使用Spring Initializr的快速入门,返回推荐的材料,并尝试自己配置一切,遇到很多不同的问题,否则将来在理解各种事物上会有差距。


快速上手


使用Spring Initializr为我们的Web应用程序创建一个项目,该项目是我们小型Web应用程序的必要依赖项:


  • Spring Data JPA(用于数据库)
  • Vaadin(用于Web应用程序开发)
  • 龙目岛(减少样板代码)
  • MySQL驱动程序(我使用mariadb,在春季初始化它不是)

设置application.properties和数据库


在Spring Initializr上创建的项目几乎可以运行了,我们只需要通过指定数据库路径,用户名和密码来配置application.properties。


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-auto

请勿在实时数据库或开发项目时将ddl-auto与更新值一起使用,因为它会自动更新数据库架构。
ddl-auto的现有选项:
create-将在数据库中创建一个表,该表先前已删除该表的旧版本(在架构更改的情况下会丢失数据)
validate-检查数据库中的表,如果它与实体不匹配,则休眠将抛出异常
更新-检查表,并自动更新它,而不会从实体中删除不存在的字段
create-drop-检查表,创建或更新它,然后删除它,以用于单元测试


设置了ddl-auto:update值后,hibernate将根据我们的本质在数据库中自动创建一个表,因为 我们制作一个简单的通讯录,然后创建一个联系人类。


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; } 

让我们创建一个用于处理数据库的接口,并添加一个返回List的方法,因为 默认情况下,Spring Data JPA返回Iterable而不是List。

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

Vaadin上的界面开发包括将输入,可视化和交互形式的组件添加到布局对象中,以进行元素的必要定位。 可以在框架官方网站上找到所有组件的列表


我们应用程序的主页将为ContactList。 我们将从AppLayout继承已创建页面的所有对象-这是Web应用程序的典型布局,包括:


  • 导航栏(标题)
  • 抽屉(侧边栏)
  • 内容内容
    同时,将组件添加到Navbar和Drawer,并将组件设置为Content作为Content,例如VerticalLayout,其中用户元素将以垂直排列放置。

用于编辑和创建联系人的页面将为ManageContact,我们将在其中实现HasUrlParameter接口以传输联系人ID,打开此接口后,必须将参数传递给页面。
为了将页面绑定到特定的URL,使用Route注释:


 @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); } } 

关于自动连线(已更新)

不要尝试从对象的构造函数访问contactRepository;这肯定会导致NullPointerException,从具有PostConstruct批注的方法或已经创建的对象的方法进行访问。
zesetup :contactRepository的技巧中,您可以通过构造函数进行注入:


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

作为markellg的提示:值得注意的是,在使用Spring 4.3及更高版本时,如果类包含单个构造函数,则构造函数上的Autowired注释是可选的。


VerticalLayout组件已添加到ContactList类中,用于内容中元素的垂直排列,我们将向其中添加RouterLink (转到联系创建页面)和Grid以显示表格。 网格由Contact对象键入,以便我们可以从列表中加载数据,并且在调用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 }})); 

结果

联络人清单


创建联系人编辑页面


联系人编辑页面接受参数作为联系人ID,因此我们需要实现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获取联系号码之后,因为链为:对象构造函数-> @PostConstruct-> 覆盖


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是用于创建简单Web应用程序的相当方便的框架,使用它,您可以快速制作出仅具有Java知识的应用程序,并且可以正常工作。 但是不幸的是,整个接口是在服务器端创建的,比使用HTML5 + JS更加需要资源。 该框架更适合需要快速完成而无需研究前端技术的小型项目。


本文介绍了如何无需预先设计数据库即可快速轻松地创建Web应用程序,避免使用冗长的xml配置以及开发Web界面的速度如何。 在大多数情况下,Spring Boot和Spring Data JPA使开发人员的工作更轻松,并简化了开发。 本文不会对已经建立的开发人员透露任何新​​内容,但是将帮助初学者开始掌握Spring框架。


带项目的存储库


文章中可能存在语法和标点错误;检测到后,请以个人名义发送

Source: https://habr.com/ru/post/zh-CN480852/


All Articles