[JAVA] Erstellen Sie eine Anfrage-App mit Spring Boot

Auch dieses Mal habe ich mit Spring Boot eine App zum Lernen erstellt. Wir planen, jederzeit Funktionen hinzuzufügen.

2020/06/06: Hinzufügen einer Löschfunktion

Nutzungsumgebung

・ Windows 10 (64 Bit) ・ Spring-Boot: 2.2.6 ・ Eclipse: 4.9.0 ・ H2 ・ Bootstrap

Abschlusszeichnung

Es ist eine einfache Anfrage.

image.png

Entity

Inquiry.java


import java.time.LocalDateTime;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import org.springframework.format.annotation.DateTimeFormat;

@Entity
public class Inquiry {

	@Id
	@GeneratedValue
	private int id;

	private String name;
	private String email;
	private String contents;

	@DateTimeFormat(pattern="yyyy-MM-dd")
	private LocalDateTime created;

	public Inquiry() {
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getContents() {
		return contents;
	}

	public void setContents(String contents) {
		this.contents = contents;
	}

	public LocalDateTime getCreated() {
		return created;
	}

	public void setCreated(LocalDateTime created) {
		this.created = created;
	}
}

Repository

InquiryDao.java


import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface InquiryDao extends JpaRepository<Inquiry, Integer> {

}

Service

InquiryService.java


import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class InquiryService {

	@Autowired
	InquiryDao inquiryDao;

	//Prozess speichern
	public Inquiry save(Inquiry inquiry) {

		return inquiryDao.saveAndFlush(inquiry);
	}

	//Suchvorgang
	public List<Inquiry> find() {

		return inquiryDao.findAll();
	}

	//Prozess löschen
	public void delete(int id) {

		inquiryDao.deleteById(id);
	}
}

Form Bereiten Sie eine Formularklasse vor, die den eingegebenen Wert enthält. Hier wird auch die Validierungsprüfung eingestellt.

InquiryForm.java


import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;

public class InquiryForm {

	@Size(min=1, max=20, message="Fehler bei der Namenseingabeprüfung")
	private String name;

	@NotEmpty(message="Nicht beigetreten")
	private String email;

	@NotEmpty(message="Nicht beigetreten")
	private String contents;

	public  InquiryForm() {}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getContents() {
		return contents;
	}
	public void setContents(String contents) {
		this.contents = contents;
	}
}

Controller

InquiryController.java


import java.time.LocalDateTime;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
@RequestMapping("/inquiry")
public class InquiryController {

	@Autowired
	InquiryService inquiryService;

	//Listenbildschirmverarbeitung
	@GetMapping()
	public String index(Model model) {

		//Alle Suchvorgänge
		List<Inquiry> list = inquiryService.find();
		model.addAttribute("list", list);
		model.addAttribute("title", "Listenbildschirm");
		return "index_boot";
	}

	//Verarbeitung von Anfrageeingaben
	@GetMapping("form")
	public String form(@ModelAttribute("inquiryForm") InquiryForm inquiryForm, Model model, @ModelAttribute("complete") String complete) {

		model.addAttribute("title", "Anfrageformular");
		return "form_boot";
	}

	//Verarbeitung, die durch Drücken der Schaltfläche "Zurück" auf der Bestätigungsseite durchgeführt wurde
	@PostMapping("form")
	public String formGoBack(@ModelAttribute("inquiryForm") InquiryForm inquiryForm, Model model) {

		model.addAttribute("title", "Anfrageformular");
		return "form_boot";
	}

	/*Verarbeitung, wenn Sie den Eingabeinhalt eingeben und auf die "Bestätigungsseite" klicken
	 * @Führen Sie die Eingabeprüfung der Formularklasse mit Validated,
	 *Speichern Sie das Prüfergebnis in BindingResult
	*/
	@PostMapping("confirm")
	public String confirm(@ModelAttribute("inquiryForm") @Validated InquiryForm inquiryForm, BindingResult res, Model model) {

		//Wenn das Ergebnis von BindingResult ein Fehler ist, wird eine Fehlermeldung ausgegeben.
		if(res.hasErrors()) {
			model.addAttribute("title", "Anfrageformular");
			return "form_boot";
		}
		model.addAttribute("title", "Bestätigungsseite");
		return "confirm_boot";
	}

