Spring Boot CRUD-Anwendung mit Thymeleaf

1. Übersicht

Die Implementierung von DAO-Schichten, die CRUD-Funktionen für JPA-Entitäten bereitstellen, kann eine sich wiederholende, zeitaufwändige Aufgabe sein, die wir in den meisten Fällen vermeiden möchten. Glücklicherweise macht es Spring Boot einfach, CRUD-Anwendungen über eine Schicht von Standard-JPA-basierten CRUD-Repositorys zu erstellen.

In diesem Tutorial erfahren Sie, wie Sie eine CRUD-Webanwendung mit Spring Boot und Thymeleaf entwickeln .

2. Die Maven-Abhängigkeiten

In diesem Fall verlassen wir uns auf Spring-Boot-Starter-Parent für die einfache Verwaltung von Abhängigkeiten, die Versionierung und die Plug-In-Konfiguration. Infolgedessen müssen wir die Versionen der Projektabhängigkeiten nicht in unserer Datei pom.xml angeben , außer um die Java-Version zu überschreiben:

 org.springframework.boot spring-boot-starter-parent 2.2.2.RELEASE    org.springframework.boot spring-boot-starter-web   org.springframework.boot spring-boot-starter-thymeleaf   org.springframework.boot spring-boot-starter-data-jpa   com.h2database h2   

3. Die Domänenschicht

Nachdem alle Projektabhängigkeiten bereits vorhanden sind, implementieren wir jetzt eine naive Domänenschicht.

Der Einfachheit halber enthält diese Ebene eine einzelne Klasse, die für die Modellierung von Benutzerentitäten verantwortlich ist :

@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @NotBlank(message = "Name is mandatory") private String name; @NotBlank(message = "Email is mandatory") private String email; // standard constructors / setters / getters / toString }

Denken Sie daran, dass wir die Klasse mit der Annotation @Entity versehen haben . Daher kann die JPA-Implementierung, in diesem Fall der Ruhezustand, CRUD-Operationen für die Domänenentitäten ausführen. Eine Einführung in Hibernate finden Sie in unserem Tutorial zu Hibernate 5 with Spring.

Darüber hinaus haben wir die Namens- und E-Mail- Felder mit der @ NotBlank- Einschränkung eingeschränkt. Dies bedeutet, dass wir den Hibernate Validator zum Überprüfen der eingeschränkten Felder verwenden können, bevor eine Entität in der Datenbank beibehalten oder aktualisiert wird.

Die Grundlagen hierzu finden Sie in unserem zugehörigen Tutorial zur Bean-Validierung.

4. Die Repository-Schicht

Zu diesem Zeitpunkt führt unsere Beispiel-Webanwendung nichts aus. Aber das wird sich bald ändern.

Mit Spring Data JPA können wir JPA-basierte Repositorys (ein ausgefallener Name für die Implementierung von DAO-Mustern) mit minimalem Aufwand implementieren .

Spring Data JPA ist eine Schlüsselkomponente von Spring Boot's Spring-Boot-Starter-Data-Jpa , die es einfach macht, CRUD-Funktionen durch eine leistungsstarke Abstraktionsebene hinzuzufügen, die über einer JPA-Implementierung platziert wird. Diese Abstraktionsschicht ermöglicht uns den Zugriff auf die Persistenzschicht, ohne dass wir unsere eigenen DAO-Implementierungen von Grund auf neu bereitstellen müssen.

Um unserer Anwendung grundlegende CRUD-Funktionen für Benutzerobjekte bereitzustellen , müssen wir lediglich die CrudRepository- Oberfläche erweitern:

@Repository public interface UserRepository extends CrudRepository {}

Und das ist es! Durch die Erweiterung der CrudRepository- Schnittstelle bietet Spring Data JPA Implementierungen für die CRUD-Methoden des Repositorys für uns.

5. Die Controller-Schicht

Dank der Abstraktionsebene, die Spring-Boot-Starter-Data-JPA über der zugrunde liegenden JPA-Implementierung platziert, können wir unserer Webanwendung über eine grundlegende Webebene problemlos einige CRUD-Funktionen hinzufügen .

In unserem Fall reicht eine einzelne Controller-Klasse aus, um GET- und POST-HTTP-Anforderungen zu verarbeiten und sie dann Aufrufen unserer UserRepository- Implementierung zuzuordnen .

Die Controller-Klasse basiert auf einigen der Hauptfunktionen von Spring MVC. Eine ausführliche Anleitung zu Spring MVC finden Sie in unserem Spring MVC-Tutorial.

Beginnen wir mit den Methoden showSignUpForm () und addUser () des Controllers .

Ersteres zeigt das Benutzeranmeldeformular an, während letzteres eine neue Entität in der Datenbank beibehält, nachdem die eingeschränkten Felder überprüft wurden.

