Spring MVC 使用表单 :checkbox to bind data

标签 spring spring-mvc

我知道已经有关于这个话题的问题,但我还没有想出如何解决以下问题:

我有一个用户/角色关系,我想将 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 文档是这样说的: 当绑定(bind)值是数组或 java.util.Collection 类型时,如果绑定(bind)的 Collection 中存在配置的 setValue(Object) 值,则输入(复选框)标记为“已选中”。

这里不是这样吗?我在这里错过了什么?

非常感谢。

保罗

最佳答案

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

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.

这是正确的,但要检查 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

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

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

用户类别:

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 类(注意 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>

附注只是对您的 JSP 的一项观察。 如果您为 form:checkbox 执行 value="${role}" 您将获得 HTML 复选框属性,例如 value="your.pack .age.declaration.RoleEntity@1" 以后可能会给你带来另一种麻烦。

关于Spring MVC 使用表单 :checkbox to bind data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8700339/

相关文章:

html - 如何防止 Tomcat 7/Spring/Tiles 修剪 HTML 输出的空格

java - 使用 JPA/Hibernate 过滤 DataSet 中的行

java - 如何配置 spring batch 作业模块化?

java - 如何在 apache camel + spring 中动态加载属性文件值

java - Hibernate - 使用@OneToMany 或@ManyToMany 定位未映射的类 : com. podro.model.Journey.roadWay[com.podro.model.RoadElement]

java - Spring Bean 范围

java - Spring Restful Service将所有url重定向到index.html

java - 我的坚持有什么问题吗?

java - 迁移到 Spring Boot 2 - 安全编码密码看起来不像 BCrypt

java - Cors 过滤器 - 允许所有子域