项目需要做用户权限管理,管理的粒度只到菜单,这样就比较简单了。
数据库表设计:
用户------角色------权限
很通用的表设计。
因为菜单有父子的一个关系,所以在设计表的时候,也将父子关系设置其中。
表中的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); } } } } } }
如果大家遇到第二种情况,且不知如何处理的话,可以留言。