This time as well, I created an app with Spring Boot for studying. We plan to add functions at any time.
・ Windows10 (64bit) ・ Spring-boot: 2.2.6 -Eclipse: 4.9.0 ・ H2 ・ Bootstrap
It is a simple inquiry application.
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;
//Save process
public Inquiry save(Inquiry inquiry) {
return inquiryDao.saveAndFlush(inquiry);
}
//Search process
public List<Inquiry> find() {
return inquiryDao.findAll();
}
//Delete process
public void delete(int id) {
inquiryDao.deleteById(id);
}
}
Form Prepare a Form class to hold the entered value. The validation check is also set here.
InquiryForm.java
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
public class InquiryForm {
@Size(min=1, max=20, message="Name input check error")
private String name;
@NotEmpty(message="Not entered")
private String email;
@NotEmpty(message="Not entered")
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;
//List screen processing
@GetMapping()
public String index(Model model) {
//All search processing
List<Inquiry> list = inquiryService.find();
model.addAttribute("list", list);
model.addAttribute("title", "List screen");
return "index_boot";
}
//Inquiry input processing
@GetMapping("form")
public String form(@ModelAttribute("inquiryForm") InquiryForm inquiryForm, Model model, @ModelAttribute("complete") String complete) {
model.addAttribute("title", "Inquiry form");
return "form_boot";
}
//Processing that flew by pressing the "Back" button from the confirmation page
@PostMapping("form")
public String formGoBack(@ModelAttribute("inquiryForm") InquiryForm inquiryForm, Model model) {
model.addAttribute("title", "Inquiry form");
return "form_boot";
}
/*Processing when you type in the input contents and press the "confirmation page"
* @Perform input check of form class with Validated,
*Store the check result in BindingResult
*/
@PostMapping("confirm")
public String confirm(@ModelAttribute("inquiryForm") @Validated InquiryForm inquiryForm, BindingResult res, Model model) {
//If the result of BindingResult is an error, an error message is output.
if(res.hasErrors()) {
model.addAttribute("title", "Inquiry form");
return "form_boot";
}
model.addAttribute("title", "Confirmation page");
return "confirm_boot";
}
//Processing when the "Save" button is pressed
@PostMapping("complete")
public String complete(@ModelAttribute("inquiryForm") @Validated InquiryForm inquiryForm, BindingResult res, Model model, RedirectAttributes redirectAttributes) {
if(res.hasErrors()) {
return "form_boot";
}
//Repacking Inquiry from the Inquiry Form container
Inquiry inquiry = new Inquiry();
inquiry.setName(inquiryForm.getName());
inquiry.setEmail(inquiryForm.getEmail());
inquiry.setContents(inquiryForm.getContents());
inquiry.setCreated(LocalDateTime.now());
//Save process
inquiryService.save(inquiry);
redirectAttributes.addFlashAttribute("complete", "Save completed");
return "redirect:/inquiry/form";
}
//Delete process
@GetMapping("delete")
public String delete(Model model) {
List<Inquiry> deleteList = inquiryService.find();
model.addAttribute("title", "Delete page");
model.addAttribute("list", deleteList);
return "delete_boot";
}
//URL id@Receive with PathVariable and use as an argument
@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">The inquiry list screen will be displayed.</p>
</div>
<!--List items in the table-->
<table class="table table-striped">
<thead>
<tr>
<th scope="col">id</th>
<th scope="col">Full name</th>
<th scope="col">Email</th>
<th scope="col">Contents</th>
<th scope="col">date</th>
</tr>
</thead>
<tbody>
<!--th:Output the value repeatedly with each-->
<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">You can enter your inquiry here</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>
<!--To retain the value entered on this input screen when the "Back" button is pressed
th:Use value-->
<!--th:If the result of if is true, th:errors apply(The validation set for each item is output) -->
<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">Verification</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">You can check the input contents on this screen.</p>
</div>
<!--Extract each value packed in the inquiryForm-->
<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>
<!--With hidden, you can send a value by pressing a button-->
<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">Return</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">Select the item you want to delete</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">Full name</th>
<th scope="col">Email</th>
<th scope="col">Contents</th>
<th scope="col">date</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
<!--th:Output the value repeatedly with each-->
<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})}">Delete</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>
Click "Inquiry Form" in the header to move to the form screen. Enter your name, email, and content, and click the "Confirm" button. The screen will change to the confirmation screen, but click the "Back" button to return to the previous screen. Change the contents, etc., and click the "Confirm" button again. Click the "Post" button on the confirmation screen to save the content.
Click the "Delete" button of Natto. Then you can see that it has been deleted.
Recommended Posts