一、流程分析

网上图书商城项目学习笔记-010显示所有分类_项目

 

网上图书商城项目学习笔记-010显示所有分类_css_02

二、代码

1.view层

1)main.jsp

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 3 
 4 
 5 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 6 <html>
 7   <head>
 8     
 9     <title>main</title>
10     
11     <meta http-equiv="pragma" content="no-cache">
12     <meta http-equiv="cache-control" content="no-cache">
13     <meta http-equiv="expires" content="0">    
14     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
15     <meta http-equiv="description" content="This is my page">
16     <meta http-equiv="content-type" content="text/html;charset=utf-8">
17     <!--
18     <link rel="stylesheet" type="text/css" href="styles.css">
19     -->
20     <link rel="stylesheet" type="text/css" href="<c:url value='/jsps/css/main.css'/>">
21   </head>
22   
23   <body>
24 <table class="table" align="center">
25     <tr class="trTop">
26         <td colspan="2" class="tdTop">
27             <iframe frameborder="0" src="<c:url value='/jsps/top.jsp'/>" name="top"></iframe>
28         </td>
29     </tr>
30     <tr>
31         <td class="tdLeft" rowspan="2">
32             <iframe frameborder="0" src="<c:url value='/CategoryServlet?method=findAll'/>" name="left"></iframe>
33         </td>
34         <td class="tdSearch" style="border-bottom-width: 0px;">
35             <iframe frameborder="0" src="<c:url value='/jsps/search.jsp'/>" name="search"></iframe>
36         </td>
37     </tr>
38     <tr>
39         <td style="border-top-width: 0px;">
40             <iframe frameborder="0" src="<c:url value='/jsps/body.jsp'/>" name="body"></iframe>
41         </td>
42     </tr>
43 </table>
44   </body>
45 </html>

 

2)left.jsp

 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
 2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 3 
 4 
 5 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 6 <html>
 7   <head>
 8     <title>left</title>
 9     <base target="body"/>
10     <meta http-equiv="pragma" content="no-cache">
11     <meta http-equiv="cache-control" content="no-cache">
12     <meta http-equiv="expires" content="0">    
13     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
14     <meta http-equiv="description" content="This is my page">
15     <meta http-equiv="content-type" content="text/html;charset=utf-8">
16     <!--
17     <link rel="stylesheet" type="text/css" href="styles.css">
18     -->
19     <script type="text/javascript" src="<c:url value='/jquery/jquery-1.5.1.js'/>"></script>
20     <script type="text/javascript" src="<c:url value='/menu/mymenu.js'/>"></script>
21     <link rel="stylesheet" href="<c:url value='/menu/mymenu.css'/>" type="text/css" media="all">
22     <link rel="stylesheet" type="text/css" href="<c:url value='/jsps/css/left.css'/>">
23 <script language="javascript">
24 /*
25  * 1. 对象名必须与第一个参数相同!
26    2. 第二个参数是显示在菜单上的大标题
27  */
28 var bar = new Q6MenuBar("bar", "传智播客网上书城");
29 $(function() {
30     bar.colorStyle = 4;//指定配色样式,一共0,1,2,3,4
31     bar.config.imgDir = "<c:url value='/menu/img/'/>";//小工具所需图片的路径
32     bar.config.radioButton=true;//是否排斥,多个一级分类是否排斥
33 
34     /*bar.add("程序设计", "Java Javascript", "/goods/jsps/book/list.jsp", "body");
35     bar.add("程序设计", "JSP", "/goods/jsps/book/list.jsp", "body");
36     bar.add("程序设计", "C C++ VC VC++", "/goods/jsps/book/list.jsp", "body");
37     
38     bar.add("办公室用书", "微软Office", "/goods/jsps/book/list.jsp", "body");
39     bar.add("办公室用书", "计算机初级入门", "/goods/jsps/book/list.jsp", "body");
40     
41     bar.add("图形 图像 多媒体", "Photoshop", "/goods/jsps/book/list.jsp", "body");
42     bar.add("图形 图像 多媒体", "3DS MAX", "/goods/jsps/book/list.jsp", "body");
43     bar.add("图形 图像 多媒体", "网页设计", "/goods/jsps/book/list.jsp", "body");
44     bar.add("图形 图像 多媒体", "Flush", "/goods/jsps/book/list.jsp", "body");
45     
46     bar.add("操作系统/系统开发", "Windows", "/goods/jsps/book/list.jsp", "body");
47     bar.add("操作系统/系统开发", "Linux", "/goods/jsps/book/list.jsp", "body");
48     bar.add("操作系统/系统开发", "系统开发", "/goods/jsps/book/list.jsp", "body");*/
49     
50     /*
51     1. 程序设计:一级分类名称
52     2. Java Javascript:二级分类名称
53     3. /goods/jsps/book/list.jsp:点击二级分类后链接到的URL
54     4. body:链接的内容在哪个框架页中显示
55     */
56     <c:forEach items="${parents}" var="parent">
57         <c:forEach items="${parent.children}" var="child">
58             bar.add("${parent.cname}", "${child.cname}", "/goods/BookServlet?method=findByCategory&cid=${child.cid}", "body");
59         </c:forEach>
60     </c:forEach>
61     $("#menu").html(bar.toString());
62 });
63 </script>
64 </head>
65   
66 <body>  
67   <div id="menu"></div>
68 </body>
69 </html>

 

3)mymenu.js

  1 /*
  2  * MenuBar只负责生成<div>,不会实现功能。
  3  * MenuBar的add()方法:bar.add("menu1", "item1", "http://www.qdmmy6.com/");
  4  * MenuBar的menus属性是一个数组(其时它是一个Map),每个元素对应一个menu。
  5  * 数组中的元素还是一个数组,这个数组中的元素是MenuItem对象。
  6  * add()方法首先查找menus["menu1"]元素(即名为"menu1"的菜单)是否存在,
  7  * 如果存在,使用"item1"与"http://www.qdmmy6.com/"创建MenuItem对象。然后把MenuItem对象添加到menus["menu1"]中去。
  8  * 如果不存在,先创建menus["menu1"],在把MenuItem添加进去。
  9  */
 10 function Q6MenuBar(objName, barName) {
 11     this.obj = objName;
 12     this.barName = barName;
 13     this.config = {
 14         topHeight:null,
 15         bottomHeight:null,
 16         width:null,
 17         radioButton:true,
 18         imgDir:"img/"
 19     };
 20     this.icon = {jiaIcon:"jia.png",jianIcon:"jian.png"};
 21     this.colorStyle = 2;
 22     this.colors = [];
 23     this.colors[0] = {
 24         menuBgColor:"rgb(246,133,1)",
 25         menuBorderColor:"rgb(236,171,87)",
 26         itemBgColor:"rgb(38,38,38)",
 27         itemBorderColor:"rgb(100,100,100)",
 28         itemBgMoveColor:"rgb(32,145,177)",
 29         itemBorderMoveColor:"rgb(119,171,113)",
 30         itemMoveColor:"rgb(255,255,255)",
 31         itemColor:"rgb(255,255,255)",
 32         menuBarColor:"rgb(255,255,255)",
 33         menuContentColor:"rgb(255,255,255)"
 34     };
 35     this.colors[2] = {
 36         itemBgMoveColor:"rgb(246,133,1)",
 37         itemBorderMoveColor:"rgb(236,171,87)",
 38         menuBgColor:"rgb(78,78,78)",//38
 39         menuBorderColor:"rgb(102,102,102)",//100
 40         itemBgColor:"rgb(32,145,177)",
 41         itemBorderColor:"rgb(119,171,113)",
 42         itemMoveColor:"rgb(255,255,255)",
 43         itemColor:"rgb(255,255,255)",
 44         menuBarColor:"rgb(255,255,255)",
 45         menuContentColor:"rgb(255,255,255)"
 46     };
 47     this.colors[1] = {
 48         menuBgColor:"rgb(25,119,176)",
 49         menuBorderColor:"rgb(211,211,211)",
 50         itemBgColor:"rgb(121,201,236)",
 51         itemBorderColor:"rgb(68,141,174)",
 52         itemBgMoveColor:"rgb(110,172,44)",
 53         itemBorderMoveColor:"rgb(172,221,74)",
 54         itemMoveColor:"rgb(255,255,255)",
 55         itemColor:"rgb(255,255,255)",
 56         menuBarColor:"rgb(255,255,255)",
 57         menuContentColor:"#333333"
 58     };
 59     this.colors[3] = {
 60         menuBgColor:"rgb(159,153,138)",
 61         menuBorderColor:"rgb(142,132,107)",
 62         itemBgColor:"rgb(254,238,189)",
 63         itemBorderColor:"rgb(164,91,19)",
 64         itemBgMoveColor:"rgb(252,211,61)",
 65         itemBorderMoveColor:"rgb(164,91,19)",
 66         itemMoveColor:"rgb(76,48,0)",
 67         itemColor:"rgb(0,116,199)",
 68         menuBarColor:"rgb(76,48,0)",
 69         menuContentColor:"rgb(76,48,0)"
 70     };
 71     this.colors[4] = {
 72         menuBgColor:"#15B69A",
 73         menuBorderColor:"gray",
 74         itemBgColor:"#EAFFFA",
 75         itemBorderColor:"#15B69A",
 76         itemBgMoveColor:"rgb(13,133,96)",
 77         itemBorderMoveColor:"gray",
 78         itemMoveColor:"#FFFFFF",
 79         itemColor:"gray",
 80         menuBarColor:"#FFFFFF",
 81         menuContentColor:"gray"
 82     };
 83     this.font = {
 84     };
 85     this.menus = [];
 86     //<div class="title" name="title"><span class="titleText">' + barName + '</span></div><div>
 87 }
 88 
 89 /*
 90  * 添加方法
 91  * 首先查看this.menus[menuName]这个菜单(就是一个数组)是否存在。
 92  * 如果不存在,先创建这个菜单(数组)。
 93  * 使用menuItemName和url创建MenuItem对象,把MenuItem对象添加到菜单(数组)尾部。
 94  * frameName -- 指定在哪个帧中打开页面
 95  */
 96 Q6MenuBar.prototype.add = function(menuName, menuItemName, url, frameName) {
 97     if (!this.menus[menuName]) {
 98         this.menus[menuName] = [];
 99     }
100     var len = this.menus[menuName].length;
101     this.menus[menuName][len] = new MenuItem(menuItemName, url, frameName);
102 
103     // MenuItem类
104     function MenuItem(menuItemName, url, frameName) {
105         this.menuItemName = menuItemName;
106         this.url = url;
107         this.frameName = frameName;
108     }
109 }
110 /*
111 MenuBar的toString()方法
112 该方法会生成与MenuBar相关的HTML代码,然后遍历menus属性,生成每个菜单对应HTML代码。
113 */
114 Q6MenuBar.prototype.toString = function() {
115     // menuBar对应的<div>
116     var str = '<div style="border:1px solid' + this.colors[this.colorStyle].menuBorderColor + ';color:' + this.colors[this.colorStyle].menuBarColor + ';" class = "menuBar" name="menuBar" onClick="' + this.obj + '.showMenu(event, this)">\n';
117     // menuBar的标题<div>
118     str += '<div style="background-color:' + this.colors[this.colorStyle].menuBgColor + ';" class="barTitle" name="barTitle"><span class="barTitleText">' + this.barName + '</span></div>\n';
119     // 使用循环添加每个菜单对应的HTML代码。
120     for(var menuName in this.menus) {
121         str += this.menu2Str(menuName);
122     }
123     // menuBar尾部对应的<div>
124     str += '<div style="background-color:' + this.colors[this.colorStyle].menuBgColor + ';" name="barBottom" class="barBottom">';
125     str += '</div>';
126     return str;
127 }
128 
129 /*
130  * 该方法首先生成与菜单对应的HTML代码。
131  * menuName是菜单名字,可以使用menus[menuName]来获取一维数组。
132  * 遍历一维数组,获取其中每个MenuItem,生成MenuItem对应的HTML代码。
133  */
134 Q6MenuBar.prototype.menu2Str = function(menuName){
135     var icon = this.config.imgDir + this.icon.jiaIcon;
136     // 菜单对应的<div>
137     var str = '<div name="menu">\n';
138     // 菜单标题对应的<div>,其中包含icon与text两部分。
139     str += '<div style="background-color:' + this.colors[this.colorStyle].menuBgColor + ';border-right-color:' + this.colors[this.colorStyle].menuBorderColor + ';border-bottom-color:' + this.colors[this.colorStyle].menuBorderColor + ';" name="menuTitle" class="menuTitle"><span name="menuTitleIcon" class="menuTitleIcon"><img src="' + icon + '"/></span><span class="menuTitleText">' + menuName + '</span></div>\n';
140     // 菜单内容对象的<div>,所有菜单荐都存放在这个<div>中。
141     str += '<div style="color:' + this.colors[this.colorStyle].menuContentColor + ';" class="menuContent"  name="menuContent">\n';
142     // 使用循环添加每个MenuItem对应的HTML
143     for(var i = 0; i < this.menus[menuName].length; i++) {
144         str += this.item2Str(this.menus[menuName][i]);
145     }
146     str += '</div>\n</div>\n';
147     return str;
148 }
149 
150 /*
151  * menuItem是MenuItem类型的对象。
152  * 该方法生成menuItem对应的HTML代码。
153  */
154 Q6MenuBar.prototype.item2Str = function(menuItem){
155     return '<div style="border:1px solid ' + this.colors[this.colorStyle].itemBorderColor + ';background-color:' + this.colors[this.colorStyle].itemBgColor + '; color:' + this.colors[this.colorStyle].itemColor + ';" class="menuItem" onMouseMove="' + this.obj + '.itemMouseMove(this)" onMouseOut="' + this.obj + '.itemMouseOut(this)" onClick="skip(\'' + menuItem.url + '\', \'' + menuItem.frameName + '\')">' + menuItem.menuItemName + '</div>\n';
156 }
157 
158 function skip(url, frameName) {
159     if(parent[frameName]) {
160         parent[frameName].location.href=url;
161     } else {
162         location.href=url;
163     }
164 }
165 
166 
167 ///////////////////////////
168 
169 
170 
171 /*
172     获取当前被点击的menu元素。
173     只有点击:div menuTitle、img、menuTitleText,才获取父元素。
174     如果父元素是menuContent,返回null。
175 */
176 Q6MenuBar.prototype.getCurrMenu = function(res) {
177     tagName = res.tagName;
178     name = res.getAttribute("name");
179     while(tagName != "DIV" || name != "menu") {
180 //        alert(tagName + ", " + name);
181         res = res.parentNode;
182         if(!res) {
183             return null;
184         }
185         tagName = res.tagName;
186         name = res.getAttribute("name");
187         if(tagName == "DIV" && name == "menuContent") {
188             return null;
189         }
190     }
191     return res;
192 }
193 
194 Q6MenuBar.prototype.attr = function(ele, attrName) {
195     if(ele.getAttribute)  {
196         return ele.getAttribute(attrName);
197     }
198     return null;
199 }
200 
201 Q6MenuBar.prototype.showMenu = function(evt, menuBar) {
202     var e = evt ? evt : window.event;
203     var res = e.srcElement || e.target;
204     var menu = this.getCurrMenu(res);//获取当前被点击的menu
205     if(!menu) return;
206     this.openMenu(menuBar, menu);
207 }
208 
209 // 打开或关闭menu
210 Q6MenuBar.prototype.openMenu = function(menuBar, menu) {
211     var childs = menu.childNodes;//获取menuBar的所有子元素
212     for(var i = 0; i < childs.length; i++) {
213         //因为Firefor中,换行会出现空白节点,所以需要小心。
214         //获取所有content元素
215         if(this.attr(childs[i], "name") == 'menuContent') {
216             var display = childs[i].style.display;
217             if(!display || display=='none') {
218                 if (this.config.radioButton) {
219                     this.closeMenu(menuBar);//关闭所有menu
220                 }
221                 childs[i].style.display='block';//打开当前menu
222                 this.changeImg(menu, false);//更换当前menu图标
223             } else {
224                 if (this.config.radioButton) {
225                     this.closeMenu(menuBar);//关闭所有menu
226                 }
227                 childs[i].style.display='none';
228                 this.changeImg(menu, true);
229             }
230         }
231     }
232 }
233 
234 // 更换图片
235 Q6MenuBar.prototype.changeImg = function (menu, flag) {
236     var img = menu.getElementsByTagName("img")[0];
237     var jiaIcon = this.config.imgDir + this.icon.jiaIcon;
238     var jianIcon = this.config.imgDir + this.icon.jianIcon;
239     img.src = flag ? jiaIcon : jianIcon;
240 }
241 
242 // 关闭所有menu
243 Q6MenuBar.prototype.closeMenu = function(menuBar) {
244     var menus = menuBar.childNodes;
245     //获取menuBar中所有menu
246     for(var i=0; i < menus.length; i++) {
247         if(this.attr(menus[i], 'name') != 'menu') continue;
248         var childs = menus[i].childNodes;
249         //获取当前menu中所有content
250         for(var j = 0; j < childs.length; j++) {
251             if(this.attr(childs[j], 'name') != 'menuContent') continue;
252             childs[j].style.display='none';
253         }
254         this.changeImg(menus[i], true);
255     }
256 }
257 
258 Q6MenuBar.prototype.itemMouseMove = function(e) {
259     e.style.border = "1px solid " + this.colors[this.colorStyle].itemBorderMoveColor;
260     e.style.backgroundColor = this.colors[this.colorStyle].itemBgMoveColor;
261     e.style.color = this.colors[this.colorStyle].itemMoveColor;
262     e.style.fontWeight = "bold";
263 }
264 
265 Q6MenuBar.prototype.itemMouseOut = function(e) {
266     e.style.border = "1px solid " + this.colors[this.colorStyle].itemBorderColor;
267     e.style.backgroundColor = this.colors[this.colorStyle].itemBgColor;
268     e.style.color = this.colors[this.colorStyle].itemColor;
269     e.style.fontWeight = "";
270 }

 

 

