实战Struts-Menu

实战Struts-Menu
一、简介
  Struts-Menu是一组从基于XML的配置文件中生成多种样式的菜单的JSP Tags,并且可以结合API开发通过数据库生成的动态菜单。Struts-Menu支持国际化和多种权限控制。

二、运行环境
  Windows 2000 Professional
  JDK 1.4.2_03
  Eclipse 3.1
  Tomcat 5.0.28
  Tomcat Plugin 3.1Beta
  Struts 1.2.7
  Commons-Lang 2.1
  Commons-Collections 3.1
  Struts-Menu 2.3
  MySQL 4.1.10a-nt

三、下载与安装
  1:从http://java.sun.com下载J2SDK,当前1.4.x系列的最新版本为1.4.2_08
  2:从http://www.eclipse.org下载Eclipse,当前最新版本为3.1正式版
  3:从http://jakarta.apache.org/tomcat下载Tomcat,当前5.x系列的最新版本为5.0.28
  4:从http://www.sysdeo.com/eclipse/tomcatplugin下载Eclipse的Tomcat插件,对应Eclipse3.1x的最新版本为3.1Beta
  5:从http://struts.apache.org下载Struts,当前最新版本为1.2.7
  6:从http://jakarta.apache.org/commons/下载Commons-Lang,当前最新版本为2.1,下载Commons-Collections,当前最新版本为3.1
  7:从http://struts-menu.sourceforge.net下载Struts Menu,当前最新版本为2.3
  8:从http://www.mysql.com下载MySQL数据库,4.x系列的最新版本是4.1.12a
  9:MySQL、JDK、Eclipse、Tomcat和TomcatPlugin的安装及配置请参考相关资料

四、运行示例程序
  1:安装好Tomcat后,解压缩struts-menu-2.3.zip,将struts-menu.war释放到Tomcat安装目录下的webapps下,运行Tomcat
  2:在地址栏输入http://localhost:8080/struts-menu

五、安装与配置
  1:在Eclipse中新建Tomcat项目,Context为/mymenu,Subdirectory为/web
  2:在项目目录下面新建lib目录和web目录及WEB-INF,在web/WEB-INF目录下新建web.xml,内容如下:


<? xml version="1.0" encoding="ISO-8859-1" ?>

<! DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd"
>

< web-app >
  
< display-name > My Example Application -- Vinton Lee </ display-name >
      
  
<!--  ============= The Struts ActionServlet Configuration =============  -->
  
< servlet >
    
< servlet-name > action </ servlet-name >
    
< servlet-class > org.apache.struts.action.ActionServlet </ servlet-class >
    
< init-param >
      
< param-name > config </ param-name >
      
< param-value > /WEB-INF/struts-config.xml </ param-value >
    
</ init-param >
    
< load-on-startup > 1 </ load-on-startup >
  
</ servlet >
  
<!--  ==================================================================  -->
    
  
<!--  ============= The Struts Action Servlet Mapping ==================  -->
  
< servlet-mapping >
    
< servlet-name > action </ servlet-name >
    
< url-pattern > *.do </ url-pattern >
  
</ servlet-mapping >
  
<!--  ==================================================================  -->
  
  
<!--  The Welcome File List  -->
  
< welcome-file-list >
    
< welcome-file > index.jsp </ welcome-file >
  
</ welcome-file-list >

  
<!--  =============== The Struts Taglib Definition =====================  -->
  
< taglib >
    
< taglib-uri > struts-bean </ taglib-uri >
    
< taglib-location > /WEB-INF/struts-bean.tld </ taglib-location >
  
</ taglib >
  
< taglib >
    
< taglib-uri > struts-html </ taglib-uri >
    
< taglib-location > /WEB-INF/struts-html.tld </ taglib-location >
  
</ taglib >
  
< taglib >
    
< taglib-uri > struts-logic </ taglib-uri >
    
< taglib-location > /WEB-INF/struts-logic.tld </ taglib-location >
  
</ taglib >
  
< taglib >
    
< taglib-uri > struts-nested </ taglib-uri >
    
< taglib-location > /WEB-INF/struts-nested.tld </ taglib-location >
  
</ taglib >
  
