项目需要做用户权限管理,管理的粒度只到菜单,这样就比较简单了。
数据库表设计:
用户------角色------权限
很通用的表设计。
因为菜单有父子的一个关系,所以在设计表的时候,也将父子关系设置其中。
表中的func_id代表的是菜单ID,parent代表的是上级ID.
接下来谈谈如何控制菜单,有两种情况:
第一种:配置文件中,已经配置好所有的菜单项,那么就只需要控制这些菜单项的Visible属性即可。
第二种:配置文件中,未配置菜单项,那么就根据用户权限中的数据,硬编码手动创建这些菜单项。
我的项目中,用到的是第一种方法。
好了,废话不多说,切入正题。
首先,要在登陆后,跳转到一个地方,让我来处理权限功能,(也可以写在登陆代码后面),创建一个model,供我使用。
在plugin.xml 中添加一个节点:org.eclipse.e4.workbench.model,再添加一个处理程序,这个程序就是权限控制的处理类。
选择你处理的类。
在处理类中,需要获得Main Menu,所以,需要添加一个参数,参数的ID就是Application.e4xmi中Main Menu中的ID。
这样配置好了的话,在程序启动时,就会触发这个处理器,在处理器中进行权限的控制。
@SuppressWarnings("all")
public class MenuFilterHandler {
@Inject
@Named("menu:omse4client.main.menu")
private MMenu mMenu; //获得Main Menu
private Users users; //登陆用户信息
@Inject
private UserClientDao clientDao;
@Inject
private FuncClientDao funcClientDao;
private Map<String,Func> funcMaps,addFuncMaps;
@Execute
/**
* 获得用户权限,将所有权限保存在funcMaps中,循环迭代系统中已配置好的菜单,如果菜单ID在funcMaps中不存在,那么就将该菜单的visible属性设置为false,
* 如果遇到下级菜单,就将下级菜单继续迭代.
*/
private void filter(){
funcMaps = new HashMap<String, Func>();
addFuncMaps = new HashMap<String, Func>();
//获得登陆用户的权限
Object object = clientDao.queryCurrentUser();
if(null == object){
MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "提示", "当前用户不存在或未分配角色权限,请与系统管理员联系");
System.exit(0);
return;
}
users = (Users) object;
List<Role> roles = users.getRoles();
//一个用户可能拥有多个角色
for (Iterator<Role> iterator2 = roles.iterator(); iterator2.hasNext();) {
Role role = (Role) iterator2.next();
List<Func> funcs = role.getFuncs();
//角色对应多个权限
for (Iterator<Func> iterator3 = funcs.iterator(); iterator3.hasNext();) {
Func func = (Func) iterator3.next();
//如果用户角色权限有重复的地方,用HashMap保存的话,可以起到去重的一个效果
funcMaps.put(func.getFuncId(), func);
}
}
/**
* mMenu.getChildren()返回的是一个List<MMenuElement>
* MMenuElement无法获取到下一级,在DEBUG时,发现可以看到它的下一级数据,然而它的数据类型是:EObjectContainmentWithInverseEList
* 所以,进行了一下强制类型转换
*/
EObjectContainmentWithInverseEList<?> elements = (EObjectContainmentWithInverseEList<?>) mMenu.getChildren();
for (Iterator<?> iterator = elements.iterator(); iterator.hasNext();) {
Object object1 = (Object) iterator.next();
MMenuElement element = (MMenuElement) object1;
/**
* addFuncMaps 中保存的是配置文件中可视的所有的菜单项
* 初始化数据库中权限的数据
*/
if(element.isVisible()){
Func func = getFunc(element.getElementId(),element.getLabel(),element.getElementId());
addFuncMaps.put(element.getElementId(),func);
iteratorMenu(object1);
}
}
funcClientDao.insertFunc(addFuncMaps);
}
private Func getFunc(String funcId,String name,String parentId){
Func func = new Func();
func.setFuncId(funcId);
func.setName(name);
func.setParent(parentId);
return func;
}
/**
* 迭代菜单项
* @param object
*/
private void iteratorMenu(Object object){
if(null!=object){
/**
* 菜单下可能会出现下级菜单,也有可能出现处理菜单项
* 所有这个地方做了一个判断,如何使下级菜单,那么就对下级菜单进行迭代
*/
if(object instanceof MenuImpl){
MenuImpl element = (MenuImpl) object;
if(element.isVisible()){
Func func = getFunc(element.getElementId(),element.getLabel(),element.getParent().getElementId());
addFuncMaps.put(element.getElementId(),func);
//判断用户权限中是否包含此菜单项,将未包含的菜单项的visible属性设置为:false
if(!funcMaps.containsKey(element.getElementId())){
element.setVisible(false);
}
EObjectContainmentWithInverseEList<?> elements = (EObjectContainmentWithInverseEList<?>) element.getChildren();
for (Iterator<?> iterator = elements.iterator(); iterator.hasNext();) {
Object object2 = (Object) iterator.next();
iteratorMenu(object2);
}
}
}else if(object instanceof HandledMenuItemImpl){
HandledMenuItemImpl element = (HandledMenuItemImpl) object;
if(element.isVisible()){
Func func = getFunc(element.getElementId(),element.getLabel(),element.getParent().getElementId());
addFuncMaps.put(element.getElementId(),func);
if(!funcMaps.containsKey(element.getElementId())){
element.setVisible(false);
}
}
}
}
}
}
上面提到,有两种情况,我这是第一种情况下的处理方式。
如果大家遇到第二种情况,且不知如何处理的话,可以留言。