WEB开发中前后台树形菜单的展示设计

在WEB开发中经常需要进行树形菜单的展示,本例通过不同角度的总结了如下三种实现方式:

  1. 通过JS的递归实现前端菜单DOM的动态创建
  2. 通过JSP的include指令结合JSTL表达式语言递归实现菜单的展示
  3. 通过扩展JSP的标签在后端实现菜单的DOM节点并响应给前端展示

针对第一种方法,可以采用JS的相关组件,或者使用JS的递归调用将服务端相应的数据组装成DOM节点内容,动态添加到菜单的Container中,网上的例子较多,在此不再赘述,本例就后两种方案进行讲解。

通过JSP的include指令结合JSTL表达式语言递归实现菜单的展示

由于JSP中的JSTL不支持递归,又不想在JSP中加入Java脚本,可以采用JSP动态包含的方式组装菜单,当前方案需要服务端将菜单列表组装成树形结构,具体算法如下:

主页面menu.jsp

1 <ul class="nav nav-list">
2    <c:if test="${not empty sessionScope.SESSION_MENUS}">
3       <c:forEach items="${sessionScope.SESSION_MENUS }" var="menu">
4           <%@include file="recursiveMenu.jsp"%>
5       </c:forEach>
6    </c:if>
7 </ul><!-- /.nav-list -->

递归调用页面recursiveMenu.jsp

 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
 2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 3 <li>
 4   <c:choose>
 5       <c:when test="${empty menu.children }">
 6           <a href="${menu.url }">
 7              <i class="${menu.icon }"></i>
 8              <span class="menu-text"> ${menu.name } </span>
 9            </a>
10       </c:when>
11       <c:otherwise>
12           <a href="javascript:void(0);" class="dropdown-toggle">
13             <i class="${menu.icon }"></i>
14             <span class="menu-text"> ${menu.name } </span>
15             <b class="arrow icon-angle-down"></b>
16             <ul class="submenu">
17                <c:forEach items="${menu.children }" var="menu">
18                    <c:set var="menu" value="${menu}" scope="request"/>
19                    <jsp:include page="recursiveMenu.jsp"/>
20                </c:forEach>
21              </ul>
22           </a>
23       </c:otherwise>
24   </c:choose>
25 </li>

通过扩展JSP的标签在后端实现菜单的DOM节点并相应给前端展示

当前方案采用扩展JSP标签的方式实现具体实现方法如下

1、新建标签实现类MenuTa.java

  1 package com.luwei.console.mg.tag;
  2
  3 import java.io.IOException;
  4 import java.util.List;
  5
  6 import javax.servlet.jsp.JspException;
  7 import javax.servlet.jsp.tagext.TagSupport;
  8
  9 import org.apache.commons.lang.StringUtils;
 10 import org.slf4j.Logger;
 11 import org.slf4j.LoggerFactory;
 12
 13 import com.luwei.console.mg.constant.KeyConst;
 14 import com.luwei.console.mg.entity.ext.MenuExt;
 15
 16 /**
 17  * <Description> 菜单标签<br>
 18  *
 19  * @author lu.wei<br>
 20  * @email [email protected] <br>
 21  * @date 2016年12月25日 <br>
 22  * @since V1.0<br>
 23  * @see com.luwei.console.mg.tag <br>
 24  */
 25 public class MenuTag extends TagSupport {
 26     private Logger logger = LoggerFactory.getLogger(this.getClass());
 27
 28     /**
 29      * serialVersionUID <br>
 30      */
 31     private static final long serialVersionUID = -2755997672501044414L;
 32
 33     @SuppressWarnings("unchecked")
 34     @Override
 35     public int doStartTag() throws JspException {
 36         Object menusObj = pageContext.getSession().getAttribute(KeyConst.KEY_SESSION_MENUS);
 37         if (null != menusObj) {
 38             List<MenuExt> menus = (List<MenuExt>) menusObj;
 39             String menuStr = assumbleMenuHtml(menus);
 40             try {
 41                 pageContext.getOut().println(menuStr);
 42             }
 43             catch (IOException e) {
 44                 logger.error("菜单标签创建菜单出错:{} ", e.getMessage(), e);
 45             }
 46         }
 47         return super.doStartTag();
 48     }
 49
 50     /**
 51      * <Description> TODO<br>
 52      *
 53      * @author lu.wei<br>
 54      * @email [email protected] <br>
 55      * @date 2016年12月25日 上午9:29:26 <br>
 56      * @param menus
 57      * @return <br>
 58      */
 59     private String assumbleMenuHtml(List<MenuExt> menus) {
 60         StringBuffer sb = new StringBuffer("");
 61
 62         if (!menus.isEmpty()) {
 63             long activeMenuId = 1;
 64             Object avtiveMenuIdObj = pageContext.getSession().getAttribute(KeyConst.SESSION_ACTIVE_MENU_ID);
 65             if (null != avtiveMenuIdObj) {
 66                 activeMenuId = (Long) avtiveMenuIdObj;
 67             }
 68             for (MenuExt menu : menus) {
 69
 70                 if (menu.getId() == activeMenuId) {
 71                     sb.append("<li class=‘active‘>");
 72                 }
 73                 else {
 74                     sb.append("<li>");
 75                 }
 76
 77                 boolean hasChild = false;
 78                 if (null != menu.getChildren() && !menu.getChildren().isEmpty()) {
 79                     hasChild = true;
 80                 }
 81                 if (hasChild) {
 82                     sb.append("<a href=‘#‘ class=‘dropdown-toggle‘> ");
 83                 }
 84                 else {
 85                     String url = menu.getUrl();
 86                     if (StringUtils.isNotEmpty(url)) {
 87                         if (url.contains("?")) {
 88                             url = (url + "&mid=" + menu.getId());
 89                         }
 90                         else {
 91                             url = (url + "?mid=" + menu.getId());
 92                         }
 93                     }
 94                     sb.append("<a href=‘").append(url).append("‘>");
 95                 }
 96
 97                 if (StringUtils.isNotEmpty(menu.getIcon())) {
 98                     sb.append("<i class=‘").append(menu.getIcon()).append("‘></i>");
 99                 }
100                 sb.append("<span class=‘menu-text‘>").append(menu.getName()).append("</span>");
101                 if (hasChild) {
102                     sb.append("<b class=‘arrow icon-angle-down‘></b>");
103                 }
104                 sb.append("</a>");
105                 if (hasChild) {
106                     sb.append("<ul class=‘submenu‘>").append(assumbleMenuHtml(menu.getChildren())).append("</ul>");
107                 }
108                 sb.append("</li>");
109             }
110         }
111         return sb.toString();
112     }
113 }

2、配置标签

在项目的WEB-INFO目录下新建文件treeMenuAssum.tld

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
 3  " http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
 4 <taglib>
 5     <tlibversion>1.0</tlibversion>
 6     <jspversion>1.2</jspversion>
 7     <shortname>menu</shortname>
 8     <uri>http://www.luwei.com/web/ext/menus</uri>
 9     <tag>
10         <name>menu</name>
11         <tagclass>com.luwei.console.mg.tag.MenuTag</tagclass>
12     </tag>
13 </taglib>

3、使用菜单标签

在JSP页面中直接使用新建标签

<%@ taglib prefix="menu" uri="http://www.luwei.com/web/ext/menus" %>
<menu:menu/>   

总结

  以上三种方式均能够实现后端服务的配置管理的无限树形菜单在前端显示出来,第一种方法服务端只需要将数据组装成前端需要的格式相应给前端,前端通过空间或者递归的方式动态创建DOM节点就可以了;二后两种方式采用纯Java相关的知识完全由服务端生成树形菜单,服务端会有一定的负载,同时采用JSP动态包含的方式,如果是在菜单中存在复杂逻辑的话不容易实现,因此推荐使用第一和第三中方案。

  具体采用哪种方式可以根据各自项目进行选择,但是实现原理都是相同的。

  

  

  

时间: 2024-10-12 19:32:30

WEB开发中前后台树形菜单的展示设计的相关文章

Web开发中前台与后台技术小结--关于EL表达式,JSTL,eval()函数

在我们日常Web开发中,常常用到EL表达式,JSTL标签,还有可能用到JavaScript中的eval().下面就这样技术和函数小小说明一下. EL(Expression Language),全称表达式语言,既然是开发语言,那么就像Java等语言一样是用来写语句的,通常是用在JSP页面中,我们为了获取JSP提供的内置对象的属性值, 我们通常会使用到EL表达式,比如开发中常见的一个需求就是获取项目的根目录,如果项目的名值变化了,我们在指定路径时,如果把项目的根目录用一个变量来表示的话,那么就不 需

Asp.Net Web API开发微信后台

如果说用Asp.Net开发微信后台是非主流,那么Asp.Net Web API的微信后台绝对是不走寻常路. 需要说明的是,本人认为Asp.Net Web API在开发很多不同的请求方法的Restful服务的时候是利器,可在开发微信后台的时候,因为微信调用我们这个后台的时候来来去去就一个方法,所以Web API有点杀鸡用牛刀的感觉. 而且由于Web API其实是微软封装了大量的类库,所以会导致后台相当臃肿.所以,不建议Asp.Net Web API开发微信后台. 如果好奇心太强实在想试一下,可以参

关于java 展示树形菜单Tree的一些备忘信息。[bootstrap tree]

最近在项目中,需要迭代,显示树形菜单,这里我们使用的是bootstracp,所以使用的是bootstracp多级列表树, 使用的时候,非常简单,只需 <!-- Required Stylesheets --> <link href="./css/bootstrap.css" rel="stylesheet"> <!-- Required Javascript --> <script src="./js/jquery

C++后台实践:古老的CGI与Web开发

本文写给C/C++程序猿,也适合其他对历史感兴趣的程序猿 ============================================= 谈到web开发,大家首先想到的PHP.JavaEE/JSP..NET/ASP.Ruby on rails.Python的Django等等.可谓百花齐放,你一般不会想到C++和Web开发有什么关系,但其实动态网页的开发(web开发)可是在这些动态网页语言诞生之前就存在了的.所以C/C++也是可以做web开发的,它利用的技术是--CGI. 在天地初开,

discuzx3.2后台管理菜单定制,管理菜单二次开发,discuzx3.2后台管理菜单自定义

discuzx3.2后台管理菜单定制,管理菜单二次开发 详情请参考:http://www.infosz.com/forum.php?mod=viewthread&tid=199 第一步:source\admincp\menu下添加 menu_infosz.php,内容如下: 第二步:source\admincp目录下添加admincp_infosz.php 文件,内容如下: 第三步: source\language\lang_admincp_menu.php添加如下内容: 第四步:source\

网页设计、web前端、后台的开发流程和注意事项 -----转

工作2年了,总感觉每次做项目的时候,都是赶时间,赶时间,加班几班,可是最后总结一看,百分之50的时间都浪费在做无用功上面了,甚至因为设计人员的失误,造成了前端和程序大量的返工,休整,加班,造成了开发人员的疲惫. 我个人总结了一下觉得认为比较好的能够节省时间效率的工作流程应该是: 1.产品经理做出整体的构思,提出明确需求,并且形成文档和demo 包括:网站的中心思想,即属于什么类型的,是电子商务还是企业网站还是门户网站等,不同类型的网站风格定位就不一样,一个网站需要注意的地方,例如登录注册的页面,

使用ztree展示树形菜单结构

官网:http://www.treejs.cn/v3/main.php#_zTreeInfo 一.功能简介 在权限系统中,实现给角色指定菜单权限的功能.主要包括以下几点: 读取全部菜单项,并以树形结构展现: 勾选角色拥有的菜单权限,保存入库: 重新编辑角色权限时,默认选中角色已有的菜单权限. 二.界面 三.实现过程 1.在服务端获取全部菜单资源,并转换为json字符串. @RequestMapping("/edit") public String edit(Integer roleId

java web 开发三剑客 -------电子书

Internet,人们通常称为因特网,是当今世界上覆盖面最大和应用最广泛的网络.根据英语构词法,Internet是Inter + net,Inter-作为前缀在英语中表示“在一起,交互”,由此可知Internet的目的是让各个net交互.所以,Internet实质上是将世界上各个国家.各个网络运营商的多个网络相互连接构成的一个全球范围内的统一网,使各个网络之间能够相互到达.各个国家和运营商构建网络采用的底层技术和实现可能各不相同,但只要采用统一的上层协议(TCP/IP)就可以通过Internet

YiShaAdmin,基于.NET Core Web开源的后台快速开发框架

YiShaAdmin YiShaAdmin 基于.NET Core Web开发,借鉴了很多开源项目的优点,让你开发Web管理系统和移动端Api更简单,所以我也把她开源了. 她可以用于所有的Web应用程序,例如网站管理后台.CMS.CRM.ERP.OA这类的系统和移动端Api. 代码地址:https://github.com/liukuo362573/YiShaAdmin 如果对你有帮助,请帮忙点个 star :) 内置功能 员工管理:员工是系统操作者,该功能主要完成系统用户配置 部门管理:配置系