就是图中的菜单是动态添加,就是每次在数据库里读取菜单,不在配置文件里读取,这个要如何实现,请求大神解答一下,谢谢
放到数据库里去,然后重写若干代码,我正在干这个事!
1 个赞
没有现成的示例,理论上是可以实现的。
如果只是需要简单地动态添加菜单,可扩展 AppMainWindow 类,然后使用这个类上定义的 mainMenu 实现动态添加菜单。
mainMenu.addMenuItem
大神给我贴个代码参考一下,感谢了大神
思路如下:
平台是读取的XML来生产菜单,为了尽量少侵入现有的代码,我现在是先从数据库读取后,然后产生XML的Document对象给平台来生成菜单,这样权限那边的代码可以不需要改。主要代码如下供参考:
1、定义了Menu实体用来在数据库里保存菜单和菜单项
@NamePattern("#getNP|code,caption")
@Table(name = "YDZH_MENU")
@Entity(name = "ydzh_Menu")
public class Menu extends BaseEntity {
private static final long serialVersionUID = -3388382443199117731L;
@NotNull
@Column(name = "CODE",unique = true, nullable = false,length = 32)
protected String code;
@Column(name = "CAPTION", length = 64)
protected String caption;
@Column(name = "ICON", length = 128)
protected String icon;
@Column(name = "DESCRIPTION", length = 128)
protected String description;
@Column(name = "STYLENAME", length = 128)
protected String stylename;
@Column(name = "SEPARATOR")
protected Boolean separator;
@Column(name = "INSERTBEFORE", length = 32)
protected String insertBefore;
@Column(name = "INSERTAFTER", length = 32)
protected String insertAfter ;
@Column(name = "SCREEN", length = 64)
protected String screen;
@Column(name = "BEAN", length = 64)
protected String bean;
@Column(name = "BEANMETHOD", length = 64)
protected String beanMethod;
@Column(name = "RUNCLASS", length = 64)
protected String runClass;
@Column(name = "RESIZABLE")
protected Boolean resizable;
@Column(name = "OPENTYPE", length = 8)
protected String openType;
@Column(name = "SHORTCUT", length = 32)
protected String shortcut;
@NotNull
@Column(name = "ITEM", nullable = false)
protected Boolean item=false;
@Column(name = "SORT")
protected Double sort=0D;
@Lookup(type = LookupType.DROPDOWN)
@OnDeleteInverse(DeletePolicy.DENY)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARENT_ID")
protected Menu parent;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCaption() {
return caption;
}
public void setCaption(String caption) {
this.caption = caption;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getStylename() {
return stylename;
}
public void setStylename(String stylename) {
this.stylename = stylename;
}
public String getInsertBefore() {
return insertBefore;
}
public void setInsertBefore(String insertBefore) {
this.insertBefore = insertBefore;
}
public String getInsertAfter() {
return insertAfter;
}
public void setInsertAfter(String insertAfter) {
this.insertAfter = insertAfter;
}
public Menu getParent() {
return parent;
}
public void setParent(Menu parent) {
this.parent = parent;
}
public Boolean getSeparator() {
return separator;
}
public void setSeparator(Boolean separator) {
this.separator = separator;
}
public MenuItemOpenType getOpenType() {
return openType==null?null: MenuItemOpenType.fromId(openType);
}
public void setOpenType(MenuItemOpenType openType) {
this.openType = openType==null?null:openType.getId();
}
public String getScreen() {
return screen;
}
public void setScreen(String screen) {
this.screen = screen;
}
public String getBean() {
return bean;
}
public void setBean(String bean) {
this.bean = bean;
}
public String getBeanMethod() {
return beanMethod;
}
public void setBeanMethod(String beanMethod) {
this.beanMethod = beanMethod;
}
public String getRunClass() {
return runClass;
}
public void setRunClass(String runClass) {
this.runClass = runClass;
}
public Boolean getResizable() {
return resizable;
}
public void setResizable(Boolean resizable) {
this.resizable = resizable;
}
public String getShortcut() {
return shortcut;
}
public void setShortcut(String shortcut) {
this.shortcut = shortcut;
}
public Boolean getItem() {
return item;
}
public void setItem(Boolean item) {
this.item = item;
}
public Double getSort() {
return sort;
}
public void setSort(Double sort) {
this.sort = sort;
}
public String getNP(){
Messages messages= AppBeans.get("cuba_Messages");
String result=messages.getMainMessage("menu-config."+ code);
if (result.equals("menu-config."+ code))
return caption;
else
return result;
}
public enum MenuItemOpenType implements EnumClass<String> {
/**
* Open a screen in new tab of the main window.
* <br> In Web Client with {@code AppWindow.Mode.SINGLE} the new screen replaces current screen.
*/
NEW_TAB("NEW_TAB"),
/**
* Open a screen on top of the current tab screens stack.
*/
THIS_TAB("THIS_TAB"),
/**
* Open a screen as modal dialog.
*/
DIALOG("DIALOG"),
/**
* In Desktop Client open a screen in new main window, in Web Client the same as new {@link #NEW_TAB}
*/
NEW_WINDOW("NEW_WINDOW"),
/**
* In Web Client opens a screen as main
*/
ROOT("ROOT");
private String id;
MenuItemOpenType(String id) {
this.id = id;
}
@Override
public String getId() {
return id;
}
public static MenuItemOpenType fromId(String id) {
for (MenuItemOpenType openType : MenuItemOpenType.values()) {
if (openType.getId().equals(id))
return openType;
}
return null;
}
}
2、覆盖平台的MenuConfig类,覆盖checkInitialized、getItemCaption、init
public class DBMenuConfig extends MenuConfig {
private final Logger log = LoggerFactory.getLogger(DBMenuConfig.class);
private HashMap<String,String> menuCaptions=new HashMap<>();
@Inject
private DataManager dataManager;
@Override
protected void checkInitialized(){
super.checkInitialized();
//始终加载菜单
initialized=false;
}
@Override
public String getItemCaption(String id) {
if (menuCaptions.containsKey(id))
return menuCaptions.get(id);
else
return super.getItemCaption(id);
}
@Override
protected void init() {
rootItems.clear();
menuCaptions.clear();
String configName = AppContext.getProperty(MENU_CONFIG_XML_PROP);
//去掉应用的本地菜单配置,改从数据库读取
configName=configName.lastIndexOf(" ")>0?configName.substring(0,configName.lastIndexOf(" ")):"";
if (!StringUtils.isEmpty(configName)) {
StringTokenizer tokenizer = new StringTokenizer(configName);
for (String location : tokenizer.getTokenArray()) {
Resource resource = resources.getResource(location);
if (resource.exists()) {
try (InputStream stream = resource.getInputStream()) {
Element rootElement = Dom4j.readDocument(stream).getRootElement();
loadMenuItems(rootElement, null);
} catch (IOException e) {
throw new RuntimeException("Unable to read menu config", e);
}
} else {
log.warn("Resource {} not found, ignore it", location);
}
}
}
try {
//获取根菜单
List<KeyValueEntity> menus=dataManager.loadValues("select e.id, e.code,e.caption, e.icon,e.description,e.stylename,e.separator,e.insertBefore,e.insertAfter from ydzh_Menu e where e.item=false and e.parent.id in (select p.id from ydzh_Menu p where p.parent is null) order by e.sort, e.createTs")
.properties("id","code","caption","icon","description","stylename","separator","insertBefore","insertAfter")
.list();
if (menus.size()>0) {
Document document = DocumentHelper.createDocument();
Element config = document.addElement("menu-config");
for (KeyValueEntity e : menus) {
Boolean separator= (Boolean) e.getValue("separator");
if (separator!=null && separator){
config.addElement("separator");
}
Element menu = config.addElement("menu");
String id= (String) e.getValue("code");
menu.addAttribute("id",id);
String caption = (String) e.getValue("caption");
if (!StringUtils.isEmpty(caption))
menuCaptions.put(id,caption);
String icon = (String) e.getValue("icon");
if (!StringUtils.isEmpty(icon))
menu.addAttribute("icon", icon);
String description = (String) e.getValue("description");
if (!StringUtils.isEmpty(description))
menu.addAttribute("description", description);
String stylename = (String) e.getValue("stylename");
if (!StringUtils.isEmpty(stylename))
menu.addAttribute("stylename", stylename);
String insertBefore = (String) e.getValue("insertBefore");
if (!StringUtils.isEmpty(insertBefore))
menu.addAttribute("insertBefore", insertBefore);
String insertAfter = (String) e.getValue("insertAfter");
if (!StringUtils.isEmpty(insertAfter))
menu.addAttribute("insertAfter", insertAfter);
UUID parentId=(UUID)e.getValue("id");
loadSubMenu(menu,parentId);
}
log.debug("菜单内容:\n"+ Dom4jUtils.toXMLString(document));
//加载菜单
loadMenuItems(document.getRootElement(), null);
}
} catch (Exception e) {
throw new RuntimeException("Unable to read DBMenu config", e);
}
}
private void loadSubMenu(Element parentMenu,UUID parentId){
//获取菜单
List<KeyValueEntity> menus=dataManager.loadValues("select e.id, e.code,e.caption,e.icon,e.description,e.stylename,e.separator,e.insertBefore,e.insertAfter,e.openType,e.screen,e.bean,e.beanMethod,e.runClass,e.item from ydzh_Menu e where e.parent.id=:parentId order by e.sort, e.createTs")
.properties("id","code","caption","icon","description","stylename","separator","insertBefore","insertAfter","openType","screen","bean","beanMethod","runClass","item")
.parameter("parentId",parentId)
.list();
for (KeyValueEntity e : menus) {
Boolean isItem= (Boolean) e.getValue("item");
Boolean separator= (Boolean) e.getValue("separator");
if (separator!=null && separator){
parentMenu.addElement("separator");
}
if (isItem){
//菜单项
Element item = parentMenu.addElement("item");
String id= (String) e.getValue("code");
item.addAttribute("id",id);
String caption = (String) e.getValue("caption");
if (!StringUtils.isEmpty(caption))
menuCaptions.put(id,caption);
String icon = (String) e.getValue("icon");
if (!StringUtils.isEmpty(icon))
item.addAttribute("icon", icon);
String description = (String) e.getValue("description");
if (!StringUtils.isEmpty(description))
item.addAttribute("description", description);
String stylename = (String) e.getValue("stylename");
if (!StringUtils.isEmpty(stylename))
item.addAttribute("stylename", stylename);
String insertBefore = (String) e.getValue("insertBefore");
if (!StringUtils.isEmpty(insertBefore))
item.addAttribute("insertBefore", insertBefore);
String insertAfter = (String) e.getValue("insertAfter");
if (!StringUtils.isEmpty(insertAfter))
item.addAttribute("insertAfter", insertAfter);
String openType = (String) e.getValue("openType");
if (!StringUtils.isEmpty(openType))
item.addAttribute("openType", openType);
String screen = (String) e.getValue("screen");
if (!StringUtils.isEmpty(screen))
item.addAttribute("screen", screen);
String bean = (String) e.getValue("bean");
if (!StringUtils.isEmpty(bean))
item.addAttribute("bean", bean);
String beanMethod = (String) e.getValue("beanMethod");
if (!StringUtils.isEmpty(beanMethod))
item.addAttribute("beanMethod", beanMethod);
String runClass = (String) e.getValue("runClass");
if (!StringUtils.isEmpty(runClass))
item.addAttribute("class", runClass);
}else{
//菜单
Element menu = parentMenu.addElement("menu");
String id= (String) e.getValue("code");
menu.addAttribute("id",id);
String caption = (String) e.getValue("caption");
if (!StringUtils.isEmpty(caption))
menuCaptions.put(id,caption);
String icon = (String) e.getValue("icon");
if (!StringUtils.isEmpty(icon))
menu.addAttribute("icon", icon);
String description = (String) e.getValue("description");
if (!StringUtils.isEmpty(description))
menu.addAttribute("description", description);
String stylename = (String) e.getValue("stylename");
if (!StringUtils.isEmpty(stylename))
menu.addAttribute("stylename", stylename);
String insertBefore = (String) e.getValue("insertBefore");
if (!StringUtils.isEmpty(insertBefore))
menu.addAttribute("insertBefore", insertBefore);
String insertAfter = (String) e.getValue("insertAfter");
if (!StringUtils.isEmpty(insertAfter))
menu.addAttribute("insertAfter", insertAfter);
loadSubMenu(menu,(UUID)e.getValue("id"));
}
}
}
}
简要说明:
1、覆盖checkInitialized是因为平台默认是启动加载一次菜单,现在改成多次加载以反应数据的变化;
2、覆盖getItemCaption是因为平台默认通过id读取配置文件来显示菜单名称,我在实体上增加了一个caption属性允许将菜单名称保存到数据库;
3、覆盖init是将原来从本地XML获取菜单数据改成从数据库获取,首先依然加载其它组件中通过XML定义的菜单,忽略本地的XML菜单(如不想忽略可屏蔽那行代码)。最后从数据库获取菜单项,按sort属性排序显示;
4、Menu表里有一条默认的根菜单main,对用户不可见;
5、需要在spring里配置一下使得bean生效,代码没有优化,供参考。
5 个赞
感谢大哥