Spring MVC使用form:checkbox绑定数据


问题内容

我知道有关此主题的问题已经存在,但是我还没有弄清楚如何解决以下问题:

我有一个用户/角色关系,我想列出JSP中的所有可用角色作为复选框,在其中选中了用户分配的复选框。但是,不检查匹配项(这里我使用的是Spring 3.1)。

从用户对象中提取:

private Set<RoleEntity> roles = new HashSet<RoleEntity>();

从Spring Controller中提取(将用户对象和角色列表添加到Model):

UserEntity userEntity = userEntityService.findById(UserEntity.class, new Long(id));
model.addAttribute("userAttribute", userEntity);

List<RoleEntity> roleList = roleEntityService.findAll();
model.addAttribute("roleList", roleList);

从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>

Spring
MVC文档说:当绑定值是array或java.util.Collection类型时,如果绑定的Collection中存在已配置的setValue(Object)值,则将input(checkbox)标记为“
checked”。

这里不是这样吗?我在这里想念什么?

非常感谢。

保罗


问题答案:

我的猜测是 您缺少 RoleEntity类上equalsand hashcode方法的实现

当绑定值的类型为array或java.util.Collection时,如果绑定的Collection中存在已配置的setValue(Object)值,则将input(checkbox)标记为“
checked”。

这是正确的,但是要检查HashSet您是否需要equalshashcode正确实施。

就像进行快速测试以查看是否是问题一样,替换此行:

model.addAttribute("roleList", roleList);

用这一行:

model.addAttribute("roleList", userEntity.getRoles());

您是否选中了所有复选框?如果是,则您没有提供您自己的equalshashcode而是使用默认值(继承自的默认值Object)。

缺省情况下equals比较身份,这意味着一个变量与另一个变量拥有相同的实例。平等意味着可以说两个不同的对象包含相同的状态或具有相同的含义。

使用model.addAttribute("roleList", userEntity.getRoles())触发器会默认equals方法返回true,因为列表和您检查列表中是否存在的值是相同的(两个相同的对象始终相等)。

但是在您的情况下,您将userEntityService.findById一个和roleEntityService.findAll另一个用于不同的对象。在这一点上,您必须使用适当的相等性测试而不是身份。

您已经equals/ hashcode实施了吗?

根据您的代码, 这是一个有效的示例:

控制器:

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";
    }
}

用户类别:

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;
    }
}

角色类(请 注意equalshashcode方法;如果删除它们,该示例将不再起作用):

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;
    }
}

视图:

<%@ 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>

PS关于JSP的一项观察。
如果您value="${role}"对form:checkbox进行操作,则将获得HTML复选框属性,例如value="your.pack.age.declaration.RoleEntity@1",稍后可能会给您带来其他麻烦的HTML复选框属性。