Spring MVC 使用 form:checkbox 绑定数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8700339/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring MVC usage of form:checkbox to bind data
提问by Paul Kuhn
I know there have been already questions around this topic, but I have not figured out how to solve the following issue:
我知道已经有关于这个主题的问题,但我还没有想出如何解决以下问题:
I have a user/roles relationship and I want to list all available roles in a JSP as checkbox items, where the users assigned checkboxes are selected. However, the matching items are not checked (here I am using Spring 3.1).
我有一个用户/角色关系,我想将 JSP 中的所有可用角色列为复选框项目,其中选择了分配给用户的复选框。但是,不会检查匹配的项目(这里我使用的是 Spring 3.1)。
Extract from the User object:
从 User 对象中提取:
private Set<RoleEntity> roles = new HashSet<RoleEntity>();
Extract from the Spring Controller (adding user object and role list to Model):
从 Spring Controller 中提取(将用户对象和角色列表添加到模型):
UserEntity userEntity = userEntityService.findById(UserEntity.class, new Long(id));
model.addAttribute("userAttribute", userEntity);
List<RoleEntity> roleList = roleEntityService.findAll();
model.addAttribute("roleList", roleList);
Extract from the JSP:
从 JSP 中提取:
<form:form modelAttribute="userAttribute" method="POST" action="${saveUrl}">
...
<table align="center">
<tr>
<td>ID</td>
<td>Role Name</td>
</tr>
<c:forEach items="${roleList}" var="role" varStatus="status">
<tr>
<td><form:checkbox path="roles" value="${role}" label="${role.id}" /></td>
<td><c:out value="${role.name}" /></td>
</tr>
</c:forEach>
</table>
...
</form:form>
The Spring MVC documentation says this: When the bound value is of type array or java.util.Collection, the input(checkbox) is marked as 'checked' if the configured setValue(Object) value is present in the bound Collection.
Spring MVC 文档是这样说的:当绑定值是数组或 java.util.Collection 类型时,如果绑定的集合中存在配置的 setValue(Object) 值,则输入(复选框)被标记为“已选中”。
Isn't that the case here? What am I missing here?
这里不是这样吗?我在这里缺少什么?
Thanks a lot.
非常感谢。
Paul
保罗
回答by Bogdan
My guess is you are missing the implementation for the equalsand hashcodemethods on the RoleEntity class.
我的猜测是您缺少RoleEntity 类上的equals和hashcode方法的实现。
When the bound value is of type array or java.util.Collection, the input(checkbox) is marked as 'checked' if the configured setValue(Object) value is present in the bound Collection.
当绑定值是数组或 java.util.Collection 类型时,如果绑定的集合中存在配置的 setValue(Object) 值,则输入(复选框)标记为“已选中”。
This is correct, but to check for presence in a HashSetyou need equalsand hashcodeimplemented correctly.
这是正确的,但要检查HashSet您需要equals并hashcode正确实施的存在。
Just as a quick test to see if that's the problem, replace this line:
就像快速测试以查看是否有问题一样,请替换此行:
model.addAttribute("roleList", roleList);
with this line:
用这一行:
model.addAttribute("roleList", userEntity.getRoles());
Do you get all your checkboxes checked? If yes, then you didn't provide your own equalsand hashcodeand the default ones are used (those inherited from Object).
您是否检查了所有复选框?如果是,那么您没有提供自己的equals,hashcode并且使用了默认的(继承自 的那些Object)。
The default equalscompares identity which means that a variable holds the same instance as another variable. Equality means two different object contain the same state or have the same meaning, so to speak.
默认equals比较身份,这意味着一个变量与另一个变量拥有相同的实例。平等意味着两个不同的对象包含相同的状态或具有相同的含义,可以这么说。
Using model.addAttribute("roleList", userEntity.getRoles())triggers the default equalsmethod to return true because the list and values you check for presence in the list are identical (two identical objects are always equal).
使用model.addAttribute("roleList", userEntity.getRoles())会触发默认equals方法返回 true,因为您检查列表中是否存在的列表和值是相同的(两个相同的对象始终相等)。
But in your case you use userEntityService.findByIdfor one and roleEntityService.findAllfor the other which means different objects. At this point you have to use a proper equality test as opposed to identity.
但是在您的情况下,您使用userEntityService.findByIdfor one 和roleEntityService.findAllfor other 这意味着不同的对象。在这一点上,您必须使用适当的相等性测试而不是身份。
Do you have equals/hashcodeimplemented?
你有equals/hashcode实施了吗?
Based on your code, here is an example that works:
根据您的代码,这是一个有效的示例:
Controller:
控制器:
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class SomeController {
@RequestMapping(value = "/something", method = { RequestMethod.GET, RequestMethod.POST })
public String handle(Model model) {
UserEntity userEntity = new UserEntity();
userEntity.setRoles(new HashSet<RoleEntity>());
Collections.addAll(userEntity.getRoles(),
new RoleEntity(1, "one"),
new RoleEntity(3, "three"));
model.addAttribute("userAttribute", userEntity);
List<RoleEntity> roleList = Arrays.asList(
new RoleEntity(1, "one"),
new RoleEntity(2, "two"),
new RoleEntity(3, "three")
);
model.addAttribute("roleList", roleList);
return "view";
}
}
User class:
用户类:
import java.util.HashSet;
import java.util.Set;
public class UserEntity {
private Set<RoleEntity> roles = new HashSet<RoleEntity>();
public Set<RoleEntity> getRoles() {
return roles;
}
public void setRoles(Set<RoleEntity> roles) {
this.roles = roles;
}
}
Roles class (notice the equalsand hashcodemethods; if you remove them, the example no longer works):
Roles 类(注意equals和hashcode方法;如果删除它们,示例将不再有效):
public class RoleEntity {
private long id;
private String name;
@Override
public int hashCode() {
return new Long(id).hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (! (obj instanceof RoleEntity)) {
return false;
}
return this.id == ((RoleEntity)obj).getId();
}
public RoleEntity(long id, String name) {
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
View:
看法:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<form:form modelAttribute="userAttribute" method="POST" action="/something">
<table align="center">
<tr>
<td>ID</td>
<td>Role Name</td>
</tr>
<c:forEach items="${roleList}" var="role">
<tr>
<td><form:checkbox path="roles" value="${role}" label="${role.id}" /></td>
<td><c:out value="${role.name}" /></td>
</tr>
</c:forEach>
</table>
</form:form>
P.S. Just one observation about your JSP.If you do value="${role}"for your form:checkbox you will get HTML checkbox attributes like value="your.pack.age.declaration.RoleEntity@1"which might get you in another sort of trouble later on.
PS 只是对您的 JSP 的一项观察。如果你value="${role}"为你的 form:checkbox做,你会得到 HTML checkbox 属性,比如value="your.pack.age.declaration.RoleEntity@1"这可能会让你以后遇到另一种麻烦。