< taglib >
    
< taglib-uri > struts-tiles </ taglib-uri >
    
< taglib-location > /WEB-INF/struts-tiles.tld </ taglib-location >
  
</ taglib >
  
<!--  ==================================================================  -->
  
  
<!--  ============= The Struts-Menu Taglib Definition ==================  -->
  
< taglib >
    
< taglib-uri > struts-menu </ taglib-uri >
    
< taglib-location > /WEB-INF/struts-menu.tld </ taglib-location >
  
</ taglib >
  
<!--  ==================================================================  -->
</ web-app >

3:解压缩struts-1.2.7.zip,将压缩包中的lib目录下所有的8个jar释放到lib目录中,将5个tld文件释放到web\WEB-INF目录中,在web\WEB-INF目录中新建struts-config.xml,内容如下:

<? xml version="1.0" encoding="ISO-8859-1"  ?>

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

< struts-config >

    
<!--  ========== Data Source Configuration ===============================  -->
    
< data-sources  />

    
<!--  ========== Form Bean Definitions ===================================  -->
    
< form-beans  />

    
<!--  ========== Global Exception Definitions ============================  -->
    
< global-exceptions  />

    
<!--  ========== Global Forward Definitions ==============================  -->
    
< global-forwards  />

    
<!--  ========== Action Mapping Definitions ==============================  -->
    
< action-mappings  />

    
<!--  ========== Controller Configuration ================================  -->

    
<!--  ========== Message Resources Definitions ===========================  -->
    
< message-resources  parameter ="application"   />

    
<!--  ========== Plug Ins Configuration ==================================  -->
    
< plug-in  className ="net.sf.navigator.menu.MenuPlugIn" >
      
< set-property  property ="menuConfig"  value ="/WEB-INF/menu-config.xml" />
    
</ plug-in >

</ struts-config >

4:解压缩struts-menu-2.3.zip,将压缩包中的jstl-1.0.6.jar、standard-1.0.6.jar、struts-menu-2.3.jar释放到lib目录中,将压缩包中的struts-menu.tld、struts-menu-el.tld释放到web\WEB-INF目录中,解压缩commons-lang-2.1.zip,将commons-lang-2.1.jar解压缩到lib目录中,注意,在Struts-Menu的文档中没有看到需要这个包,但是没有这个包却无法成功加载。在web\WEB-INF目录中新建menu-config.xml,内容如下:
<? xml version="1.0" encoding="UTF-8"  ?>

< MenuConfig >

  
< Displayers >
    
< Displayer    name ="DropDown"
                 type
="net.sf.navigator.displayer.DropDownMenuDisplayer" />
    
< Displayer    name ="Simple"
                 type
="net.sf.navigator.displayer.SimpleMenuDisplayer" />
    
< Displayer    name ="CoolMenu"
                 type
="net.sf.navigator.displayer.CoolMenuDisplayer" />
    
< Displayer    name ="CoolMenu4"
                 type
="net.sf.navigator.displayer.CoolMenuDisplayer4" />
    
< Displayer    name ="MenuForm"
                 type
="net.sf.navigator.example.PermissionsFormMenuDisplayer" />
    
< Displayer    name ="ListMenu"
                 type
="net.sf.navigator.displayer.ListMenuDisplayer" />
    
< Displayer    name ="TabbedMenu"
                 type
="net.sf.navigator.displayer.TabbedMenuDisplayer" />
    
< Displayer    name ="Velocity"
                 type
="net.sf.navigator.displayer.VelocityMenuDisplayer" />
  
</ Displayers >

  
< Menus >
    
< Menu   name ="DoorSite"   title ="DoorSite"   description ="Some famous doorsite"  width ="50" >
       
< Item    name ="Yahoo"    title ="Yahoo" >
           
< Item    name ="YahooIndex"    title ="Yahoo Index"    location ="http://www.yahoo.com.cn" />
           
< Item    name ="YahooMail"     title ="Yahoo Mail"     location ="http://cn.mail.yahoo.com" />
       
</ Item >
       
< Item     name ="Sohu"   title ="Sohu"    location ="http://www.sohu.com" />
       
< Item     name ="Sina"   title ="Sina"    location ="http://www.sina.com.cn" />
    
</ Menu >
  
</ Menus >

</ MenuConfig >

5:将第四步的示例程序中的struts-menu应用目录下的images、scripts、styles三个目录中的内容复制到web目录下

  6:你的目录结构应该类似如下:

%PROJECT_HOME%\classes
    %PROJECT_HOME%\lib
    %PROJECT_HOME%\lib\antlr.jar
    %PROJECT_HOME%\lib\commons-beanutils.jar
    %PROJECT_HOME%\lib\commons-digester.jar
    %PROJECT_HOME%\lib\commons-fileupload.jar
    %PROJECT_HOME%\lib\commons-lang-
2.1 .jar
    %PROJECT_HOME%\lib\commons-logging.jar
    %PROJECT_HOME%\lib\commons-validator.jar
    %PROJECT_HOME%\lib\jakarta-oro.jar
    %PROJECT_HOME%\lib\jstl-
1.0.6 .jar
    %PROJECT_HOME%\lib\standard-
1.0.6 .jar
    %PROJECT_HOME%\lib\struts.jar
    %PROJECT_HOME%\lib\struts-menu-
2.3 .jar
    %PROJECT_HOME%\src
    %PROJECT_HOME%\src\log4j.properties
    %PROJECT_HOME%\src\application.properties
    %PROJECT_HOME%\src\application_zh_CN.properties
    %PROJECT_HOME%\web
 %PROJECT_HOME%\web\images\
 %PROJECT_HOME%\web\scripts\
 %PROJECT_HOME%\web\styles\
    %PROJECT_HOME%\web\WEB-INF
    %PROJECT_HOME%\web\WEB-INF\menu-config.xml
    %PROJECT_HOME%\web\WEB-INF\struts-bean.tld
    %PROJECT_HOME%\web\WEB-INF\struts-config.xml
    %PROJECT_HOME%\web\WEB-INF\struts-html.tld
    %PROJECT_HOME%\web\WEB-INF\struts-logic.tld
    %PROJECT_HOME%\web\WEB-INF\struts-menu.tld
    %PROJECT_HOME%\web\WEB-INF\struts-menu-el.tld
    %PROJECT_HOME%\web\WEB-INF\struts-nested.tld
    %PROJECT_HOME%\web\WEB-INF\struts-tiles.tld
    %PROJECT_HOME%\web\WEB-INF\web.xml

六、实战Struts-Menu
  1:使用配置文件实现静态菜单
  新建JSP文件web/static-menu.jsp,内容如下:

<% @ page contentType = " text/html; charset=GBK "   %>
<% @ taglib uri = " struts-menu "  prefix = " menu "   %>

< menu:useMenuDisplayer  name ="ListMenu"  
    bundle
="org.apache.struts.action.MESSAGE" >
    
< menu:displayMenu  name ="DoorSite" />
</ menu:useMenuDisplayer >

运行Tomcat,在IE地址栏输入 http://localhost:8080/mymenu/static-menu.jsp查看

2:实现中文化
  > 在src\application_zh_CN.properties中增加下面的内容,Unicode可以通过JDK自带的native2ascii工具得到:
#门户网站
menu.DoorSite
= \u95e8\u6237\u7f51\u7ad9
#雅虎
menu.Yahoo
= \u96c5\u864e
#雅虎首页
menu.YahooIndex
= \u96c5\u864e\u9996\u9875
#雅虎邮件
menu.YahooMail
= \u96c5\u864e\u90ae\u4ef6
#搜狐
menu.Sohu
= \u641c\u72d0
#新浪
menu.Sina
= \u65b0\u6d6a
> 在src\application.properties中增加下面的内容:

#门户网站
menu.DoorSite
= DoorSite
#雅虎
menu.Yahoo
= Yahoo
#雅虎首页
menu.YahooIndex
= Yahoo Index
#雅虎邮件
menu.YahooMail
= Yahoo Mail
#搜狐
menu.Sohu
= Sohu
#新浪
menu.Sina
= Sina
> 修改menu-config.xml文件<Menus></Menus>部分:

< Menus >
    
< Menu   name ="DoorSite"   title ="menu.DoorSite"   description ="Some famous doorsite"  width ="50" >
       
< Item    name ="Yahoo"    title ="menu.Yahoo" >
           
< Item    name ="YahooIndex"    title ="menu.YahooIndex"    location ="http://www.yahoo.com.cn" />
           
< Item    name ="YahooMail"     title ="menu.YahooMail"     location ="http://cn.mail.yahoo.com" />
       
</ Item >
       
< Item     name ="Sohu"   title ="menu.Sohu"    location ="http://www.sohu.com" />
       
< Item     name ="Sina"   title ="menu.Sina"    location ="http://www.sina.com.cn" />
    
</ Menu >
  
</ Menus >
重起Tomcat,在IE地址栏输入 http://localhost:8080/mymenu/static-menu.jsp查看

  3:结合数据库实现动态菜单
  > 新建数据myexamples:
CREATE DATABASE myexamples
  > 新建数据库表menu_item:

CREATE TABLE menu_item (
   id BIGINT not null
,
   parent_name VARCHAR(
30 ) ,
   name VARCHAR(
30 ) ,
   title VARCHAR(
30 ) ,
   titleCN VARCHAR(
30 ) ,
   description VARCHAR(
50 ) ,
   location VARCHAR(
255 ) ,
   target VARCHAR(
10 ) ,
   onclick VARCHAR(
100 ) ,
   onmouseover VARCHAR(
100 ) ,
   onmouseout VARCHAR(
100 ) ,
   image VARCHAR(
50 ) ,
   altImage VARCHAR(
30 ) ,
   tooltip VARCHAR(
100 ) ,
   roles VARCHAR(
100 ) ,
   page VARCHAR(
255 ) ,
   width VARCHAR(
5 ) ,
   height VARCHAR(
5 ) ,
   forward VARCHAR(
50 ) ,
   action VARCHAR(
50 ) ,
   primary key (id)
)


> 插入测试数据:
INSERT INTO menu_item
    (id
,  parent_name ,  name ,  title ,  titleCN ,  location)
VALUES
    (
1 , null , 'DatabaseMenu' , 'Database Menu' , '数据库动态菜单' , null) ,
    (
2 , 'DatabaseMenu' , 'Yahoo' , 'Yahoo Mail' , '雅虎邮件' , 'http://mail.yahoo.com') ,
    (
3 , 'DatabaseMenu' , 'JavaBlogs' , 'JavaBlogs' , 'Java博客' , 'http://javablogs.com') ,
    (
4 , null , 'StandaloneMenu' , 'Standalone Menu' , '独立的菜单' , 'http://www.sohu.com')
> 将数据库驱动程序放到lib目录中,并加入到Build Path,如MySQL的数据库驱动mysql-connector-java-3.1.8-bin.jar,解压缩commons-collections-3.1.zip,将commons-collections-3.1.jar释放到lib目录,并加入Build Path
  > 新建一个Struts的Action,代码如下:

package  cn.appex.menu;

import  java.io.UnsupportedEncodingException;
import  java.sql.Connection;
import  java.sql.DriverManager;
import  java.sql.PreparedStatement;
import  java.sql.ResultSet;
import  java.sql.SQLException;
import  java.util.ArrayList;
import  java.util.HashMap;
import  java.util.ListResourceBundle;
import  java.util.Map;

import  com.mysql.jdbc.Driver;

import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;
import  javax.servlet.http.HttpSession;

import  net.sf.navigator.menu.MenuComponent;
import  net.sf.navigator.menu.MenuRepository;
import  net.sf.navigator.menu.PermissionsAdapter;

import  org.apache.struts.action.Action;
import  org.apache.struts.action.ActionForm;
import  org.apache.struts.action.ActionForward;
import  org.apache.struts.action.ActionMapping;

