我目前正在开发一个简单的SpringMVC应用程序。我最近开始使用Spring-security。用户及其各自的角色保存在数据库中。我目前的任务是实现一个注册用户"形成。我使用简单的.jsp和spring形式。用户可以有两个角色:ROLE_USER和ROLE_ADMIN,默认情况下会检查ROLE_USER。
以下是我的AppUser和AppUserRoles模型。
AppUser.java:
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
@Entity
@Table(name="appusers")
public class AppUser {
@Id
@Column(name="USERNAME", unique = true, nullable = false, length = 45)
@NotEmpty(message="Username field cannot be empty")
private String username;
@Column(name="PASSWORD", nullable = false, length = 60)
@NotEmpty(message="Password field cannot be empty")
@Size(min=6,max=10,message="Password must be between 6 and 10 letters")
private String password;
@NotEmpty(message="The user must have at least one defined role")
@OneToMany(fetch = FetchType.LAZY, mappedBy = "appUser")
private Set<AppUserRole> userRole = new HashSet<AppUserRole>(0);
public AppUser() {
super();
}
public AppUser(String username, String password) {
super();
this.username = username;
this.password = password;
}
public AppUser(String username, String password, Set<AppUserRole> userRole) {
super();
this.username = username;
this.password = password;
this.userRole = userRole;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<AppUserRole> getUserRole() {
return userRole;
}
public void setUserRole(Set<AppUserRole> userRole) {
this.userRole = userRole;
}
}
AppUserRole.java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="appuser_roles")
public class AppUserRole {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "USER_ROLE_ID", unique = true, nullable = false)
private Integer userRoleId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "username", nullable = false)
private AppUser appUser;
@Column(name = "ROLE", nullable = false, length = 45)
private String role;
public AppUserRole() {
super();
}
public AppUserRole(AppUser appuser, String role) {
super();
this.appUser = appuser;
this.role = role;
}
public Integer getUserRoleId() {
return userRoleId;
}
public void setUserRoleId(Integer userRoleId) {
this.userRoleId = userRoleId;
}
public AppUser getAppuser() {
return appUser;
}
public void setAppuser(AppUser appuser) {
this.appUser = appuser;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
包含registerUser()方法的AppUserDAOImpl.java片段:
@Override
public void registerUser(AppUser appUser) {
sessionFactory.getCurrentSession().persist(appUser);
logger.info(appUser.getUsername() + " persisted");
}
与注册表单相关的UserController.java片段:
@RequestMapping(value="/register")
public String goRegister(Model model) {
model.addAttribute("AppUser", new AppUser());
return "register";
}
@RequestMapping(value= "/registeruser_action", method = RequestMethod.POST)
public String addUser(@ModelAttribute("AppUser") @Valid AppUser appUser, BindingResult result){
if(result.hasErrors()){
return "register";
}
appUserDetailsService.registerUser(appUser);
return "redirect:/menu";
}
register.jsp片段与实际形式:
<sf:form commandName="AppUser" action="registeruser_action" method="POST" >
<div>
Username:<br>
<sf:input type="text" path="username"/>
<sf:errors path="username" cssClass="errors"/>
</div>
<div>
Password<br>
<sf:input type="text" path="password"/>
<sf:errors path="password" cssClass="errors"/>
</div>
<div>
User role:<br>
<sf:checkbox path="userRole" value="ROLE_USER"
disabled="true" checked="true" /> User <br>
<sf:checkbox path="userRole" value="ROLE_ADMIN"/> Admin <br>
<sf:errors path="userRole" cssClass="errors"/>
</div>
<br>
<input type="submit" value="Submit">
</sf:form>
具体来说,我想做什么,似乎无法在网上找出或找到: 我希望将复选框选择添加到我的AppUser.java模型中设置的userRole,然后保留它们。问题是,我在项目之前已将表单输入映射到对象字段,但从未收集过。我的乐观主义者非常希望我能够通过将复选框映射到弹簧形式的userRole路径来实现它,也许java和spring会自动地#34;明白它应该将它们添加到该集合中。我的现实主义者知道它并非那么简单。老实说,我知道它非常简单,但我似乎无法找到解决方案。希望在这里找到解决方案。
PS:我只发布了我认为对这个问题很重要的内容。例如,服务层似乎是额外的。将根据需要发布额外的信息/代码。修改 好的,我按照akshay的建议在构造函数中添加了ROLE_USER。在尝试注册新用户时产生的异常让我意识到我完全错了。我试图将一个String分配给一个Set对象。 userRole的类型为Set,ROLE_USER是一个字符串。该集包含AppUserRole对象,其中应包含用户名和相应的角色字符串。基本上,现在的问题是:如何直接从spring形式添加包含用户名和相应角色的新对象到userRole集?
答案 0 :(得分:0)
好的,你需要做一些事情。
假设您要显示所有可用角色的列表:用户检查他想要分配给当前用户的那些角色。
当前Role是一个简单的String,因此没有任何内容可以将复选框绑定到。然后,您可以在视图层上创建一个包装器:
public class RoleWrapper{
private String roleName;
private boolean selected;
}
在您的控制器上,您要添加将加载所有可用角色的ModelAttribute。请注意,您无法绑定到原始集合,因此需要包装此列表。因此,创建另一个类来包装您的列表:
public class RoleList{
private List<RoleWrapper> roles;
}
在控制器中构造一个实例并设置为模型属性:
@ModelAttribute("availableRoles")
public RoleList getAvailableRoles(){
//load from db and construct list
}
在JSP中,创建一个由此列表支持的表单,并将复选框绑定到布尔字段:
<form:form modelAttribute="roleList" method="post">
<table>
<thead>
<tr>
<th style="width: 80%;">Role</th>
<th>Select</th>
</tr>
</thead>
<tbody>
<c:forEach items="${roleList.roles}"
var="role" varStatus="status">
<tr>
<td>role.name</td>
<td><form:checkbox
path="roles[${status.index}].selected" /></td>
</tr>
</c:forEach>
</tbody>
</table>
</form>
更新您的控制器以在提交时传递此列表。迭代并相应地设置用户角色:
@RequestMapping(value= "/registeruser_action", method = RequestMethod.POST)
public String addUser(@ModelAttribute("AppUser") @Valid AppUser appUser, @ModelAttribute("roleList") RoleList roleList, BindingResult result){
if(result.hasErrors()){
return "register";
}
for(RoleWrapper role : roleList.getRoles()){
if(role.isSelected()){
//add to user
}
}
appUserDetailsService.registerUser(appUser);
return "redirect:/menu";
}
关于您坚持的问题,您需要执行以下操作。向关系添加级联选项,如果持久保留非拥有方(在本例中为AppUser),请确保关系的两侧都已设置。您应该封装添加/删除操作以确保域对象之间的关系是一致的。因此:
@Entity
@Table(name="appusers")
public class AppUser {
@NotEmpty(message="The user must have at least one defined role")
@OneToMany(fetch = FetchType.LAZY, cascade = cascadeType.ALL, mappedBy = "appUser")
private Set<AppUserRole> userRoles = new HashSet<AppUserRole>(0);
/**
* Force clients through add/remove. Plus, do not provide setter.
*/
public Set<AppUserRole> getUserRoles() {
return Collections.unmodifiableSet(userRoles);
}
public void addRole(AppUserRole userRole){
userRole.setAppUser(this); //both sides set
userRoles.add(userRole);
}
public void removeRole(AppUserRole userRole){
userRoles.remove(userRole);
}
}