	//Verarbeitung, wenn die Schaltfläche "Speichern" gedrückt wird
	@PostMapping("complete")
	public String complete(@ModelAttribute("inquiryForm") @Validated InquiryForm inquiryForm, BindingResult res, Model model, RedirectAttributes redirectAttributes) {

		if(res.hasErrors()) {
			return "form_boot";
		}

		//Anfrage aus dem Container des Anfrageformulars neu verpacken
		Inquiry inquiry = new Inquiry();
		inquiry.setName(inquiryForm.getName());
		inquiry.setEmail(inquiryForm.getEmail());
		inquiry.setContents(inquiryForm.getContents());
		inquiry.setCreated(LocalDateTime.now());

		//Prozess speichern
		inquiryService.save(inquiry);

		redirectAttributes.addFlashAttribute("complete", "Speicherung abgeschlossen");
		return "redirect:/inquiry/form";
	}

	//Prozess löschen
	@GetMapping("delete")
	public String delete(Model model) {

		List<Inquiry> deleteList = inquiryService.find();
		model.addAttribute("title", "Seite löschen");
		model.addAttribute("list", deleteList);
		return "delete_boot";
	}

	//URL-ID@Mit PathVariable empfangen und als Argument verwenden
	@GetMapping("dell/{id}")
	public String deletes(@PathVariable("id") int id, Model model) {

		inquiryService.delete(id);
		return "redirect:/inquiry";
	}

}

index_boot.html

index_boot.html


<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
    <meta name="generator" content="Jekyll v4.0.1">
    <title th:text="${title}">Starter Template · Bootstrap</title>

    <link rel="canonical" href="https://getbootstrap.com/docs/4.5/examples/starter-template/">

    <!-- Bootstrap core CSS -->
<link href="/docs/4.5/dist/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

    <!-- Favicons -->
<link rel="apple-touch-icon" href="/docs/4.5/assets/img/favicons/apple-touch-icon.png " sizes="180x180">
<link rel="icon" href="/docs/4.5/assets/img/favicons/favicon-32x32.png " sizes="32x32" type="image/png">
<link rel="icon" href="/docs/4.5/assets/img/favicons/favicon-16x16.png " sizes="16x16" type="image/png">
<link rel="manifest" href="/docs/4.5/assets/img/favicons/manifest.json">
<link rel="mask-icon" href="/docs/4.5/assets/img/favicons/safari-pinned-tab.svg" color="#563d7c">
<link rel="icon" href="/docs/4.5/assets/img/favicons/favicon.ico">
<meta name="msapplication-config" content="/docs/4.5/assets/img/favicons/browserconfig.xml">
<meta name="theme-color" content="#563d7c">


    <style>
      .bd-placeholder-img {
        font-size: 1.125rem;
        text-anchor: middle;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
      }

      @media (min-width: 768px) {
        .bd-placeholder-img-lg {
          font-size: 3.5rem;
        }
      }
    </style>
    <!-- Custom styles for this template -->
    <link href="starter-template.css" rel="stylesheet" th:href="@{/css/starter-template.css}">
  </head>
  <body>
    <div th:replace="~{header::headerA}"></div>

<main role="main" class="container">

