简体   繁体   English

Spring - Thymeleaf:异常处理模板

[英]Spring - Thymeleaf: Exception processing template

I'm following the a book Spring in Action 5th ed., but I believe that is presents a bug. 我正在关注Spring in Action第5版的书,但我相信这是一个错误。

This is the GitHub of the book. 这是本书的GitHub。 I'm arrived on chap 3 tacos-jdbc source of code 我来到第3章tacos-jdbc 代码源代码

When submit my order a sudden error appears: 提交订单时会出现突然错误:

在此输入图像描述

and in this way on the terminal: 并以这种方式在终端上:

2019-05-25 16:58:18.164 ERROR 11777 --- [nio-8080-exec-7] org.thymeleaf.TemplateEngine : [THYMELEAF][http-nio-8080-exec-7] Exception processing template "orderForm": An error happened during template parsing (template: "class path resource [templates/orderForm.html]") 2019-05-25 16:58:18.164 ERROR 11777 --- [nio-8080-exec-7] org.thymeleaf.TemplateEngine:[THYMELEAF] [http-nio-8080-exec-7]异常处理模板“orderForm” :模板解析期间发生错误(模板:“类路径资源[templates / orderForm.html]”)

org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/orderForm.html]") org.thymeleaf.exceptions.TemplateInputException:模板解析期间发生错误(模板:“类路径资源[templates / orderForm.html]”)

在此输入图像描述

OrderController: OrderController:

@Controller
@RequestMapping("/orders")
@SessionAttributes("order")
public class OrderController {

    private OrderRepository orderRepo;

    public OrderController(OrderRepository orderRepo) {
        this.orderRepo = orderRepo;
    }

    @GetMapping("/current")
    public String orderForm() {
        return "orderForm";
    }

    @PostMapping
    public String processOrder(@Valid Order order, Errors errors,
                               SessionStatus sessionStatus) {
        if (errors.hasErrors()) {
            return "orderForm";
        }

        orderRepo.save(order);
        sessionStatus.setComplete();

        return "redirect:/";
    }

}

and orderForm: 和orderForm:

 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>Taco Cloud</title> <link rel="stylesheet" th:href="@{/styles.css}" /> </head> <body> <form method="POST" th:action="@{/orders}" th:object="${order}"> <h1>Order your taco creations!</h1> <img th:src="@{/images/TacoCloud.png}"/> <a th:href="@{/design}" id="another">Design another taco</a><br/> <div th:if="${#fields.hasErrors()}"> <span class="validationError"> Please correct the problems below and resubmit. </span> </div> <h3>Deliver my taco masterpieces to...</h3> <label for="name">Name: </label> <input type="text" th:field="*{name}"/> <br/> <label for="street">Street address: </label> <input type="text" th:field="*{street}"/> <br/> <label for="city">City: </label> <input type="text" th:field="*{city}"/> <br/> <label for="state">State: </label> <input type="text" th:field="*{state}"/> <br/> <label for="zip">Zip code: </label> <input type="text" th:field="*{zip}"/> <br/> <label for="ccNumber">Credit Card #: </label> <input type="text" th:field="*{ccNumber}"/> <span class="validationError" th:if="${#fields.hasErrors('ccNumber')}" th:errors="*{ccNumber}">CC Num Error</span> <label for="ccExpiration">Expiration: </label> <input type="text" th:field="*{ccExpiration}"/> <br/> <label for="ccCVV">CVV: </label> <input type="text" th:field="*{ccCVV}"/> <br/> <input type="submit" value="Submit order"/> </form> </body> </html> 

I fixed with this code adding delivery prefix: 我修复了这段代码添加delivery前缀:

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Taco Cloud</title>
    <link rel="stylesheet" th:href="@{/styles.css}" />
</head>

<body>

