浏览 4510 次
锁定老帖子 主题:动态扩展struts-menu
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-01-18
前端时间把struts-menu扩展成动态从数据库中读取的方式,遇到了一些问题,归纳如下: 从上面的资料不难看出要动态构造sturts-menu菜单只需要构造出符合 struts-menu中需要用的menuComponent,并把这些menuComponen添加到 MenuRepository中,设置MenuRepository的displayers,并把MenuRepository 存入到容器中,那么只要在jsp中指定MenuRepository和displayer以及是否需要 权限控制即可以打印出菜单了。路子已经有了,第一部要做的就是构造这个list, 官方例子为了方便演示将持久层和业务层放在一起了,我是分开做的:构造自定义 的Menu对象,如下为所需的属性,struts-menu的menuComponent的属性要比这些多很多,需要的可以自己查查看。 Model层 Menu对象所需属性: private String parentName; private String name; private String title; private String description; private String location; private String roles; service层: 1)interface: public interface MenuManager { /** * 通过menuList构造MenuRepository来生成struts-menu * @return MenuRepository */ public MenuRepository getMenuRepository(); } 2)impl public class MenuManagerImpl implements MenuManager { private AcegiCacheManager acegiCacheManager; private ResourcesDao resourcesDao; public AcegiCacheManager getAcegiCacheManager() { return acegiCacheManager; } public void setAcegiCacheManager(AcegiCacheManager acegiCacheManager) { this.acegiCacheManager = acegiCacheManager; } public ResourcesDao getResourcesDao() { return resourcesDao; } public void setResourcesDao(ResourcesDao resourcesDao) { this.resourcesDao = resourcesDao; } /** * 从数据库中读取资源构造Menu的list对象 * @return menuList */ private List getMenuList(){ List menuList = new ArrayList(); Menu menu = null; Resources res = null; String roles; String parentId; String parentName; List ressList = resourcesDao.getResourcesByType(com.wonder.cdc.oa.service.security.Constants.RESOURCE_URL); if(ressList != null){ for(int i = 0; i < ressList.size(); i++){ res = (Resources)ressList.get(i); menu = new Menu(); if(!StringUtils.isBlank(res.getResource())){ roles = acegiCacheManager.getPrivsByResources(res.getResource()); }else{ roles = ""; } menu.setDescription(res.getDescription()); if(!StringUtils.isBlank(res.getResource())){ menu.setLocation(res.getResource()); } menu.setName(res.getName()); //如果为子类的情况下需存入父类的名字 if(res.getId().length() > 3){ parentId = res.getId().substring(0,res.getId().length() - 3); parentName = resourcesDao.findNameById(parentId); if(!StringUtils.isBlank(parentName)){ menu.setParentName(parentName); } } menu.setRoles(roles); menu.setTitle(res.getName()); menuList.add(menu); } } return menuList; } /** * @see com.wonder.cdc.oa.service.MenuManager#getMenuRepository() */ public MenuRepository getMenuRepository(){ MenuRepository repository = new MenuRepository(); List list = getMenuList(); for (int i=0; i < list.size(); i++) { MenuComponent menuComponent = new MenuComponent(); Menu menu = (Menu)list.get(i); String name = menu.getName(); menuComponent.setName(name); String parent = (String) menu.getParentName(); if (parent != null) { MenuComponent parentMenu = repository.getMenu(parent); if (parentMenu == null) { parentMenu = new MenuComponent(); parentMenu.setName(parent); repository.addMenu(parentMenu); } menuComponent.setParent(parentMenu); } String title = (String) menu.getTitle(); menuComponent.setTitle(title); String description = (String) menu.getDescription(); menuComponent.setDescription(description); String location = (String) menu.getLocation(); if(!StringUtils.isBlank(location)){ menuComponent.setLocation("/" + Constants.APP_NAME + location); } String roles = (String) menu.getRoles(); if(!StringUtils.isBlank(roles)){ menuComponent.setRoles(roles); } repository.addMenu(menuComponent); } return repository; } } 需要注意的,如果location为空则菜单项不显示,如果菜单项没有对应权限那么就不要设置setRoles,如果 setRoles为空字符串,而当前用户又没有空字符串的权限的话那么此菜单项也不显示。 现在数据都准备好了,在何处构造MenuRepository对象合适那? 我想到了3处,但是权衡利弊后我选择了第一项。 1.系统启动时 优点:响应快速 缺点:如果修改resources以及用户相关信息需重新启动系统后修改才可以生效或者修改resources的同时更新application范围内的 MenuRepository,后者导致增加代码量,增加日后系统维护、扩展的难度 疑问:如果在系统正式发布后菜单项不变的情况下是可行的,系统启动MenuRepository对象会常驻内存,仅需要1次访问数据库 2.用户登陆时 优点:菜单灵活度提高,菜单相关信息改变后的响应时间缩短,只需用户再次登陆就可以生效 缺点:每个用户登陆都要构造用户相对应的MenuRepository对象存在会话中,过度占用系统资源 3.定指标签,每个页面包含 优点:菜单灵活度提高,只需刷新页面即可获得最新的菜单项 缺点:每次刷新页面都会访问一次数据库,导致系统性能降低,当然可以通过cache来解决过渡访问数据库的问题,但同时也增加了代码量 我想针对不同的应用可以采取如上3种不同的解决方案(我认为的3种,应该会有更好的),针对我们目前的项目感觉采取第一种方案比较适合 启动时实现就非常的简单了,在实现了ServletContextListener的类的contextInitialized(ServletContextEvent event)中添加如下代码: MenuRepository defaultRepository = (MenuRepository) context.getAttribute(MenuRepository.MENU_REPOSITORY_KEY); MenuRepository mr = menuManager.getMenuRepository(); mr.setDisplayers(defaultRepository.getDisplayers()); context.setAttribute("repository",mr); 这里我遇到了一个问题,context.getAttribute(MenuRepository.MENU_REPOSITORY_KEY)这句返回的是个空 到网上查了一下(http://struts-menu.sourceforge.net/faq.html) 发现menu-config.xml文件是通过MenuContextListener加载的,查看了一下web.xml确实声明了这个listener. 我怀疑这里是否能加载上.继续看那个网页发现如果version在2.3以上(我的是2.4)可以通过spring的ioc容器来管理。 修改一下,重起,问题解决了。但是为什么通过listener的方式加载不了我还没有研究,正常来讲应该也是可以的。 剩下的就是页面了: 包含这句就可以了 java 代码
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |