<%
// invoke this file like: picture-dom.jsp?file=foo.pix
%>
<%@include file="init.jsp"%>
<%
String picturefile =
application.getRealPath("/" + request.getParameter("file"));
System.out.println(picturefile);
Document doc = DOMUtils.xml4jParse(picturefile);
Element nodeRoot = doc.getDocumentElement();
Node nodeTitle = DOMUtils.getChild(nodeRoot, "title");
String title = (nodeTitle == null) ? null : DOMUtils.getTextValue(nodeTitle);
Node nodeCaption = DOMUtils.getChild(nodeRoot, "caption");
String caption = (nodeCaption == null) ? null : DOMUtils.getTextValue(nodeCaption);
Node nodeDate = DOMUtils.getChild(nodeRoot, "date");
String date = (nodeDate == null) ? null : DOMUtils.getTextValue(nodeDate);
Node nodeImage = DOMUtils.getChild(nodeRoot, "image");
Node nodeSrc = DOMUtils.getChild(nodeImage, "src");
String src = DOMUtils.getTextValue(nodeSrc);
Node nodeWidth = DOMUtils.getChild(nodeImage, "width");
String width = DOMUtils.getTextValue(nodeWidth);
Node nodeHeight = DOMUtils.getChild(nodeImage, "height");
String height = DOMUtils.getTextValue(nodeHeight);
%>
<html>
<head>
<title><%=title%></title>
</head>
<body>
<center>
<table bgcolor="#CCCCCC" border="0" cellspacing="0" cellpadding="8">
<tr>
<td align="left" bgcolor="#6666AA" width="100%">
<b><%=title%></b>
</td></tr>
<tr>
<td align="center" valign="top">
<table bgcolor="#FFFFFF" border="0" cellspacing="0" cellpadding="5">
<tr>
<td align="center" valign="center">
<a href="picture-sm-dom.jsp"><img src="<%=src%>" width="<%=width%>" height="<%=height%>" border="0" alt="<%=src%>"></a></td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="center" valign="center">
<% if (caption != null) { %>
<b><%=caption%></b><br/>
<% } %>
<% if (date != null) { %>
<font size="-1"><i><%=date%></i></font><br/>
<% } %>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
使用JSP beans 来分开模型和视图
上面的代码picture-dom.jsp并不吸引人。当你要在JSP内放置大量的Java代码时,有一个简洁的办法:可以使用JSP JavaBeans来存储大量的Java代码。好处是在JSP页面内可节省JSP 脚本 tags (<% and %>) ,以便于控制程序流与减少变量的操作。为了原型开发的目的,把所有的Java代码放入JSP内可能开始觉得轻松愉快。也可以在有了好主意后,回头将必要代码抽出放入JavaBeans。这样做的代价有点高,但是会在今后得到回报,如果你的应用需要模块化的话。可以在不同的页面内使用同一Beans,而不用做讨厌的copy-and-paste,以支持代码重用。
在以上的例子中,从XML文件中抽出字串的值可以作成一个JSP JavaBean。定义 Picture,Image,Thumbnails类来表达XML中的主要元素。这些Beans将有构造函数或setter方法,调用DOM结点或文件名来从中抽出需要的值。从参考资料或picture-beans.jsp中可以找到 picturebeans包的源码。
阅读源码时请注意:
在实现类以外单独定义了接口,因此今后可以自由地选择改变实现。可以在列表中,在DOM里甚至在database里存储数据。
beans被定义在一个定制包 picturebeans内。所有 JSP beans 都必须放在一个包内;大部分JSP引擎不能找到缺省包内的类。
除get方法之外还提供了set方法。现在,还只能读而不能改变图片的属性。将来可以用来改变这些属性以便用户编辑图片。
自从需要的值被存储在beans中而不是在局部变量中后,就必须用<%=picture.getCaption()%>而不是<%=caption%>了。当然,也可定义局部变量比如String caption = picture.getCaption();.这样使代码较容易理解。
用thumbnails来进行缩放
在第一个JSP的输出中,显示了全尺寸的图像文件。可以稍微修改代码,让它显示由一些稍小一点的图象组成的列表。这要使用到存储在XML数据文件中的图像列表。
首先定义一个参数 zoom,它可以决定显示那一幅Thumbnails图像。在小图像上点击鼠标,可以看到全尺寸的原来图像。点击Zoom In 和 Zoom Out按钮可以选择下一幅或前一幅Thumbnails图像。
Thumbnails对象返回 java.util.List图像对象,找到正确的Thumbnails对象却不怎么容易,仅仅说(Image)picture.getThumbnails().get(i)是不够的。
做 Zoom In 和 Zoom Out 链接时,必须用不同的参数生成对同一个页面的递归调用。这样可以使用request.getRequestURI()方法。仅仅是将路径传给servlet,不需要带其它参数,因此可以附加自己需要的参数。
<%
if (zoom < (thumbnails.size() -1)) {
out.print("<a href=" +
request.getRequestURI() +
"?file=" + request.getParameter("file") +
"&zoom=" + (zoom+1) +
">");
out.print("Zoom In</a>");
}
%>
Here is an HTML screenshot of the working JSP page.
这里有一个关于JSP页面工作的例子。
使用JSP bean标记
JSP规范中定义了<jsp:useBean>标记,以在JSP页面中自动实例化和使用JavaBeans。useBean标记通常都可被内嵌的Java代码所替换。在这里我已经替换了。基于此,很多人都在询问useBean 和 setProperty标记何时需要使用的问题。关于这些标记有以下几点:
标记语法不会对 HTML 设计者构成干扰
useBean 有一个scope 参数,可以自动决定Beans是否应该存储在局部变量或 session变量中或作为一个application的属性。
如果变量是长期有效的(session或application),在必要时,useBean会初始化它,但是只有当变量已经存在时才能使用。
标记对于将来的JSP版本规范来说,潜在地具有很多优点,可以灵活地改变它的实现。(例如,一个假定的JSP引擎可以储存变量于 database或通过server进程来共享)
对于这个应用来说等价useBean语法如下:
<jsp:useBean id="picture" scope="request" class="picturebeans.DOMPicture">
<%
Document doc = DOMUtils.xml4jParse(picturefile);
Element nodeRoot = doc.getDocumentElement();
nodeRoot.normalize();
picture.setNode(nodeRoot);
%>
</jsp:useBean>
或者,如果你在 DOMBean中定义了一个setFile(String) 方法的话:
<jsp:useBean id="picture" scope="request" class="picturebeans.DOMPicture">
<jsp:setProperty name="picture" property="file" value="<%=picturefile%>"/>
</jsp:useBean>
使用XMLEntryList
为了克服使用DOM API的一些困难,做了一个XMLEntryList类。它实现了Java集合接口java.util.List并包含java.util.Map的get,put方法,提供了直接的方法集合去遍历简单XML树结构。可以用集合API的标准抽出方法来做诸如查询,迭代和子视图。实体列表中的每个实体都有键和值,如同一个Map对象。键是子结点的名字,值或是字串或子XMLEntryLists.
XMLEntryList 并不是DOM的完全替代。有好几个DOM功能它不能实现。可是,它是一个便利的包装器,用来做基本的getting, setting,list-oriented功能来处理 XML数据结构。例如为了得到picture 结点的标题属性的值,可以这样写:
String caption = (String)picturelist.get("caption");
标题属性的值被解析出并被存入一个字串中。
Caching缓存
不论XML文件有什么优点,解析它会花很多时间。为了提高基于XML的应用程序的性能,必须使用一些缓存技术。缓存必须基于XML文件名在内存中存储XML对象。如果上次加载以来,XML文件被更新了,则必须重新加载。我做了关于实现这个数据结构的一个简单工具CachedFS.java。可以使用内部类给把CachedFS作为一个回调函数来使用,就能实现XML解析,转换文件为一个对象。cache就可以将对象存储在内存。
下面是产生cache的代码。这个对象具有应用程序的范围,可以被反复使用。这段代码被放入了init.jsp。
<jsp:useBean id="cache" class="com.purpletech.io.CachedFS" scope="application">
<% cache.setRoot(application.getRealPath("/"));
cache.setLoader( new CachedFS.Loader() {
// load in a single Picture file
public Object process(String path, InputStream in) throws IOException
{
try {
Document doc = DOMUtils.xml4jParse
(new BufferedReader(new InputStreamReader(in)));
Element nodeRoot = doc.getDocumentElement();
nodeRoot.normalize();
Picture picture = new DOMPicture(nodeRoot);
return picture;
}
catch (XMLException e) {
e.printStackTrace();
throw new IOException(e.getMessage());
}
}
});
%>
</jsp:useBean>
XPath
XPath 是一个查找定位XML树结点的简单句法单位。它比DOM易于使用。当你想从一个结点进入下一个结点时,不用调用making方法。可以把全部路径嵌入一个字串,如/picture/thumbnails/image[2]。在Resin中,包括了XPath对象,可直接在应用中调用。
Node verse = XPath.find("chapter/verse", node);
XSL
这篇文章讨论了如何将Java代码嵌入JSP,用来提取 XML结点的数据。另外还有一个流行的模型来完成这个工作。就是XSL (Extensible Stylesheet Language)。它完全不同于已讨论过的JSP模型。在JSP中,主文档模型是HTML,包含有Java代码;在XSL中文档模型是XSL,包含有HTML。对于XSL和Java/JSP的关系,有许多值得讨论的地方。这里限于篇幅,就不深入了。将来在JavaWorld 中要讨论XSL 和JSP一起用的问题。
结论与展望未来之路
读完这篇文章,读者应该对于 JSP-XML应用的结构与强大之处以及缺陷有教好的理解了吧。
在开发JSP-XML应用中,最单调乏味的事是为每个 XML模式的元素构造JavaBeans。 XML Data Binding group正在开发能从给定的模式自动生成Java类的技术。我也开发了一个公开源代码的Java-XML数据绑定的原型。IBM alphaWorks最近也发布了XML Master 或(XMas),这是另外一个Java-XML数据绑定系统。
另外一个可能就是拓展文件系统的功能,构造一些更强大的特征,比如查询或事物处理。自然,我也在考虑开发源代码公开的工程来实现这种功能。有谁想写 XML搜寻引擎呢?
(c) 版权所有 2000 ITworld.com, Inc., an IDG Communications company
Resources
文章中的源代码可以从下面找到:
http://www.javaworld.com/jw-03-2000/jspxml/jspxml-webapp.zip
For future updates to that source code:
http://www.purpletech.com/jspxml/
XML:
http://www.xml.org/
http://www.xml.com/
http://www.jguru.com/faq/XML
SML, a controversial simplification of XML syntax:
http://www.xml.com/pub/1999/11/sml/index.html
http://www.xml.com/pub/1999/12/sml/responses.html
JSP:
http://java.sun.com/products/jsp
http://www.jguru.com/faq/JSP
DOM specification:
http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/java-language-binding.html
http://www.w3.org/TR/REC-DOM-Level-1/
Java-XML data binding:
JSR 31: http://java.sun.com/aboutJava/communityprocess/jsr/jsr_031_xmld.html
IBM XML Master :http://alphaworks.ibm.com/tech/xmas
Purple Technology XDB: http://www.purpletech.com/xdb/
XBeans: http://www.xbeans.org/
Tomcat open source servlet/JSP engine:
http://jakarta.apache.org/
Java Server Web Development Kit (JSWDK):
http://java.sun.com/products/servlets
XML4J, IBMs DOM parser:
http://alphaworks.ibm.com/
For XMLEntryList:
http://www.purpletech.com/code/src/com/purpletech/xml/XMLEntryList.java
For Resin, by Caucho (XPath processor):
http://www.caucho.com/
"Understanding JSP Model 2 Architecture," Govind Seshadri (JavaWorld, December 1999):
http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html
文章来源于领测软件测试网 https://www.ltesting.net/