2.servlet层

1)CategoryServlet.java

 

 1 public class CategoryServlet extends BaseServlet {
 2 
 3     private CategoryService categoryService = new CategoryService();
 4     
 5     /**
 6      * 查询所有分类
 7      * @param request
 8      * @param response
 9      * @return
10      */
11     public String findAll(HttpServletRequest request, HttpServletResponse response) {
12         List<Category> parents = categoryService.findAll();
13         request.setAttribute("parents", parents);
14         return "f:/jsps/left.jsp";
15     }
16 }

 

3.service层

1)CategoryService.java

 

 1 public class CategoryService {
 2 
 3     private CategoryDao categoryDao = new CategoryDao();
 4     
 5     /**
 6      * 查询所有分类
 7      * @return
 8      */
 9     public List<Category> findAll() {
10         try {
11             return categoryDao.findAll();
12         } catch (SQLException e) {
13             throw new RuntimeException(e);
14         }
15     }
16 }

 

4.dao层

1)CategoryDao.java

 1 public class CategoryDao {
 2 
 3     private QueryRunner qr = new TxQueryRunner();
 4     
 5     /**
 6      * 返回所有分类
 7      * @return
 8      * @throws SQLException
 9      */
10     public List<Category> findAll() throws SQLException {
11         // 1. 查询出所有一级分类
12         String sql = "SELECT * FROM t_category WHERE pid IS NULL ORDER BY orderBy";
13         List<Map<String,Object>> mapList = qr.query(sql, new MapListHandler());
14         
15         List<Category> parents = toCategoryList(mapList);
16         
17         // 2. 循环遍历所有的一级分类,为每个一级分类加载它的二级分类 
18         for(Category parent : parents) {
19             // 查询出当前父分类的所有子分类
20             List<Category> children = findByparent(parent.getCid());
21             // 设置给父分类
22             parent.setChildren(children);
23         }
24         return parents;
25     }
26 
27     /**
28      * 通过父分类查询子分类
29      * @param cid
30      * @return
31      * @throws SQLException
32      */
33     private List<Category> findByparent(String cid) throws SQLException {
34         String  sql = "select * from t_category where pid=?";
35          List<Map<String,Object>> mapList = qr.query(sql, new MapListHandler(), cid);
36         return toCategoryList(mapList);
37     }
38 
39 
40     /**
41      * 可以把多个Map(List<Map>)映射成多个Category(List<Category>)
42      * @param mapList
43      * @return
44      */
45     private List<Category> toCategoryList(List<Map<String, Object>> mapList) {
46         List<Category> categoryList = new ArrayList<Category>();
47         for(Map<String,Object> map : mapList) {
48             Category c = toCategory(map);
49             categoryList.add(c);
50         }
51         return categoryList;
52     }
53 
54     /**
55      * 把一个Map中的数据映射到Category中
56      * @param map
57      * @return
58      */
59     private Category toCategory(Map<String, Object> map) {
60         /*
61          * map {cid:xx, cname:xx, pid:xx, desc:xx, orderBy:xx}
62          * Category{cid:xx, cname:xx, parent:(cid=pid), desc:xx}
63          */
64         Category category = CommonUtils.toBean(map, Category.class);
65         return category;
66     }
67 }

 

You can do anything you set your mind to, man!