Spring Boot+Thymeleaf实现字段依赖校验:覆盖值需小于计算值
Spring Boot + Thymeleaf 实现覆盖值小于计算值的校验方案
一、后端校验(保障数据合法性)
后端校验是核心防线,可避免前端校验被绕过导致非法数据入库。
1. 实体类添加自定义校验逻辑
在表单对应的实体类中,通过@AssertTrue注解标记校验方法,实现覆盖值小于计算值的规则:
import javax.validation.constraints.NotNull; import javax.validation.constraints.AssertTrue; public class CalculationForm { @NotNull(message = "计算值不能为空") private Integer calculatedValue; private Integer overridingValue; // 自定义校验:覆盖值小于计算值,若覆盖值为空则默认合法 @AssertTrue(message = "覆盖值必须小于计算值") public boolean isOverridingValueValid() { if (calculatedValue == null) { return true; // 计算值为空的情况由@NotNull单独校验 } return overridingValue == null || overridingValue < calculatedValue; } // Getter & Setter public Integer getCalculatedValue() { return calculatedValue; } public void setCalculatedValue(Integer calculatedValue) { this.calculatedValue = calculatedValue; } public Integer getOverridingValue() { return overridingValue; } public void setOverridingValue(Integer overridingValue) { this.overridingValue = overridingValue; } }
2. Controller处理表单提交
在Controller中用@Valid触发校验,通过BindingResult捕获错误,返回表单页面展示错误信息:
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.PostMapping; import javax.validation.Valid; @Controller public class CalculationController { @GetMapping("/calculation") public String showForm(Model model) { model.addAttribute("calculationForm", new CalculationForm()); return "calculation-form"; } @PostMapping("/calculation") public String submitForm(@Valid CalculationForm calculationForm, BindingResult bindingResult) { if (bindingResult.hasErrors()) { // 校验失败,返回原表单展示错误 return "calculation-form"; } // 校验通过,执行业务逻辑 return "success"; } }
二、前端校验(提升用户体验)
前端实时校验能让用户在输入时立刻得到反馈,无需等待表单提交。
1. Thymeleaf页面渲染后端错误
在表单页面中,通过Thymeleaf的表单错误表达式展示后端返回的校验提示:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>计算表单</title> </head> <body> <form th:action="@{/calculation}" th:object="${calculationForm}" method="post"> <div> <label>计算值:</label> <input type="number" th:field="*{calculatedValue}" /> <span th:if="${#fields.hasErrors('calculatedValue')}" th:errors="*{calculatedValue}" style="color: red;"></span> </div> <div> <label>覆盖值:</label> <input type="number" th:field="*{overridingValue}" id="overridingInput" /> <span th:if="${#fields.hasErrors('overridingValue')}" th:errors="*{overridingValue}" style="color: red;"></span> <!-- 前端实时错误提示 --> <span id="frontError" style="color: red; display: none;">覆盖值必须小于计算值</span> </div> <button type="submit">提交</button> </form> <script> const calculatedInput = document.querySelector('[name="calculatedValue"]'); const overridingInput = document.querySelector('#overridingInput'); const frontError = document.querySelector('#frontError'); // 实时校验逻辑 function validate() { const calculatedVal = parseInt(calculatedInput.value); const overridingVal = parseInt(overridingInput.value); if (!isNaN(calculatedVal) && !isNaN(overridingVal) && overridingVal >= calculatedVal) { frontError.style.display = 'inline'; } else { frontError.style.display = 'none'; } } // 监听输入变化 calculatedInput.addEventListener('input', validate); overridingInput.addEventListener('input', validate); // 提交前二次校验 document.querySelector('form').addEventListener('submit', function(e) { validate(); if (frontError.style.display === 'inline') { e.preventDefault(); // 阻止非法提交 } }); </script> </body> </html>
补充说明
- 如果需要支持小数类型,只需将实体类中的
Integer改为Double,JS中替换parseInt为parseFloat即可; - 后端校验不可省略,即使做了前端校验,也必须保留后端校验来拦截非法请求。
内容的提问来源于stack exchange,提问作者Syed Iftekharuddin
相关产品推荐
相关产品推荐

