Servlet和XML:互为补充
Doug Tidwell
developerWorks 职员
2000 年 4
月
研究 Java servlet 和 XML 如何共同生成 XML 文档和 DOM
树,以及它们如何与数据库对接。本文包括几项有用的技术:使用 HTTP 参数控制 DOM 树的处理与生成,而无需 XML 源文档。
对 Java 程序员来说,Servlet 和 XML 是最令人振奋的两项技术。本文是为 2000 年 2 月 17 日旧金山
City Java 用户组准备的演示文稿。在本文中您将看到如何使用 servlet 组成一个简单的 XML 文档,构建一个 DOM
树,并将部分内容显示在用户屏幕上,最后您将看到如何从一个数据库查询生成 XML。
对于本文讨论的示例来说,我们将扩展 HTTPServlet 类。HTTPServlet 类提供了通常与 CGI
程序相关的功能。它支持 put 和 get,并且使您的代码具有对 HTTP 请求标头的完全访问权,包括 UserAgent 域。我们将创建一些简单的
servlet,并说明它们如何处理以 XML 标签标记的信息。在这一过程中我们还将说明文档对象模型 (DOM) 的一些方法。这些简单的应用程序将使您了解当将
servlet 和 XML 组合在一起时您能够做哪些事情。
第一个 servlet 示例
作为开始,我们将编写一个用来生成 XML 文档的
10 行 servlet。在构建理解 XML 的 servlet 时,我们将按以下三个步骤进行:
将内容类型设为 text/xml。
创建 XML 文档。
将 XML 文档写回客户机。
在我们的大多数 Servlet 中,主要精力放在第二步。我们可能根据数据库查询创建一个 XML 文档,也可能基于从客户传送来的 HTTP
参数生成它,或者也可能使用其他类型的数据检索或生成方法。在本文的示例中,将主要考虑 HTTP 参数和数据库查询。
一个基本的 servlet
对于第一个示例,第二步“创建 XML
文档”不是我们所关心的;我们只想生成一个有效的 XML 文档。我们已将文档硬编码到源代码中,如清单 1 所示。
彩色编码
彩色编码清单是本文的一个特色,我们正在 dW
进行试验。为了生成我们的彩色编码清单,我正在使用一些开放源代码的工具。首先,我将文档(Java、HTML、XML 等)载入 Emacs 中。Emacs
定义了关键字、注释、函数名以及其他编程语言构件(大约有十多种)的颜色。在 Emacs 载入文件并为其加上颜色以后,我使用 HTMLize
程序包,这是一种用曾经流行的 Emacs Lisp 语言编写的开放源代码实用工具。HTMLize 接收一个清单(这个清单看起来与在 Emacs
中完全一样),然后将其转换为 HTML。结果将是一个完全彩色编码的文件,它突出显示关键字、注释、函数名等。
请告拆我们您对这些新的、改进的代码清单的想法。
如果您也想这样做,请参阅参考资料中的相应链接。
清单 1. xmlfromscratch.java
public class xmlfromscratch extends HttpServlet
{
public void service(HttpServletRequest
request,
HttpServletResponse response)
throws IOException,
ServletException
{
response.setContentType("text/xml");
PrintWriter out =
response.getWriter();
out.println("<?xml version=\"1.0\"?>");
out.println("<greeting language=\"en_US\">");
out.println(" Hello, World!");
out.println("</greeting>");
}
}
这一段令人兴奋的代码生成的结果如下所示:
清单 2. xmlfromscratch.java 的结果
<?xml version="1.0"?><greeting> Hello,
World!
</greeting>
您可以查看完整清单的 HTML 视图或直接查看 Java 源文件。
生成 XML 段
现在,我们已经创建了一个
servlet,它通过硬编码生成一个没有意义的简单 XML 文档。在下一个 servlet 中,我们从零开始生成一个 DOM 树,然后将 DOM
树的一部分显示在请求者的屏幕上。向请求者发送回的 DOM 树部分取决于 servlet 接收到的 HTTP 参数。本例展示了几项有用的技术:使用 HTTP
参数控制 DOM 树的处理与生成,而无需 XML 源文档。
清单 3 显示了处理 HTTP 参数的代码段:
清单 3. xmlfromdom.java
public void service(HttpServletRequest
request,
HttpServletResponse response)
throws IOException,
ServletException
{
response.setContentType("text/xml");
PrintWriter out =
response.getWriter();
Enumeration
keys;
String key;
String
requestedSubtree = "";
keys =
request.getParameterNames();
while
(keys.hasMoreElements())
{
key = (String)
keys.nextElement();
if
(key.equalsIgnoreCase("subtree"))
requestedSubtree = request.getParameter(key);
}
正如在上一个示例中那样,我们将内容类型设置为 text/xml。在此之后,我们使用
HttpServletRequest.getParameterNames 方法从 HTTP 请求中检索所有参数。
在处理完这些参数以后,我们需要查找用户所请求的信息。我们使用的信息从对象中构建 DOM 树;该 DOM
树包含了莎士比亚十四行诗的文本,以及关于这首十四行诗的其他信息。我们将根据 HTTP subtree 参数返回 DOM 树的一部分。清单 4 显示了构建 DOM
树的部分代码:
清单 4. 构建 DOM 树
Document doc = null;
Element author =
null;
Element lines = null;
Element title =
null;
public void initialize()
{
doc =
(Document)Class.
forName("org.apache.xerces.dom.DocumentImpl").
newInstance();
if (doc !=
null)
{
Element root =
doc.createElement("sonnet");
root.setAttribute("type", "Shakespearean");
author =
doc.createElement("author");
Element lastName =
doc.createElement("last-name");
lastName.appendChild(doc.createTextNode("Shakespeare"));
author.appendChild(lastName);
我们创建了一个 Java 类的实例,该类实现了 DOM Document
接口,然后我们要求那个节点为我们创建各种节点。您很容易重新编写这个应用程序,使它通过分析 XML 文件生成 DOM
树。为了简化这个示例(并减少我的工作量),我们定义了一些实例变量来保存准备为其提供服务的节点的值。这些值在类声明顶部声明,并在 initialize
方法中初始化。
最后一步是将被请求的 DOM
树部分发送给用户。为了实现这一任务,我们使用一个递归方法,printDOMTree,它处理节点及其所有子节点。因为这个方法是递归的,所以我们从文档根节点还是从
DOM 树的其他节点开始并不重要。如果所请求的是我们知道的一个节点,则可以将这个节点传递给方法 printDOMTree。否则,我们可以传递 Document
节点。清单 5 显示了这一步骤。
清单 5. printDOMTree
if
(requestedSubtree.equalsIgnoreCase("author"))
printDOMTree(author, out);
else if
(requestedSubtree.equalsIgnoreCase("lines"))
printDOMTree(lines, out);
else if
(requestedSubtree.equalsIgnoreCase("title"))
printDOMTree(title, out);
else
printDOMTree(doc, out);
如果 subtree 参数是 author,则结果是:
<author>
<last-name>Shakespeare</last-name>
<first-name>William</first-name>
<nationality>British</nationality>
<year-of-birth>1564</year-of-birth>
<year-of-death>1616</year-of-death> </author>
如果 subtree 参数是 title,则结果是:
<title>Sonnet 130</title>
您可以查看完整清单的 HTML 视图或直接查看 Java
源文件。
与数据库对接
我们的最后一个示例是根据数据库查询生成
XML。有许多方法可做到这一点(请参阅 developerWorks 的文章 Generating XML from a Data
Store);对于本例而言,我们将使用 IBM 的 XML Extender for DB2(请参阅参考资料)。这个免费产品使您能够在 DB2 中存储 XML
文档。我们的查询从 DB2 中提取这些文档,然后将其传送给用户。
如果您使用 Oracle 8i 代替 DB2,您将会发现它自称具有类似的功能(请参阅参考资料)。对于不理解 XML
的数据库,您可以将 XML 文档存储为字符大对象 (CLOB),并以文本块的方式检索文档。
但是,在安装数据库以后,您需要完成以下三件事情才能使此代码工作:
首先,将 DbOwner、DbUserid 和 DbPasswd 变量改为适合系统的适当值。
/////////////////////////////////////////////////////////////////
//
一定要正确更改这三个字符串,否则
//
// servlet
不会工作。
//
/////////////////////////////////////////////////////////////////
DbUserid = "xxxxxxxx";
DbPasswd =
"xxxxxxxx";
DbOwner = "xxxxxxxx";
下一步,使用适合您的系统的 JDBC 驱动程序。我们在使用 DB2。
static
String JDBCDriver = "COM.ibm.db2.jdbc.app.DB2Driver";
...
try
{
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver").newInstance();
}
catch (Exception e)
{
System.out.println("Can't get the driver!");
e.printStackTrace();
}
如果你愿意,可以改掉下面的 SQL 查询语句。为了简化示例,此处仅检索 sales_order_view 表的 order
列中的全部 XML 文档。
// 我们在此处对 SQL
语句进行硬编码;如果根据用户输入
// 限制查询,则情况会更为复杂。
String query = "select order from " + DbOwner + ".sales_order_view";
在 service 方法中,我们的 servlet 连接
DB2,执行一个查询(其结果为一组 XML 文档),分析查询结果,并将分析过的数据写入输出流中。清单 6 显示了与此关系最密切的代码部分:
清单 6. xmlfromdb2.java
// 我们在此处对 SQL
语句进行硬编码;如果根据用户输入
// 限制查询,则情况会更为复杂。
String query = "select order from " + DbOwner + ".sales_order_view";
res.setContentType("text/xml");
try
{
ConInfo index = new
ConInfo();
Connection con =
getCon(index);
Statement stmt =
con.createStatement();
ResultSet
rs = stmt.executeQuery(query);
...
// 显示结果集。我们从每行取出 XML
文档,
// 对其进行分析,然后打印 DOM
树。当没有更多的行时,rs.next() 返回
//
false。 while
(rs.next())
{
String
nextOrder =
rs.getString(1).trim();
Document doc =
null;
StringReader sr = new
StringReader(nextOrder);
InputSource iSrc = new
InputSource(sr);
try
{
parser.parse(iSrc);
doc =
parser.getDocument();
}
catch
(Exception
e)
{
System.err.println("Sorry, an error occurred: " +
e);
}
if (doc
!=
null)
printDOMTree(doc,
out);
}
要了解全部细节,您可以查看完整清单的 HTML 视图或直接查看Java
源文件。
小结
尽管这些 servlet 示例中没有一个可以改变世界,但它们确实展示了
XML 和 servlet 配合得有多么好。Servlet 是向客户发送内容的一种伟大机制,而 XML 是发送结构化数据的一种完美机制。您还可以使用
servlet 处理服务器上的 XML
文档,并将它们的内容发送给客户机。最重要的是,这两种技术都是跨平台技术,可为您的应用程序带来更大的灵活性和可移值性。
参考资料
了解有关 DB2
XML Extender 的详细信息。产品附带的文档中有一个深入的教程,它可帮助您将 XML 文档带入关系数据库的世界中。
了解有关 Oracle
数据库产品的详细信息。
试用 WebSphere 附带的免费 servlet
教程。
通过 developerWorks 的 XML programming in
Java 教程深入研究如何分析 XML 文件。
下载作者为 City Java 用户组制作的演示文稿的 PDF
版本。
在 www.gnu.org
网站学习使用 Emacs 彩色编码代码清单。HTMLize 程序包可从网址 jagor.srce.hr 获得。
作者简介
 |
Doug Tidwell 是 IBM 的高级程序员。从在 Reagan
管理机关的初期开始,他就一直在编写程序。尽管他起誓他从 20 世纪 50 年代后期开始就始终在编写 Java 程序,但事实上他出生于 60
年代中期,这使许多人他的说法表示怀疑。作为一名计算机传道者,他的工作是帮助客户评估并实现新技术。由于老板的特殊安排,他的薪水全部用巧克力支付。可以通过
dtidwell@us.ibm.com 与 Doug
联系。 |
如果您希望与本文章的作者或其所在机构,进一步交流,请联系:畅享网 姜小姐
jill.jiang@amteam.org | 021-51096826-112 |
在线联系