Struts+Hibernate+Javascript 实现无限级树形菜单(重新上传带图片)

Struts+Hibernate+Javascript 实现无限级树形菜单

 

一、说明:

 

1、开发环境:

Eclipse3.2.1+MyEclipse5.1+Tomcat5.5+Microsoft SQL Server 2000

 

2、主要实现技术:Struts1.2+Hibernate3.0+JavaScript+JSTL1.1+自定义标签

 

3、页面的树形菜单的节点用 JavaScript进行控制

 

4、数据库中的商品类别表productCategory包含一个引用自身主键的外键,从而形成自身一对多关系

5、自定义标签实现类Recursion中主要用了递归实现节点的展开

 

补充:测试数据通过TestMain.java插入数据库的(连接数据库用的驱动程序是jtds-1.2.jar,自己加载),这个类用的JUnit单元测试,所以也要把JUnit的包加入构建路径中:-) 完整代码打包下载在后面的链接中

二、完成后运行效果如下图:

 

 

三、具体实现步骤:

1、新建一个Web 工程(随便加载JSTL1.1的支持),创建如下图所示的结构目录

 

2、创建数据库

数据库中就只有两张表,其中商品类别à商品为一对多关系,商品类别自身形成一对多关系(引用主键:类别编号做外键:父类编号),下面是由PowerDesigner 12 画的概念图

生成的数据库脚本tree.sql如下:

/*==============================================================*/

/* DBMS name:      Microsoft SQL Server 2000                    */

/* Created on:     2007-07-14 09:10:40                          */

/*==============================================================*/

 

/*==============================================================*/

/* Table: product                                               */

/*==============================================================*/

create database tree

go

use tree

go

create table product (

   productId            int          identity        not null,

   CategoryId           int                  not null,

   productName          varchar(100)         not null,

   productPrice         money                not null,

   constraint PK_PRODUCT primary key nonclustered (productId)

)

go

 

/*==============================================================*/

/* Index: ProductCategoryToProduct_FK                           */

/*==============================================================*/

create index ProductCategoryToProduct_FK on product (

CategoryId ASC

)

go

/*==============================================================*/

/* Table: productCategory                                       */

/*==============================================================*/

create table productCategory (

   CategoryId           int        identity          not null,

   ParentCategoryId     int                  null,

   CategoryName         varchar(50)          not null,

   constraint PK_PRODUCTCATEGORY primary key nonclustered (CategoryId)

)

go

/*==============================================================*/

/* Index: 商品类别拥有商品类别_FK                                         */

/*==============================================================*/

create index 商品类别拥有商品类别_FK on productCategory (

ParentCategoryId ASC

)

go

alter table product

   add constraint FK_PRODUCT_PRODUCTCA_PRODUCTC foreign key (CategoryId)

      references productCategory (CategoryId)

go

alter table productCategory

   add constraint FK_PRODUCTC_商品类别拥有商品类_PRODUCTC foreign key (ParentCategoryId)

      references productCategory (CategoryId)

用查询分析器运行上述脚本,在数据库中建

product结构如下图:

 

productCategory结构如下图:

 

3、数据库建好后,通过MyEclipse加载Struts 1.2Hibernate 3.0的支持  

 

 

4、切换到MyEclipse Database 视图,通过Hibernate Reverse Engineering生成两张表的Pojo类和*.hbm.xml映射文件

 

5、对自动生成的Pojo类和*.hbm.xml映射文件进行适当的修改,修改后的文件如下:

1)Product.java

package  com.lideedu.yame.tree.pojos;

 

public   class  Product   implements  java.io.Serializable  {

    
private Integer productId;

     
private ProductCategory productCategory;

     
private String productName;

     
private Double productPrice;

 

    
public Product() {

    }


    
public Integer getProductId() {

        
return this.productId;

    }
    

    
public void setProductId(Integer productId) {

        
this.productId = productId;

    }


    
public ProductCategory getProductCategory() {

        
return this.productCategory;

    }
    

    
public void setProductCategory(ProductCategory productCategory) {

        
this.productCategory = productCategory;

    }


    
public String getProductName() {

        
return this.productName;

    }
    

    
public void setProductName(String productName) {

        
this.productName = productName;

    }


    
public Double getProductPrice() {

        
return this.productPrice;

    }
    

    
public void setProductPrice(Double productPrice) {

        
this.productPrice = productPrice;

    }


}


 

