📄 新建 文本文档 (4).txt
字号:
<HTML>
<HEAD>
<TITLE>JDBC hidden example</TITLE>
</HEAD>
<BODY>
<P>This page has been hit
<jsp:getProperty name="hitCounter" property="int" />
times. The page counter is implemented indirectly: a JavaBeans component containing the
hit count is inserted into the environment and referenced within the page using
the JSP getProperty action. The JSP page doesn′t have any exposure to JDBC.</P>
</BODY>
</HTML>
被包含的 hitCounter.jsp 文件负责设置环境。内容可以是 scriptlet、标记或只是一个 taglib 伪指令;只要是为表示页面建立预期环境的都可以作为内容。如果您愿意,您可以把 getProperty 操作替换成定制标记;例如:
This page has been hit
<page:hitcounter />
times.
如前所述,这些点击计数器示例纯粹用作说明;每个页面都执行这样的数据库操作将会是不必要的开销。上面这个示例说明事实上您希望以何种方式显现点击计数器。通过把它隐藏在定制标记里,我们就把该实现彻底隐藏了起来。现在我们可以聚集点击计数运行时信息,并周期性的更新数据库(比如,在每次会话结束时)。甚至连存储方式(数据库或是别的)也对表示页面作者隐藏了。这正是我们在 DevTech 实现点击计数器的方式:我们利用 bean 类实现点击计数器模式行为。标记把该行为结合到了我们的页面里。
集成 JavaBean 组件
到目前为止,示例一直都相当简单,但大多数数据库操作都比这些简单的查询和更新要复杂。因此,既然我们已经讨论了把 JDBC 用于 JSP 页面的一些基本原则,就让我们用一个略微复杂些但肯定更加通用的一类应用来结束这篇文章。
这一部分的示例(下面清单 9)将指出一种方法以支持 Web 站点上访问者提供的内容。换句话说,我们希望允许访问者读取与某一 URI 关联的数据库内容并撰写额外的内容。这样的内容在现在的 Web 站点上相当常见。同样的基本部分可用于构造:
评论页面,例如在 Amazon.com 找到的那些页面
链接页面
公告牌
Wikiweb
通过由不同技术背景的设计人员编写,本例中 JSP 组件稍微再精细些的版本就可以实现看上去截然不同的 Web 页面。这些页面看上去的唯一的相同之处就是用于访问者撰写内容。
我们的 annotation(注释)示例使用 HTML 表单。HTML 表单用于 JSP 时,使用属性映射到表单域的 bean 变得方便了。这使 setProperty 标记可以变戏法:
清单 6. 映射到表单的 Bean 实例
<%-- setup a bean instance that matches our form --%>
<jsp:useBean id="instance-name" class="bean-class" ... />
<%-- set all bean properties that match a form field --%>
<jsp:setProperty name="instance-name" property="*" />
映射 bean 和 ResultSet
示例使用 com.devtech.sql 以使说明简洁。示例使用 Java Reflection 和 Introspection,依靠列名及属性名提供 JDBC 数据和 bean 属性间的映射。您可以把 DevTech 包替换成自己的代码。
集成 JavaBean 组件是 JSP 技术设计方面的一个过人之处。不幸的是,bean 和 JDBC 之间的集成根本不是无缝的,因此我们针对 DevTech 的 JDBC 工作开发了一个包,它不仅提供了 bean 和 JDBC 的集成,而且还有必要的异常处理,从而使程序员不必应付这些细节。
annotation(注释)示例使用 com.devtech.sql 包中的两种查询和更新方法。这里用到的查询方法传递一个 bean 类、一个 SQL 查询和一个 Object 数组填充查询中的占位符。在这种情况下,仅有的占位符是给页面的 URL 的。结果是一个数据库游标对象,它必须是一种迭代器。
清单 7. 数据库游标对象
dataBase.queryCursor(AnnotationDBBean.class, new String[] { URL },
"select page, author, annotation, DATE_FORMAT(whenPosted, ′%W %d%b%y %T′)" +
" as whenPosted from annotations where page like ?");
这个查询方法的有趣之处在于指定类型的 bean 将会为您实例化,只要 bean 属性名同 ResultSet 中的列名相对应,属性值就会被自动设置。每次您用游标选择下一行时,bean 的属性就会根据 ResultSet 被自动设置。
用到的这种特殊更新方法有一个 bean 实例、一个 String 数组及一条 update 语句作为参数。String 数组值规定了用来填充更新中的占位符的预期 bean 属性。在这种情况下,page、author 和 annotation 属性是根据 bean 选择的。
清单 8. 更新方法
int count = dataBase.update(annotationBean,
new String[] { "page", "author", "annotation" },
"insert into annotations(page, author, annotation) values(?, ?, ?)");
我们的 JSP 页面示例 annotations.jsp 如清单 9 中所示。高亮的部分指出两个可以用定制标记替换的 scriptlet,如清单 10 中所示。一些为页面设计者提供帮助的 JSP 组件、把动态内容放到页面上去的 getProperty 操作以及标准 HTML 组成了页面的剩余部分。使用 JSP 注释的原因是因为 JSP 注释是私有的,不会出现在输出流中。
清单 9. annotation(注释)的 JSP 页面
<jsp:directive.include file="/pagelets/annotate.jsp" />
<%--
By the time we arrive here, the annotation bean has been established, and if the
form is submitted, the contents will be posted to the database. The page
property is initialized. If the author is known during this session, that property
is also initialized.
Bean: "annotation"
Properties: String page;
String author;
String annotation;
String whenPosted;
Access to any bean property follows the format:
<jsp:getProperty name="annotation" property="property-name" />
--%>
<HTML>
<HEAD>
<TITLE>Comments for <jsp:getProperty name="annotation" property="page" /></TITLE>
</HEAD>
<BODY>
<p align="left"><font size="+1">
Comments for <i><jsp:getProperty name="annotation" property="page" /></i>
</font>.</p>
<CENTER><HR WIDTH="100%"></CENTER>
<!-- Annotation Submission Form -->
<FORM method="POST">
<TABLE>
<TR>
<TH align="left">Name:</TH>
<TD><INPUT type=text name=author size=50 maxlength=60
value="<jsp:getProperty name="annotation" property="author" />"> </TD>
</TR>
<TR>
<TH valign="top" align="left">Note:</TH>
<TD><TEXTAREA name=annotation cols=40 rows=5 wrap=virtual>
<jsp:getProperty name="annotation" property="annotation" /></TEXTAREA></TD>
</TR>
<TR>
<TD align="center" colspan="2"><INPUT type=submit value="Add Comment"></TD>
</TR>
</TABLE>
</FORM>
<!-- End of Annotation Submission Form -->
<!-- beginning of annotations -->
<%--
The following section iterates through all annotations in the database for the
requested page. To change the look of the page, just change anything in the
demarcated area.
--%>
<jsp:scriptlet>
Database.Cursor annotations = annotation.getCursor();
while (annotations.next(annotation) != null)
{
</jsp:scriptlet>
<%-- beginning of annotation change area --%>
<CENTER><HR WIDTH="100%"></CENTER>
From: <jsp:getProperty name="annotation" property="author" /></A>
at <jsp:getProperty name="annotation" property="whenPosted" /><BR>
<jsp:getProperty name="annotation" property="annotation" /><BR>
<%-- end of annotation change area --%>
<jsp:scriptlet>
}
annotations.close();
</jsp:scriptlet>
<!-- end of annotations -->
</BODY>
</HTML>
定制标记等价程序清楚,但不提供信息:
清单 10. 定制标记等价程序
<sql:results queryName="annotations" bean="annotation">
<CENTER><HR WIDTH="100%"></CENTER>
From: <jsp:getProperty name="annotation" property="author" /></A>
at <jsp:getProperty name="annotation" property="whenPosted" /><BR>
<jsp:getProperty name="annotation" property="annotation" /><BR>
</sql:results>
我们在这个示例中使用 scriptlet 只是要让您(一位程序员)知道正在发生的事情。如果用陈述性的标记替换 scriptlet,那么页面设计者会很清楚,但您却一头雾水。
逻辑并不复杂。annotation.getCursor() 调用能得到同服务器的连接、发出查询并在结果集建立一个数据库游标对象 annotations。每次调用 annotations.next() 时,从结果集中取出一个新行,其中的值移到 bean 里,方法返回的正是这个 bean 的引用。所用的这个特殊的 next() 方法使用一个要植入的 bean 参数。虽然我们本可以使游标为每一行实例化一个新的 bean,但反复使用一个 bean 更加高效。
请注意真正的查询及更新都没有在表示页面中出现。被包括的页面设置表示页面环境,也包括 setProperty 和 update 操作。这些操作独立于表示页面;只有注释 bean 的属性所包含的 contract 是重要的。这遵守了将表示与模式行为相分离的策略。页面设计者完全有能力更改表示是如何呈现的,但无从得知数据库是如何集成的。如果更改在数据库更新或查询时生效,就应当由 JSP 程序员负责。
总结
本文对结合使用 JavaServer Page、JavaBean 和 JDBC 技术并通过关系数据库生成动态内容的进行了总结性介绍。我们从对于 JSP 程序员新手来说最显而易见的方法(scriptlet)开始。我们看到不加控制的使用 scriptlet 是如何使逻辑和表示纠缠在一起的,使两者都难以维护。我们还看到标记库并不一定会改善 MVC 分离,如果用编程术语来表示标记,则页面设计人员可能无法理解使用这样的标记的页面。最后,我们看了更为复杂的示例,这些示例说明了几种使数据库访问与内容表示分离的途径。
现在您应该对在对页面设计人员隐藏真实的数据库访问的同时如何把数据库内容集成到一个 Web 站点中有一些基本概念。还请注意,对您(一个程序员)而言,几乎不含信息的那些示例是最适合于页面设计人员的示例。当您为 JSP 解决方案制定计划时,千万要为页面设计人员设身处地地想一想。
参考资料
参加关于本文的讨论论坛。
JavaServer Pages 是一个极佳的起点,它有大量关于 JSP 技术的信息,包括了所有官方文档。
Jakarta Project 的官方主页有 Java Servlet 及 JavaServer Pages 技术的参考实现,并作为许多其它有关的开放源代码团体的中心提供服务。
Java Developer Connection 有一篇关于多个 Jakarta Taglibs Project 库的文章,包括数据库标记。
IBM developerWorks Java 技术专区提供了与供应商无关的、全面的Java (包括 JavaServer Pages 技术)教程和文章。
“JavaServer Pages 技术介绍”(developerWorks,2001 年 8 月),作者是 Noel J. Bergman,这是一篇说明 JavaServer Pages(JSP)技术的基本原理的介绍教程。
“一个简单的 JDBC 包装器”(developerWorks,2001 年 8 月),作者是 Greg Travis,描述了一种简单的包装器库使基本数据库使用成了小事一桩。
“JDBC 3.0 中新增了哪些内容?” (developerWorks,2001 年 7 月)提供了对 Java 数据库连接性 3.0 规范中的新的和增强功能的概要。
JDBC 的官方主页提供了有用的参考资料。
Allaire 的 JRun Server Tags 技术使快速建立定制标记原型成为可能。
关于作者
Noel Bergman 在面向对象编程方面的经历持续 20 多年,包括参与最早的 CORBA 和“公共对象服务任务小组(Common Object Services Task Forces)”。Colorado Software Summit 及其它的业界会议上他一直作为受欢迎的演讲者享有盛誉;他还担任导师和顾问,为客户提供量身定制的服务。
目前,Noel 正涉足于使用开放源代码免费软件为手持设备编程以及开发交互式以数据库为后台的 Web 站点。最后,Noel 还是 GNUJSP 的合著者,GNUJSP 是 JavaServer Pages 技术的开放源代码实现,而且他还首创了 JSP Developers GuideWeb 站点。
查看该新闻的相关评论
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -