Struts原理与实践(8)
来源:互联网 发布:php pathinfo模式 编辑:程序博客网 时间:2024/06/02 03:31
Struts原理与实践(8) 作者:张永美 罗会波 发文时间:2004.11.05 在上一篇文章中介绍JavaScript实现级联下拉菜单的例子,本篇继续介绍一个利用现存的JavaScript代码配合struts构成一个树型菜单的例子。
大家知道,树型菜单在应用中有着十分广泛的用途。实现树型菜单的途径较多,本文介绍的一种觉得理解起来比较直观,与上篇文章的方法比较类似:就是将树型菜单的节点保存在数据库表中(当然,在实际项目中,节点的信息往往并不是放在一个单一的表中的。比如:在一个权限管理系统中,这些信息可能分别放在用户表、角色表、功能表等表中,只要设法让查询出来的结果与下面给出的表格的内容相似就可以了。只要稍微有些数据库方面的知识做到这点并不难,详细的实现细节超出了本文的主题,不在此细说)。通过数据访问对象将其从数据库中查出后放在一个集合对象中,并将该集合对象传递给客户端,再用一段现存的JavaScript代码--dtree(一个免费的JavaScript程序)来操作集合中的数据。大方向确定之后,我们就来具体着手来实现它。
根据dtree的要求,我们来建一个数据库表来存储树的节点信息,表名为functions,其结构如下:
在表中输入如下一些记录以供后面的实验用:
到此,数据库方面的准备工作就告一段落。
接下来的工作我们仍然在先前介绍的mystruts项目中进行。先编写一个名为:FunctionsForm的ActionForm,其代码如下:
因为我们的树型节点的数据都存储在数据库表中,接下来,要做一个数据访问对象类,名称为:FunctionsDao.java,其代码如下:
这里值得注意的是:在以往我们见到的一些显示树型菜单的程序,如:一些asp程序中往往简单地采用递归调用的方法来查找到树的各个节点。这对那些树的深度不确定的场合还是有些用处,但这种处理方法也有一个致命的弱点,那就是反复地进行数据库查询,对一些节点较多的应用,对应用程序性能的影响是非常大的,有时会慢得让人难以接受;而在实际的应用中大多数情况下树的深度往往是有限的,如:用于会计科目的树一般最多也在六层以下。又如:用作网页功能菜单的情况,网页设计的原则就有一条是:达到最终目的地,鼠标点击次数最好不要多于三次。因此,在实际设计存储树型结构的表时要考虑查询的效率。对能确定树的最大深度的情况下,要设法尽量优化查询语句,减少查询次数,以提高应用程序的性能同时减少数据库的负荷。
本例对应的Action的名称为FunctionsAction,其代码如下:
在struts-config.xml文件中加入如下内容:
为了对应配置中的 ,我们还要提供一个显示错误信息的jsp页面,其代码如下:
下面,我们来看一下我们显示树型菜单的页面代码,从配置中可以看出,页面的名称为testDTree.jsp,代码如下:
从 可以看出,我们要在mystruts目录下,建一个名为js的目录,并将下载的dtree文件dtree.js放在该目录中。
再在mystruts目录下分别建一个名为img和名为css的目录,将dtree中用到的图标和层叠样式表单文件分别放在相应的目录中。
有关dtree的使用方法,详见其说明文档,如:api.html。笔者在此要感谢dtree的作者为我们提供了一个结构如此清晰的javascript程序!
现在,可以编译执行这个例子程序了,编译后在浏览器中输入:http://127.0.0.1:8080/mystruts/functionsAction.do就可以看到运行效果。效果图为:
注:dtree的下载地址为: http://www.destroydrop.com/javascripts/tree/
大家知道,树型菜单在应用中有着十分广泛的用途。实现树型菜单的途径较多,本文介绍的一种觉得理解起来比较直观,与上篇文章的方法比较类似:就是将树型菜单的节点保存在数据库表中(当然,在实际项目中,节点的信息往往并不是放在一个单一的表中的。比如:在一个权限管理系统中,这些信息可能分别放在用户表、角色表、功能表等表中,只要设法让查询出来的结果与下面给出的表格的内容相似就可以了。只要稍微有些数据库方面的知识做到这点并不难,详细的实现细节超出了本文的主题,不在此细说)。通过数据访问对象将其从数据库中查出后放在一个集合对象中,并将该集合对象传递给客户端,再用一段现存的JavaScript代码--dtree(一个免费的JavaScript程序)来操作集合中的数据。大方向确定之后,我们就来具体着手来实现它。
根据dtree的要求,我们来建一个数据库表来存储树的节点信息,表名为functions,其结构如下:
id字段:varchar 10 主键--节点标识码pid字段:varchar 10 not null--父节点标识码name字段:varchar 20 not nullurl字段:varchar 50 notnull--这个字段存储的是点击该节点时,要定位的资源(比如一个页面的url),为了不使本文的篇幅过长,暂时不给出相应的页面,您可以随便输入一个字母比如:a,以使本例能够正常运行。title字段:varchar 20target字段:varchar 10icon字段:varchar 20iconopen字段:varchar 20opened字段:char 1
在表中输入如下一些记录以供后面的实验用:
0、-1、我的权限、javascript: void(0);00、0、用户管理、javascript: void(0);0001、00、创建新用户;0002、00、删除用户;01、0、文章管理、javascript: void(0);0101、01、添加新文章;0102、01、修改文章;0103、01、删除文章;
到此,数据库方面的准备工作就告一段落。
接下来的工作我们仍然在先前介绍的mystruts项目中进行。先编写一个名为:FunctionsForm的ActionForm,其代码如下:
package entity;import org.apache.struts.action.*;import javax.servlet.http.*;public class FunctionsForm extends ActionForm { private String icon; private String iconOpen; private String id; private String name; private String opened; private String pid; private String target; private String title; private String url; public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public String getIconOpen() { return iconOpen; } public void setIconOpen(String iconOpen) { this.iconOpen = iconOpen; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getOpened() { return opened; } public void setOpened(String opened) { this.opened = opened; } public String getPid() { return pid; } public void setPid(String pid) { this.pid = pid; } public String getTarget() { return target; } public void setTarget(String target) { this.target = target; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; }}
因为我们的树型节点的数据都存储在数据库表中,接下来,要做一个数据访问对象类,名称为:FunctionsDao.java,其代码如下:
package db;import java.sql.*;import java.util.*;import entity.FunctionsForm;public class FunctionsDao { private static Connection con = null; public FunctionsDao(Connection con) { this.con=con; } public static Collection findTree() { PreparedStatement ps=null; ResultSet rs = null; ArrayList list=new ArrayList(); String sql="select * from functions"; try{ if(con.isClosed()){ throw new IllegalStateException("error.unexpected"); } ps=con.prepareStatement(sql); rs=ps.executeQuery(); while(rs.next()){ FunctionsForm functionsForm=new FunctionsForm(); functionsForm.setId(rs.getString("id")); functionsForm.setPid(rs.getString("pid")); functionsForm.setName(rs.getString("name")); functionsForm.setUrl(rs.getString("url")); functionsForm.setTitle(rs.getString("title")); functionsForm.setTarget(rs.getString("target")); functionsForm.setIcon(rs.getString("icon")); functionsForm.setIconOpen(rs.getString("iconOpen")); functionsForm.setOpened(rs.getString("opened")); list.add(functionsForm); } return list; } catch(SQLException e){ e.printStackTrace(); throw new RuntimeException("error.unexpected"); } finally{ try{ if(ps!=null) ps.close(); if(rs!=null) rs.close(); }catch(SQLException e){ e.printStackTrace(); throw new RuntimeException("error.unexpected"); } } }}
这里值得注意的是:在以往我们见到的一些显示树型菜单的程序,如:一些asp程序中往往简单地采用递归调用的方法来查找到树的各个节点。这对那些树的深度不确定的场合还是有些用处,但这种处理方法也有一个致命的弱点,那就是反复地进行数据库查询,对一些节点较多的应用,对应用程序性能的影响是非常大的,有时会慢得让人难以接受;而在实际的应用中大多数情况下树的深度往往是有限的,如:用于会计科目的树一般最多也在六层以下。又如:用作网页功能菜单的情况,网页设计的原则就有一条是:达到最终目的地,鼠标点击次数最好不要多于三次。因此,在实际设计存储树型结构的表时要考虑查询的效率。对能确定树的最大深度的情况下,要设法尽量优化查询语句,减少查询次数,以提高应用程序的性能同时减少数据库的负荷。
本例对应的Action的名称为FunctionsAction,其代码如下:
package action;import entity.*;import org.apache.struts.action.*;import javax.servlet.http.*;import javax.sql.DataSource;import java.sql.Connection;import java.sql.SQLException;import java.util.Collection;import db.FunctionsDao;public class FunctionsAction extends Action { public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { DataSource dataSource; Connection cnn=null; ActionErrors errors=new ActionErrors(); try{ dataSource = getDataSource(httpServletRequest,"A"); cnn = dataSource.getConnection(); FunctionsDao functionsDao=new FunctionsDao(cnn); Collection col=functionsDao.findTree(); httpServletRequest.setAttribute("treeList",col); return actionMapping.findForward("success"); } catch(Throwable e){ e.printStackTrace(); //throw new RuntimeException("未能与数据库连接"); ActionError error=new ActionError(e.getMessage()); errors.add(ActionErrors.GLOBAL_ERROR,error); } finally{ try{ if(cnn!=null) cnn.close(); } catch(SQLException e){ throw new RuntimeException(e.getMessage()); } } saveErrors(httpServletRequest,errors); return actionMapping.findForward("fail"); }}
在struts-config.xml文件中加入如下内容:
<form-beans> <form-bean name="functionsForm" type="entity.FunctionsForm" /> </form-beans><action-mappings> <action name="functionsForm" path="/functionsAction" scope="request"type="action.FunctionsAction" validate="false" ><forward name="success" path="/testDTree.jsp" /><forward name="fail" path="/genericError.jsp" /> </action> </action-mappings>
为了对应配置中的
<%@ page contentType="text/html; charset=UTF-8" %><%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><html><head><title>genericError</title><link href="css/mycss.css" rel="stylesheet" type="text/css"></head><body bgcolor="#ffffff"><html:errors/></body></html>
下面,我们来看一下我们显示树型菜单的页面代码,从配置中可以看出,页面的名称为testDTree.jsp,代码如下:
<%@ page contentType="text/html; charset=UTF-8" %><%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %><%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><html><head><title>testDTree</title><link rel="StyleSheet" href="css/dtree.css" type="text/css" /></head><body bgcolor="#eeeeee"><body leftmargin="0" topmargin="0"><table width="180"><tr><td height="300" valign="top" nowrap><script type="text/javascript" src="js/dtree.js"></script><script type='text/javascript'>tree = new dTree('tree');tree.config.folderLinks=false;tree.config.useCookies=false;<logic:iterate id="functionsForm" name="treeList" scope="request"type="entity.FunctionsForm"> tree.add("<bean:write name="functionsForm" property="id"/>","<bean:writename="functionsForm" property="pid"/>","<bean:write name="functionsForm"property="name"/>","<bean:write name="functionsForm"property="url"/>","<bean:write name="functionsForm"property="title"/>","<bean:write name="functionsForm"property="target"/>","<bean:write name="functionsForm" property="icon"/>");</logic:iterate> document.write(tree);</script> </td> </tr></table></body></html>
从 可以看出,我们要在mystruts目录下,建一个名为js的目录,并将下载的dtree文件dtree.js放在该目录中。
再在mystruts目录下分别建一个名为img和名为css的目录,将dtree中用到的图标和层叠样式表单文件分别放在相应的目录中。
有关dtree的使用方法,详见其说明文档,如:api.html。笔者在此要感谢dtree的作者为我们提供了一个结构如此清晰的javascript程序!
现在,可以编译执行这个例子程序了,编译后在浏览器中输入:http://127.0.0.1:8080/mystruts/functionsAction.do就可以看到运行效果。效果图为:
注:dtree的下载地址为: http://www.destroydrop.com/javascripts/tree/
- Struts原理与实践(8)
- Struts原理与实践(8)
- [Struts]原理与实践
- Struts原理与实践 - -
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践 - -
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践(1)
- Struts原理与实践(2)
- Struts原理与实践(3)
- Struts原理与实践(1)
- Struts原理与实践(2)
- samba的简单配置
- Struts原理与实践(7)
- 通过 Java Swing 看透 MVC 设计模式
- 3·14 - 心里永远不会忘记的日子
- JAVA从入门到精通
- Struts原理与实践(8)
- MVC在Web系统中的模式与应用
- Struts学习(一)*.jsp生成的*.java文件路径自定义
- JAVA程序员面试32问,你能回答多少题?(ZZ)
- 入门1
- 利用母版页快速标准化站点
- 入门2
- 入门3
- 通过可视化继承和页面模板控制站点设计