2
기본적으로 양식 제출의 양식 백업 오브젝트는 항상 null입니다. 누구나 이것이 왜 그렇게 볼 수 있습니까?Thymeleaf, Spring MVC 양식 제출시 양식 백업 오브젝트 누락 : null
저는 장치 목록을 표시하는 간단한 컨트롤러가 있습니다. 장치를 선택하고 기능을 적용 할 수 있습니다.
DeviceViewModel
@Entity //TODO: no connection between device and device details!
@Table(name="device")
public class Device {
@Id
@GeneratedValue
private Long id;
/**
* This is an external representation of the device, and the ID for which the device is most
* commonly searched for. The deviceID is a common reference point, used in T2 and in device reporting
* on the client side.
*/
@Column(name="device_id")
private String deviceId;
/**
* A reference to the store number or store identification. Stores may have more than one device.
*/
@Column(name="retailer_id")
private String retailerId;
/**
* The name of the store where the device is situated.
*/
@Column(name="retailer_name")
private String retailerName;
/**
* The current version of the client software, which launches the browser. This is only applicable to integrated solutions
*/
@Column(name="current_client_version")
private String currentClientVersion;
/**
* The target version of the client software, which launches the browser. This is only applicable to integrated solutions
*/
@Column(name="next_client_version")
private String nextClientVersion;
/**
* Commands to be performed on the client, used most often to "clear the cache". As soon as hte se commands are run, they
* are cleared from this column.
*/
@Column(name="commands")
private String commands;
@Column(name = "language")
private String language;
/**
* The signature is the client's position in the marketplace and used by other entities
* to determine their applicability to the device.
* RETAILER_GROUP:Tobaccoland|CHANNEL:Logistik|LOCALE:de-AT|INDUSTRY:5499
* The * notation means any, the locale is using the standard locale code (up to 10 characters)
* and the industry uses the merchant category codes, which in this case is
* Miscellaneous Food Stores - Convenience Stores and Specialty Markets
*/
@Column(name = "signature")
private String signature; //TODO: normalise?
/**
* This is the traceId that the device is currently up to
*/
@Column(name = "trace_id")
private Long traceId;
/**
* This is a tracing number that will be generated by touchpoint on each request.
*/
@Column(name = "last_trace_id")
private Long lastTraceId;
/**
* This is the transaction number that will come from Mercury in each response.
*/
@Column(name = "last_transaction_id")
private Long lastTransactionId;
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="device_role",
joinColumns = {@JoinColumn(name="device_id", referencedColumnName="id")},
inverseJoinColumns = {@JoinColumn(name="role_id", referencedColumnName="id")}
)
private List<Role> roles;
@ManyToMany(cascade= CascadeType.ALL, mappedBy = "devices", fetch = FetchType.LAZY)
private Set<User> users;
// getters, setters, equals, hashcode, omitted
}
및 DeviceMapper와 DeviceViewModel에 매핑된다 :
@Controller
@RequestMapping
public class DeviceListController {
private static final Logger LOG = LoggerFactory.getLogger(DeviceListController.class);
@Autowired
DeviceService deviceService;
@RequestMapping("/devices/list")
public String getDevicesPage(ModelMap model) {
int page = 0;
int size = 10;
if(model.get("deviceCommand") != null) {
DeviceCommand cmd = (DeviceCommand) model.get("deviceCommand");
page = cmd.getPage();
size = cmd.getSize();
}
Pageable pageRequest = new PageRequest(page, size);
Page<Device> devices = deviceService.findAllPaginated(pageRequest);
model.addAttribute("devices", DeviceMapper.map(devices));
model.addAttribute("deviceCommand", new DeviceCommand(page, size));
return "devices";
}
@RequestMapping("/devices/modify")
public String modifyDevices(ModelMap model) {
LOG.debug("Trying to get the device command {}.", model.get("deviceCommand"));
if(model.get("deviceCommand") != null) {
DeviceCommand cmd = (DeviceCommand) model.get("deviceCommand");
LOG.debug("Processing directives {} and {} for {}.", cmd.getNewVersion(),cmd.getNewCommand(),cmd.getDeviceModificationIds());
}
return getDevicesPage(model);
}
}
장치 모델 객체가 절전 엔티티 : 이것은 컨트롤러
public class DeviceViewModel {
private String id;
private String retailerName;
private String currentClientVersion;
private String nextClientVersion;
private String commands;
private boolean shallModify;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getRetailerName() {
return retailerName;
}
public void setRetailerName(String retailerName) {
this.retailerName = retailerName;
}
public String getCurrentClientVersion() {
return currentClientVersion;
}
public void setCurrentClientVersion(String currentClientVersion) {
this.currentClientVersion = currentClientVersion;
}
public String getNextClientVersion() {
return nextClientVersion;
}
public void setNextClientVersion(String nextClientVersion) {
this.nextClientVersion = nextClientVersion;
}
public String getCommands() {
return commands;
}
public void setCommands(String commands) {
this.commands = commands;
}
public boolean isShallModify() {
return shallModify;
}
public void setShallModify(boolean shallModify) {
this.shallModify = shallModify;
}
}
및 DeviceMapper :
지금public class DeviceMapper {
public static DeviceViewModel map(Device device) {
DeviceViewModel dto = new DeviceViewModel();
dto.setId(device.getDeviceId());
dto.setRetailerName(device.getRetailerName());
dto.setCurrentClientVersion(device.getCurrentClientVersion());
dto.setNextClientVersion(device.getNextClientVersion());
dto.setCommands(device.getCommands());
return dto;
}
public static List<DeviceViewModel> map(Page<Device> devices) {
List<DeviceViewModel> dtos = new ArrayList<>();
for(Device device : devices) {
dtos.add(map(device));
}
return dtos;
}
}
내 폼 지원 객체 인 DeviceCommand, :
public class DeviceCommand {
private List<String> deviceModificationIds;
private String newVersion;
private String newCommand;
private int page;
private int size;
public DeviceCommand() {}
public DeviceCommand(int page, int size) {
this.page = page;
this.size = size;
}
public List<String> getDeviceModificationIds() {
return deviceModificationIds;
}
public void setDeviceModificationIds(List<String> deviceModificationIds) {
this.deviceModificationIds = deviceModificationIds;
}
public String getNewVersion() {
return newVersion;
}
public void setNewVersion(String newVersion) {
this.newVersion = newVersion;
}
public String getNewCommand() {
return newCommand;
}
public void setNewCommand(String newCommand) {
this.newCommand = newCommand;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
과 마지막으로 devices.html 페이지의 관련 부분 : 양식 동작하지만
<form action="#" th:action="@{/devices/modify}" th:object="${deviceCommand}" method="post">
<table class="box-table-a">
<h1 th:text="#{device.table.caption}">Site Users</h1>
<thead>
<tr>
<th scope="col" th:text="#{device.check.label}">Select</th>
<th scope="col" th:text="#{device.id.label}">(<span th:text="${device.retailer.name.label}"></span>)</th>
<th scope="col" th:text="#{device.current.label}">Curr Version</th>
<th scope="col" th:text="#{device.next.label}">Next Version</th>
<th scope="col" th:text="#{device.commands.label}">Commands</th>
</tr>
</thead>
<tbody>
<tr th:each="d : ${devices}">
<td><input type="checkbox" th:field="*{deviceModificationIds}" th:value="${d.id}"/></td>
<td th:text="${d.id}">(<span th:text="${d.retailerName}"></span>)</td>
<td th:text="${d.currentClientVersion}">Washington</td>
<td th:text="${d.nextClientVersion}">gwash</td>
<td th:text="${d.commands}">gwash</td>
</tr>
<tr>
<td colspan="2">
</td>
<td th:text="#{device.change.version.label}"></td>
<td th:text="#{device.add.command.label}"></td>
<td></td>
</tr>
<tr>
<td colspan="2">
</td>
<td><input type="text" th:field="*{newVersion}"/></td>
<td><input type="text" th:field="*{newCommand}"/></td>
<td><button type="submit" th:text="#{device.modify.action.button}">Action</button></td>
</tr>
</tbody>
</table>
</form>
, 컨트롤러의 modifyDevices 메소드에 도달하지만 deviceCommand 양식 백업 객체는 null입니다.
왜 이렇게됩니까? 그 답이다 -
화려한를 찾을 수 있습니다처럼 그렇게 될 것이다
modifyDevices
방법에 유형
DeviceViewModel
의 매개 변수를 추가합니다. 사실, 나는 단지 @ModelAttribute 주석의 놀라운 점을 발견했다. –