Spring 验证器未检测到错误

exo*_*nik 1 spring spring-mvc spring-boot

此代码创建一个 hmtl 表单,您可以在其中选择一些 chekcboxes 并设计一个 Taco。我正在尝试执行模型字段验证,但它不起作用。例如,如果名称的输入字段框为空或者根本没有选择任何复选框,则此代码应该返回错误。但控制器中的错误变量永远不会捕获任何错误。可能发生什么事情。这段代码是《Spring in Action》书中的复制粘贴示例,所以我不确定为什么它不起作用。

模型

@Data
public class Taco {

 @NotNull
 @Size(min=5, message = "Name must be at least 5 characters long")
 private String name;
 @Size(min=1, message = "You must choose at least 1 ingredient")
 private List<String> ingredients;
}
Run Code Online (Sandbox Code Playgroud)

控制器

@Slf4j
@Controller
@RequestMapping("/design")
public class DesignTacoController {

@GetMapping
public String showDesignFromModel(Model model){
    List<Ingredient> ingredients = Arrays.asList(
            new Ingredient("FLTO","Flour Tortilla", WRAP),
            new Ingredient("COTO","Corn Tortilla", WRAP),
            new Ingredient("GRBF","Ground Beef", PROTEIN),
            new Ingredient("CARN","Carnitas", PROTEIN),
            new Ingredient("TMTP","Diced Tomatoes", VEGGIES),
            new Ingredient("LETC","Lettuce", VEGGIES),
            new Ingredient("CHED","Cheddar", CHEESE),
            new Ingredient("JACK","Monterrey Jack", CHEESE),
            new Ingredient("SLSA","Salsa", SAUCE),
            new Ingredient("SRCR","Sour Cream", SAUCE)
    );


    Type[] types = Ingredient.Type.values();
    for (Type type : types){
        model.addAttribute(type.toString().toLowerCase(),
                ingredients.stream()
                        .filter(e -> e.getType() == type)
                        .collect(Collectors.toList()));

    }
    model.addAttribute("design",new Taco());
    return "design";
}

@PostMapping
public String processDesign(@Valid Taco design , Errors errors){
    if(errors.hasErrors()){
        System.out.println("Many errors " + errors);
        return "design";
    }
    System.out.println("Process design: " + design);
    System.out.println("No errors " + errors);
    log.info("Process design: " + design);
    return "redirect:/orders/current";
}
}
Run Code Online (Sandbox Code Playgroud)

看法

<!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>
<h1>Design your taco!</h1>
<img th:src="@{/images/TacoCloud.png}" alt="Taco Cloud Logo"/>
<form method="POST" th:object="${design}">
    <div class="grid">
        <div class="ingredient-group" id="wraps">
           <h3>Designate your wrap:</h3>
           <div th:each="ingredient : ${wrap}">
               <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
               <span th:text="${ingredient.name}">INGREDIENT</span><br/>
           </div>
        </div>
        <div class="ingredient-group" id="proteins">
            <h3>Pick your protein:</h3>
            <div th:each="ingredient : ${protein}">
                <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                <span th:text="${ingredient.name}">INGREDIENT</span><br/>
            </div>
        </div>
        <div class="ingredient-group" id="cheeses">
            <h3>Choose your cheese:</h3>
            <div th:each="ingredient : ${cheese}">
                <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                <span th:text="${ingredient.name}">INGREDIENT</span><br/>
            </div>
        </div>
        <div class="ingredient-group" id="veggies">
            <h3>Determine your veggies:</h3>
            <div th:each="ingredient : ${veggies}">
                <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                <span th:text="${ingredient.name}">INGREDIENT</span><br/>
            </div>
        </div>
        <div class="ingredient-group" id="sauces">
            <h3>Select your sauce:</h3>
            <div th:each="ingredient : ${sauce}">
                <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>
                <span th:text="${ingredient.name}">INGREDIENT</span><br/>
            </div>
        </div>
    </div>
    <div>
        <h3>Name your taco creation:</h3>
        <input type="text" th:field="*{name}"/>
        <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Error</span>
        <br/>
        <button>Submit your taco</button>
    </div>
</form>
</body>


</html>
Run Code Online (Sandbox Code Playgroud)

M. *_*num 6

当验证不起作用时,通常存在一件事不正确。javax.validation类路径上没有 API 的实现。validation-api仅向from添加依赖项javax.validation不会执行任何操作,因为这只是 API,而不是实际的实现。

您还需要添加一个实现,例如hibernate-validator。

现在,在 Spring Boot 的早期版本(2.3 之前)中,添加spring-boot-starter-web为依赖项时会自动包含验证。然而在较新的版本(2.3+)中,这已被删除。您现在需要显式包含 spring-boot-starter-validation启动器依赖项。这包括 API 和实现。

话虽这么说,也可能是类路径上有 Jakarta Validation API 及其实现(例如hibernate-validator版本 7 或更高版本),而不是 Java Validation API。Spring 或 Spring Boot 尚不支持 Jakarata Validation API(或大多数 JakartaEE API)。因此,即使您的类路径上有该 API,它也不起作用,您需要 Java Validation API。