⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 新建 文本文档 (4).txt

📁 网站设计方法
💻 TXT
📖 第 1 页 / 共 2 页
字号:
使用JSP技术和JDBC技术访问基于Web的动态数据 
作者:未知     文章来源:www.jspcn.net
访问次数: 次    加入时间:2005-01-19 
 

内容: 

JDBC 基础知识 
JDBC 用于 JSP 页面 
JSP scriptlet 示例 
使用 DBTag 的标记库示例 
对表示页面隐藏 JDBC 
结合 JavaBean 组件 
总结 
参考资料 
关于作者 
评价本文 


相关内容: 

JDBC 3.0 中新增了哪些内容? 
教程:JavaServer Page 技术介绍 
一个简单的 JDBC 包装器 


在 Java 专区中还有: 

教程 
工具和产品 
代码和组件 
文章 




Noel J. Bergman (noel@jspdevguide.com)
CTO,Development Technologies,Inc./DevTech
2001 年 9 月

本文讨论使用 JSP 和 JDBC 技术把静态的、动态的及数据库内容集成在 Web 站点中。为了简洁明了的说明问题,文中的 JSP 页面使用短的 scriptlet 让 JSP 开发者接触到底层的 JDBC 概念,而不是把其隐藏在定制标记中。作者介绍一种集成 JavaBeans 组件和 JDBC 的主要设计方法,该方法同一直以来 JavaServer Pages 技术采用的、把 bean 用于 HTTP 的方式类似。他还提供实现该集成的代码。请在讨论论坛同作者及其它读者分享对本文的理解。
JavaServer Page(JSP)技术建立在 Java Servlet 技术的基础之上,是核心的生成动态内容的服务器端 Java 体系结构。关系数据库是动态内容的来源之一。Web 站点使用关系数据库存储各类信息:目录项、图像、文本、关于注册成员的资料等等,从而管理从在线社区到电子商务交易的一切事务。本文讨论通过 Java 数据库连接(JDBC)把 JSP 技术应用于关系数据库。正是 JDBC 使 Java 程序可以使用关系数据库。

要深入理解本文,您应该熟悉 JDBC 和 SQL。

JDBC 基础知识
JDBC 是 Java 代码和 SQL 数据库之间的一座桥梁。主要的 JDBC 对象表示同数据库的连接及利用这些连接执行的语句。用于关系数据库的两种基本语句是查询和更新。两者都需要的一个前提条件就是,您首先要利用 java.sql.DriverManager 类同数据库建立连接。建立连接要花很长时间(就计算机时间而言),因此在 Web 服务器这种事务繁忙的环境中,您希望尽可能重用连接。这样的重用叫做建立连接池。

如果您的 JDBC 技术有些荒疏了,那么清单 1 中的代码片断说明的是同一个测试数据库建立 connection、创建用于该 connection 的 statement(语句)对象、发出 SQL 查询、处理 results(结果)及释放 JDBC 资源的全过程:

清单 1. 简单的 JDBC 代码 
Connection connection = DriverManager.getConnection(URL, user, password);
Statement statement = connection.createStatement();
ResultSet results = statement.executeQuery(sqlQuery);

while (results.next())
{
... process query results ...
logSQLWarnings(results.getWarnings());
}

results.close();
statement.close();
connection.close();



在现实生活中,JDBC 代码不会如此简单;因为需要处理异常和警告情况。清单 2 说明的是同一个 JDBC 示例,但添加了对 JDBC 异常和警告的处理。在这个示例中,异常和警告只记入日志,并且,对于异常情况,我们将异常终止操作。不过 finally{} 子句将确保资源清除过程进行。 

对真实的结果处理过程在此仅作一下提示;我们将在本文后面的部分接着更仔细的分析这个问题。如果我们正在执行的不是数据库查询而是更新,那我们可以把 while 循环替换成如下语句:

int count = statement.executeUpdate(sqlUpdate); 

除 executeQuery() 和 executeUpdate() 之外,Statement 类也支持一般的 execute() 方法。虽然这允许编写一般的 SQL 代码,但处理结果的过程更复杂了。 
executeUpdate() 方法返回 update 语句所作用的行的总数。

如果这些代码清单中的材料显得陌生,您也许希望花些时间重温一下在参考资料部分中找到的一些 JDBC 教程信息。

JDBC 用于 JSP 页面
那么我们怎样结合使用 JDBC 和 JSP 技术才能使我们的动态内容来自数据库呢?

作为一条普遍的法则,良好的 JSP 惯例建议您应当把表示同模式行为分离。这与面向对象编程中的“模式-视图-控制器(MVC)”范例类似。分离原因之一是,基于 JSP 技术的应用很可能由程序员编写“模式(Model)”和“控制器(Controller)”组件,而由页面设计人员编写“视图(View)”组件。就 JSP 应用体系结构而言,负责表示的“视图”角色由 JSP 页面处理。负责对请求做出响应的“控制器”的角色通常由 servlet 担当,但许多 JSP 用户开始认识到用 JSP 页面来担任“控制器”的角色的优点。“模式”这一角色负责为应用实体的行为构建模式,典型情况下由 JavaBean 组件来担当。

