使用复选框编辑用户的角色
Edit the roles of an user using checkboxes
我正在尝试使用 html 和 thymeleaf 编辑用户的角色。关键是一切正常,我可以编辑用户名、密码等,但是当涉及到角色时,我在保存列表时得到 null。我在互联网上找不到任何有用的东西,现在我已经为此苦苦挣扎了几个星期,我需要一种方法来编辑这些角色,因此该页面将 return 一个包含已检查角色的列表.
我这里有用户详细信息:
@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 +
'}';
}
}
这是角色 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;
}
控制器:
@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>
这里是带表格的图片,这个用户同时有user和admin两种角色,进入页面时都勾选了,但是如果我去update,角色会被修改为null。
你能帮我解决这个问题吗?
https://i.stack.imgur.com/DWpRw.png
映射不需要多对多,像这样使用单向:
@OneToMany(fetch = FetchType.EAGER,cascade = CascadeType.PERSIST)
@JoinTable(
name = "user_role",
joinColumns = @JoinColumn(
name = "user_id",
referencedColumnName = "id"
),
inverseJoinColumns = @JoinColumn(
name = "role_id",
referencedColumnName = "id"
))
private List<Role> roles;
因为一个角色不需要为它正在被使用的相应用户提供参考。然后创建 table 'user_role'。之后,如果您更改角色并保存用户,则应在 user_role table.
中更新
更新
返回用户时你能试试这个吗:
@GetMapping(path = "/test")
@ResponseStatus(HttpStatus.OK)
public User test() {
User user = // get user here by id
//set roles there
return user;
}
显然我的问题是我将 MyUserInterface class 添加到模型
insted 的用户。所以在控制器中我添加了这个:
MyUserDetails userDetails=userService.findUserById(id);
User user = userDetails.getUser();
现在 thymeleaf 可以直接访问用户列表。
<th:block th:each="role:${roleList}">
<input type="checkbox"
name="roles"
th:field="*{roles}"
th:value="${role.id}"
th:text="${role.name}" class="m-2"/>
</th:block>
我正在尝试使用 html 和 thymeleaf 编辑用户的角色。关键是一切正常,我可以编辑用户名、密码等,但是当涉及到角色时,我在保存列表时得到 null。我在互联网上找不到任何有用的东西,现在我已经为此苦苦挣扎了几个星期,我需要一种方法来编辑这些角色,因此该页面将 return 一个包含已检查角色的列表.
我这里有用户详细信息:
@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 +
'}';
}
}
这是角色 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;
}
控制器:
@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>
这里是带表格的图片,这个用户同时有user和admin两种角色,进入页面时都勾选了,但是如果我去update,角色会被修改为null。 你能帮我解决这个问题吗?
https://i.stack.imgur.com/DWpRw.png
映射不需要多对多,像这样使用单向:
@OneToMany(fetch = FetchType.EAGER,cascade = CascadeType.PERSIST)
@JoinTable(
name = "user_role",
joinColumns = @JoinColumn(
name = "user_id",
referencedColumnName = "id"
),
inverseJoinColumns = @JoinColumn(
name = "role_id",
referencedColumnName = "id"
))
private List<Role> roles;
因为一个角色不需要为它正在被使用的相应用户提供参考。然后创建 table 'user_role'。之后,如果您更改角色并保存用户,则应在 user_role table.
中更新更新 返回用户时你能试试这个吗:
@GetMapping(path = "/test")
@ResponseStatus(HttpStatus.OK)
public User test() {
User user = // get user here by id
//set roles there
return user;
}
显然我的问题是我将 MyUserInterface class 添加到模型 insted 的用户。所以在控制器中我添加了这个:
MyUserDetails userDetails=userService.findUserById(id);
User user = userDetails.getUser();
现在 thymeleaf 可以直接访问用户列表。
<th:block th:each="role:${roleList}">
<input type="checkbox"
name="roles"
th:field="*{roles}"
th:value="${role.id}"
th:text="${role.name}" class="m-2"/>
</th:block>