2)Product.hbm.xml

 

<? xml version="1.0" encoding="utf-8" ?>

<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

<!--  

    Mapping file autogenerated by MyEclipse - Hibernate Tools

-->

< hibernate-mapping >

    
< class  name ="com.lideedu.yame.tree.pojos.Product"  table ="product" >

        
< id  name ="productId"  type ="java.lang.Integer" >

            
< column  name ="productId"   />

            
< generator  class ="native"   />

        
</ id >         

        
< many-to-one  name ="productCategory"  outer-join ="true"

                 class
="com.lideedu.yame.tree.pojos.ProductCategory" >

            
< column  name ="CategoryId"  not-null ="true" />

        
</ many-to-one >         

        
< property  name ="productName"  type ="java.lang.String" >

            
< column  name ="productName"  length ="100"  not-null ="true"   />

        
</ property >

        
< property  name ="productPrice"  type ="java.lang.Double" >

            
< column  name ="productPrice"  scale ="4"  not-null ="true"   />

        
</ property >         

    
</ class >

</ hibernate-mapping >

 

3)ProductCategory.java

package  com.lideedu.yame.tree.pojos;

 

import  java.util.HashSet;

import  java.util.Set;

 

@SuppressWarnings(
" serial " )

public   class  ProductCategory  implements  java.io.Serializable  {

    
private Integer categoryId;

    
private String categoryName;

    
private ProductCategory parentCategory;

    
private Set subCategories = new HashSet(0);

    
private Set products = new HashSet(0);

    
public Set getProducts() {

       
return products;

    }


    
public void setProducts(Set products) {

       
this.products = products;

    }


    
public ProductCategory() {

    }


    
public Integer getCategoryId() {

       
return this.categoryId;

    }


    
public void setCategoryId(Integer categoryId) {

       
this.categoryId = categoryId;

    }


    
public String getCategoryName() {

       
return this.categoryName;

    }


    
public void setCategoryName(String categoryName) {

       
this.categoryName = categoryName;

    }


    
public ProductCategory getParentCategory() {

       
return parentCategory;

    }


    
public void setParentCategory(ProductCategory parentCategory) {

       
this.parentCategory = parentCategory;

    }


    
public Set getSubCategories() {

       
return subCategories;

    }


    
public void setSubCategories(Set subCategories) {

       
this.subCategories = subCategories;

    }


}


 

4)ProductCategory.hbm.xml

 

<? xml version="1.0" encoding="utf-8" ?>

<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

<!--  

    Mapping file autogenerated by MyEclipse - Hibernate Tools

-->

< hibernate-mapping >

    
< class  name ="com.lideedu.yame.tree.pojos.ProductCategory"  table ="productCategory" >

        
< id  name ="categoryId"  type ="java.lang.Integer" >

            
< column  name ="CategoryId"   />

            
< generator  class ="native"   />

        
</ id >                 

        
< property  name ="categoryName"  type ="java.lang.String" >

            
< column  name ="CategoryName"  length ="50"  not-null ="true"   />

        
</ property >         

        
< set  name ="products"  inverse ="true"  cascade ="all"  lazy ="false" >

            
< key >

                
< column  name ="CategoryId"  not-null ="true"   />

            
</ key >

            
< one-to-many  class ="com.lideedu.yame.tree.pojos.Product"   />

        
</ set >         

        
< many-to-one  name ="parentCategory"  class ="com.lideedu.yame.tree.pojos.ProductCategory"  

                 cascade
="save-update"   >

            
< column  name ="ParentCategoryId"   />

        
</ many-to-one >         

        
< set  name ="subCategories"  inverse ="true"  lazy ="false" >

            
< key >

                
< column  name ="ParentCategoryId"   />

            
</ key >

            
< one-to-many  class ="com.lideedu.yame.tree.pojos.ProductCategory"   />

        
</ set >         

    
</ class >

</ hibernate-mapping >

 

6、编写DAO

1) ProductDAO

package  com.lideedu.yame.tree.dao;

 

import  java.util.List;

import  org.hibernate.Session;

import  org.hibernate.Transaction;

