新的项目需要对用户权限进行控制,经过和项目经理商量我们决定使用XML文件存储权限代码和层次关系,这样比较方便也便于维护,使用SAX读取XML文件,我发现在读取的时候可以顺便将XML文件中的内容封装为实体Bean,便于页面使用JSTL进行迭代。
 一、XML结构
我的XML结构为这样的
<root>
 <basemenu  id="" name="基础信息" url="#">
  <menu id="" name="仓储位设置" url="#">
   <submenu id="" name="仓库设置" url="">
    <button id="" name="查询" url="#"></button>
   </submenu>
  </menu>
 </basemenu>
</root>
二、实体Bean
针对这种结构我定义了几个实体Bean
使用SAX解析XML封装实体Bean_XML
看名字就能知道对应的XML标记的名字,由于所有的标记都有三个属性,我就将他们抽象出来定义了一个超类,
public class WMSBean {
 public String id;
 public String name;
 public String url;
//省略set,get方法
下面依次是各个实体类的代码
public class RootBean {
 public List<BaseMenuBean> baseMenuBean;
public class BaseMenuBean extends WMSBean {
 public List<MenuBean> menuBean;
public class MenuBean extends WMSBean {
 public List<Submenu> submenu;
public class Submenu extends WMSBean {
 public List<Button> button;
public class Button extends WMSBean {
}
实体类内部成员变量使用了List类型,这样的话可以存放多个相同的标记(Button在最底层没有成员变量)
三、解析XML并封装
开始看我解析XML的代码了
public class ParseXml extends DefaultHandler {
 public RootBean rootBean;//成员变量
 public ParseXml() {
  super();
  this.rootBean = new RootBean();//初始化
 }
 public void startElement(String namespaceURI, String localName,//此方法读取XML元素
   String name, Attributes atts) {
  WMSBean bean = this.doInstanceBean(name);//调用doInstanceBean方法
  for (int i = 0; i < atts.getLength(); i++) {//对实体Bean进行初始化
   if ("id".equals(atts.getLocalName(i))) {
    bean.setId(atts.getValue(i));
   }
   if ("name".equals(atts.getLocalName(i))) {
    bean.setName(atts.getValue(i));
   }
   if ("url".equals(atts.getLocalName(i))) {
    bean.setUrl(atts.getValue(i));
   }
  }
  this.doSetBean(bean);//将实体Bean进行封装
 }
//根据名称初始化一个实体对象,并返回,这个方法充分的利用了java的多态特性
 private WMSBean doInstanceBean(String name) {  
if ("basemenu".equals(name)) {
   return new BaseMenuBean();
  else if ("menu".equals(name)) {
   return new MenuBean();
  else if ("submenu".equals(name)) {
   return new Submenu();
  else if ("button".equals(name)) {
   return new Button();
  else {
  }
  return null;
 }
 private void doSetBean(WMSBean bean) {
  if (bean instanceof BaseMenuBean) {//判断其类型
   this.rootBean.setBaseMenuBean((BaseMenuBean) bean);
  }
 else if (bean instanceof MenuBean) {
   List<BaseMenuBean> baseMenuBeanList = this.rootBean .getBaseMenuBean();
   baseMenuBeanList.get(baseMenuBeanList.size() - 1).setMenuBea( (MenuBean) bean);
//获得List中最后一个对想,并add
  
else if (bean instanceof Submenu) {
   List<BaseMenuBean> baseMenuBeanList = this.rootBean .getBaseMenuBean();
   BaseMenuBean baseMenuBean = baseMenuBeanList.get(baseMenuBeanList
     .size() - 1);
   List<MenuBean> menuBeanList = baseMenuBean.getMenuBean();
   menuBeanList.get(menuBeanList.size() - 1).setSubmenu((Submenu) bean);
  
else if (bean instanceof Button) {//依次重复相同操作
   List<BaseMenuBean> baseMenuBeanList = this.rootBean .getBaseMenuBean();
   BaseMenuBean baseMenuBean = baseMenuBeanList.get(baseMenuBeanList
     .size() - 1);
   List<MenuBean> menuBeanList = baseMenuBean.getMenuBean();
   MenuBean menuBean = menuBeanList.get(menuBeanList.size() - 1);
   List<Submenu> submenuList = menuBean.getSubmenu();
   submenuList.get(submenuList.size() - 1).setButton((Button) bean);
  else { }
 }
 public RootBean getRootBean() {
  return rootBean;
 }
 public void setRootBean(RootBean rootBean) {
  this.rootBean = rootBean;
 }
}
四、调用、运行
public ModelAndView menu(HttpServletRequest request, HttpServletResponse response) throws Exception {
  SAXParserFactory sf = SAXParserFactory.newInstance();
  SAXParser sp = sf.newSAXParser();//初始化对象
  ParseXml parseXml = new ParseXml();//初始化对象
  sp.parse(new InputSource(this.getServletContext().getRealPath(
    "/WEB-INF/quanxian.xml")), parseXml);
//通过Servlet容器获得xml文件,将我们的parseXml作为参数传递进去
  RootBean bean = parseXml.getRootBean();//获得parseXml内部的成员变量RootBean
  return new ModelAndView().addObject("RootBean", bean);
//添加进request对象中并返回到页面以供迭代
 }
五、迭代
为了代码的简练我省去了一部分html代码,只保留了迭代RootBean部分的代码,使用JSTL进行迭代,即简单又不出错。
<c:forEach items="${RootBean.baseMenuBean}" var="base">
 <li id="${base.id}"><href="${base.url}">${base.name}</a>
  <ul>
  <c:forEach items="${base.menuBean}" var="menu"> 
  <li id="${menu.id}"><href="${menu.url}">${menu.name}</a>
    <ul>
    <c:forEach items="${menu.submenu}" var="sub">
    <li id="${sub.id}"><href="${sub.url}">${sub.name}</a>
     <ul>
     <c:forEach items="${sub.button}" var="button">
      <li id="${button.id}"><href="${button.url}">${button.name}</a></li>
     </c:forEach>
     </ul>    
    </li>
    </c:forEach>
    </ul>
  </li>  
  </c:forEach>
  </ul>
 </li>
</c:forEach>
总结,不是所有的应用都要按照某某方式去做,我没有使用Digester但是我封装的实体也比较灵活,至少很符合我的使用,这已经足够了。