Spring Thymeleaf 表单复选框与集合映射示例

  • by

本文将一些代码示例,使用 Spring MVC 和 Thymeleaf 以 HTML 形式展示复选框。复选框的值与一个集合映射,该集合是模型类的字段。 例如要编写如下所示的用户表单:

一个用户可以有一个或多个角色,因此此表单中的“Roles”字段由多个复选框表示。

在数据库中,有 3 个表来实现用户和角色之间的多对多关系:

在 Java 代码中创建实体类 User:

package org.91tech
 
import java.util.*;
import javax.persistence.*
 
@Entity
@Table(name = "users")
public class User {
     
     
    @ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
    @JoinTable(
            name = "users_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id")
            )
    private Set<Role> roles = new HashSet<>();
     
}

可以看到 User 类中用 Set 来保存角色。下面编写 Role 类并重写 toString ,equals 和 hashCode 方法:

package org.91tech;
 
import javax.persistence.*;
 
@Entity
@Table(name = "roles")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
 
    // getters and setters are not shown
     
    @Override
    public String toString() {
        return this.name;
    }
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Role other = (Role) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }  
}

重写 toString 方法,是为了展示角色名称。重写 equals 和 hashCode 方法是为了表单处于编辑模式时,Spring MVC 和 Thymeleaf 能正确显示选中标记。

对于 Spring Data JPA 存储接口,即 UserRepository 和 RoleRepository,没什么特别的,我们不必编写这部分代码。

在 Spring MVC 控制器类中,需要对处理程序进行编码,创建新用户并编辑现有用户:

package org.91tech;
 
@Controller
public class UserController {
 
    @Autowired
    private UserServices service;
     
    @Autowired
    private RoleRepository roleRepository;
     
    @GetMapping("/users/new")
    public ModelAndView newUser() {
        User user = new User();
        ModelAndView mav = new ModelAndView("user_form");
        mav.addObject("user", user);
         
        List<Role> roles = (List<Role>) roleRepository.findAll();
         
        mav.addObject("allRoles", roles);
         
        return mav;    
    }  
     
    @GetMapping("/users/edit/{id}")
    public ModelAndView editUser(@PathVariable(name = "id") Integer id) {
        User user = service.get(id);
        ModelAndView mav = new ModelAndView("user_form");
        mav.addObject("user", user);
         
        List<Role> roles = (List<Role>) roleRepository.findAll();
         
        mav.addObject("allRoles", roles);
         
        return mav;
    }  
}

这里的关键点是将 Role 对象的集合添加到模型中:

List<Role> roles = (List<Role>) roleRepository.findAll();
mav.addObject("allRoles", roles);

在 Thymeleaf 的视图中,编写用于显示复选框的代码:

<form th:action="@{/users/save}" th:object="${user}" method="post">
<p>
    <label>Roles:
        <input type="checkbox" name="roles"
            th:each="role : ${allRoles}"
            th:text="${role.name}"
            th:value="${role.id}"
            th:field="*{roles}"
        />
    </label>
</p>
</form>

然后,在创建新 User 时,将显示带有角色名称的复选框。

不需要为保存用户编写任何特殊代码,因为 Spring MVC,Thymeleaf 和 Spring Data JPA 可以出色地完成自动持久化 User 对象和关联 Role 对象的工作。

在编辑模式下,它将根据用户和角色之间的关联正确显示复选框的选中状态。

⬅返回目录

发表评论

电子邮件地址不会被公开。 必填项已用*标注