我有一个对象,它可以有两个或三个重复的字段集。似乎最简单的处理方法是使用列表和一个表单,该表单将随着列表的大小而扩展或收缩。
不幸的是,我一直收到一个错误,提示Thymeleaf无法识别我试图绑定到主表单对象的变量。这个问题在this article中得到了解决,但由于某种原因,我无法得到相同的结果。
∮我所尝试的∮
DTO
package nathanLively.subAlignerjava.DTO;
import lombok.Builder;
import lombok.Data;
import nathanLively.subAlignerjava.Models.Enums.UnitsEnum;
import nathanLively.subAlignerjava.Models.PreAlignment;
import nathanLively.subAlignerjava.Models.Speaker;
import nathanLively.subAlignerjava.Models.UserAlignment;
import nathanLively.subAlignerjava.Models.UserAlignmentSource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Data
@Builder
public class UserAlignmentDTO {
private UnitsEnum units;
private List<UserAlignmentSourceDTO2> userAlignmentSources;
public UserAlignment toUserAlignment(PreAlignment preAlignment) {
Set<UserAlignmentSource> userAlignmentSourceList = userAlignmentSources.stream()
.map(UserAlignmentSourceDTO2::toUserAlignmentSource)
.collect(Collectors.toSet());
UserAlignment userAlignment = UserAlignment.builder()
.preAlignment(preAlignment)
.userAlignmentSources(userAlignmentSourceList)
.distanceUnit(units)
.build();
return userAlignment;
}
}
package nathanLively.subAlignerjava.DTO;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import nathanLively.subAlignerjava.Models.Enums.UnitsEnum;
import nathanLively.subAlignerjava.Models.PreAlignment;
import nathanLively.subAlignerjava.Models.PreAlignmentSource;
import nathanLively.subAlignerjava.Models.Speaker;
import nathanLively.subAlignerjava.Models.UserAlignmentSource;
@Data
@Builder
public class UserAlignmentSourceDTO2 {
private String modelName;
private Integer count;
private Float distance;
public UserAlignmentSource toUserAlignmentSource() {
UserAlignmentSource userAlignmentSource = UserAlignmentSource.builder()
// .speaker(speaker)
.count(count)
.distance(distance)
.build();
return userAlignmentSource;
}
}
控制器
package nathanLively.subAlignerjava.Controllers;
import lombok.RequiredArgsConstructor;
import nathanLively.subAlignerjava.DTO.UserAlignmentDTO;
import nathanLively.subAlignerjava.DTO.UserAlignmentSourceDTO;
import nathanLively.subAlignerjava.DTO.UserAlignmentSourceDTO2;
import nathanLively.subAlignerjava.Models.*;
import nathanLively.subAlignerjava.Models.Enums.UnitsEnum;
import nathanLively.subAlignerjava.Services.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@Controller
@RequiredArgsConstructor
@RequestMapping("/align")
public class AlignController {
@Autowired
private final BrandService brandService;
@Autowired
private final SpeakerModelService speakerModelService;
@Autowired
private final DspPresetService dspPresetService;
@Autowired
private final UserAlignmentService userAlignmentService;
@Autowired
private final SpeakerService speakerService;
@Autowired
private final PreAlignmentService preAlignmentService;
// Show pre-alignments
@GetMapping("/pre-alignments")
public String showPreAlignments(Model model) {
// Show pre-alignments in model
model.addAttribute("preAlignments", preAlignmentService.findAll());
return "pre-alignments";
}
// Add pre-alignment to user alignment
@GetMapping("/pre-alignment/{id}")
public String showUserAlignment(@PathVariable("id") Long preAlignmentId, Model model) {
// Find pre-alignment and add to model
PreAlignment preAlignment = preAlignmentService.findById(preAlignmentId);
model.addAttribute("preAlignment", preAlignment);
// Initialize UserAlignmentSourceDTO2
int numberOfPreAlignmentSources = preAlignment.getPreAlignmentSources().size();
List<UserAlignmentSourceDTO2> userAlignmentSourceDTO2s = new ArrayList<>();
for (int i = 0; i < numberOfPreAlignmentSources; i++) {
UserAlignmentSourceDTO2 userAlignmentSourceDTO2 = UserAlignmentSourceDTO2.builder()
.modelName(preAlignment.getPreAlignmentSources().get(i).getSpeaker().getSpeakerModel().getName())
.build();
userAlignmentSourceDTO2s.add(userAlignmentSourceDTO2);
}
// Initialize UserAlignmentDTO and add to model
UserAlignmentDTO userAlignmentDTO = UserAlignmentDTO.builder()
.userAlignmentSources(userAlignmentSourceDTO2s)
.build();
model.addAttribute("userAlignmentDTO", userAlignmentDTO);
// Show distance units in model
model.addAttribute("units", List.of(UnitsEnum.METERS, UnitsEnum.FEET));
return "user-alignment";
}
// Create UserAlignment and calculate result
@PostMapping("/calculate/{id}")
public String calculateUserAlignment(@PathVariable("id") Long preAlignmentId, @ModelAttribute("userAlignmentDTO") UserAlignmentDTO userAlignmentDTO, Model model) {
// Find pre-alignment
PreAlignment preAlignment = preAlignmentService.findById(preAlignmentId);
// preAlignment.getPreAlignmentSources().get(0)
// Convert UserAlignmentDTO to UserAlignment
UserAlignment userAlignment = userAlignmentDTO.toUserAlignment(preAlignment);
// Calculate result
// userAlignment.calculateResult();
// Save user alignment
userAlignmentService.save(userAlignment);
// Show result
model.addAttribute("userAlignment", userAlignment);
return "result";
}
Thymeleaf模板
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout}"
th:with="activeMenuItem='align'"
xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>User Alignment</title>
</head>
<body>
<div layout:fragment="page-content">
<h1>User-Alignment</h1>
<form id="source-form"
th:object="${userAlignmentDTO}"
th:action="@{/align/calculate/{id}(id=${preAlignment.id})}"
method="post">
<th:block th:each="source,iter : *{userAlignmentSources}">
<label th:text="${iter.index + 1} + '.'"></label>
<label>Total [[${source.modelName}]] in array:</label>
<input type="number"
th:field="*{userAlignmentSources[__${iter.index}__].count}">
<label>Distance from [[${source.modelName}]] to FOH:</label>
<input type="number"
th:field="*{userAlignmentSources[__${iter.index}__].distance}">
</th:block>
<label>Unit</label>
<select th:field="*{units}">
<option th:each="unit : ${units}"
th:text="${unit.fullName}"
th:value="${unit}">meters
</option>
</select>
<button type="submit">Align</button>
</form>
</div>
</body>
</html>
期望
我的期望是,当用户单击Align按钮时,表单将发送到端点并持久化到数据库。
错误
Invalid property 'userAlignmentSources[0]' of bean class [nathanLively.subAlignerjava.DTO.UserAlignmentDTO]: Illegal attempt to get property 'userAlignmentSources' threw exception
1条答案
按热度按时间jm81lzqq1#
看起来我错过了Thymeleaf的正确NoArgs构造函数。
来自chatGPT:
根据错误消息,UserAlignmentSourceDTO2类似乎没有默认构造函数。这意味着Thymeleaf在尝试将表单数据绑定到UserAlignmentDTO对象时无法创建此类的示例。