Spring MVC использование формы: флажок для привязки данных - PullRequest
13 голосов
/ 02 января 2012

Я знаю, что по этой теме уже были вопросы, но я не понял, как решить следующую проблему:

У меня есть отношение пользователь / роли, и я хочу перечислить все доступные роли в JSP в качестве элементов флажков, где установлены назначенные пользователям флажки. Однако соответствующие элементы не проверяются (здесь я использую Spring 3.1).

Выписка из объекта User:

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

Извлечение из Spring Controller (добавление объекта пользователя и списка ролей в модель):

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, вход (флажок) помечается как «флажок», если в привязанной коллекции присутствует настроенное значение setValue (Object).

Разве это не так? Что мне здесь не хватает?

Большое спасибо.

Пол

1 Ответ

20 голосов
/ 04 января 2012

Полагаю, вам не хватает реализации методов equals и hashcode в классе RoleEntity .

Когда значение привязки имеет тип массив илиjava.util.Collection, вход (флажок) помечается как «флажок», если сконфигурированное значение setValue (Object) присутствует в связанной коллекции.

Это правильно, но для проверки на наличиев HashSet необходимо, чтобы equals и hashcode были реализованы правильно.

Чтобы быстро проверить, не в этом ли проблема, замените эту строку:

model.addAttribute("roleList", roleList);

на эту строку:

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

Получили ли вы все свои флажкипроверил?Если да, то вы не указали свои equals и hashcode, и используются значения по умолчанию (наследуемые от 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;
    }
}

Класс ролей ( обратите внимание на 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;
    }
}

Представление:

<%@ 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}" для своей формы: флажок, вы получите атрибуты HTML-флажка, такие как value="your.pack.age.declaration.RoleEntity@1", которые могут впоследствии привести к другим неприятностям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...