转载

关于权限管理系统的设计问题和思考,以及其springbootjpa的实现方法

在项目中,通常会需要对用户的访问权限做一个限制和区分,即经典的 用户--角色--菜单 角色管理架构。在这个架构中,用户和角色的关系基本确定,即多对一的关系;而角色和菜单之前,其实还增加了“菜单操作”这样的操作权限,例如某个角色拥有的菜单操作权限如下图:

关于权限管理系统的设计问题和思考,以及其springbootjpa的实现方法

菜单和操作权限是一对多的关系,使用springbootjpa的实体类分别是

菜单:

@Entity
@Table(name = "menu", uniqueConstraints = { @UniqueConstraint(name = "idx_menuname", columnNames = { "menuName" }) })
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
public class Menu implements Serializable {
    private static final long serialVersionUID = -6499256046633708586L;

    @Id
    @Column(columnDefinition = "varchar(64) comment '菜单id'")
    private String menuId; // 菜单ID

    @Column(nullable = false, columnDefinition = "varchar(255) comment '菜单名称'")
    private String menuName; // 菜单名称

    @OneToMany(mappedBy = "menu", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<MenuHandle> menuHandles;//菜单操作权限
}

菜单操作权限:

@Entity
@Table(name = "menu_handle")
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
public class MenuHandle implements Serializable {
    private static final long serialVersionUID = -5909986386327673973L;

    @Id
    @Column(columnDefinition = "varchar(64) comment '操作权限id'")
    private String handleId; // 操作权限id

    @Column(nullable = false, columnDefinition = "varchar(255) comment '权限名称'")
    private String name; // 权限名称

    @ManyToOne(targetEntity = Menu.class)
    @JoinColumn(name = "menu_id", updatable = false)
    private Menu menu;//权限对应菜单
}

角色和菜单是多对多的关系,角色和操作也是多对多的关系

角色:

@Entity
@Table(name = "role", uniqueConstraints = { @UniqueConstraint(name = "idx_rolename", columnNames = { "roleName" }) })
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
public class Role implements Serializable {
    private static final long serialVersionUID = -5553646385121286353L;

    @Id
    @Column(columnDefinition = "varchar(64) comment '角色id'")
    private String roleId;

    @Column(nullable = false, columnDefinition = "varchar(255) comment '角色名称'")
    private String roleName;

    @ManyToMany
    private List<Menu> menus;//角色的菜单

    @ManyToMany
    private List<MenuHandle> roleMenuHandles;//角色的操作权限
}

那么在这个设计中,当我通过springbootjpa api查询某个角色时,角色的menus和roleMenuHandles就会无限循环级联查询,导致查询的对象生成不了正确的json。

我当前的做法是:在权限实体中重写toString方法:

@Override
    public String toString() {
        JSONObject jso = new JSONObject();
        jso.put("handleId", handleId);
        jso.put("name", name);
        jso.put("menuId", menu.getMenuId());
        return jso.toJSONString();
    }

如有更好的做法,欢迎补充。

原文  https://segmentfault.com/a/1190000021002991
正文到此结束
Loading...