除确定在 MVC 范例中的何处同数据库交互之外,关于在 JSP 页面中集成 JDBC 技术您有多种选择。例如,您可以使用 scriptlet 插入 JDBC 或使用标记库插入,还可以把它隐藏在定制标记或其它的类里。接下来我们要看看一些方式的示例并讨论其用法。

JSP scriptlet 示例
JSP 程序员新手有可能做的第一件事是写一个 scriptlet 来访问 JDBC。也许写出来的这个 scriptlet 象清单 3 中的示例一样使用 JDBC 来实现该页面的“点击计数器”。(这个页面的实际版本位于 JavaServer Page Developers Guide Web 站点上)

清单 3. JSP 页面通过 scriptlet 使用 JDBC 
<jsp:directive.page import="java.sql.*" />
<jsp:scriptlet>
Class.forName("org.gjt.mm.mysql.Driver");
Connection connection = 
DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "", "");
Statement statement = connection.createStatement();
int changed = 
statement.executeUpdate("update counters set hitCount = hitCount + 1 " +
"where page like ′" + request.getRequestURI() + "′");
if (changed == 0) statement.executeUpdate("insert counters(page) values(′" +
request.getRequestURI() + "′)");
ResultSet rs =
statement.executeQuery("select hitCount from counters where page like ′" +
request.getRequestURI() + "′");
rs.next();
int hitCount = rs.getInt(1);
statement.close();
connection.close();
</jsp:scriptlet>

<HTML>
<HEAD>
<TITLE>JDBC scriptlet example</TITLE>
</HEAD>
<BODY>

<P>This page has been hit 
<jsp:expression>hitCount</jsp:expression>
times. The page counter is implemented by a JSP scriptlet calling
the JDBC package directly.</P>

</BODY>
</HTML>



该页面中有一个 scriptlet(高亮的第一部分)连接到数据库、创建 statement(语句)并试图对一个以页面的 URI 为主键的计数器记录进行更新。如果更新没有对任何行起作用,那么这个示例就假定没有这样的记录并添加一条。最后,这个 scriptlet 查询数据库中当前点击计数并把结果赋给一个局部变量。继续往下看,这个 JSP 页面的“表示”部分中高亮的 JSP 表达用于显示点击计数器的值。

注:您也许不希望真的以这种方式实现点击计数器。为每一次请求而更新数据库的开支是不必要的开销。但是,我们可以用点击计数器这个对数据库进行更新和查询的简单示例来说明在您的 JSP 页面中集成 JDBC 的各种途径。 
尽管 JSP 页面能起作用,但它有许多问题。首先,不编程的页面设计者不会希望在页面中看到 scriptlet。坦白的讲,连程序员也不会希望在页面中有这类内容,因为它使页面的实际内容变得杂乱。第二,为简化示例,这个页面缺少异常处理,而这个异常处理应该是实际的 JDBC 代码中的一部分。第三,点击计数器的实现的确是嵌在 JSP 页面里的,因此对点击计数器的任何更改都需复制到使用点击计数器的每个 JSP 页面。

那么我们怎样修改这个 JSP 页面呢?一种常用的解决方案是使用标记库换掉 scriptlet。在下一个示例中,我们会看一下这种可选择的解决方案。

使用 DBTag 的标记库示例
通常善意的朋友和专家会告诉 JSP 程序员新手一些基本知识,其中之一就是不要使用 scriptlet。相反,他们会让 JSP 程序员新手使用定制标记。我们利用定制标记扩展 JSP 平台的功能:同代码库相连的定制 XML 样式标记实现预期功能。我们将会在下个示例中看到 DBTag 的工作情况。

Jakarta TagLibs Project 是 Jakarta Project(请参阅参考资料)的一个子工程,该工程是 Java Servlet 和 JavaServer Pages 技术的官方参考实现。

在 Jakarta TagLibs Project 的支持下开发的一个包是 DBTag 定制标记库(以前叫做 JDBC 标记库)。清单 4 里的 JSP 页面把 scriptlet 替换成定制标记,实现的点击计数器和清单 3 中的一模一样。

清单 4. JSP 页面使用 DBTag 
<HTML>
<HEAD>
<TITLE>Jakarta DBTags example</TITLE>
</HEAD>
<BODY>

<%@ taglib uri="http://jakarta.apache.org/taglibs/dbtags" prefix="sql" %>

<%-- open a database connection --%>

<sql:connection id="conn1">
<sql:url>jdbc:mysql://localhost/test</sql:url>
<sql:driver>org.gjt.mm.mysql.Driver</sql:driver>
</sql:connection>