<form method="POST" th:action="@{/orders}" th:object="${order}">
    <h1>Order your taco creations!</h1>

    <img th:src="@{/images/TacoCloud.png}"/>

    <h3>Your tacos in this order:</h3>
    <a th:href="@{/design}" id="another">Design another taco</a><br/>
    <ul>
        <li th:each="taco : ${order.tacos}"><span th:text="${taco.name}">taco name</span></li>
    </ul>

    <div th:if="${#fields.hasErrors()}">
        <span class="validationError">
        Please correct the problems below and resubmit.
        </span>
    </div>

    <h3>Deliver my taco masterpieces to...</h3>
    <label for="deliveryName">Name: </label>
    <input type="text" th:field="*{deliveryName}"/>
    <span class="validationError"
          th:if="${#fields.hasErrors('deliveryName')}"
          th:errors="*{deliveryName}">Name Error</span>
    <br/>

    <label for="deliveryStreet">Street address: </label>
    <input type="text" th:field="*{deliveryStreet}"/>
    <span class="validationError"
          th:if="${#fields.hasErrors('deliveryStreet')}"
          th:errors="*{deliveryStreet}">Street Error</span>
    <br/>

    <label for="deliveryCity">City: </label>
    <input type="text" th:field="*{deliveryCity}"/>
    <span class="validationError"
          th:if="${#fields.hasErrors('deliveryCity')}"
          th:errors="*{deliveryCity}">City Error</span>
    <br/>

    <label for="deliveryState">State: </label>
    <input type="text" th:field="*{deliveryState}"/>
    <span class="validationError"
          th:if="${#fields.hasErrors('deliveryState')}"
          th:errors="*{deliveryState}">State Error</span>
    <br/>

    <label for="deliveryZip">Zip code: </label>
    <input type="text" th:field="*{deliveryZip}"/>
    <span class="validationError"
          th:if="${#fields.hasErrors('deliveryZip')}"
          th:errors="*{deliveryZip}">Zip Error</span>
    <br/>

    <h3>Here's how I'll pay...</h3>
    <label for="ccNumber">Credit Card #: </label>
    <input type="text" th:field="*{ccNumber}"/>
    <span class="validationError"
          th:if="${#fields.hasErrors('ccNumber')}"
          th:errors="*{ccNumber}">CC Num Error</span>
    <br/>

    <label for="ccExpiration">Expiration: </label>
    <input type="text" th:field="*{ccExpiration}"/>
    <span class="validationError"
          th:if="${#fields.hasErrors('ccExpiration')}"
          th:errors="*{ccExpiration}">CC Num Error</span>
    <br/>

    <label for="ccCVV">CVV: </label>
    <input type="text" th:field="*{ccCVV}"/>
    <span class="validationError"
          th:if="${#fields.hasErrors('ccCVV')}"
          th:errors="*{ccCVV}">CC Num Error</span>
    <br/>

    <input type="submit" value="Submit order"/>
</form>

</body>
</html>

You are using th:object="${order}" in your orderForm template but Thymeleaf doesn't know about it. 您在orderForm模板中使用th:object="${order}"但Thymeleaf不知道它。 You have to let Thymeleaf know about this object by passing it to the template like so 你必须通过将Thymeleaf传递给模板来让他们了解这个对象

@GetMapping("/current")
public ModelAndView orderForm() {
    ModelAndView mv = new ModelAndView("orderForm");
    mv.addObject("order", new Order());
    return mv;
}

Note: You will have to pass the object from your controller layer at all the places where you are using that object in the template. 注意:您必须在模板中使用该对象的所有位置从控制器层传递对象。


Update 1 更新1

Also update you post method 还要更新发布方法

@PostMapping
public ModelAndView processOrder(@Valid Order order, Errors errors,
                           SessionStatus sessionStatus) {
    if (errors.hasErrors()) {
        ModelAndView mv = new ModelAndView("orderForm");
        mv.addObject("order", new Order());
        return mv;
    }

    orderRepo.save(order);
    sessionStatus.setComplete();

    return new ModelAndView("redirect:/");
}

I think you could do it this way 我想你可以这样做

@Controller
public class OrderController {

   @GetMapping("/orders")
   public String orders(Order order) {
      return "orderForm";
   }

   @PostMapping("/orders")
   public String orderForm(@Valid Order order, BindingResult result, Model model) {
       if(result.hasErrors()) {
           return "orderForm";
       } else {
           retrun "your_success_view";   
       }
    }
}

I think you should handle the display of the validation errors in all the input in the orderForm.html as mentioned in the book as following: (Source Git) 我认为您应该在orderForm.html中的所有输入中处理验证错误的显示,如下所述:(来源Git)