  <div class="starter-template">
    <h1 th:text="${title}"></h1>
    <p class="lead">Der Bildschirm mit der Anfrageliste wird angezeigt.</p>
  </div>
<!--Listen Sie die Elemente in der Tabelle auf-->
<table class="table table-striped">
  <thead>
    <tr>
      <th scope="col">id</th>
      <th scope="col">Vollständiger Name</th>
      <th scope="col">Email</th>
      <th scope="col">Inhalt</th>
      <th scope="col">Datum</th>
    </tr>
  </thead>
  <tbody>
  <!--th:Geben Sie den Wert jeweils wiederholt aus-->
    <tr th:each="list:${list}">
      <th scope="row" th:text="${list.id}">1</th>
	  <td th:text="${list.name}">
	  <td th:text="${list.email}">
	  <td th:text="${list.contents}">
      <td th:text="${list.created}">
    </tr>
  </tbody>
</table>
</main><!-- /.container -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
      <script>window.jQuery || document.write('<script src="/docs/4.5/assets/js/vendor/jquery.slim.min.js"><\/script>')</script><script src="/docs/4.5/dist/js/bootstrap.bundle.min.js" th:src="@{/js/bootstrap.bundle.min.js}" integrity="sha384-1CmrxMRARb6aLqgBO7yyAxTOQE2AKb9GfXnEo760AUcUmFx3ibVJJAzGytlQcNXd" crossorigin="anonymous"></script></body>
</html>

form_boot.html

form_boot.html


<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../../../favicon.ico">

    <title>Starter Template for Bootstrap</title>

    <!-- Bootstrap core CSS -->
    <link href="/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="starter-template.css"  th:href="@{/css/starter-template.css}" rel="stylesheet">
  </head>

  <body>


	<div th:replace="~{header::headerA}"></div>
    <main role="main" class="container">

      <div class="starter-template">
        <h1 th:text="${title}">Bootstrap starter template</h1>
        <p class="lead">Hier können Sie Ihre Anfrage eingeben</p>
      </div>


	<div th:unless="${#strings.isEmpty(complete)}" >
		<div th:text="${complete}" class="alert alert-success" role="alert">
		  A simple success alert?check it out!
		</div>
	</div>
	<!--Um den auf diesem Eingabebildschirm eingegebenen Wert beizubehalten, wenn die Taste "Zurück" gedrückt wird
			th:Nutzwert-->
	<!--th:Wenn das Ergebnis von if wahr ist, th:Fehler gelten(Der Validierungssatz für jedes Element wird ausgegeben)  -->
	<form method="post" action="#" th:action="@{/inquiry/confirm}" th:object="${inquiryForm}">
	  <div class="form-group">
	    <label for="name">Name</label>
	    <input type="text" name="name" class="form-control" id="name" th:value="*{name}">
	  </div>
	  <div class="text-danger mb-4" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></div>
	  <div class="form-group">
	    <label for="email">Email</label>
	    <input type="text" name="email" class="form-control" id="email"  th:value="*{email}">
	  </div>
	  <div class="text-danger mb-4" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></div>
	  <div class="form-group">
	    <label for="contents">Inquiry</label>
	    <textarea  name="contents" class="form-control" id="detail" rows="3" th:field="*{contents}"></textarea>
	  </div>
	  <div class="text-danger mb-4" th:if="${#fields.hasErrors('contents')}" th:errors="*{contents}"></div>
	  <button type="submit" class="btn btn-primary">Bestätigung</button>
	</form>
    </main><!-- /.container -->

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script>window.jQuery || document.write('<script src="@{/js/jquery-slim.min.js}"><\/script>')</script>
    <script src="../../assets/js/vendor/popper.min.js"  th:src="@{/js/popper.min.js}"></script>
    <script src="../../dist/js/bootstrap.min.js"  th:src="@{/js/bootstrap.min.js}"></script>
  </body>

confirm_boot.html

confirm_boot.html


<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../../../favicon.ico">

    <title>Starter Template for Bootstrap</title>

    <!-- Bootstrap core CSS -->
    <link href="/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="starter-template.css"  th:href="@{/css/starter-template.css}" rel="stylesheet">
  </head>

  <body>

	<div th:replace="~{header::headerA}"></div>
    <main role="main" class="container">

