我正在尝试向我的表单添加代码端验证。我基于本教程:https://www.javacodegeeks.com/2017/10/validation-thymeleaf-spring.html-但无需付出任何努力。
我有一个实体InvoiceData:
@Data
@Document
@NoArgsConstructor
public class InvoiceData {
@Id private String id;
private ContractorData data;
@NotNull
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date receptionDate;
@NotNull
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date orderDate;
@NotNull
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date invoiceIssueDate;
@NotNull
@DateTimeFormat(pattern = "yyyy-MM-dd")
@NotNull
private Date contractDate;
@NotBlank
private String invoiceNumber;
private String additionalCosts;
private String contractorComment;
@NotEmpty
private List<InvoiceTask> invoiceTasks = new ArrayList<>();
和Controller方法:
@RequestMapping(value = "/addinvoice/{contractorId}", method = RequestMethod.POST, produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String addInvoice(@PathVariable("contractorId") String contractorId, @ModelAttribute @Valid InvoiceData data, Model model, BindingResult result, RedirectAttributes attr, HttpSession session) {
if (result.hasErrors()) {
System.out.println("BINDING RESULT ERROR");
attr.addFlashAttribute("org.springframework.validation.BindingResult.data", result);
attr.addFlashAttribute("register", result);
return "redirect:/add";
} else {
Contractor contractor = contractorRepository.findById(contractorId).get();
data.setData(contractor.getContractorData());
if (contractor.getInvoices() == null) {
contractor.setInvoices(new ArrayList<InvoiceData>());
}
contractor.getInvoices().add(data);
invoiceDataRepository.save(data);
contractorRepository.save(contractor);
model.addAttribute("contractor", contractor);
return "index";
}
}
还有一小块胸腺,以保持清晰(其他所有字段看起来都与此相似)
<form action="#" th:action="@{addinvoice/{id}(id=${contractorid})}" th:object="${invoicedata}" method="post">
<ul class="form-style-1">
<li>
<label>Reception date<span class="required">*</span></label>
<input type="date" th:field="*{receptionDate}" id="receptionDate">
</li>
问题是,当我尝试发送无效的表单时,我没有重定向到
/add
,但是却收到一个错误页面,提示:发生意外错误(类型=错误的请求,状态= 400)。
对象=“ invoiceData”的验证失败。错误计数:6
和stacktrace(出于清晰起见,仅来自一个字段):
字段'invoiceIssueDate'上的对象'invoiceData'中的字段错误:拒绝的值[null];代码[NotNull.invoiceData.invoiceIssueDate,NotNull.invoiceIssueDate,NotNull.java.util.Date,NotNull];参数[org.springframework.context.support.DefaultMessageSourceResolvable:代码[invoiceData.invoiceIssueDate,invoiceIssueDate];参数[];默认消息[invoiceIssueDate]];默认消息[不得为空]
因此,我认为这是我可以从验证程序中防止的行为之一。
但是有一件事,当我在控制器中设置断点时,在
if
语句开始的方法的开头,并且我发送了无效的表单,调试器永远不会在那里停止,因此似乎该代码永远不会停止。到达...但是当我发送正确填写的表格时-一切正常,代码可以正常工作,数据发送到数据库等。
我的问题是:这是验证程序的正常行为吗?当表单无效时,如何使代码运行,以便获得BindingResult并向用户显示错误输出?
最佳答案
您需要将BindingResult参数移到带有@Valid批注的参数旁边。
@RequestMapping(value = "/addinvoice/{contractorId}", method = RequestMethod.POST, produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String addInvoice(@PathVariable("contractorId") String contractorId, @ModelAttribute @Valid InvoiceData data, BindingResult result, Model model , RedirectAttributes attr, HttpSession session) {
if (result.hasErrors()) {
System.out.println("BINDING RESULT ERROR");
attr.addFlashAttribute("org.springframework.validation.BindingResult.data", result);
attr.addFlashAttribute("register", result);
return "redirect:/add";
} else {
Contractor contractor = contractorRepository.findById(contractorId).get();
data.setData(contractor.getContractorData());
if (contractor.getInvoices() == null) {
contractor.setInvoices(new ArrayList<InvoiceData>());
}
contractor.getInvoices().add(data);
invoiceDataRepository.save(data);
contractorRepository.save(contractor);
model.addAttribute("contractor", contractor);
return "index";
}
}
现在,BindingResult变量将附加到InvoiceData变量。同样,如果要验证API中的多个参数,则需要在所有这些参数旁边声明其对应的BindingResult变量。