import  com.lideedu.yame.tree.db.HibernateSessionFactory;

import  com.lideedu.yame.tree.pojos.Product;

 

public   class  ProductDAO  {

    
private Session session= null;

    
private Transaction tx = null;

    
public void save(Product product){     

       
try {

           session 
= HibernateSessionFactory.getSession();

           tx 
= session.beginTransaction();

           session.save(product);

           tx.commit();

       }
 catch (Exception e) {

           e.printStackTrace();

           
if(tx != null)

              tx.rollback();

       }
finally{

           HibernateSessionFactory.closeSession();

           tx 
= null;

       }
      

    }


    
public List queryAll(){

       List list 
= null;

       
try {

           session 
= HibernateSessionFactory.getSession();

           list 
= session.createQuery("from Product p left join fetch p.productCategory").list();

       }
 catch (Exception e) {

           e.printStackTrace();

       }
finally{

           HibernateSessionFactory.closeSession();

       }


       
return list;             

    }


    
public List queryByProductId(int productId){

       List list 
= null;

       
try {

           session 
= HibernateSessionFactory.getSession();

           list 
= session.createQuery("from Product p left join fetch p.productCategory where p.productId="+productId).list();

       }
 catch (Exception e) {

           e.printStackTrace();

       }
finally{

           HibernateSessionFactory.closeSession();

       }


       
return list;      

    }


    
public List queryByCategoryId(int categoryId){

       List list 
= null;

       
try {

           session 
= HibernateSessionFactory.getSession();

           list 
= session.createQuery("from Product p left join fetch p.productCategory where p.productCategory.categoryId="+categoryId).list();

       }
 catch (Exception e) {

           e.printStackTrace();

       }
finally{

           HibernateSessionFactory.closeSession();

       }


       
return list;

    }


}


 

 

2) ProductCategoryDAO

package  com.lideedu.yame.tree.dao;

 

import  java.util.List;

import  org.hibernate.Session;

import  org.hibernate.Transaction;

import  com.lideedu.yame.tree.db.HibernateSessionFactory;

import  com.lideedu.yame.tree.pojos.ProductCategory;

 

public   class  ProductCategoryDAO  {

    
private Session session= null;

    
private Transaction tx = null;

    
public void save(ProductCategory pc){     

       
try {

           session 
= HibernateSessionFactory.getSession();

           tx 
= session.beginTransaction();

           session.save(pc);        

           tx.commit();

       }
 catch (Exception e) {

           e.printStackTrace();

           
if(tx != null)

              tx.rollback();

       }
finally{

           HibernateSessionFactory.closeSession();

           tx 
= null;

       }
      

    }


    
public List queryAll(){

       List list 
= null;

       
try {

           session 
= HibernateSessionFactory.getSession();

           list 
= session.createQuery("from ProductCategory p left join fetch p.parentCategory").list();

       }
 catch (Exception e) {

           e.printStackTrace();

       }
finally{

           HibernateSessionFactory.closeSession();

       }


       
return list;             

    }


}


 

 

7、编写Struts 控制类

1)ListCategoryAction.java

这个类的作用是从数据库中查出根类,存放到List中,然后把List保存到request范围,在前台通过自定义标签取出后,在自定义标签的实现类RecursionTag中通过递归做成一棵目录树,在页面显示出来,页面的节点的展开和折叠是通过JavaScript控制的。

package  com.lideedu.yame.tree.struts.action;

 

import  java.util.ArrayList;

import  java.util.Iterator;

import  java.util.List;

import  javax.servlet.http.HttpServletRequest;

import  javax.servlet.http.HttpServletResponse;

import  org.apache.struts.action.Action;

import  org.apache.struts.action.ActionForm;

import  org.apache.struts.action.ActionForward;

import  org.apache.struts.action.ActionMapping;

import  com.lideedu.yame.tree.dao.ProductCategoryDAO;

import  com.lideedu.yame.tree.pojos.ProductCategory;

 

public   class  ListCategoryAction  extends  Action  {