<%-- insert a row into the database --%>

<sql:statement id="stmt1" conn="conn1">
<%-- set the SQL query --%> 
<sql:query>
insert counters(page,hitCount) values(′<%=request.getRequestURI()%>′, 0)
</sql:query>
<%-- the insert may fail, but the page will continue --%>
<sql:execute ignoreErrors="true"/>
</sql:statement>

<%-- update the hit counter --%>

<sql:statement id="stmt1" conn="conn1">
<%-- set the SQL query --%> 
<sql:query>
update counters set hitCount = hitCount + 1 where page like ′<%=request.getRequestURI()%>′
</sql:query>
<%-- execute the query --%>
<sql:execute/>
</sql:statement>

<P>This page has been hit

<%-- query the hit counter --%>

<sql:statement id="stmt1" conn="conn1"> 
<sql:query>
select hitCount from counters where page like ′<%=request.getRequestURI()%>′
</sql:query>
<%-- process only the first row of the query --%>
<sql:resultSet id="rset2" loop="false">
<sql:getColumn position="1"/>
</sql:resultSet>
</sql:statement>

times. The page counter is implemented using the Jakarta Project′s
DBTags tag library, calling JDBC indirectly.</P>

<%-- close a database connection --%>
<sql:closeConnection conn="conn1"/>

</BODY>
</HTML>



我不知道您的感受如何,可我感觉到有一点失望。在我看来这似乎还不如 scriptlet 示例清晰,而且我知道也不会有哪个不编程的 HTML 页面设计者会对此感到满意。但是问题出在哪儿呢?毕竟,我们已听从了大多数人的建议:我们抛弃了 scriptlet,用定制标记取而代之。

开发定制标记库相对简单些,但也要费些思考,而且费时。我常推荐的做法是标记库的作者们先用 scriptlet 为标记行为建立原型,再把这些 scriptlet 变成标记。 
一种可选择的解决方案是使用 Allaire 的 JRun Server Tag(JST),使您可以通过把每个标记作为一个 JSP 页面(以 .jst 为扩展名)来编写,从而为标记库建立原型。JST 把页面转变成运行时标记处理程序,这样 JST 技术对客户机页面来说就是透明的。虽然 Allaire 宣称“目标是把 JST 建成一种可移植技术以使 J2EE 社区的所有成员都能从中受益”,但 JST 目前还只能在 JRun 中使用。时间将会证明 JST 是否会成为开发标记更通用的工具。与此同时,我们发现 scriptlet 为开发标记的业务逻辑奠定了良好的基础;逻辑经调试后,我们把它迁移成为标记处理程序类。

关于标记库 Allaire 没有告诉您的是:标记设计是一种语言设计。迄今为止,所写的大多数标记库是由程序员为程序员写的;这些标记的语义适合于其它的程序员。不仅如此,还记得模式和表示的分离吗?DBTag 对这一点不太支持。sql:getColumn 标记同 jsp:getProperty 动作类似:它把标记的结果直接发给输出流。这给 DBTag 的利用与把输出转化成要求的格式之间的分离带来了困难。最后,请注意清单 3 和 清单 4 的逻辑差异。DBTag 的 execute 标记使用所有来自通过 JDBC 发送的 update 语句的更新计数;可以回收的只有查询结果。这意味我们无从知道 update 语句更新了多少行。因此我们不得不切换 update 和 insert 语句;我们总是试图插入新记录、迫使 DBTag ?略任何错误,然后执行更新。

对 DBTag 标记库公正的评价是,对于程序员来说这是个不错的标记库。除更新计数的使用外,代码提供的与 JDBC 的映射相当不错。但其中也存在问题:标记提供的只不过是对 JDBC 包的直接翻译。除隐藏了一些异常处理之外,标记库实际上并没有提供对 scriptlet 任何抽象。这对从功能中分离表示当然于事无补。

因此,真正的问题不在于是使用 scriptlet 还是使用标记;这种问题不是分离功能和表示的问题的原因,而是结果。解决方案是要以适当的说明级别上为表示页面的作者提供更高级别的功能。认为标记优于 scriptlet 的原因在于:根据定义,scriptlet 是编程,而标记可以表示高级概念。

对表示页面隐藏 JDBC
将 JDBC 同 JSP 技术集成时,我们希望对表示作者尽可能多的隐藏该集成。在我们显现数据库概念的地方,我们希望在恰当的抽象级别上显现这些概念。这一方法引出了我们的下一个示例。

在清单 5 中的示例中,我们对表示页面隐藏了 JDBC 集成。(这个页面的实际版本位于 JavaServer Pages Developers Guide Web 站点)

清单 5. 隐藏了 JDBC 的 JSP 页面 
<jsp:directive.include file="/pagelets/hitCounter.jsp" />

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -