我正在嘗試使用 html 和 thymeleaf 編輯用戶的角色。關鍵是一切正常,我可以編輯用戶名、密碼等,但是當涉及到角色時,保存串列時我得到空值。我在互聯網上找不到任何有用的東西,而且我已經為此苦苦掙扎了幾個星期,我需要一種方法來編輯這些角色,因此該頁面將回傳一個包含這些已檢查角色的串列。
這里我有用戶詳細資訊:
@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>
這是表單的圖片,這個用戶有user和admin兩個角色,進入頁面時都被檢查,但是如果我去更新,角色將被修改為null。你能幫我解決這個問題嗎?
https://i.stack.imgur.com/DWpRw.png
uj5u.com熱心網友回復:
映射不需要多對多,像這樣使用單向:
@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;
因為角色不需要參考它正在使用的相應用戶。然后讓表創建'user_role'。之后,如果您更改角色并保存用戶,它應該在 user_role 表中更新。
更新 回傳用戶時你能試試這個嗎:
@GetMapping(path = "/test")
@ResponseStatus(HttpStatus.OK)
public User test() {
User user = // get user here by id
//set roles there
return user;
}
uj5u.com熱心網友回復:
顯然我的問題是我正在將 MyUserInterface 類添加到 Model insted Of User。所以在控制器中我添加了這個:
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>
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/456727.html