    @SuppressWarnings(
"unchecked")

    
public ActionForward execute(ActionMapping mapping, ActionForm form,

           HttpServletRequest request, HttpServletResponse response) 
{

       ProductCategoryDAO pcDAO 
= new ProductCategoryDAO();

       List list 
= new ArrayList();

       Iterator it 
= pcDAO.queryAll().iterator();

       
for (Iterator iter = it; iter.hasNext();) {

           ProductCategory element 
= (ProductCategory) iter.next();

           
if(element.getParentCategory() == null)

              list.add(element);

       }


       request.setAttribute(
"all", list);

       
return mapping.findForward("list");

    }


}

 

2)QueryProductAction.java

此类用于显示具体商品的名称时调用,当页面目录树展开到没有子类的节点时,就调用此类从数据库中查询出该类别下所有商品的信息

package  com.lideedu.yame.tree.struts.action;

 

import  java.util.List;

import  javax.servlet.http.HttpServletRequest;

import  javax.servlet.http.HttpServletResponse;

import  org.apache.struts.action.Action;

import  org.apache.struts.action.ActionForm;

import  org.apache.struts.action.ActionForward;

import  org.apache.struts.action.ActionMapping;

import  com.lideedu.yame.tree.dao.ProductDAO;

public   class  QueryProductAction  extends  Action  {

    
private ProductDAO productDAO = new ProductDAO();

    
public ActionForward execute(ActionMapping mapping, ActionForm form,

           HttpServletRequest request, HttpServletResponse response) 
{

       
int productId = new Integer(request.getParameter("productId"));

       List list 
= productDAO.queryByProductId(productId);

       request.setAttribute(
"products", list);

       
return mapping.findForward("listProducts");

    }


}

 

8Struts配置文件àstruts-config.xml

<? xml version="1.0" encoding="UTF-8" ?>

<! DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd" >

 

< struts-config >

  
< data-sources  />

  
< form-beans  />

  
< global-exceptions  />

  
< global-forwards  />

  
< action-mappings  >

    
< action  path ="/listCategory"  type ="com.lideedu.yame.tree.struts.action.ListCategoryAction" >

    
< forward  name ="list"  path ="/ListCategory.jsp" />

    
</ action >

    
< action  path ="/queryProduct"  type ="com.lideedu.yame.tree.struts.action.QueryProductAction" >

      
< forward  name ="listProducts"  path ="/ListProducts.jsp"   />

    
</ action >

    

  
</ action-mappings >

 

  
< message-resources  parameter ="com.lideedu.yame.tree.struts.ApplicationResources"   />

</ struts-config >

 

9、几个JSP页面文件

1) main.jsp 此页面非常简单,只是提供个调用ListCategoryAction的入口

<% @ page language="java" import="java.util.*" pageEncoding="gbk" %>

 

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >

< html >

  
< head >     

    
< title > Main </ title >

    

    
< meta  http-equiv ="pragma"  content ="no-cache" >

    
< meta  http-equiv ="cache-control"  content ="no-cache" >

    
< meta  http-equiv ="expires"  content ="0" >     

    
< meta  http-equiv ="keywords"  content ="keyword1,keyword2,keyword3" >

    
< meta  http-equiv ="description"  content ="This is my page" >

    
<!--

    <link rel="stylesheet" type="text/css" href="styles.css">

    
-->

 

  
</ head >

  

  
< body >

    
< h3 >< href ="listCategory.do" > 显示所有商品类别目录 </ a ></ h3 >

  
</ body >

</ html >

 

2) ListProducts.jsp

此页用来显示某个具体商品的详细信息

<% @ page language="java" import="java.util.*" pageEncoding="GBK" %>

<% @ taglib uri="http://jakarta.apache.org/struts/tags-bean"

    prefix
="bean"
%>

<% @ taglib uri="http://jakarta.apache.org/struts/tags-html"

    prefix
="html"
%>

<% @ taglib uri="http://jakarta.apache.org/struts/tags-logic"

    prefix
="logic"
%>

<% @ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

 

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >

< html >

  
< head >

    
< title > My JSP 'ListProducts.jsp' starting page </ title >

    

    
< meta  http-equiv ="pragma"  content ="no-cache" >

    
< meta  http-equiv ="cache-control"  content ="no-cache" >

    
< meta  http-equiv ="expires"  content ="0" >     

    
< meta  http-equiv ="keywords"  content ="keyword1,keyword2,keyword3" >

    
< meta  http-equiv ="description"  content ="This is my page" >

    
<!--

       <link rel="stylesheet" type="text/css" href="styles.css">

    
