我在使用ThymeLeaf和javax验证来验证另一个对象内的对象列表时遇到问题。
从代码方面看,它看起来像这样。对于豆:
public class InvoiceData {
@Id private String id;
private ContractorData data;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date receptionDate;
private String invoiceNumber;
@NotEmpty(message = "Lista zadań nie może być pusta!")
private List<InvoiceTask> invoiceTasks = new ArrayList<>();
// getters, setters below
}
然后使用自定义验证程序:
@Component
public class InvoiceFormValidator implements Validator {
Logger logger = LoggerFactory.getLogger(InvoiceFormValidator.class);
@Override
public boolean supports(Class<?> clazz) {
return InvoiceData.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmpty(errors, "receptionDate", "empty");
ValidationUtils.rejectIfEmpty(errors, "invoiceNumber", "empty");
ValidationUtils.rejectIfEmpty(errors, "invoiceTasks", "empty");
}
}
现在使用InvoiceTask类:
@Data
@Builder
@Document
@AllArgsConstructor
public class InvoiceTask {
private String taskName;
private String project;
private BigDecimal hoursCount;
}
messages.properties中的某些消息与此处无关。
最后但并非最不重要的,控制器:
@RequestMapping(value = "/addinvoice", method = RequestMethod.POST, produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String addInvoice(@CurrentUser Contractor contractor, @ModelAttribute("invoicedata") @Validated InvoiceData invoicedata, BindingResult result, Model model, RedirectAttributes attr) {
if (result.hasErrors()) {
return "add";
} else {
invoicedata.setData(contractor.getContractorData());
// TODO check if we can remove the next 3 lines of code.
if (contractor.getInvoices() == null) {
contractor.setInvoices(new ArrayList<InvoiceData>());
}
contractor.getInvoices().add(invoicedata);
invoiceDataRepository.save(invoicedata);
contractorRepository.save(contractor);
model.addAttribute("contractor", contractor);
logger.info("Invoice number "+ invoicedata.getInvoiceNumber() +" with ID " + invoicedata.getId() + " created for Contractor with ID " + contractor.getId());
return "index";
}
}
现在可以使用Thymeleaf模板:它是基于<ul>
的{{1}},因此在这里我将为您提供有趣的片段以提高可读性:
<form>
现在,当我尝试向<li id="items">
<fieldset>
<div th:each="task, rowStat : ${invoicedata.invoiceTasks}">
<input th:field="${invoicedata.invoiceTasks[__${rowStat.index}__].taskName}" placeholder="Nazwa zadania" required> <input th:field="${invoicedata.invoiceTasks[__${rowStat.index}__].project}" placeholder="Projekt" required> <input type="number" th:field="${invoicedata.invoiceTasks[__${rowStat.index}__].hoursCount}" placeholder="Liczba godzin" required>
<button type="button" name="removeItem" th:value="${rowStat.index}">Remove task</button>
</div>
</fieldset>
<button type="button" name="addItem">Add task</button>
<script type="text/javascript">
function replaceItems (html) {
// Replace the <fieldset id="items"> with a new one returned by server.
$('#items').replaceWith($(html));
}
$('button[name="addItem"]').click(function (event) {
event.preventDefault();
var data = $('form').serialize();
// Add parameter "addItem" to POSTed form data. Button's name and value is
// POSTed only when clicked. Since "event.preventDefault();" prevents from
// actual clicking the button, following line will add parameter to form
// data.
data += '&addItem';
$.post('/add', data, replaceItems);
});
$('button[name="removeItem"]').click(function (event) {
event.preventDefault();
var data = $('form').serialize();
// Add parameter and index of item that is going to be removed.
data += '&removeItem=' + $(this).val();
$.post('/add', data, replaceItems);
});
</script>
</li>
<li>
<input type="submit" value="Save protocol" />
</li>
</ul>
添加这样的内容时:
<fieldset>
只是为了证明列表不为空,我什么也没有得到,也没有消息,并且得到这样的错误:
java.lang.IllegalStateException:既不绑定结果也不简单 可根据请求提供bean名称“ invoiceTasks”的目标对象 属性
更有趣的是,JavaScript停止正常运行。 “删除任务”按钮仍然可以正常工作,但是“添加任务”按钮完全停止工作...
尝试
<span class="error" th:if="${#fields.hasErrors('invoiceTasks')}" th:errors="*{invoiceTasks}">Generic error</span>
得到我:
<span class="error" th:if="${#fields.hasErrors('invoicedata.invoiceTasks')}" th:errors="*{invoicedata.invoiceTasks}">Generic error</span>
和
There was an unexpected error (type=Internal Server Error, status=500).
Exception evaluating SpringEL expression: "#fields.hasErrors('invoicedata.invoiceTasks')" (template: "add" - line 60, col 49)
是的,我还没有设置/ error页面。
所有其他验证器运行正常。
目标是能够验证org.springframework.beans.NotReadablePropertyException: Invalid property 'invoicedata' of bean class [com.look4app.generator.entity.InvoiceData]: Bean property 'invoicedata' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
对象内的3个字段,并验证InvoiceTask
列表,使其不为空。
是否有可能实现这一目标?