一、简介
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,代码如下:
1
package cn.appex.menu;
2
3
import java.io.UnsupportedEncodingException;
4
import java.sql.Connection;
5
import java.sql.DriverManager;
6
import java.sql.PreparedStatement;
7
import java.sql.ResultSet;
8
import java.sql.SQLException;
9
import java.util.ArrayList;
10
import java.util.HashMap;
11
import java.util.ListResourceBundle;
12
import java.util.Map;
13
14
import com.mysql.jdbc.Driver;
15
16
import javax.servlet.http.HttpServletRequest;
17
import javax.servlet.http.HttpServletResponse;
18
import javax.servlet.http.HttpSession;
19
20
import net.sf.navigator.menu.MenuComponent;
21
import net.sf.navigator.menu.MenuRepository;
22
import net.sf.navigator.menu.PermissionsAdapter;
23
24
import org.apache.struts.action.Action;
25
import org.apache.struts.action.ActionForm;
26
import org.apache.struts.action.ActionForward;
27
import org.apache.struts.action.ActionMapping;
28
29
public class MenuAction extends Action
{
30
public ActionForward execute(ActionMapping mapping, ActionForm form,
31
HttpServletRequest request, HttpServletResponse response)
32
throws Exception
{
33
buildMenuRepository(request);
34
buildMenuResourceBundle(request);
35
buildMenuPermissions(request);
36
return (mapping.findForward("success"));
37
}
38
39
/** *//**
40
* 创建菜单数据结构
41
*
42
* @param request
43
*/
44
private void buildMenuRepository(HttpServletRequest request)
{
45
MenuRepository repository = new MenuRepository();
46
// Get the repository from the application scope - and copy the
47
// DisplayerMappings from it.
48
MenuRepository defaultRepository = (MenuRepository) request
49
.getSession().getServletContext().getAttribute(
50
MenuRepository.MENU_REPOSITORY_KEY);
51
repository.setDisplayers(defaultRepository.getDisplayers());
52
53
Map[] menus = getMenuComponents();
54
for (int i=0; i < menus.length; i++)
{
55
MenuComponent mc = new MenuComponent();
56
Map row = menus[i];
57
String name = (String) row.get("name");
58
mc.setName(name);
59
String parent = (String) row.get("parent_name");
60
System.out.println(name + ", parent is: " + parent);
61
if (parent != null)
{
62
MenuComponent parentMenu = repository.getMenu(parent);
63
if (parentMenu == null)
{
64
System.out.println("parentMenu '" + parent + "' doesn't exist!");
65
// create a temporary parentMenu
66
parentMenu = new MenuComponent();
67
parentMenu.setName(parent);
68
repository.addMenu(parentMenu);
69
}
70
71
mc.setParent(parentMenu);
72
}
73
String title = (String) row.get("title");
74
mc.setTitle(title);
75
String location = (String) row.get("location");
76
mc.setLocation(location);
77
String description = (String) row.get("description");
78
mc.setDescription(description);
79
repository.addMenu(mc);
80
}
81
82
request.setAttribute("examplesRepository", repository);
83
}
84
85
/** *//**
86
* 从数据库中读取菜单配置信息
87
*
88
* @return
89
*/
90
private Map[] getMenuComponents()
{
91
ArrayList list = new ArrayList();
92
Connection conn = null;
93
PreparedStatement pstmt = null;
94
ResultSet rest = null;
95
String sql = "select name,parent_name,title,location,description from menu_item order by id";
96
try
{
97
Class.forName("com.mysql.jdbc.Driver").newInstance();
98
conn = DriverManager.getConnection("jdbc:mysql://localhost/myexamples?user=root&password=mywangya&useUnicode=true&characterEncoding=UTF-8");
99
pstmt = conn.prepareStatement(sql);
100
rest = pstmt.executeQuery();
101
while (rest.next())
{
102
int i = 1;
103
HashMap map = new HashMap();
104
map.put("name", rest.getString(i++));
105
map.put("parent_name", rest.getString(i++));
106
map.put("title", rest.getString(i++));
107
map.put("location", rest.getString(i++));
108
map.put("description", rest.getString(i++));
109
list.add(map);
110
}
111
} catch (SQLException ex)
{
112
ex.printStackTrace();
113
} catch (InstantiationException e)
{
114
e.printStackTrace();
115
} catch (IllegalAccessException e)
{
116
e.printStackTrace();
117
} catch (ClassNotFoundException e)
{
118
e.printStackTrace();
119
} finally
{
120
try
{
121
if (null!=rest) rest.close();
122
if (null!=pstmt) pstmt.close();
123
if (null!=conn) conn.close();
124
} catch (SQLException e)
{
125
e.printStackTrace();
126
}
127
}
128
129
return (Map[]) list.toArray(new HashMap[0]);
130
}
131
132
/** *//**
133
* 构造菜单权限
134
*
135
* @param request
136
*/
137
private void buildMenuPermissions(HttpServletRequest request)
{
138
PermissionsAdapter permession = new PermissionsAdapter()
{
139
public boolean isAllowed(MenuComponent menu)
{
140
// 名称等于StandaloneMenu的菜单不显示
141
return !"StandaloneMenu".equalsIgnoreCase(menu.getName());
142
}
143
};
144
request.setAttribute("examplesPermession", permession);
145
}
146
147
/** *//**
148
* 构造菜单显示标题
149
*
150
* @param request
151
*/
152
private void buildMenuResourceBundle(HttpServletRequest request)
{
153
MenuResourceBundle resourceBundle = new MenuResourceBundle();
154
request.setAttribute("examplesBundle", resourceBundle);
155
}
156
157
/** *//**
158
* MenuResourceBundle树状菜单国际语言显示
159
*
160
* @author wenbin.zhang
161
*
162
*/
163
class MenuResourceBundle extends ListResourceBundle
{
164
private ArrayList list = new ArrayList();
165
166
public MenuResourceBundle()
{
167
Connection conn = null;
168
PreparedStatement pstmt = null;
169
ResultSet rest = null;
170
String sql = "select title,titleCN from menu_item order by id";
171
try
{
172
Class.forName("com.mysql.jdbc.Driver").newInstance();
173
conn = DriverManager.getConnection("jdbc:mysql://localhost/myexamples?user=root&password=mywangya&useUnicode=true&characterEncoding=UTF-8");
174
pstmt = conn.prepareStatement(sql);
175
rest = pstmt.executeQuery();
176
while (rest.next())
{
177
int i = 1;
178
String[] message = new String[2];
179
message[0] = rest.getString(i++);
180
try
{
181
message[1] = new String(rest.getString(i++).getBytes("latin1"), "gbk");
182
} catch (UnsupportedEncodingException e)
{
183
e.printStackTrace();
184
}
185
if (message[0] != null && message[1] != null)
{
186
list.add(message);
187
}
188
}
189
} catch (SQLException ex)
{
190
ex.printStackTrace();
191
} catch (InstantiationException e)
{
192
e.printStackTrace();
193
} catch (IllegalAccessException e)
{
194
e.printStackTrace();
195
} catch (ClassNotFoundException e)
{
196
e.printStackTrace();
197
} finally
{
198
try
{
199
if (null!=rest) rest.close();
200
if (null!=pstmt) pstmt.close();
201
if (null!=conn) conn.close();
202
} catch (SQLException e)
{
203
e.printStackTrace();
204
}
205
}
206
207
}
208
209
public Object[][] getContents()
{
210
return (String[][]) list.toArray(new String[0][0]);
211
}
212
}
213
}
214
215
216
>将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" %>
没有使用Bundle和权限控制:
<menu:useMenuDisplayer name="ListMenu" repository="examplesRepository">
<menu:displayMenu name="DatabaseMenu"/>
<menu:displayMenu name="StandaloneMenu"/>
</menu:useMenuDisplayer>
使用Bundle, 没有使用权限控制:
<menu:useMenuDisplayer name="ListMenu" bundle="examplesBundle" repository="examplesRepository">
<menu:displayMenu name="DatabaseMenu"/>
<menu:displayMenu name="StandaloneMenu"/>
</menu:useMenuDisplayer>
使用Bundle和权限控制:
<menu:useMenuDisplayer name="ListMenu" permissions="examplesPermession" bundle="examplesBundle" repository="examplesRepository">
<menu:displayMenu name="DatabaseMenu"/>
<menu:displayMenu name="StandaloneMenu"/>
</menu:useMenuDisplayer>
重起Tomcat,在地址栏输入http://localhost:8080/mymenu/menuAction.do
七、关于Struts-Menu配置文件和API的使用方法,请参考附录中的官方网站
附:
Struts-Menu官方网站:http://struts-menu.sourceforge.net
数据库驱动的动态菜单:http://demo.raibledesigns.com/struts-menu/dynamicMenu.jsp
posted on 2007-07-11 10:19
冰封的爱 阅读(250)
评论(0) 编辑 收藏 所属分类:
J2EE