Wenn die Entität die Validierung nicht besteht, wird das Anmeldeformular erneut angezeigt. Andernfalls wird nach dem Speichern der Entität die Liste der persistierten Entitäten in der entsprechenden Ansicht aktualisiert:

@Controller public class UserController { @GetMapping("/signup") public String showSignUpForm(User user) { return "add-user"; } @PostMapping("/adduser") public String addUser(@Valid User user, BindingResult result, Model model) { if (result.hasErrors()) { return "add-user"; } userRepository.save(user); return "redirect:/index"; } // additional CRUD methods }

Wir benötigen auch eine Zuordnung für die / index- URL:

@GetMapping("/index") public String showUserList(Model model) { model.addAttribute("users", userRepository.findAll()); return "index"; }

Im UserController haben wir auch die Methode showUpdateForm () , die für das Abrufen der Benutzerentität verantwortlich ist , die mit der angegebenen ID aus der Datenbank übereinstimmt .

Wenn die Entität vorhanden ist, wird sie als Modellattribut an die Ansicht zum Aktualisieren des Formulars übergeben. Daher kann das Formular mit den Werten der Felder name und email gefüllt werden:

@GetMapping("/edit/{id}") public String showUpdateForm(@PathVariable("id") long id, Model model) { User user = userRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id)); model.addAttribute("user", user); return "update-user"; } 

Schließlich haben wir die Methoden updateUser () und deleteUser () in der UserController- Klasse.

Die erste behält die aktualisierte Entität in der Datenbank bei, während die letzte die angegebene Entität entfernt.

In beiden Fällen wird die Liste der persistierten Entitäten entsprechend aktualisiert:

@PostMapping("/update/{id}") public String updateUser(@PathVariable("id") long id, @Valid User user, BindingResult result, Model model) { if (result.hasErrors()) { user.setId(id); return "update-user"; } userRepository.save(user); return "redirect:/index"; } @GetMapping("/delete/{id}") public String deleteUser(@PathVariable("id") long id, Model model) { User user = userRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id)); userRepository.delete(user); return "redirect:/index"; }

6. Die Ansichtsebene

Zu diesem Zeitpunkt haben wir eine funktionale Controller-Klasse implementiert, die CRUD-Operationen für Benutzerentitäten ausführt . Trotzdem fehlt in diesem Schema noch eine Komponente: die Ansichtsebene.

Im Ordner src / main / resources / templates müssen die HTML-Vorlagen erstellt werden, die zum Anzeigen des Anmeldeformulars, des Aktualisierungsformulars und zum Rendern der Liste der beibehaltenen Benutzerentitäten erforderlich sind.

Wie in der Einführung angegeben, verwenden wir Thymeleaf als zugrunde liegende Vorlagen-Engine zum Parsen der Vorlagendateien.

Hier ist der relevante Abschnitt der Datei add-user.html :

 Name   Email    

Beachten Sie, wie wir den URL-Ausdruck @ {/ adduser} verwendet haben, um das Aktionsattribut des Formulars und die Variablenausdrücke $ {} zum Einbetten von dynamischem Inhalt in die Vorlage anzugeben , z. B. die Werte der Namens- und E-Mail- Felder und die Nachvalidierung Fehler .

Ähnlich wie bei add-user.html sieht die Vorlage update-user.html folgendermaßen aus:

 Name   Email    

Schließlich haben wir die Datei index.html , in der die Liste der persistierten Entitäten zusammen mit den Links zum Bearbeiten und Entfernen vorhandener Entitäten angezeigt wird:

No users yet!

Users

Name Email Edit Delete
Edit Delete

Add a new user

Der Einfachheit halber sehen die Vorlagen eher skelettartig aus und bieten nur die erforderliche Funktionalität, ohne unnötige Kosmetika hinzuzufügen.

Um den Vorlagen ein verbessertes, auffälliges Aussehen zu verleihen, ohne zu viel Zeit mit HTML / CSS zu verbringen, können wir problemlos ein kostenloses Twitter Bootstrap UI-Kit wie Shards verwenden.

7. Ausführen der Anwendung

Zuletzt definieren wir den Einstiegspunkt der Anwendung. Wie die meisten Spring Boot-Anwendungen können wir dies mit einer einfachen alten main () -Methode tun :

@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

Klicken Sie jetzt in unserer IDE auf "Ausführen", öffnen Sie unseren Browser und zeigen Sie auf // localhost: 8080 .

Wenn der Build erfolgreich kompiliert wurde , sollte ein grundlegendes CRUD-Benutzer-Dashboard mit Links zum Hinzufügen neuer und zum Bearbeiten und Entfernen vorhandener Entitäten angezeigt werden.

8. Fazit

In diesem Tutorial haben wir gelernt, wie Sie mit Spring Boot und Thymeleaf eine grundlegende CRUD-Webanwendung erstellen.

Wie üblich sind alle im Artikel gezeigten Codebeispiele auf GitHub verfügbar.