<!-- tag::allButValidation[] -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Taco Cloud</title>
    <link rel="stylesheet" th:href="@{/styles.css}" />
  </head>

  <body>

    <form method="POST" th:action="@{/orders}" th:object="${order}">
      <h1>Order your taco creations!</h1>

      <img th:src="@{/images/TacoCloud.png}"/>
      <a th:href="@{/design}" id="another">Design another taco</a><br/>

      <div th:if="${#fields.hasErrors()}">
        <span class="validationError">
        Please correct the problems below and resubmit.
        </span>
      </div>

      <h3>Deliver my taco masterpieces to...</h3>
      <label for="name">Name: </label>
      <input type="text" th:field="*{name}"/>
<!-- end::allButValidation[] -->
      <span class="validationError"
            th:if="${#fields.hasErrors('name')}"
            th:errors="*{name}">Name Error</span>
<!-- tag::allButValidation[] -->
      <br/>

      <label for="street">Street address: </label>
      <input type="text" th:field="*{street}"/>
<!-- end::allButValidation[] -->
      <span class="validationError"
            th:if="${#fields.hasErrors('street')}"
            th:errors="*{street}">Street Error</span>
<!-- tag::allButValidation[] -->
      <br/>

      <label for="city">City: </label>
      <input type="text" th:field="*{city}"/>
<!-- end::allButValidation[] -->
      <span class="validationError"
            th:if="${#fields.hasErrors('city')}"
            th:errors="*{city}">City Error</span>
<!-- tag::allButValidation[] -->
      <br/>

      <label for="state">State: </label>
      <input type="text" th:field="*{state}"/>
<!-- end::allButValidation[] -->
      <span class="validationError"
            th:if="${#fields.hasErrors('state')}"
            th:errors="*{state}">State Error</span>
<!-- tag::allButValidation[] -->
      <br/>

      <label for="zip">Zip code: </label>
      <input type="text" th:field="*{zip}"/>
<!-- end::allButValidation[] -->
      <span class="validationError"
            th:if="${#fields.hasErrors('zip')}"
            th:errors="*{zip}">Zip Error</span>
<!-- tag::allButValidation[] -->
      <br/>

      <h3>Here's how I'll pay...</h3>
<!-- tag::validatedField[] -->
      <label for="ccNumber">Credit Card #: </label>
      <input type="text" th:field="*{ccNumber}"/>
<!-- end::allButValidation[] -->
      <span class="validationError"
            th:if="${#fields.hasErrors('ccNumber')}"
            th:errors="*{ccNumber}">CC Num Error</span>
<!-- tag::allButValidation[] -->
<!-- end::validatedField[] -->
      <br/>

      <label for="ccExpiration">Expiration: </label>
      <input type="text" th:field="*{ccExpiration}"/>
<!-- end::allButValidation[] -->
      <span class="validationError"
            th:if="${#fields.hasErrors('ccExpiration')}"
            th:errors="*{ccExpiration}">CC Num Error</span>
<!-- tag::allButValidation[] -->
      <br/>

      <label for="ccCVV">CVV: </label>
      <input type="text" th:field="*{ccCVV}"/>
<!-- end::allButValidation[] -->
      <span class="validationError"
            th:if="${#fields.hasErrors('ccCVV')}"
            th:errors="*{ccCVV}">CC Num Error</span>
<!-- tag::allButValidation[] -->
      <br/>

      <input type="submit" value="Submit order"/>
    </form>

  </body>
</html>
<!-- end::allButValidation[] -->

I think you are not inserting the right information in the form according to validation rules added in the beans as explained in the chapter. 我认为您没有按照本章中解释的bean中添加的验证规则在表单中插入正确的信息。 By displaying the validation error, you will know exactly which input is not correctly inserted when you submit the order. 通过显示验证错误,您将确切地知道在提交订单时未正确插入哪个输入。


After investigating your code. 在调查你的代码之后。 The name of attributes in the Order.java are not the same as in the view page orderForm.html Order.java中的属性名称与视图页面orderForm.html中的属性名称不同

For example, in orderForm the attribute is name 例如,在orderForm中,属性是name

  <h3>Deliver my taco masterpieces to...</h3>
    <label for="name">Name: </label>
    <input type="text" th:field="*{name}"/>

Whereas in Order.java is deliveryName . 而Order.java中的是deliveryName

 @NotBlank(message="Delivery name is required")
    private String deliveryName;

The solution is to use the same name of the attribute in the Order.java and orderForm.html page. 解决方案是在Order.java和orderForm.html页面中使用相同的属性名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM