使用复选框编辑用户的角色

发布于 2025-01-18 00:29:15 字数 5140 浏览 0 评论 0原文

我正在尝试使用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。 你能帮我解决这个问题吗?

https://i.sstatic.net/dwprw.png

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?

https://i.sstatic.net/DWpRw.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

彼岸花ソ最美的依靠 2025-01-25 00:29:15

映射不需要是多对多,请使用单向,如下所示:

@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;
}

The mapping does not need to be many to many, Use a uni directional as this:

@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;

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:

@GetMapping(path = "/test")
@ResponseStatus(HttpStatus.OK)
public User test() {
    User user = // get user here by id
    //set roles there

    return user;
}
木落 2025-01-25 00:29:15

显然我的问题是我将 MyUserInterface 类添加到模型中
安装的用户。所以在控制器中我添加了以下内容:

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>

Apparently my problem was that I was adding the MyUserInterface class to the Model
insted Of User. So in the Controller I added this:

MyUserDetails userDetails=userService.findUserById(id);
User user = userDetails.getUser();

And now thymeleaf can get access to the list of the User directly.

 <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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文