-->

 

  
</ head >

  

  
< body >

    
< logic:iterate  id ="product"  name ="products"  scope ="request" >

    
< center >< h3 > 商品详细信息 </ h3 ></ center >

    商品所属类别:${product.productCategory.categoryName}
< br />

    商品编号:${product.productId}
< br />

    商品名称:${product.productName}
< br />

    价格:${product.productPrice}元
< br />

    
</ logic:iterate >

  
</ body >

</ html >

 

*** 3) ListCategory.jsp ***

核心页面 显示商品类别目录树和具体商品信息,

 

<% @ page language="java" import="java.util.*" pageEncoding="gbk" %>

<% @ taglib uri="http://jakarta.apache.org/struts/tags-bean"

    prefix
="bean"
%>

<% @ taglib uri="http://jakarta.apache.org/struts/tags-html"

    prefix
="html"
%>

<% @ taglib uri="http://jakarta.apache.org/struts/tags-logic"

    prefix
="logic"
%>

<% @ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<% @ taglib uri="/WEB-INF/recursion.tld" prefix="r" %>

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >

< html >

    
< head >

       
< title > 无限级树型菜单 </ title >

 

       
< meta  http-equiv ="pragma"  content ="no-cache" >

       
< meta  http-equiv ="cache-control"  content ="no-cache" >

       
< meta  http-equiv ="expires"  content ="0" >

       
< script  type ="text/javascript"  src ="js/myjs.js" ></ script >

       
< link  href ="css/mycss.css"  rel ="stylesheet"  type ="text/css"   />

    
</ head >

 

    
< body  background ="images/bg.jpg" >

       
< table  width ="100%"  height ="100%"  border ="0"  cellSpacing ="0"

           cellPadding
="0" >

           
< tr >

              
< td  width ="45%"  height ="100%"  valign ="top"  nowrap ="nowrap" >

                  
< ul  id ="containerul" >

                     
< c:choose >

                         
< c:when  test ="${not empty all}" >

                            
< li >

                                所有商品

                                
< ul >

                                   
<!--  自定义标签  -->

                                   
< r:yame  list ="${all}" />

                                
</ ul >

                            
</ li >

                         
</ c:when >

                         
< c:otherwise >

                            
< center >

                                
< h1 >

                                   
< font  color ="red" > 没有任何商品!!! </ font >

                                
</ h1 >

                            
</ center >

                         
</ c:otherwise >

                     
</ c:choose >

                  
</ ul >

                  
< p >

                     
< script  type ="text/javascript" > initiate(); </ script >

                  
</ p >

              
</ td >

              
< td  valign ="top" >

                  
< iframe  id =mainFrame  name =mainFrame  src ="about:blank"  frameborder =0

                     
width ="92%"  height =280

                     
onload ="iframeResize(); document.body.scrollTop=0;" >

                     您的浏览器不支持此功能,请您使用最新的版本。

                  
</ iframe >

              
</ td >

           
</ tr >

       
</ table >

       
< script  type =text/javascript >  

            
function iframeResize()

              
{

                  
var dyniframe   = null;

                  
var indexwin    = null;

              

                  
if (document.getElementById)

                  
{

                     dyniframe       
= document.getElementById("mainFrame");

                     indexwin        
= window;

              

                     
if (dyniframe)

                     
{

                         
if (dyniframe.contentDocument)

                         
{

                            dyniframe.height 
= dyniframe.contentDocument.body.scrollHeight + 10;

                         }


                         
else if (dyniframe.document && dyniframe.document.body.scrollHeight)

                         
{

                              iframeheight
= mainFrame.document.body.scrollHeight + 10;

                            dyniframe.height 
= iframeheight;

                         }


                     }


                  }


              }


       
</ script >

    
</ body >

</ html >

 

10、用到的JavaScript脚本和样式表(控制树节点的关键

1) myjs.js

             var  temp, temp2, cookieArray, cookieArray2, cookieCount;
            
            