public   class  MenuAction  extends  Action {
    
public  ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            
throws  Exception {
        buildMenuRepository(request);
        buildMenuResourceBundle(request);
        buildMenuPermissions(request);
        
return  (mapping.findForward( " success " ));
    }

    
/**
     * 创建菜单数据结构
     * 
     * 
@param  request
     
*/
    
private   void  buildMenuRepository(HttpServletRequest request) {
        MenuRepository repository 
=   new  MenuRepository();
        
//  Get the repository from the application scope - and copy the
        
//  DisplayerMappings from it.
        MenuRepository defaultRepository  =  (MenuRepository) request
                .getSession().getServletContext().getAttribute(
                        MenuRepository.MENU_REPOSITORY_KEY);
        repository.setDisplayers(defaultRepository.getDisplayers());

        Map[] menus 
=  getMenuComponents();
        
for  ( int  i = 0 ; i  <  menus.length; i ++ ) {
            MenuComponent mc 
=   new  MenuComponent();
            Map row 
=  menus[i];
            String name 
=  (String) row.get( " name " );
            mc.setName(name);
            String parent 
=  (String) row.get( " parent_name " );
            System.out.println(name 
+   " , parent is:  "   +  parent);
            
if  (parent  !=   null ) {
                MenuComponent parentMenu 
=  repository.getMenu(parent);
                
if  (parentMenu  ==   null ) {
                    System.out.println(
" parentMenu ' "   +  parent  +   " ' doesn't exist! " );
                    
//  create a temporary parentMenu
                    parentMenu  =   new  MenuComponent();
                    parentMenu.setName(parent);
                    repository.addMenu(parentMenu);
                }

                mc.setParent(parentMenu);
            }
            String title 
=  (String) row.get( " title " );
            mc.setTitle(title);
            String location 
=  (String) row.get( " location " );
            mc.setLocation(location);
            String description 
=  (String) row.get( " description " );
            mc.setDescription(description);
            repository.addMenu(mc);
        }
        
        request.setAttribute(
" examplesRepository " , repository);
    }

    
/**
     * 从数据库中读取菜单配置信息
     * 
     * 
@return
     
*/
    
private  Map[] getMenuComponents() {
        ArrayList list 
=   new  ArrayList();
        Connection conn 
=   null ;
        PreparedStatement pstmt 
=   null ;
        ResultSet rest 
=   null ;
        String sql 
=   " select name,parent_name,title,location,description from menu_item order by id " ;
        
try  {
            Class.forName(
" com.mysql.jdbc.Driver " ).newInstance();
            conn 
=  DriverManager.getConnection( " jdbc:mysql://localhost/myexamples?user=root&password=mywangya&useUnicode=true&characterEncoding=UTF-8 " );
            pstmt 
=  conn.prepareStatement(sql);
            rest 
=  pstmt.executeQuery();
            
while  (rest.next()) {
                
int  i  =   1 ;
                HashMap map 
=   new  HashMap();
                map.put(
" name " , rest.getString(i ++ ));
                map.put(
" parent_name " , rest.getString(i ++ ));
                map.put(
" title " , rest.getString(i ++ ));
                map.put(
" location " , rest.getString(i ++ ));
                map.put(
" description " , rest.getString(i ++ ));
                list.add(map);
            }
        } 
catch  (SQLException ex) {
            ex.printStackTrace();
        } 
catch  (InstantiationException e) {
            e.printStackTrace();
        } 
catch  (IllegalAccessException e) {
            e.printStackTrace();
        } 
catch  (ClassNotFoundException e) {
            e.printStackTrace();
        } 
finally  {
            
try  {
                
if  ( null != rest) rest.close();
                
if  ( null != pstmt) pstmt.close();
                
if  ( null != conn) conn.close();
            } 
catch  (SQLException e) {
                e.printStackTrace();
            }
        }
        
        
return  (Map[]) list.toArray( new  HashMap[ 0 ]);
    }
    
    
/**
     * 构造菜单权限
     * 
     * 
@param  request
     
*/
    
private   void  buildMenuPermissions(HttpServletRequest request) {
        PermissionsAdapter permession 
=   new  PermissionsAdapter() {
            
public   boolean  isAllowed(MenuComponent menu) {
                
//  名称等于StandaloneMenu的菜单不显示
                 return   ! " StandaloneMenu " .equalsIgnoreCase(menu.getName());
            }
        };
        request.setAttribute(
" examplesPermession " , permession);
    }

    
/**
     * 构造菜单显示标题
     * 
     * 
@param  request
     
*/
    
private   void  buildMenuResourceBundle(HttpServletRequest request) {
        MenuResourceBundle resourceBundle 
=   new  MenuResourceBundle();
        request.setAttribute(
" examplesBundle " , resourceBundle);
    }
    
    
/**
     * MenuResourceBundle树状菜单国际语言显示
     * 
     * 
@author  wenbin.zhang
     *  
     
*/
    
class  MenuResourceBundle  extends  ListResourceBundle {
        
private  ArrayList list  =   new  ArrayList();

        
public  MenuResourceBundle() {
            Connection conn 
=   null ;
            PreparedStatement pstmt 
=   null ;
            ResultSet rest 
=   null ;
            String sql 
=   " select title,titleCN from menu_item order by id " ;
            
try  {
                Class.forName(
" com.mysql.jdbc.Driver " ).newInstance();
                conn 
=  DriverManager.getConnection( " jdbc:mysql://localhost/myexamples?user=root&password=mywangya&useUnicode=true&characterEncoding=UTF-8 " );
                pstmt 
=  conn.prepareStatement(sql);
                rest 
=  pstmt.executeQuery();
                
while  (rest.next()) {
                    
int  i  =   1 ;
                    String[] message 
=   new  String[ 2 ];
                    message[
0 =  rest.getString(i ++ );
                    
try  {
                        message[
1 =   new  String(rest.getString(i ++ ).getBytes( " latin1 " ),  " gbk " );
                    } 
catch  (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    
if  (message[ 0 !=   null   &&  message[ 1 !=   null ) {
                        list.add(message);
                    }
                }
            } 
catch  (SQLException ex) {
                ex.printStackTrace();
            } 
catch  (InstantiationException e) {
                e.printStackTrace();
            } 
catch  (IllegalAccessException e) {
                e.printStackTrace();
            } 
catch  (ClassNotFoundException e) {
                e.printStackTrace();
            } 
finally  {
                
try  {
                    
if  ( null != rest) rest.close();
                    
if  ( null != pstmt) pstmt.close();
                    
if  ( null != conn) conn.close();
                } 
catch  (SQLException e) {
                    e.printStackTrace();
                }
            }

        }

        
public  Object[][] getContents() {
            
return  (String[][]) list.toArray( new  String[ 0 ][ 0 ]);
        }
    }
}

> 将struts-config.xml文件的<action-mappings />部分修改为:
< action-mappings >
  
< action  path ="/menuAction"  type ="cn.appex.menu.MenuAction"   >
    
< forward  name ="success"  path ="/struts-menu/dynamic-menu.jsp"   />
  
</ action >
</ action-mappings >
> 新建JSP文件web/dynamic-menu.jsp,内容如下:
<% @ page contentType="text/html; charset=GBK"  %>
<% @ taglib uri="struts-menu" prefix="menu"  %>

< p > 没有使用Bundle和权限控制:
< menu:useMenuDisplayer  name ="ListMenu"  repository ="examplesRepository" >
    
< menu:displayMenu  name ="DatabaseMenu" />
    
< menu:displayMenu  name ="StandaloneMenu" />
</ menu:useMenuDisplayer ></ p >

< p > 使用Bundle, 没有使用权限控制:
< menu:useMenuDisplayer  name ="ListMenu"  bundle ="examplesBundle"  repository ="examplesRepository" >
    
< menu:displayMenu  name ="DatabaseMenu" />
    
< menu:displayMenu  name ="StandaloneMenu" />
</ menu:useMenuDisplayer ></ p >

< p > 使用Bundle和权限控制:
< menu:useMenuDisplayer  name ="ListMenu"  permissions ="examplesPermession"   bundle ="examplesBundle"  repository ="examplesRepository" >
    
< menu:displayMenu  name ="DatabaseMenu" />
    
< menu:displayMenu  name ="StandaloneMenu" />
</ menu:useMenuDisplayer ></ p >

七、关于Struts-Menu配置文件和API的使用方法,请参考附录中的官方网站


附:
Struts-Menu官方网站:http://struts-menu.sourceforge.net
数据库驱动的动态菜单:http://demo.raibledesigns.com/struts-menu/dynamicMenu.jsp

你可能感兴趣的:(实战Struts-Menu)