      <div class="starter-template">
        <h1 th:text="${title}">Bootstrap starter template</h1>
        <p class="lead">Sie können den Eingabeinhalt auf diesem Bildschirm überprüfen.</p>
      </div>

<!--Extrahieren Sie jeden in der Anfrageform gepackten Wert-->
<div th:object="${inquiryForm}">
<div class="mb-5">
<ul class="list-group">
  <li th:text="*{name}" class="list-group-item"></li>
  <li th:text="*{email}" class="list-group-item"></li>
  <li th:text="*{contents}"class="list-group-item"></li>
</ul>
</div>
<!--Mit versteckt können Sie einen Wert per Knopfdruck senden-->
<form method="post" th:action="@{/inquiry/form}">
	<input type="hidden" name="name" th:value="*{name}">
	<input type="hidden" name="email" th:value="*{email}">
	<input type="hidden" name="contents" th:value="*{contents}">
	<button type="submit" class="btn btn-primary">Rückkehr</button>
</form>
<form method="post" th:action="@{/inquiry/complete}" th:object="${inquiryForm}">
	<input type="hidden" name="name" th:value="*{name}">
	<input type="hidden" name="email" th:value="*{email}">
	<input type="hidden" name="contents" th:value="*{contents}">
	<button type="submit" class="btn btn-primary">Post</button>
</form>
</div>

    </main><!-- /.container -->

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script>window.jQuery || document.write('<script src="@{/js/jquery-slim.min.js}"><\/script>')</script>
    <script src="../../assets/js/vendor/popper.min.js"  th:src="@{/js/popper.min.js}"></script>
    <script src="../../dist/js/bootstrap.min.js"  th:src="@{/js/bootstrap.min.js}"></script>
  </body>
</html>

delete_boot.html

html.delete_boot.html



<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../../../favicon.ico">

    <title>Starter Template for Bootstrap</title>

    <!-- Bootstrap core CSS -->
    <link href="/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="starter-template.css"  th:href="@{/css/starter-template.css}" rel="stylesheet">
  </head>

  <body>


	<div th:replace="~{header::headerA}"></div>
    <main role="main" class="container">

      <div class="starter-template">
        <h1 th:text="${title}">Bootstrap starter template</h1>
        <p class="lead">Bitte wählen Sie den Artikel aus, den Sie löschen möchten</p>
      </div>