function  initiate() {
            
              cookieCount
=0;
            
              
if(document.cookie){
            
                cookieArray
=document.cookie.split(";");
                cookieArray2
=new Array();
            
                
for(i in cookieArray){
                  cookieArray2[cookieArray[i].split(
"=")[0].replace(/ /g,"")]=cookieArray[i].split("=")[1].replace(/ /g,"");
                }

            
              }

            
              cookieArray
=(document.cookie.indexOf("state=")>=0)?cookieArray2["state"].split(","):new Array();
            
              temp
=document.getElementById("containerul");
            
              
for(var o=0;o<temp.getElementsByTagName("li").length;o++){
            
                
if(temp.getElementsByTagName("li")[o].getElementsByTagName("ul").length>0){
            
                  temp2                
= document.createElement("span");
                  temp2.className            
= "symbols";
                  temp2.style.backgroundImage    
= (cookieArray.length>0)?((cookieArray[cookieCount]=="true")?"url(images/minus.png)":"url(images/plus.png)"):"url(images/plus.png)";
                  temp2.onclick
=function(){
                    showhide(
this.parentNode);
                    writeCookie();
                  }

            
                  temp.getElementsByTagName(
"li")[o].insertBefore(temp2,temp.getElementsByTagName("li")[o].firstChild)
            
                  temp.getElementsByTagName(
"li")[o].getElementsByTagName("ul")[0].style.display = "none";
            
                  
if(cookieArray[cookieCount]=="true"){
                    showhide(temp.getElementsByTagName(
"li")[o]);
                  }

            
                  cookieCount
++;
            
                }

                
else{
            
                  temp2                
= document.createElement("span");
                  temp2.className            
= "symbols";
                  temp2.style.backgroundImage    
= "url(images/page.png)";
            
                  temp.getElementsByTagName(
"li")[o].insertBefore(temp2,temp.getElementsByTagName("li")[o].firstChild);
            
                }

            
              }

            
            }

            
            
            
            
function  showhide(el) {
            
              el.getElementsByTagName(
"ul")[0].style.display=(el.getElementsByTagName("ul")[0].style.display=="block")?"none":"block";
            
              el.getElementsByTagName(
"span")[0].style.backgroundImage=(el.getElementsByTagName("ul")[0].style.display=="block")?"url(images/minus.png)":"url(images/plus.png)";
            
            }

            
            
            
            
function  writeCookie() {        // Runs through the menu and puts the "states" of each nested list into an array, the array is then joined together and assigned to a cookie.
            
              cookieArray
=new Array()
            
              
for(var q=0;q<temp.getElementsByTagName("li").length;q++){
            
                
if(temp.getElementsByTagName("li")[q].childNodes.length>0){
                  
if(temp.getElementsByTagName("li")[q].childNodes[0].nodeName=="SPAN" && temp.getElementsByTagName("li")[q].getElementsByTagName("ul").length>0){
            
                    cookieArray[cookieArray.length]
=(temp.getElementsByTagName("li")[q].getElementsByTagName("ul")[0].style.display=="block");
            
                  }

                }

            
              }

            
              document.cookie
="state="+cookieArray.join(",")+";expires="+new Date(new Date().getTime() + 365*24*60*60*1000).toGMTString();
            
            }

2) mycss.css

#containerul, #containerul ul {
              text-align
:left;
              margin
:0;                /* Removes browser default margins applied to the lists. */
              padding
:0;                /* Removes browser default padding applied to the lists. */
            
}

            
            #containerul li
{
              margin
:0 0 0 30px;            /* A left margin to indent the list items and give the menu a sense of structure. */
              padding
:0;                /* Removes browser default padding applied to the list items. */
              list-style-type
:none;            /* Removes the bullet point that usually goes next to each item in a list. */
            
}

            
            #containerul .symbols
{            /* Various styles to position the symbols next to the items in the menu. */
              float
:left;
              width
:12px;
              height
:1em;
              background-position
:0 50%;
              background-repeat
:no-repeat;
            
}

 

11、自定义标签的编写

 

