使用复选框编辑用户的角色
我正在尝试使用HTML和Thymeleaf编辑用户的角色。关键是一切正常,我可以编辑用户名,密码等,但是当涉及到角色时,保存列表时我会得到零。我在互联网上找不到任何有用的东西,并且我已经挣扎了几个星期,我需要一种编辑这些角色的方法,因此该页面将返回包含所检查角色的列表。
在这里,我有userDetails:
@Getter
@Setter
public class MyUserDetails implements UserDetails {
private final User user;
public MyUserDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getRoles().stream()
.map(role->new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
public int getId(){return this.user.getId();}
public User getUser(){
return this.user;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return user.isEnabled();
}
}
这是用户:
@Builder
@Getter
@Setter
@Entity
@Table(name="user",schema = "public")
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@Column(name="user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@NotEmpty(message = "You must provide a username!")
@Size(min=5, max=30)
private String username;
@NotEmpty(message = "You must provide a password!")
@ValidPassword
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private boolean enabled;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name="user_roles",
joinColumns = @JoinColumn(name="user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private List<Role> roles;
@JoinColumn(name="last_played")
private LocalDate lastPlayed;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
public List<String> getRoleNames(){
return roles.stream()
.map(Role::getName)
.collect(Collectors.toList());
}
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Reward> rewards;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", enabled=" + enabled +
", roles=" + roles +
", lastPlayed=" + lastPlayed +
", rewards=" + rewards +
'}';
}
}
这是角色类:
@Getter
@Setter
@Entity
@Table(name="role",schema = "public")
public class Role {
@Id
@Column(name="role_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
}
控制器:
@Controller
@RequiredArgsConstructor
public class EditUserController {
private final IUserDetailsService userService;
private final RoleService roleService;
@PostMapping(USERS_SAVE)
public String saveEdit( @ModelAttribute(AttributeNames.USER) User user,
BindingResult bindingResult){
if(bindingResult.hasErrors()){
return EDIT_USER;
}
userService.updateUser(user);
return REDIRECT+ USERS;
}
@GetMapping("/users/{id}")
public String editUser(@PathVariable int id, Model model){
List<Role> roleList = roleService.findAll();
UserDetails user = userService.findUserById(id);
model.addAttribute(AttributeNames.USER, user);
model.addAttribute(AttributeNames.ROLE_LIST, roleList);
return EDIT_USER;
}
@DeleteMapping(Mappings.USERS_DELETE_ID)
public String deleteUser(@PathVariable int id){
userService.deleteUser(id);
return REDIRECT+USERS;
}
}
最后是角色的HTML零件:
<div class="form-group row">
<label class="col-form-label col-4">Roles</label>
<div class="col-8">
<th:block th:each="role:${roleList}">
<input type="checkbox"
name="roles"
th:field="*{user.roles}"
th:value="${role.id}"
th:text="${role.name}" class="m-2"/>
</th:block>
</div>
</div>
这是带有表单的图片,此用户既有用户和admin的角色,又是两者都在输入页面时检查了两者,但是如果我要进行更新,则角色将被修改为null。 你能帮我解决这个问题吗?
I am trying to edit the Roles of an user using html and thymeleaf. The point is that everything works ok, I can edit the username, the password, etc but when it comes to the roles, I get null when saving the List. I can't find anything useful on the internet and I'm struggling with this for a couple of weeks now, I need a way to edit those roles, so the page will return a List containing those roles that are checked.
Here I have the UserDetails:
@Getter
@Setter
public class MyUserDetails implements UserDetails {
private final User user;
public MyUserDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getRoles().stream()
.map(role->new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
public int getId(){return this.user.getId();}
public User getUser(){
return this.user;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return user.isEnabled();
}
}
Here is the User:
@Builder
@Getter
@Setter
@Entity
@Table(name="user",schema = "public")
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@Column(name="user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@NotEmpty(message = "You must provide a username!")
@Size(min=5, max=30)
private String username;
@NotEmpty(message = "You must provide a password!")
@ValidPassword
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private boolean enabled;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name="user_roles",
joinColumns = @JoinColumn(name="user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private List<Role> roles;
@JoinColumn(name="last_played")
private LocalDate lastPlayed;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
public List<String> getRoleNames(){
return roles.stream()
.map(Role::getName)
.collect(Collectors.toList());
}
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Reward> rewards;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", enabled=" + enabled +
", roles=" + roles +
", lastPlayed=" + lastPlayed +
", rewards=" + rewards +
'}';
}
}
Here is the Role class:
@Getter
@Setter
@Entity
@Table(name="role",schema = "public")
public class Role {
@Id
@Column(name="role_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
}
The controller:
@Controller
@RequiredArgsConstructor
public class EditUserController {
private final IUserDetailsService userService;
private final RoleService roleService;
@PostMapping(USERS_SAVE)
public String saveEdit( @ModelAttribute(AttributeNames.USER) User user,
BindingResult bindingResult){
if(bindingResult.hasErrors()){
return EDIT_USER;
}
userService.updateUser(user);
return REDIRECT+ USERS;
}
@GetMapping("/users/{id}")
public String editUser(@PathVariable int id, Model model){
List<Role> roleList = roleService.findAll();
UserDetails user = userService.findUserById(id);
model.addAttribute(AttributeNames.USER, user);
model.addAttribute(AttributeNames.ROLE_LIST, roleList);
return EDIT_USER;
}
@DeleteMapping(Mappings.USERS_DELETE_ID)
public String deleteUser(@PathVariable int id){
userService.deleteUser(id);
return REDIRECT+USERS;
}
}
And finally the html part for the roles :
<div class="form-group row">
<label class="col-form-label col-4">Roles</label>
<div class="col-8">
<th:block th:each="role:${roleList}">
<input type="checkbox"
name="roles"
th:field="*{user.roles}"
th:value="${role.id}"
th:text="${role.name}" class="m-2"/>
</th:block>
</div>
</div>
Here is a picture with the form, this user has both roles of user and admin, and they are both checked when entering the page, but if I go for the update, the roles will be modified to null.
Can you help me figure this out?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
映射不需要是多对多,请使用单向,如下所示:
因为角色不需要拥有其所使用的相应用户的引用。然后创建表“user_role”。之后,如果您更改角色并保存用户,则应在 user_role 表中更新它。
更新
返回用户时您可以尝试一下吗:
The mapping does not need to be many to many, Use a uni directional as this:
Because a role does not need to have references for corresponding users it's being used by. Then have the table created 'user_role'. After that if you change roles and save the user it should be updated in user_role table.
UPDATE
Could you try this when returning user:
显然我的问题是我将 MyUserInterface 类添加到模型中
安装的用户。所以在控制器中我添加了以下内容:
现在 thymeleaf 可以直接访问用户列表。
Apparently my problem was that I was adding the MyUserInterface class to the Model
insted Of User. So in the Controller I added this:
And now thymeleaf can get access to the list of the User directly.