	<div th:unless="${#strings.isEmpty(complete)}" >
		<div th:text="${complete}" class="alert alert-success" role="alert">
		  A simple success alert?check it out!
		</div>
	</div>
	<table class="table table-striped">
	  <thead>
	    <tr>
	      <th scope="col">id</th>
	      <th scope="col">Vollständiger Name</th>
	      <th scope="col">Email</th>
	      <th scope="col">Inhalt</th>
	      <th scope="col">Datum</th>
	      <th scope="col">Löschen</th>
	    </tr>
	  </thead>
	  <tbody>
	  <!--th:Geben Sie den Wert jeweils wiederholt aus-->
	    <tr th:each="list:${list}">
	      <th scope="row" th:text="${list.id}"></th>
		  <td th:text="${list.name}">
		  <td th:text="${list.email}">
		  <td th:text="${list.contents}">
	      <td th:text="${list.created}">
	      <td><a th:href="@{/inquiry/dell/{id}(id=${list.id})}">Löschen</a>
	    </tr>
	  </tbody>
	</table>
    </main><!-- /.container -->

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script>window.jQuery || document.write('<script src="@{/js/jquery-slim.min.js}"><\/script>')</script>
    <script src="../../assets/js/vendor/popper.min.js"  th:src="@{/js/popper.min.js}"></script>
    <script src="../../dist/js/bootstrap.min.js"  th:src="@{/js/bootstrap.min.js}"></script>
  </body>

Verarbeitungsmuster

Klicken Sie in der Kopfzeile auf "Anfrageformular", um zum Formularbildschirm zu gelangen. Geben Sie Ihren Namen, Ihre E-Mail-Adresse und Ihren Inhalt ein und klicken Sie auf die Schaltfläche "Bestätigen". Der Bildschirm wechselt zum Bestätigungsbildschirm, aber klicken Sie auf die Schaltfläche "Zurück", um zum vorherigen Bildschirm zurückzukehren. Ändern Sie den Inhalt usw. und klicken Sie erneut auf die Schaltfläche "Bestätigen". Klicken Sie im Bestätigungsbildschirm auf die Schaltfläche "Posten", um den Inhalt zu speichern.

image.png

image.png

image.png

image.png

image.png

Muster löschen

Klicken Sie auf die Schaltfläche "Löschen" von Natsuta. Dann können Sie sehen, dass es gelöscht wurde. image.png

image.png

Referenz

Einführung in den Frühling

Recommended Posts

Erstellen Sie eine Anfrage-App mit Spring Boot
[Spring Boot] Erstellung von Webanwendungen
Verarbeitung beim Starten einer Anwendung mit Spring Boot
Starten Sie die Entwicklung von Webanwendungen mit Spring Boot
Starten Sie die Nginx + Spring Boot-Anwendung mit Docker-Compose
Führen Sie die WEB-Anwendung mit Spring Boot + Thymeleaf aus
Spring Boot 2.3 Verfügbarkeit von Anwendungen
Mit Spring Boot herunterladen
Konfigurieren Sie die Spring Boot-Anwendung mit dem Maven Multi-Modul
Spring Boot2-Webanwendungsentwicklung mit Visual Studio Code Hello World-Erstellung
Generieren Sie mit Spring Boot einen Barcode
Hallo Welt mit Spring Boot
Implementieren Sie GraphQL mit Spring Boot
Beginnen Sie mit Spring Boot
Führen Sie LIFF mit Spring Boot aus
SNS-Login mit Spring Boot
Datei-Upload mit Spring Boot
Spring Boot beginnt mit dem Kopieren
CICS-Java-Anwendung ausführen- (4) Spring Boot-App
Spring Boot beginnend mit Docker
Hallo Welt mit Spring Boot
Setzen Sie Cookies mit Spring Boot
Verwenden Sie Spring JDBC mit Spring Boot
Modul mit Spring Boot hinzufügen
Erste Schritte mit Spring Boot
Erstellen Sie mit Spring Boot einen Mikrodienst
Mail mit Spring Boot verschicken
Versuchen Sie, OpenID Connect mit Keycloak (Spring Boot-Anwendung) zu verwenden.
Spring Boot-Anwendungsentwicklung in Eclipse
Überprüfungspunkte für den Spring Boot-Anwendungscode
Erstellen Sie eine App mit Spring Boot 2
Datenbankverknüpfung mit doma2 (Spring Boot)
Implementieren Sie die REST-API mit Spring Boot und JPA (Application Layer).
Spring Boot Programmierung mit VS Code
Bis "Hallo Welt" mit Spring Boot
Erhalten Sie Validierungsergebnisse mit Spring Boot
(Intellij) Hallo Welt mit Spring Boot
Erstellen Sie eine App mit Spring Boot
Google Cloud Platform mit Spring Boot 2.0.0
Implementieren Sie die Spring Boot-Anwendung in Gradle
Ich habe GraphQL mit Spring Boot ausprobiert
[Java] LINE-Integration mit Spring Boot
Spring Boot-Anwendung, die DB-Verbindungseinstellungen mit Parametern angibt
Beginnend mit Spring Boot 0. Verwenden Sie Spring CLI
Ich habe Flyway mit Spring Boot ausprobiert
Die Nachrichtenkooperation begann mit Spring Boot
Lassen Sie uns mit Spring Boot part3 eine Webanwendung für die Buchverwaltung erstellen
Lassen Sie uns mit Spring Boot part2 eine Webanwendung für die Buchverwaltung erstellen
[Anfänger] Versuchen Sie, die REST-API für die Todo-App mit Spring Boot zu schreiben
Hallo Welt mit Eclipse + Spring Boot + Maven
Senden Sie regelmäßige Benachrichtigungen mit LineNotify + Spring Boot
Führen Sie einen Transaktionsbestätigungstest mit Spring Boot durch
HTTPS mit Spring Boot und Let's Encrypt
Versuchen Sie es mit Spring Boot mit VS-Code
Ich habe Lazy Initialization mit Spring Boot 2.2.0 ausprobiert
Implementieren Sie CRUD mit Spring Boot + Thymeleaf + MySQL
Asynchrone Verarbeitung mit Spring Boot unter Verwendung von @Async
CI / CD Spring-Anwendung mit CircleCI (Heroku)