1)       创建标签处理类(Tag Handler ClassàRecursionTag.java

package  com.lideedu.yame.utils;

 

import  java.io.IOException;

import  java.util.Iterator;

import  java.util.List;

import  java.util.Set;

import  javax.servlet.jsp.JspException;

import  javax.servlet.jsp.JspWriter;

import  javax.servlet.jsp.tagext.TagSupport;

import  com.lideedu.yame.tree.dao.ProductDAO;

import  com.lideedu.yame.tree.pojos.Product;

import  com.lideedu.yame.tree.pojos.ProductCategory;

 

@SuppressWarnings(
" serial " )

public   class  RecursionTag  extends  TagSupport  {   

    
private List list = null;

    

    
public List getList() {

       
return list;

    }


 

    
public void setList(List list) {

       
this.list = list;

    }


 

    
public int doStartTag() throws JspException {

       JspWriter out 
= pageContext.getOut();

       
for (Iterator iter = list.iterator(); iter.hasNext();) {

           ProductCategory element 
= (ProductCategory) iter.next();

           printTreeNode(out, element);

       }


       
return TagSupport.SKIP_BODY;

    }


 

    
/**

     * 由MyEclipse重构的方法

     * 
@param out

     * 
@param element

     
*/


    
private void printTreeNode(JspWriter out, ProductCategory element) {

       
try {

           out.println(
"<li>"+element.getCategoryName()+"<ul>");

       }
 catch (IOException e) {

           e.printStackTrace();

       }
   

       printAllCategory(element);

       
try {

           out.println(
"</ul></li>");

       }
 catch (IOException e) {

           e.printStackTrace();

       }


    }


    

    
private void  printAllCategory(ProductCategory pc){

       JspWriter out 
= pageContext.getOut();

       ProductDAO productDAO 
= new ProductDAO();

       
//  如果该类还拥有子类,则进行递归

       
if(pc.getSubCategories().size()>0){       

           Set set 
= pc.getSubCategories();

           
for (Iterator iter = set.iterator(); iter.hasNext();) {

              ProductCategory element 
= (ProductCategory) iter.next();

              printTreeNode(out, element);

           }
          

       
//  打印出无子类的商品类别下的所有商品信息

       }
else if(productDAO.queryByCategoryId(pc.getCategoryId()) != null){

           List list 
= productDAO.queryByCategoryId(pc.getCategoryId());

           
for (Iterator iter = list.iterator(); iter.hasNext();) {

              Product element 
= (Product) iter.next();

              
try {

                  
//  为具体商品添加超链接

                  out.println(
"<li><a href=queryProduct.do?productId=" + element.getProductId()+

                         
" title=单击查看商品详细信息 target=mainFrame>"+element.getProductName()+"</a></li>");

              }
 catch (IOException e) {

                  e.printStackTrace();

              }


           }


       }
 

       
else

           
try {

              out.println(
"<li><ul>"+pc.getCategoryName()+"</ul></li>");

           }
 catch (IOException e) {

              e.printStackTrace();

           }
          

    }


}

 

2)       创建标签库描述文件(Tag Library Descriptor Fileàrecursion.tld

放在路径 /WEB-INF/recursion.tld

<? xml version="1.0" encoding="UTF-8" ?>

<! DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "web-jsptaglibrary_1_2.dtd"  >

< taglib >

    
< tlib-version > 1.0 </ tlib-version >

    
< jsp-version > 2.0 </ jsp-version >

    
< short-name > recursion </ short-name >

    
< tag >

       
< name > yame </ name >

       
< tag-class > com.lideedu.yame.utils.RecursionTag </ tag-class >

       
< body-content > empty </ body-content >

       
< attribute >

           
< name > list </ name >

           
< required > true </ required >

           
< rtexprvalue > true </ rtexprvalue >

       
</ attribute >

    
</ tag >

</ taglib >

 

四、总结说明

 

1、 该项目只是简单的实现树形菜单,有一种业务逻辑没有考虑,就是当类别目录下同时拥有子目录和具体商品的时候只会显示子目录,而具体商品没显示,只需在标签处理类RecursionTag.java中的printAllCategory方法中添加相应的业务逻辑即可实现,有兴趣自行加工 J

2、 整个工程的完整源码打包上传,解压后直接用Eclipse导入就可运行,为方便上传下载去除了/WEB-INF/lib目录下的jar文件,自已添加便可

 

 

3、由于时间仓促、水平有限,可能存在不足之处,欢迎指教!!!有问题的也可联系

 完整代码打包下载:

 http://dl2.csdn.net/down4/20070717/17210233237.rar

EMail:zym83215@163.com

QQ:10389811

郑炎铭

    2007-07-17 2020

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值