Commit 76228886 by Patryk Czarnik

Inna wersja walidacji danych z formularza (samodzielna obsługa błędów)

parent 2696a080
package sklep.controller;
import java.util.List;
import java.util.Optional;
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.web.bind.annotation.GetMapping;
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.bind.annotation.ResponseBody;
import jakarta.validation.Valid;
import sklep.model.Product;
import sklep.photo.PhotoUtil;
import sklep.repository.ProductRepository;
import sklep.utils.ExceptionUtils;
@Controller
@RequestMapping("/products_alt")
public class ProductControllerAlt {
@Autowired
private ProductRepository productRepository;
@Autowired
private PhotoUtil photoUtil;
@GetMapping
public String wszystkieProdukty(Model model) {
List<Product> products = productRepository.findAll();
model.addAttribute("products", products);
return "products";
}
@GetMapping("/{id}")
public String jedenProdukt(@PathVariable Integer id, Model model) {
Optional<Product> product = productRepository.findById(id);
if(product.isPresent()) {
model.addAttribute("product", product.get());
return "product";
} else {
model.addAttribute("product_id", id);
return "missing_product";
}
}
@GetMapping(path="/{id}/photo", produces="image/jpeg")
@ResponseBody
public byte[] foto(@PathVariable Integer id, Model model) {
return photoUtil.readBytes(id);
}
@GetMapping("/new")
public String nowyProdukt() {
return "product_form_alt";
}
@GetMapping("/{id}/edit")
public String edytujProdukt(@PathVariable Integer id, Model model) {
Optional<Product> product = productRepository.findById(id);
if(product.isPresent()) {
model.addAttribute("product", product.get());
return "product_form_alt";
} else {
model.addAttribute("product_id", id);
return "missing_product";
}
}
@PostMapping({ "/new", "/{id}/edit" })
public String zapiszProdukt(Model model, @Valid Product product, BindingResult bindingResult) {
// W tej wersji dane z wypełnionego formularza odbieramy w postaci jednego obiektu Product.
// Spring sam wpisze dane do pól o takich samych nazwach.
// Taki parametr od razu staje się częścią modelu (to jest tzw. ModelAttribute)
System.out.println("Obiekt z formularza: " + product.getId() + " " + product.getProductName());
// W tej wersji przed parametrem Product jest adnotacja @Valid
// i dodatkowo do metoda posiada parametr BindingResult.
// Wówczas Spring dokonuje walidacji obiektu przed wywołaniem tej metody
// i informacje o wyniku walidacji przekazuje w parametrze BindingResult.
// Metoda jest wywoływana zawsze, a to programista ma sprawdzić czy walidacja się powiodła.
// W BindingResult znajdują się też informacje o błędach.
if(bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
} else try {
productRepository.save(product);
System.out.println("Obiekt po zapisie: " + product.getId() + " " + product.getProductName());
model.addAttribute("saved", true);
} catch (Exception e) {
// to jest obsługa błędów, które pojawiłyby się na etapie zapisywania do bazy danych
// czyli błędy walidacji odkrywane dopiero przez Hibernate (gdyby nie było @Valid)
// oraz błędy zgłaszane przez Postgresa
model.addAttribute("errors", ExceptionUtils.allMessages(e));
}
return "product_form_alt";
}
}
package sklep.utils;
import java.util.ArrayList;
import java.util.List;
public class ExceptionUtils {
public static List<String> allMessages(Throwable e) {
List<String> messages = new ArrayList<>();
messages.add(oneMessage(e));
Throwable cause = e.getCause();
while(cause != null) {
messages.add(oneMessage(cause));
cause = cause.getCause();
}
return messages;
}
private static String oneMessage(Throwable e) {
return e.getClass().getSimpleName() + ": " + e.getMessage();
}
}
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="jakarta.tags.core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Edycja danych produktu</title>
<link rel="stylesheet" type="text/css" href="/styl.css">
</head>
<body>
<h1>Edycja produktu</h1>
<form id="product-form" method="post">
<table class="form">
<tr>
<td><label for="id">Numer:</label></td>
<td><input name="id" placeholder="brak" type="number" readonly="readonly" value="${product.id}"/></td>
</tr>
<tr>
<td><label for="productName">Nazwa towaru:</label></td>
<td><input name="productName" placeholder="nazwa..." type="text" value="${product.productName}"/>
</td>
</tr>
<tr>
<td><label for="price">Cena:</label></td>
<td><input name="price" placeholder="12.90" title="tu wpisz cenę" type="number" step="0.01" value="${product.price}"/>
</td>
</tr>
<tr>
<td><label for="vat">Stawka VAT:</label></td>
<td><input name="vat" placeholder="0.23" title="tu wpisz vat" type="number" step="0.01" value="${product.vat}"/>
</td>
</tr>
<tr>
<td><label for="description">Opis:</label></td>
<td><textarea name="description" rows="10" cols="120">${product.description}</textarea></td>
</tr>
<tr>
<td><button>Zapisz</button></td>
</tr>
</table>
</form>
<c:if test="${not empty(errors)}">
<div class="error">
<h4>Błędy:</h4>
<ul>
<c:forEach var="error" items="${errors}">
<li>${error}</li>
</c:forEach>
</ul>
</div>
</c:if>
<c:if test="${saved}">
<div class="info">Zapisano produkt nr ${product.productId}</div>
</c:if>
<div class="action"><a href="/products">powrót do listy produktów</a></div>
<div class="action"><a href="/">powrót do spisu treści</a></div>
</body>
</html>
......@@ -29,6 +29,7 @@
<p>Cena: <span class="product-price">${product.price}</span></p>
<p class="product-description">${product.description}</p>
<div class="action"><a href="/products/${product.id}/edit">Edytuj</a></div>
<div class="action"><a href="/products_alt/${product.id}/edit">Edytuj</a> (alt)</div>
<div class="action"><a href="/products/${product.id}/add-to-basket">Dodaj do koszyka</a></div>
</div>
</c:forEach>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment