﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-FORTUNE-随笔分类-java技术</title><link>http://www.blogjava.net/fortune/category/7486.html</link><description>THE WAY TO THE MASTER...</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 08:20:33 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 08:20:33 GMT</pubDate><ttl>60</ttl><item><title>IBM : developerWorks 中国网站 : xml 中的XML 入门 (修订版)学习及整理(转)</title><link>http://www.blogjava.net/fortune/archive/2006/10/16/75414.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Mon, 16 Oct 2006 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/10/16/75414.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/75414.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/10/16/75414.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/75414.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/75414.html</trackback:ping><description><![CDATA[
		<div>XML，或称为可扩展标记语言（Extensible Markup Language），是一种您可以用来创建自己的标记的标记语言。它由万维网协会（W3C）创建，用来克服 HTML（即超文本标记语言（Hypertext Markup Language），它是所有网页的基础）的局限。和 HTML 一样，XML 基于 SGML — 标准通</div>
		<div>用标记语言（Standard Generalized Markup Language）。尽管 SGML 已在出版业使用了数十年，但其理解方面的复杂性使许多本打算使用它的人望而却步（SGML 也代表“听起来很棒，但或许以后会用（Sounds great, maybe later）”）。XML 是为 Web 设计的。</div>
		<div> </div>
		<div>
				<strong>XML文档规则<br /></strong>有三种 XML 文档：<br />无效文档没有遵守 XML 规范定义的语法规则。如果开发人员已经在 DTD 或模式中定义了文档能够包含什么，而某个文档没有遵守那些规则，那</div>
		<div>么这个文档也是无效的。（请参阅定义文档内容以获得对 XML 文档 的 DTD 和模式的专门介绍。） <br />有效文档既遵守 XML 语法规则也遵守在其 DTD 或模式中定义的规则。 <br />格式良好的文档遵守 XML 语法，但没有 DTD 或模式。 </div>
		<div>
				<br />
				<em>
						<strong>根元素</strong>
						<br />
				</em>XML 文档必须包含在一个单一元素中。这个单一元素称为根元素，它包含文档中所有文本和所有其它元素。在下面的示例中，XML 文档包含在一</div>
		<div>个单一元素 &lt;greeting&gt; 中。请注意文档有一行注释在根元素之外；那是完全合乎规则的。</div>
		<div>
				<br />&lt;?xml version="1.0"?&gt;<br />&lt;!-- A well-formed document --&gt;<br />&lt;greeting&gt;<br />  Hello, World!<br />&lt;/greeting&gt;<br />          </div>
		<div>下面是一个不包含单一根元素的文档：</div>
		<div>
				<br />&lt;?xml version="1.0"?&gt;<br />&lt;!-- An invalid document --&gt;<br />&lt;greeting&gt;<br />  Hello, World!<br />&lt;/greeting&gt;<br />&lt;greeting&gt;<br />  Hola, el Mundo!<br />&lt;/greeting&gt;<br />          </div>
		<div>不管该文档可能包含什么信息，XML 解析器都会拒绝它。</div>
		<div>
				<br />
				<em>
						<strong>元素不能重叠</strong>
				</em>
				<br />XML 元素不能重叠。下面是一些不合乎规则的标记：</div>
		<div>
				<br />&lt;!-- NOT legal XML markup --&gt;            <br />&lt;p&gt;<br />  &lt;b&gt;I &lt;i&gt;really <br />  love&lt;/b&gt; XML.<br />  &lt;/i&gt;<br />&lt;/p&gt;<br />          </div>
		<div>如果您在 &lt;b&gt; 元素中开始了 &lt;i&gt; 元素，则必须在 &lt;b&gt; 元素中结束 &lt;i&gt; 元素。如果您希望文本 XML 以斜体出现，那么您需要添加第二个 &lt;i&gt; </div>
		<div>元素以更正标记：</div>
		<div>
				<br />&lt;!-- legal XML markup --&gt;<br />&lt;p&gt;<br />  &lt;b&gt;I &lt;i&gt;really <br />  love&lt;/i&gt;&lt;/b&gt;<br />  &lt;i&gt;XML.&lt;/i&gt;<br />&lt;/p&gt;<br />          </div>
		<div>XML 解析器将只接受这种标记；大多数 Web 浏览器中的 HTML 解析器对于两者都接受。</div>
		<div>
				<br />
				<strong>
						<em>结束标记是必需的</em>
				</strong>
				<br />不能省去任何结束标记。在下面第一个示例中，标记是不合乎规则的，因为没有结束段落（&lt;/p&gt;）标记。尽管这在 HTML（以及某些情况下在 </div>
		<div>SGML）中可以接受，但 XML 解析器将拒绝它。</div>
		<div>
				<br />&lt;!-- NOT legal XML markup --&gt;<br />&lt;p&gt;Yada yada yada...<br />&lt;p&gt;Yada yada yada...<br />&lt;p&gt;...<br />          </div>
		<div>如果一个元素根本不包含标记，则称为空元素；HTML 换行（&lt;br&gt;）和图像（&lt;img&gt;）元素就是两个例子。在 XML 文档的空元素中，您可以把结束</div>
		<div>斜杠放在开始标记中。下面的两个换行元素和两个图像元素对于 XML 解析器来说是一回事：</div>
		<div>
				<br />&lt;!-- Two equivalent break elements --&gt;<br />&lt;br&gt;&lt;/br&gt;<br />&lt;br /&gt;</div>
		<div>&lt;!-- Two equivalent image elements --&gt;<br />&lt;img src="../img/c.gif"&gt;&lt;/img&gt;<br />&lt;img src="../img/c.gif" /&gt;</div>
		<div>元素是区分大小写的<br />XML 元素是区分大小写的。在 HTML 中，&lt;h1&gt; 和 &lt;H1&gt; 是相同的；在 XML 中，它们是不同的。如果您试图用 &lt;/H1&gt; 标记结束 &lt;h1&gt; 元素，将会</div>
		<div>出错。在下面的示例中，顶部的标题是不合乎规则的，而底部的则是正确的。</div>
		<div>
				<br />&lt;!-- NOT legal XML markup --&gt;<br />&lt;h1&gt;Elements are <br />  case sensitive&lt;/H1&gt;</div>
		<div>&lt;!-- legal XML markup --&gt;<br />&lt;h1&gt;Elements are <br />  case sensitive&lt;/h1&gt;</div>
		<div>
				<br />
				<em>
						<strong>属性必须有用引号括起的值</strong>
				</em>
				<br />XML 文档中的属性有两个规则：</div>
		<div>属性必须有值 <br />那些值必须用引号括起。<br /> <br />比较下面的两个示例。顶部的标记在 HTML 中是合乎规则的，但在 XML 中则不是。为了在 XML 中取得相同结果，您必须给属性赋值，而且必须</div>
		<div>把值括在引号中。</div>
		<div>
				<br />&lt;!-- NOT legal XML markup --&gt;<br />&lt;ol compact&gt;</div>
		<div>&lt;!-- legal XML markup --&gt;<br />&lt;ol compact="yes"&gt;<br />          </div>
		<div>您可以使用单引号，也可以使用双引号，但要始终保持一致。</div>
		<div>如果属性值包含单引号或双引号，则您可以使用另一种引号来括起该值（如 name="Doug's car"），或使用实体 &amp;quot; 代表双引号，使用 </div>
		<div>&amp;apos; 代表单引号。实体是一个符号（如 &amp;quot;），XML 解析器会用其它文本代替该符号（如 "）。</div>
		<div> </div>
		<div>
				<strong>
						<em>XML 声明<br /></em>
				</strong>大多数 XML 文档以 XML 声明作为开始，它向解析器提供了关于文档的基本信息。建议使用 XML 声明，但它不是必需的。如果有的话，那么它一</div>
		<div>定是文档的第一样东西。</div>
		<div>声明最多可以包含三个名称-值对（许多人称它们为属性，尽管在技术上它们并不是）。version 是使用的 XML 版本；目前该值必须是 1.0。</div>
		<div>encoding 是该文档所使用的字符集。该声明中引用的 ISO-8859-1 字符集包括大多数西欧语言用到的所有字符。如没有指定 encoding，XML 解</div>
		<div>析器会假定字符在 UTF-8 字符集中，这是一个几乎支持世界上所有语言的字符和象形文字的 Unicode 标准。</div>
		<div>
				<br />&lt;?xml version="1.0" encoding="ISO-8859-1" standalone="no"?&gt;<br />          </div>
		<div>最后，standalone（可以是 yes 或 no）定义了是否可以在不读取任何其它文件的情况下处理该文档。例如，如果 XML 文档没有引用任何其它文</div>
		<div>件，则您可以指定 standalone="yes"。如果 XML 文档引用其它描述该文档可以包含什么的文件（马上会详细介绍这些文件），则您可以指定 </div>
		<div>standalone="no"。因为 standalone="no" 是缺省的，所以您很少会在 XML 声明中看到 standalone。</div>
		<div>
				<br />
				<em>
						<strong>XML 文档中的其它项<br /></strong>
				</em>您或许会在一个 XML 文档中发现其它几项：</div>
		<div>注释：注释可以出现在文档的任何位置；它们甚至可以出现在根元素的前面或后面。注释以 &lt;!-- 开始，以 --&gt; 结束。注释不能在结束部分以外</div>
		<div>包含双连字符（--）；除此之外，注释可以包含任何内容。最重要的是，注释内的任何标记都被忽略；如果您希望除去 XML 文档的一块较大部分</div>
		<div>，只需用注释括住那个部分即可。（要恢复这个注释掉的部分，只需除去注释标记即可。）下面是包含注释的标记： </div>
		<div>&lt;!-- Here's a PI for Cocoon: --&gt;<br />&lt;?cocoon-process type="sql"?&gt;<br />          </div>
		<div>处理指令：处理指令是为使用一段特殊代码而设计的标记。在上面的示例中，有一个用于 Cocoon 的处理指令（有时称为 PI），Cocoon 是来自 </div>
		<div>Apache 软件基金会（Apache Software Foundation）的 XML 处理框架。当 Cocoon 处理 XML 文档时，它会寻找以 cocoon-process 开头的处理</div>
		<div>指令，然后相应地处理 XML 文档。在该示例中，type="sql" 属性告诉 Cocoon：XML 文档包含一个 SQL 语句。 </div>
		<div>&lt;!-- Here's an entity: --&gt;<br />&lt;!ENTITY dw "developerWorks"&gt;<br />          </div>
		<div>实体：上面的示例为文档定义了一个实体。无论 XML 处理器在何处找到字符串 &amp;dw;，它都会用字符串 developerWorks 代替该实体。XML 规范</div>
		<div>还定义了五个您可以用来替代不同的特殊字符的实体。这些实体是：<br />&amp;lt; 代表小于符号 <br />&amp;gt; 代表大于符号 <br />&amp;quot; 代表一个双引号 <br />&amp;apos; 代表一个单引号（或撇号） <br />&amp;amp; 代表一个“与”符号。 </div>
		<div>
				<br />
				<em>
						<strong>名称空间</strong>
				</em>
				<br />XML 的能力来自它的灵活性，即您和我以及数百万其他人可以定义我们自己的标记来描述我们的数据。记得表示个人姓名和地址的样本 XML 文档</div>
		<div>吗？那个文档包括表示个人尊称的 &lt;title&gt; 元素，这是对元素名称非常合理的选择。如果您经营一家网上书店，您或许会创建一个表示书名的 </div>
		<div>&lt;title&gt; 元素。如果您经营一家网上抵押放款公司，您或许会创建表示一份财产名称的 &lt;title&gt; 元素。所有这些都是合理的选择，但它们都用相</div>
		<div>同的名称创建元素。如何分辨某个特定的 &lt;title&gt; 元素指的是人、书籍还是一份财产呢？可以使用名称空间。</div>
		<div>要使用名称空间，您要定义一个名称空间前缀，然后将它映射至一个特殊字符串。下面介绍如何定义我们这三个 &lt;title&gt; 元素的名称空间前缀：</div>
		<div>
				<br />&lt;?xml version="1.0"?&gt;<br />&lt;customer_summary<br />  xmlns:addr="<a href="http://www.xyz.com/addresses/"><font color="#ffffff">http://www.xyz.com/addresses/</font></a>"<br />  xmlns:books="<a href="http://www.zyx.com/books/"><font color="#ffffff">http://www.zyx.com/books/</font></a>"<br />  xmlns:mortgage="<a href="http://www.yyz.com/title/"><font color="#ffffff">http://www.yyz.com/title/</font></a>"<br />&gt;<br />... &lt;addr:name&gt;&lt;title&gt;Mrs.&lt;/title&gt; ... &lt;/addr:name&gt; ...<br />... &lt;books:title&gt;Lord of the Rings&lt;/books:title&gt; ...<br />... &lt;mortgage:title&gt;NC2948-388-1983&lt;/mortgage:title&gt; ...<br />          </div>
		<div>在该示例中，三个名称空间前缀是 addr、books 和 mortgage。请注意，为特定元素定义名称空间意味着该元素的所有子元素都属于同一名称空</div>
		<div>间。第一个 &lt;title&gt; 元素属于 addr 名称空间，因为其父元素 &lt;addr:Name&gt; 属于该名称空间。</div>
		<div>最后要指出的是：名称空间定义中的字符串仅仅是字符串。对，这些字符串看似 URL，其实不是。您可以定义 xmlns:addr="mike"，那也是有效</div>
		<div>的。名称空间唯一的重要性在于其唯一性；这就是为什么大多数名称空间定义看起来象 URL 的原因。XML 解析器不会到 </div>
		<div>
				<a href="http://www.zyx.com/books/">
						<font color="#ffffff">http://www.zyx.com/books/</font>
				</a> 去搜索 DTD 或模式，它只是把那个文本作为字符串使用。这有些令人困惑，但名称空间就是这样工作的。</div>
		<div> </div>
		<div>
				<br />
				<strong>定义文档内容 </strong>   <br />在了解到了 XML 文档的基本规则之后，您需要定义将用来表示数据的元素。做到这一点的两种方法。</div>
		<div>一种方法是使用文档类型定义（Document Type Definition），或简称 DTD。DTD 定义可以在 XML 文档中出现的元素、这些元素出现的次序、它</div>
		<div>们可以如何相互嵌套以及 XML 文档结构的其它详细信息。DTD 是最初的 XML 规范的一部分，与 SGML DTD 非常相似。 <br />另一种方法是使用 XML Schema。模式可以定义您能在 DTD 中使用的所有文档结构，它还可以定义数据类型和比 DTD 更复杂的规则。W3C 在提出</div>
		<div>最初的 XML 规范的几年之后开发了 XML Schema 规范。  </div>
		<div> </div>
		<div>
				<em>
						<strong>文档类型定义</strong>
				</em>
				<br />DTD 允许您指定 XML 文档的基本结构。下面的几页将研究 DTD 片段。首先是定义本章中地址文档示例的基本结构的 DTD，XML 是什么？：</div>
		<div>
				<br />&lt;!-- address.dtd --&gt;<br />&lt;!ELEMENT address (name, street, city, state, postal-code)&gt;<br />&lt;!ELEMENT name (title? first-name, last-name)&gt;<br />&lt;!ELEMENT title (#PCDATA)&gt;<br />&lt;!ELEMENT first-name (#PCDATA)&gt;<br />&lt;!ELEMENT last-name (#PCDATA)&gt;<br />&lt;!ELEMENT street (#PCDATA)&gt;<br />&lt;!ELEMENT city (#PCDATA)&gt;<br />&lt;!ELEMENT state (#PCDATA)&gt;<br />&lt;!ELEMENT postal-code (#PCDATA)&gt;<br />          </div>
		<div>该 DTD 定义了样本文档中使用的所有元素。它定义了三个元素：</div>
		<div>&lt;address&gt; 元素包含一个 &lt;name&gt;、一个 &lt;street&gt;、一个 &lt;city&gt;、一个 &lt;state&gt; 和一个 &lt;postal-code&gt;。所有这些元素必须出现，而且必须以</div>
		<div>这个顺序出现。 <br />&lt;name&gt; 元素包含一个可选的 &lt;title&gt; 元素（问号表示 title 这个元素是可选的），后面跟有一个 &lt;first-name&gt; 和一个 &lt;last-name&gt; 元素。 <br />所有其它包含文本的元素。（#PCDATA 代表已解析字符数据；不能在这些元素中包含另一个元素。） <br />尽管 DTD 相当简单，但它清楚地说明了什么样的元素组合是合乎规则的。&lt;postal-code&gt; 元素在 &lt;state&gt; 元素之前的地址文档是不合乎规则的</div>
		<div>，没有 &lt;last-name&gt; 元素的文档也不合乎规则。</div>
		<div>另外，请注意，DTD 语法不同于普通的 XML 语法。（相反，XML Schema 文档本身就是 XML，这导致一些有趣的结果）。尽管 DTD 的语法不同，</div>
		<div>但您仍可以将普通的注释放到 DTD 中。</div>
		<div>
				<br />
				<em>
						<strong>DTD 中的符号</strong>
				</em>
				<br />DTD 中有几个符号用于指出某元素在 XML 文档中可能会出现多少次（或是否出现）。下面是一些示例及其含义：</div>
		<div>&lt;!ELEMENT address (name, city, state)&gt; <br />&lt;address&gt; 元素必须包含一个 &lt;name&gt; 元素、一个 &lt;city&gt; 元素和一个 &lt;state&gt; 元素，并且符合上面的次序。所有的元素都是必需的。逗号表示</div>
		<div>项的列表。 </div>
		<div>&lt;!ELEMENT name (title?, first-name, last-name)&gt; <br />这意味着 &lt;name&gt; 元素包含一个可选的 &lt;title&gt; 元素，后面必须跟有一个 &lt;first-name&gt; 和一个 &lt;last-name&gt; 元素。问号表示这一项是可选的</div>
		<div>；它可以出现一次或根本不出现。 </div>
		<div>&lt;!ELEMENT addressbook (address+)&gt; <br />&lt;addressbook&gt; 元素包含一个或多个 &lt;address&gt; 元素。您可以有任意多的 &lt;address&gt; 元素，但必须至少有一个。加号表示这一项必须至少出现</div>
		<div>一次，但可出现任意次。 </div>
		<div>&lt;!ELEMENT private-addresses (address*)&gt; <br />&lt;private-addresses&gt; 元素包含零个或多个 &lt;address&gt; 元素。星号表示这一项可以出现任意次，包括零次。 </div>
		<div>&lt;!ELEMENT name (title?, first-name, (middle-initial | middle-name)?, last-name)&gt; <br />&lt;name&gt; 元素包含一个可选的 &lt;title&gt; 元素，后面跟有一个 &lt;first-name&gt; 元素，随后可能跟有一个 &lt;middle-initial&gt; 或 &lt;middle-name&gt; 元素</div>
		<div>，然后跟有一个 &lt;last-name&gt; 元素。换句话说，&lt;middle-initial&gt; 和 &lt;middle-name&gt; 都是可选的，而且您只能选择二者中的一个。竖线符号表</div>
		<div>示选择列表；您只能从列表选择一项。还要注意该示例用圆括号对特定元素进行分组，然后在这个组旁放上问号。</div>
		<div>&lt;!ELEMENT name ((title?, first-name, last-name) | (surname, mothers-name, given-name))&gt; <br />这个 &lt;name&gt; 元素可以包含两个序列中的一个：一个可选的 &lt;title&gt;，后面跟有一个 &lt;first-name&gt; 和一个 &lt;last-name&gt;；或一个 &lt;surname&gt;、</div>
		<div>一个 &lt;mothers-name&gt; 和一个 &lt;given-name&gt;。</div>
		<div> </div>
		<div>
				<strong>
						<em>定义属性</em>
				</strong>
				<br />本篇介绍性教程没有很详细地研究 DTD 如何工作，但这里要介绍一个更基本的概念：定义属性。您可以定义将在 XML 文档中出现的元素的属性</div>
		<div>。使用 DTD，您还可以：</div>
		<div>定义哪些属性是必需的 <br />定义属性的缺省值 <br />列出给定属性的所有有效值 <br />假设您要更改 DTD，使 state 成为 &lt;city&gt; 元素的属性。下面演示如何做到这一点：</div>
		<div>
				<br />&lt;!ELEMENT city (#PCDATA)&gt;<br />&lt;!ATTLIST city state CDATA #REQUIRED&gt;<br />          </div>
		<div>和以前一样，我们定义了 &lt;city&gt; 元素，但修改的示例还使用了 ATTLIST 声明来列出元素的属性。属性列表中的名称 city 告诉解析器这些属性</div>
		<div>是为 &lt;city&gt; 元素定义的。名称 state 是属性的名称，关键字 CDATA 和 #REQUIRED 告诉解析器 state 属性包含文本并且是必需的（如果它是</div>
		<div>可选的，用 CDATA #IMPLIED 即可）。</div>
		<div>要定义元素的多个属性，可象下面那样编写 ATTLIST：</div>
		<div>
				<br />&lt;!ELEMENT city (#PCDATA)&gt;<br />&lt;!ATTLIST city state CDATA #REQUIRED<br />               postal-code CDATA #REQUIRED&gt;<br />          </div>
		<div>该示例将 state 和 postal-code 都定义为 &lt;city&gt; 元素的属性。</div>
		<div>最后，DTD 允许您定义属性缺省值，并列举属性的所有有效值：</div>
		<div>
				<br />&lt;!ELEMENT city (#PCDATA)&gt;<br />&lt;!ATTLIST city state CDATA (AZ|CA|NV|OR|UT|WA) "CA"&gt;<br />          </div>
		<div>上面的示例表明它仅支持来自亚利桑那州（AZ）、加利福尼亚州（CA）、内华达州（NV）、俄勒冈州（OR）、犹他州（UT）和华盛顿州（WA）的地址，并且缺省值是加利福尼亚州。这样，您就可以进行形式非常有限的数据验证。尽管这是有用的功能，但它只是您能用 XML 模式（请参阅</div>
		<div>XML 模式）完成的工作的一个小子集。</div>
		<div> </div>
		<div>
				<strong>
						<em>XML 模式<br /></em>
				</strong>使用 XML 模式，您会有更多的能力来定义什么样的 XML 文档是有效的。它们与 DTD 相比有几个优势：</div>
		<div>XML 模式使用 XML 语法。换句话说，XML 模式是一个 XML 文档。这意味着您可以象处理任何其它文档一样处理模式。例如，您可以编写一个 XSLT 样式表，该样式表将 XML 模式转换成具有自动生成的 JavaScript 代码的 Web 表单，其中的 JavaScript 代码可以验证您输入的数据。 <br />XML 模式支持数据类型。尽管 DTD 确实支持数据类型，但很明显这些数据类型是从发布的角度开发的。XML 模式支持 DTD 中的所有原始数据类型（诸如标识和标识引用之类的类型）。它们还支持整数、浮点数、日期、时间、字符串、URL 和其它对数据处理和验证有用的数据类型。 <br />XML 模式是可扩展的。除了 XML 模式规范中定义的数据类型以外，您还可以创建自己的数据类型，并且可以基于其它数据类型派生出新的数据类型。 <br />XML 模式有更强的表达能力。例如，您可以用 XML 模式定义任何 &lt;state&gt; 属性值不得超过 2 个字符，或定义任何 &lt;postal-code&gt; 元素的值必</div>
		<div>须与正则表达式 [0-9]{5}(-[0-9]{4})? 相匹配。您无法用 DTD 做这些事。 </div>
		<div> </div>
		<div>
				<strong>
						<em>样本 XML 模式</em>
				</strong>
				<br />下面是与原始名称和地址 DTD 相匹配的 XML 模式。它增加了两个约束：&lt;state&gt; 元素的值必须刚好是两个字符长，&lt;postal-code&gt; 元素的值必</div>
		<div>须与正则表达式 [0-9]{5}(-[0-9]{4})? 相匹配。尽管这个模式比 DTD 长很多，但它更清楚地表达了有效的文档看起来是什么样子。下面是模式</div>
		<div>：</div>
		<div>
				<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;xsd:schema xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema"><font color="#ffffff">http://www.w3.org/2001/XMLSchema</font></a>"&gt;<br />  &lt;xsd:element name="address"&gt;<br />    &lt;xsd:complexType&gt;<br />      &lt;xsd:sequence&gt;<br />        &lt;xsd:element ref="name"/&gt;<br />        &lt;xsd:element ref="street"/&gt;<br />        &lt;xsd:element ref="city"/&gt;<br />        &lt;xsd:element ref="state"/&gt;<br />        &lt;xsd:element ref="postal-code"/&gt;<br />      &lt;/xsd:sequence&gt;<br />    &lt;/xsd:complexType&gt;<br />  &lt;/xsd:element&gt;</div>
		<div>  &lt;xsd:element name="name"&gt;<br />    &lt;xsd:complexType&gt;<br />      &lt;xsd:sequence&gt;<br />        &lt;xsd:element ref="title" minOccurs="0"/&gt;<br />        &lt;xsd:element ref="first-Name"/&gt;<br />        &lt;xsd:element ref="last-Name"/&gt;<br />      &lt;/xsd:sequence&gt;<br />    &lt;/xsd:complexType&gt;<br />  &lt;/xsd:element&gt;</div>
		<div>  &lt;xsd:element name="title"      type="xsd:string"/&gt;<br />  &lt;xsd:element name="first-Name" type="xsd:string"/&gt;<br />  &lt;xsd:element name="last-Name"  type="xsd:string"/&gt;<br />  &lt;xsd:element name="street"     type="xsd:string"/&gt;<br />  &lt;xsd:element name="city"       type="xsd:string"/&gt;</div>
		<div>  &lt;xsd:element name="state"&gt;<br />    &lt;xsd:simpleType&gt;<br />      &lt;xsd:restriction base="xsd:string"&gt;<br />        &lt;xsd:length value="2"/&gt;<br />      &lt;/xsd:restriction&gt;<br />    &lt;/xsd:simpleType&gt;<br />  &lt;/xsd:element&gt;</div>
		<div>  &lt;xsd:element name="postal-code"&gt;<br />    &lt;xsd:simpleType&gt;<br />      &lt;xsd:restriction base="xsd:string"&gt;<br />        &lt;xsd:pattern value="[0-9]{5}(-[0-9]{4})?"/&gt;<br />      &lt;/xsd:restriction&gt;<br />    &lt;/xsd:simpleType&gt;<br />  &lt;/xsd:element&gt;<br />&lt;/xsd:schema&gt;<br />          <br /><strong><em>定义模式中的元素</em></strong><br />样本 XML 模式中的 XML 模式用 &lt;xsd:element&gt; 元素定义了一些 XML 元素。头两个定义的元素（&lt;address&gt; 和 &lt;name&gt;）由其它元素组成。</div>
		<div>&lt;xsd:sequence&gt; 元素定义了包含在这两个元素中的元素的序列。下面是示例：</div>
		<div>
				<br />&lt;xsd:element name="address"&gt;<br />  &lt;xsd:complexType&gt;<br />    &lt;xsd:sequence&gt;<br />      &lt;xsd:element ref="name"/&gt;<br />      &lt;xsd:element ref="street"/&gt;<br />      &lt;xsd:element ref="city"/&gt;<br />      &lt;xsd:element ref="state"/&gt;<br />      &lt;xsd:element ref="postal-code"/&gt;<br />    &lt;/xsd:sequence&gt;<br />  &lt;/xsd:complexType&gt;<br />&lt;/xsd:element&gt;<br />          </div>
		<div>与 DTD 版本一样，XML 模式示例定义 &lt;address&gt; 包含一个 &lt;name&gt;、一个 &lt;street&gt;、一个 &lt;city&gt;、一个 &lt;state&gt; 和一个 &lt;postal-code&gt; 元素</div>
		<div>，并且依照上面的次序。请注意，该模式实际上用 &lt;xsd:complexType&gt; 元素定义了新的数据类型。</div>
		<div>大多数元素包含文本；定义它们很简单。您只要声明新的元素，然后指定它的数据类型为 xsd:string：</div>
		<div>
				<br />&lt;xsd:element name="title"      type="xsd:string"/&gt;<br />&lt;xsd:element name="first-Name" type="xsd:string"/&gt;<br />&lt;xsd:element name="last-Name"  type="xsd:string"/&gt;<br />&lt;xsd:element name="street"     type="xsd:string"/&gt;<br />&lt;xsd:element name="city"       type="xsd:string"/&gt;<br />          <br /><strong><em>定义模式中的元素内容<br /></em></strong>样本模式为两个元素的内容定义了约束：&lt;state&gt; 元素的内容必须是两个字符长，而 &lt;postal-code&gt; 元素的内容必须与正则表达式 [0-9]{5}(-</div>
		<div>[0-9]{4})? 匹配。下面演示如何做到那一点：</div>
		<div>
				<br />  &lt;xsd:element name="state"&gt;<br />    &lt;xsd:simpleType&gt;<br />      &lt;xsd:restriction base="xsd:string"&gt;<br />        &lt;xsd:length value="2"/&gt;<br />      &lt;/xsd:restriction&gt;<br />    &lt;/xsd:simpleType&gt;<br />  &lt;/xsd:element&gt;</div>
		<div>  &lt;xsd:element name="postal-code"&gt;<br />    &lt;xsd:simpleType&gt;<br />      &lt;xsd:restriction base="xsd:string"&gt;<br />        &lt;xsd:pattern value="[0-9]{5}(-[0-9]{4})?"/&gt;<br />      &lt;/xsd:restriction&gt;<br />    &lt;/xsd:simpleType&gt;<br />  &lt;/xsd:element&gt;<br />          </div>
		<div>对于 &lt;state&gt; 和 &lt;postal-code&gt; 元素，模式用约束定义了新的数据类型。第一个情况使用 &lt;xsd:length&gt; 元素，而第二个情况则使用 </div>
		<div>&lt;xsd:pattern&gt; 元素定义该元素必须匹配的正则表达式。</div>
		<div>这里概要的介绍仅仅触及 XML 模式能力的表面；有整本的书籍讨论这个主题。就这篇介绍性文章而言，我们足以说明 XML 模式是描述什么样的 </div>
		<div>XML 文档才算有效的非常强大和灵活的方式。</div>
		<div> </div>
		<div> </div>
		<div> <strong>XML 编程接口<br /></strong>本章将研究 XML 的多种编程接口。这些接口为开发人员使用 XML 文档提供了一致的接口。有许多 API 可以使用；本章研究最流行和广泛使用的 </div>
		<div>API 中的四种：文档对象模型（Document Object Model (DOM)）、用于 XML 的简单 API（Simple API for XML (SAX)）、JDOM 和用于 XML 解</div>
		<div>析的 Java API（Java API for XML Parsing (JAXP)）。（您可以通过参考资料中的大量链接找到有关这些 API 的更多信息。）</div>
		<div>
				<br />
				<strong>
						<em>文档对象模型<br /></em>
				</strong>文档对象模型（通常称为 DOM）为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档，然后构建一个驻留内存的树结构，然后您的代</div>
		<div>码就可以使用 DOM 接口来操作这个树结构。您可以遍历树以了解原始文档包含了什么，您可以删除树的几个部分，还可以重新排列树和添加新的</div>
		<div>分支，等等。</div>
		<div>DOM 由 W3C 创建，并且是该协会的正式建议书。</div>
		<div>DOM 问题<br />DOM 提供了一组丰富的功能，您可以用这些功能来解释和操作 XML 文档，但使用它们是有代价的。在开发用于 XML 文档的原始 DOM 时，XML-</div>
		<div>DEV 邮件列表上的许多人提出了 DOM 的几个问题：</div>
		<div>DOM 构建整个文档驻留内存的树。如果文档很大，就会要求有极大的内存。 <br />DOM 创建表示原始文档中每个东西的对象，包括元素、文本、属性和空格。如果您只需关注原始文档的一小部分，那么创建那些永远不被使用的</div>
		<div>对象是极其浪费的。 <br />DOM 解析器必须在您的代码取得控制权之前读取整个文档。对于非常大的文档，这会引起显著的延迟。 <br />这些仅仅是由文档对象模型的设计引起的问题；撇开这些问题，DOM API 是解析 XML 文档非常有用的方法。</div>
		<div>用于 XML 的简单 API  第 4 页（共8 页） </div>
		<div> </div>
		<div>
				<br />为了解决 DOM 问题，XML-DEV 参与者们（由 David Megginson 领导）创建了 SAX 接口。SAX 的几个特征解决了 DOM 的问题：</div>
		<div>SAX 解析器向您的代码发送事件。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时，它会告诉您。您可以决定什么事件对您重</div>
		<div>要，而且可以决定要创建什么类型的数据结构以保存来自这些事件的数据。如果您没有显式地保存来自某个事件的数据，它就被丢弃。 <br />SAX 解析器根本不创建任何对象，它只是将事件传递给您的应用程序。如果希望基于那些事件创建对象，这将由您来完成。 <br />SAX 解析器在解析开始的时候就开始发送事件。当解析器发现文档开始、元素开始和文本等时，代码会收到一个事件。您的应用程序可以立即开</div>
		<div>始生成结果；您不必一直等到整个文档被解析完毕。更妙的是，如果您只查找文档中某些内容，代码一旦找到所要找的东西就可以抛出一个异常</div>
		<div>。该异常会停止 SAX 解析器，然后代码用它找到的数据做它需要做的任何事。 <br />该说的都已经说了，SAX 和 DOM 各有千秋。本章余下的部分将讨论为什么您可能需要使用不同的接口。</div>
		<div> </div>
		<div>
				<strong>
						<em>SAX 问题<br /></em>
				</strong>公平而言，SAX 解析器也有些问题引人关注：</div>
		<div>SAX 事件是无状态的。当 SAX 解析器在 XML 文档中发现文本时，它就向您的代码发送一个事件。该事件仅仅给您发现的文本；它不告诉您什么</div>
		<div>元素包含那个文本。如果您想知道这一点，则必须自己编写状态管理代码。 <br />SAX 事件不是持久的。如果应用程序需要一个数据结构来对 XML 文档建模，则必须自己编写那样的代码。如果您需要从 SAX 事件访问数据，并</div>
		<div>且没有把那个数据存储在代码中，那么您不得不再次解析该文档。 <br />SAX 不是由一个集中管理的组织控制的。尽管到目前为止这还没有引起什么问题，但如果 SAX 是由象 W3C 这样的一个组织控制的话，有些开发</div>
		<div>人员会感觉更自在。 </div>
		<div> </div>
		<div>
				<strong>
						<em>JDOM</em>
				</strong>
				<br />用 DOM 和 SAX 模型完成某些任务时的困难使 Jason Hunter 和 Brett McLaughlin 感到失望，于是他们创建了 JDOM 包。JDOM 是基于 Java 技</div>
		<div>术的开放源码项目，它试图遵循 80/20 规则：用 DOM 和 SAX 20% 的功能来满足 80% 的用户需求。JDOM 使用 SAX 和 DOM 解析器，因此它是作</div>
		<div>为一组相对较小的 Java 类被实现的。</div>
		<div>JDOM 的主要特性是它极大地减少了您必须编写的代码数量。尽管本篇介绍性教程并不深入讨论编程主题，但 JDOM 应用程序的长度通常是 DOM </div>
		<div>应用程序的三分之一，大约是 SAX 应用程序的一半。（当然，坚持使用 DOM 的纯粹主义者会建议说：从长远来看，学习和使用 DOM 终会有所回</div>
		<div>报）。JDOM 并不做所有的事，但对于大多数您要做的解析，它可能正好适合您。</div>
		<div>用于 XML 解析的 Java API<br />尽管 DOM、SAX 和 JDOM 为大多数常见任务提供了标准接口，但仍有些事情是它们不能解决的。例如，在 Java 程序中创建 DOMParser 对象的过</div>
		<div>程因 DOM 解析器的不同而不同。为了修正这个问题，Sun 发布了 JAXP（用于 XML 解析的 Java API，Java API for XML Parsing）。该 API 为</div>
		<div>使用 DOM、SAX 和 XSLT 处理 XML 文档提供了公共接口。</div>
		<div>JAXP 提供的诸如 DocumentBuilderFactory 和 DocumentBuilder 之类的接口为不同的解析器提供了一个标准接口。还有一些方法可以允许您控</div>
		<div>制底层的解析器是否可以识别名称空间以及是否使用 DTD 或模式来验证 XML 文档。</div>
		<div>哪种接口适合您？<br />为了确定哪种接口适合您，您需要理解所有接口的设计要点，而且需要理解应用程序用您将要处理的 XML 文档来做什么。考虑下面的问题将有助</div>
		<div>于您找到正确的方法。</div>
		<div>要用 Java 编写应用程序吗？JAXP 使用 DOM、SAX 和 JDOM；如果您用 Java 编写代码，那么您应使用 JAXP 将您的代码与各种解析器实现的细</div>
		<div>节隔离。 <br />应用程序将如何部署？如果您的应用程序将要作为 Java applet 部署，那么您会希望使要下载的代码数量最小，别忘了 SAX 解析器比 DOM 解析</div>
		<div>器小。还要知道使用 JDOM 时，除了 SAX 或 DOM 解析器之外还要求编写少量的代码。 <br />一旦解析了 XML 文档，还需要多次访问那些数据吗？如果您需要回过头来访问 XML 文件的已解析版本，DOM 可能是正确的选择。而 SAX 事件被</div>
		<div>触发时，如果您以后需要它，则由您（开发人员）自己决定以某种方式保存它。如果您需要访问不曾保存的事件，则必须再次解析该文件。而 </div>
		<div>DOM 自动保存所有的数据。 <br />只需要 XML 源文件的少量内容吗？如果您只需要 XML 源文件的少量内容，那么 SAX 可能是正确的选择。SAX 不会为源文件中的每个东西创建对</div>
		<div>象；您要确定什么是重要的。使用 SAX，您要检查每个事件以了解它是否与您的需要有关，然后相应地处理它。更妙的是，一旦找到您正在寻找</div>
		<div>的东西，您的代码就会抛出一个异常来完全停止 SAX 解析器。 <br />您正在一台内存很少的机器上工作吗？若是的话，不管您可能考虑到的其它因素是什么，SAX 是您的最佳选择。 <br />要知道还存在用于其它语言的 XML API；尤其是 Perl 和 Python 社区有极佳的 XML 工具。</div>
		<div> </div>
		<div> </div>
		<div>
				<strong>XML 标准</strong>
				<br />XML 世界中存在多种标准。除了基本 XML 标准以外，其它标准定义了模式、样式表、链接、Web 服务、安全性和其它重要项目。本章介绍最流行</div>
		<div>的 XML 标准，并为您指出了查找其它标准的参考资料。</div>
		<div>
				<br />
				<strong>
						<em>XML 规范</em>
				</strong>
				<br />该规范（位于 <a href="http://www.w3.org/TR/REC-xml"><font color="#ffffff">http://www.w3.org/TR/REC-xml</font></a>）定义了 XML 文档的基本规则。本教程前面讨论的所有 XML 文档规则都是在此规范中定义的。</div>
		<div>除了基本 XML 标准以外，名称空间规范是 XML 的另一个重要部分。您也可以在 W3C 查找名称空间标准：<a href="http://www.w3.org/TR/REC-xml"><font color="#ffffff">http://www.w3.org/TR/REC-xml</font></a>-</div>
		<div>names/。</div>
		<div>
				<br />XML Schema<br />XML Schema 语言定义成以下三个部分：</div>
		<div>入门位于 w3.org/TR/xmlschema-0，它介绍了 XML 模式文档及其设计用途； <br />文档结构的标准位于w3.org/TR/xmlschema-1，它说明了如何定义 XML 文档的结构； <br />数据类型的标准位于w3.org/TR/xmlschema-2，它定义了一些常用数据类型以及创建新类型的规则。 <br />本教程在定义文档内容中简要地介绍了模式；如果您对于用 XML 模式可以做的所有事情，需要了解完整的详细信息，那么最好先阅读“入门”。<br /> <br />XSL、XSLT 和 XPath<br />可扩展样式表语言（Extensible Stylesheet Language（XSL））定义了一组元素（称为格式化对象），它们描述应该如何格式化数据。为清晰起</div>
		<div>见，通常将该标准称为 XSL-FO 以和 XSLT 进行区分。尽管它主要是设计用于生成高质量的可打印文档，但您也可以使用格式化对象从 XML 生成</div>
		<div>音频文件。XSL-FO 标准位于 w3.org/TR/xsl/。</div>
		<div>用于转换的可扩展样式表语言（Extensible Stylesheet Language for Transformation（XSLT））是一个描述如何将 XML 文档转换成别的东西</div>
		<div>的 XML 词汇表。该标准位于w3.org/TR/xslt（结尾没有斜杠符号）。</div>
		<div>XPath（XML 路径语言，XML Path Language）是描述 XML 文档中位置的语法。您使用 XSLT 样式表中的 XPath 来描述您希望转换 XML 文档的哪</div>
		<div>个部分。XPath 也用在其它 XML 标准中，这就是为什么它是独立于 XSLT 的标准的原因。XPath 在 w3.org/TR/xpath（结尾没有斜杠符号）中定</div>
		<div>义。</div>
		<div>DOM <br />文档对象模型定义了如何将 XML 文档转换为驻留内存的树结构。DOM 在 W3C 的许多规范中都有定义：</div>
		<div>核心 DOM 定义 DOM 本身、树结构、以及代码遍历树时会发现的各种节点和异常。完整的规范在 w3.org/TR/DOM-Level-2-Core/。 <br />事件定义对于树可以发生的事件，以及如何处理这些事件。该规范试图协调 Netscape 和 Internet Explorer 浏览器的版本 4 之后所支持对象</div>
		<div>模型之间的差异。该规范位于 w3.org/TR/DOM-Level-2-Events/。 <br />样式定义程序如何访问 XSLT 样式表和 CSS 样式表。该规范位于 w3.org/TR/DOM-Level-2-Style/。 <br />遍历和范围定义一些允许程序遍历树或定义树中节点范围的接口。可以在 w3.org/TR/DOM-Level-2-Traversal-Range/ 找到完整的规范。 <br />视图为文档本身定义 AbstractView 接口。请参阅 w3.org/TR/DOM-Level-2-Views/ 以获得更多信息。</div>
		<div> </div>
		<div>
				<strong>
						<em>SAX、JDOM 和 JAXP<br /></em>
				</strong>用于 XML 的简单 API 定义了一些事件和接口，用于与符合 SAX 的 XML 解析器进行交互。可以在 <a href="http://www.saxproject.org/"><font color="#ffffff">www.saxproject.org</font></a> 上找到完整的 SAX 规范</div>
		<div>。</div>
		<div>Jason Hunter 和 Brett McLaughlin 创建的 JDOM 项目位于 jdom.org/。在 JDOM 站点，您可以找到代码、样本程序和其它能帮助您入门的工具</div>
		<div>。（有关在 developerWorks 上介绍 JDOM 的文章，请参阅参考资料）。</div>
		<div>有关 SAX 和 JDOM 的重要一点是：二者都来自 XML 开发人员社区，而不是标准组织。它们获得的广泛接受是对全世界 XML 开发人员积极参与的</div>
		<div>回报。</div>
		<div>您可以在 java.sun.com/xml/jaxp/ 找到所有与 JAXP 有关的内容。</div>
		<div>
				<br />链接和引用<br />在 XML 世界中有两个用于链接和引用的标准：XLink 和 XPointer：</div>
		<div>XLink（XML 链接语言，XML Linking Language）定义将不同资源链接在一起的各种方法。您可以进行正常的点对点链接（就象用 HTML &lt;a&gt; 元素</div>
		<div>）或扩展的链接，后者可包括多点链接、通过第三方的链接以及定义转向给定链接的意义的规则。XLink 标准位于 <a href="http://www.w3.org/TR/xlink/"><font color="#ffffff">www.w3.org/TR/xlink/</font></a>。 <br />XPointer（XML 指针语言，XML Pointer Language）使用 XPath 作为引用其它资源的方法。它还包括对 XPath 的一些扩展。可以在 </div>
		<div>
				<a href="http://www.w3.org/TR/xptr/">
						<font color="#ffffff">www.w3.org/TR/xptr/</font>
				</a> 找到该规范。 </div>
		<div>安全性<br />有两个处理 XML 文档安全性的重要标准。一个是 XML 数字签名（XML Digital Signature）标准（w3.org/TR/xmldsig-core/），它定义了用于</div>
		<div>数字签名的 XML 文档结构。您可以为任何类型的数据创建 XML 数字签名，不管它是 XML 文档、HTML 文件、纯文本、二进制数据还是其它东西</div>
		<div>。您可以用数字签名来验证一个特定文件自签名后没有被修改过。如果您要签名的数据是 XML 文档，您可以将 XML 文档嵌入签名文件本身，这</div>
		<div>会使数据和签名的处理变得非常简单。</div>
		<div>另一个标准用于加密 XML 文档。可以将 XML 文档编写得易于人们阅读和理解，尽管这样做很好，但如果文档落入坏人之手就会引起麻烦。XML </div>
		<div>加密（XML Encryption）标准（w3.org/TR/xmlenc-core/）定义了如何加密 XML 文档的各部分。</div>
		<div>将这些标准一起使用，您就能放心地使用 XML 文档了。我可以对一个重要的 XML 文档进行数字签名，生成一个包含 XML 文档本身的签名。然后</div>
		<div>我可以加密该文档（使用我的私钥和您的公钥）然后把它发送给您。当您收到文档时，您可以用您的私钥和我的公钥解密该文档；这可以让您知</div>
		<div>道是我发送的文档。（如果需要，您还可以证明我发送了文档）。一旦您解密了文档，您可以使用该数字签名确定文档没有经过任何修改。</div>
		<div> </div>
		<div>
				<strong>
						<em>Web 服务</em>
				</strong>
				<br />Web 服务是一种新的重要的应用程序。Web 服务是一段可以用 XML 发现、描述和访问的代码。在这一领域有许多活动，但有三种主要的用于 Web </div>
		<div>服务的 XML 标准：</div>
		<div>SOAP：最初是简单对象访问协议（Simple Object Access Protocol），SOAP 定义一个 XML 文档格式，该格式描述如何调用一段远程代码的方法</div>
		<div>。我的应用程序创建一个描述我希望调用的方法的 XML 文档，并传递给它所有必需的参数，然后应用程序通过网络将该 XML 文档发送给那段代</div>
		<div>码。代码接收 XML 文档、解释它、调用我请求的方法，然后发回一个描述结果的 XML 文档。SOAP 规范版本 1.1 位于 w3.org/TR/SOAP/。请访</div>
		<div>问 w3.org/TR/ 以了解 W3C 中 SOAP 相关的所有活动。 <br />WSDL：Web 服务描述语言（Web Services Description Language）是一个描述 Web 服务的 XML 词汇表。编写一段接收 WSDL 文档然后调用其以</div>
		<div>前从未用过的 Web 服务的代码，这是可能的。WSDL 文件中的信息定义 Web 服务的名称、它的方法的名称、这些方法的参数和其它详细信息。您</div>
		<div>可以在 w3.org/TR/wsdl（结尾没有斜杠符号）找到最新的 WSDL 规范。 <br />UDDI：统一描述、发现和集成（Universal Description, Discovery, and Integration）协议向 Web 服务注册中心定义 SOAP 接口。如果您有</div>
		<div>一段代码希望作为 Web 服务部署，UDDI 规范定义如何将您的服务描述添加至注册中心。如果您在寻找一段提供某种功能的代码，UDDI 规范定义</div>
		<div>如何查询注册中心以找到您想要的信息。有关 UDDI 的所有资料来源都可以在 <a href="http://www.uddi.org/"><font color="#ffffff">www.uddi.org</font></a> 找到。 </div>
		<div>其它标准<br />还有许多其它的 XML 标准，我没有在这里深入介绍。除了象可伸缩向量图（Scalable Vector Graphic）（<a href="http://www.w3.org/TR/SVG/"><font color="#ffffff">www.w3.org/TR/SVG/</font></a>）、SMIL（同步</div>
		<div>多媒体集成语言，Synchronized Multimedia Integration Language）（<a href="http://www.w3.org/TR/smil20/"><font color="#ffffff">www.w3.org/TR/smil20/</font></a>）那样可广泛应用的标准外，还有许多特定于业</div>
		<div>界的标准。例如，HR-XML 协会已定义了许多用于人力资源的 XML 标准；您可以在 <a href="http://www.hr-xml.org/"><font color="#ffffff">www.hr-xml.org</font></a> 找到那些标准。</div>
		<div>最后，要查找有关 XML 标准的优秀信息来源，请访问 xml.org/xml/registry.jsp 上的 XML 资源库。该站点的特点是有数百个用于各行各业的</div>
		<div>标准。</div>
		<div>现实世界示例<br />到目前为止，我希望您相信 XML 具有能使电子商务的运行方式发生革命性变化的极大潜力。尽管潜力是巨大的，但真正重要的是市场中的实际结</div>
		<div>果。本章描述了三个案例研究，案例中的组织使用了 XML 来简化其业务过程并改进其结果。</div>
		<div>这里讨论的所有案例研究都来自 IBM 的 jStart 计划。jStart 团队的任务是帮助客户使用新技术来解决问题。当客户同意 jStart 约定时，他</div>
		<div>会以一定的折扣得到 IBM 咨询和开发服务，客户将被明确告之由此产生的项目将会被作为案例研究使用。如果您想看到更多案例研究，包括涉及 </div>
		<div>Web 服务和其它新技术的案例研究，请通过 ibm.com/software/jstart 访问 jStart Web 页面。</div>
		<div>请注意，jStart 团队不再从事 XML 项目的工作；小组当前的工作重点是从事 Web 服务。Web 服务以专门的方式使用 XML，通常是通过前面Web </div>
		<div>服务中提到的 SOAP、WSDL 和 UDDI 标准来使用 XML。 </div>
		<div>
				<br />用 XML 生成多个用户界面<br />除了 HTML 界面以外，还规划了 Java 客户机界面和 B2B 电子界面。针对所有这些界面，将结构化的 XML 数据转换成适当的结构和文档。该服</div>
		<div>务首次公开展示时允许一个业务伙伴 — 加拿大证券注册系统（Canadian Securities Registration Systems）使用安全套接字层（SSL）提交 </div>
		<div>XML 事务数据。然后将该 XML 事务数据转换成用于后端事务的适当格式。</div>
		<div>最终结果是马尼托巴省能够创建一个灵活的新应用程序，并且他们的最终用户可以更方便更快捷地访问财产注册中心。因为该省使用 XML 作为数</div>
		<div>据格式，所以政府 IT 团队在设计新界面和新访问方法时有极大的灵活性。最棒的是，根本不必更改后端系统。</div>
		<div>第一联合银行（First Union）使用 XML<br />第一联合银行（美国最大的银行之一）正在使用 Java 和 XML 重新设计它的许多应用程序。和大多数大公司一样，它有一个异构环境，有 </div>
		<div>OS/390、AIX、Solaris、HP/9000 以及 Windows NT 服务器和 Windows NT、Windows 98、Solaris 和 AIX 客户机。在这种环境下，第一联合银</div>
		<div>行选择 Java 作为独立于平台的代码，选择 XML 作为独立于平台的数据。</div>
		<div>用 Web 服务来帮忙！<br />为了解决这些问题，Hewitt 和 jStart 团队共同努力构建 Web 服务来满足 Hewitt 客户的需要。Web 服务是一种以许多有趣方式使用 XML 的新</div>
		<div>型应用程序：</div>
		<div>首先，Web 服务通常使用 SOAP，这是一个用于将 XML 数据从一处移至另一处的 XML 标准。 <br />其次，Web 服务提供的接口（方法名称、参数和数据类型等）是用 XML 描述的。 <br />再次，Web 服务的描述可以存储在 UDDI 注册中心，或从注册中心检索；所有进出该注册中心的信息都格式化为 XML。 <br />最后，Web 服务提供的数据本身就是 XML 数据。 <br />Hewitt 已经开发出两个应用程序，它们都证明了自己以更灵活的方式传递数据的能力：</div>
		<div>使用 Secure Participant Mailbox，经授权的用户可以请求包含关于退休和其它员工福利的个性化信息的报告。 <br />使用 Retirement Access B2B Connection，经授权的用户可以获得客户的 401(k) 财务信息的详细情况。 <br />这些应用程序都从现有的旧系统检索数据，使用 XML 格式化数据，然后在 Web 上传递格式化的信息。因为这些应用程序构建于开放标准之上，</div>
		<div>所以 Hewitt 可以快速地完成它们的开发。最妙的是，这些应用程序的灵活性使 Hewitt 从其竞争对手中脱颖而出。</div>
		<div>“我们把 Web 服务看作一种工具，它通过无所不在的数据网络，对我们参与者的业务服务和数据提供一种开放、非专有的访问。”Hewitt 首席</div>
		<div>技术决策专家 Tim Hilgenberg 这样说道。最终结果是：Hewitt 用较低的成本较快地开发出更灵活的应用程序，客户们能够更好地访问他们的数</div>
		<div>据，并且不必更改 Hewitt 现有的旧应用程序。</div>
		<div>案例研究总结<br />在所有这些案例研究中，各公司都使用 XML 来创建独立于系统的数据格式。XML 文档可以表示那些可以从一个系统或过程移到另一个的结构化数</div>
		<div>据。当前端和后端应用程序更改时，XML 可以在它们之间移动而保持不变。更妙的是，当越来越多的前端和后端应用程序添加进来时，XML 的使</div>
		<div>用将现有应用程序与任何更改都隔离起来。当 Web 服务变得越来越普遍时，XML 还将用来传输数据。</div>
		<div>有关这些案例研究的更多信息，请通过 <a href="mailto:thompsam@us.ibm.com"><font color="#ffffff">thompsam@us.ibm.com</font></a> 与 IBM 的 Sam Thompson 联系。您可以在 <a href="http://www.gov.mb.ca/"><font color="#ffffff">www.gov.mb.ca</font></a> 找到有关马尼托巴省的</div>
		<div>更多信息，第一联合银行的网站是 <a href="http://www.firstunion.com/"><font color="#ffffff">http://www.firstunion.com</font></a>，Hewitt Associates 的网站是 <a href="http://www.hewitt.com/"><font color="#ffffff">http://www.hewitt.com</font></a>。</div>
		<div>建议和参考资料<br />行动起来！<br />此时此刻，我希望您已经相信 XML 是移动和操作结构化数据的最佳方法。如果您现在还没有使用 XML，您该如何开始呢？下面是一些建议：</div>
		<div>确定您要将什么数据转换成 XML。通常这是需要从一个系统移到另一个系统的数据，或必须转换成不同格式的数据。 <br />了解是否有现有的 XML 标准。如果您正在研究很常见的数据，例如采购订单、医疗记录或股票报价，则很可能已经有人为那些数据定义了 XML </div>
		<div>标准。 <br />了解您现有的工具是否支持 XML。如果您正在使用数据库软件包、电子表格或其它数据管理工具的最新版本，则您的现有工具（或其升级版本）</div>
		<div>很可能可以使用 XML 作为输入或输出格式。 <br />学习如何构建基于 XML 的应用程序。您需要理解您的数据现在是如何存储的，需要如何转换它，以及如何将您的 XML 开发工作与现有的应用程</div>
		<div>序集成起来。Benoît Marchal 的 Working XML 专栏是开始的好地方；您可以在 <a href="http://www-106.ibm.com/developerworks/xml/library/x"><font color="#ffffff">http://www-106.ibm.com/developerworks/xml/library/x</font></a>-</div>
		<div>wxxmcol/ 找到他所有专栏文章的最新列表。 <br />加入适当的标准组织。考虑加入象万维网协会（W3C）这样的组织，以及象 HR-XML.org 这样特定于业界的组织。成为这些组织的成员将有助于您</div>
		<div>跟踪业界中所发生的事件，而且使您有机会塑造 XML 标准的未来。 <br />避免专有产品的诡计。在开发工作中仅使用基于标准的技术很重要；抵制为您提供所谓改进的供应商的诱惑。XML 的优点之一是您对数据有完全</div>
		<div>的控制权。一旦它受到某个专有数据格式的限制，您就失去了极大的控制权。 <br />联系 jStart 团队。如果您认为您的企业可以使用 jStart 约定模型，请与该团队联系以了解您可能得到什么服务？ <br />关注 developerWorks。我们的 XML 专区有涉及各种 XML 主题的数千页内容，包括 DTD 和模式开发、XML 编程和创建 XSLT 样式表。 </div>
		<div>
				<br />参考资料<br />下面是一些可以帮助您开始的参考资料：</div>
		<div>dW XML 专区是 XML 参考资料的“一站式商店”。请参阅 www-106.ibm.com/developerworks/xml 以获取您一直希望了解的有关 XML 的内容。</div>
		<div>XML 工具： developerWorks 有一个系列的“Fill your XML toolbox”文章，它们描述用于各种语言的 XML 编程工具：</div>
		<div>C/C++：请在 www-106.ibm.com/developerworks/library/x-ctlbx.html（developerWorks，2001 年 9 月）参阅 Rick Parrish 的文章。 <br />Java：请在 www-106.ibm.com/developerworks/library/java-xml-toolkit/index.html（developerWorks，2000 年 5 月）参阅 Doug Tidwell </div>
		<div>的文章。 <br />Perl：请在 www-106.ibm.com/developerworks/library/perl-xml-toolkit/index.html（developerWorks，2001 年 6 月）参阅 Parand Tony </div>
		<div>Darugar 的文章。 <br />PHP：请在 www-106.ibm.com/developerworks/library/php-xml-toolkit.html（developerWorks，2000 年 6 月）参阅 Craig Knudsen 的文章</div>
		<div>。 <br />除了这些文章以外，请在 www-106.ibm.com/developerworks/library/l-pxml.html 参阅 David Mertz 在其“Charming Python: Revisiting </div>
		<div>XML tools for Python”文章中对 Python XML 工具的评论。</div>
		<div>XML 教程：可在 developerWorks 获得数十篇有关 XML 主题的教程；请参阅 <a href="http://www-105.ibm.com/de"><font color="#ffffff">http://www-105.ibm.com/de</font></a></div>
		<div>veloperworks/education.nsf/dw/xml-onlinecourse-bytitle 以获得最新的列表。</div>
		<div>IBM 的 jStart 团队：jStart 团队使用新技术（例如 XML Web 服务）以非常低的成本帮助客户构建解决方案。作为回报，那些客户同意让 IBM </div>
		<div>将他们的项目作为案例研究公布。要了解更多信息，请参阅 ibm.com/software/jstart。</div>
		<div>XML 标准：下面是本教程中提到的所有 XML 标准的字母顺序列表。</div>
		<div>DOM，文档对象模型：<br />核心规范： w3.org/TR/DOM-Level-2-Core/ <br />事件规范： w3.org/TR/DOM-Level-2-Events/ <br />样式规范： w3.org/TR/DOM-Level-2-Style/ <br />遍历和范围规范： w3.org/TR/DOM-Level-2-Traversal-Range/ <br />视图规范： w3.org/TR/DOM-Level-2-Views/ <br />HR-XML.org，人力资源 XML 协会（Human Resources XML Consortium）：hr-xml.org <br />JAXP，用于 XML 解析的 Java API（Java API for XML Parsing）：java.sun.com/xml/jaxp/ <br />JDOM，不代表任何缩写形式：jdom.org/ <br />SAX，用于 XML 的简单 API（Simple API for XML）：saxproject.org/ <br />SMIL，同步多媒体集成语言（Synchronized Multimedia Integration Language）：<a href="http://www.w3.org/TR/smil20/"><font color="#ffffff">www.w3.org/TR/smil20/</font></a><br />SOAP，过去用于代表简单对象访问协议（Simple Object Access Protocol），但现在正式不代表任何缩写形式：w3.org/TR/SOAP/ <br />SVG，可伸缩向量图（Scalable Vector Graphics）：<a href="http://www.w3.org/TR/SVG/"><font color="#ffffff">www.w3.org/TR/SVG/</font></a><br />UDDI，统一描述、发现和集成协议（Universal Description, Discovery, and Integration Protocol）：uddi.org <br />WSDL，Web 服务描述语言（Web Services Description Language）：w3.org/TR/wsdl（结尾没有斜杠符号） <br />XLink，XML 链接语言（XML Linking Language）：w3.org/TR/xlink/ <br />XML，最基础的标准：w3.org/TR/REC-xml <br />XML 数字签名（XML Digital Signature）：w3.org/TR/xmldsig-core/ <br />XML 加密（XML Encryption）：w3.org/TR/xmlenc-core/ <br />XML 名称空间（XML Namespaces）：w3.org/TR/REC-xml-names/ <br />DTD 和模式的 XML 资源库（XML Repository）：xml.org/xml/registry.jsp <br />XML Schema：<br />第 0 部分 — 入门：w3.org/TR/xmlschema-0 <br />第 1 部分 — 文档结构：w3.org/TR/xmlschema-1 <br />第 2 部分 — 数据类型：w3.org/TR/xmlschema-2 <br />XPath，XML 路径语言（XML Path Language）：w3.org/TR/xpath（结尾没有斜杠符号） <br />XPointer，XML 指针语言（XML Pointer Language）：<a href="http://www.w3.org/TR/xptr/"><font color="#ffffff">www.w3.org/TR/xptr/</font></a><br />XSL-FO，用于格式化对象的可扩展样式表语言（Extensible Stylesheet Language for Formatting Objects）：w3.org/TR/xsl/ <br />XSLT，可扩展样式表语言（Extensible Stylesheet Language）：w3.org/TR/xslt（结尾没有斜杠符号） <br />有关 JDOM 的更多信息，请参阅以下 developerWorks 文章：</div>
		<div>Simplify XML programming with JDOM（developerWorks，2001 年 5 月，<a href="http://www.ibm.com/developerWorks/cn/java/j-jdom/index.shtml"><font color="#ffffff">http://www.ibm.com/developerWorks/cn/java/j-jdom/index.shtml</font></a></div>
		<div>） <br />Converting from DOM（developerWorks，2001 年 4 月，<a href="http://www.ibm.com/developerWorks/cn/xml/tips/x-tipcdm/index.shtml"><font color="#ffffff">http://www.ibm.com/developerWorks/cn/xml/tips/x-tipcdm/index.shtml</font></a>） <br />Converting from SAX（developerWorks，2001 年 4 月，<a href="http://www.ibm.com/developerWorks/cn/xml/tips/x-tipcsx/index.shtml"><font color="#ffffff">http://www.ibm.com/developerWorks/cn/xml/tips/x-tipcsx/index.shtml</font></a>） <br />Using JDOM and XSLT（developerWorks，2001 年 3 月，<a href="http://www.ibm.com/developerWorks/cn/xml/tips/x-tipjdom/index.shtml"><font color="#ffffff">http://www.ibm.com/developerWorks/cn/xml/tips/x-tipjdom/index.shtml</font></a>） </div>
<img src ="http://www.blogjava.net/fortune/aggbug/75414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-10-16 14:52 <a href="http://www.blogjava.net/fortune/archive/2006/10/16/75414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>连接数据库出现错误的原因</title><link>http://www.blogjava.net/fortune/archive/2006/06/06/50808.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Tue, 06 Jun 2006 08:43:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/06/06/50808.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/50808.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/06/06/50808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/50808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/50808.html</trackback:ping><description><![CDATA[
		<strong>问：服务器拒绝访问，telnet 1433 失败的问题。</strong>从来没遇到过这种问题，在客户的一台机上装了我公司的软件和Sql server ，运行时居然出现服务器不存在或拒绝访问。客户的操作系统是xp,我给他装了sql server 的个人版。
<p>　　程序是绝对没问题的，因为已被很多其他客户使用。后面我检查了一下 ping 服务器，ping ip 都可以ping 通，也可以打开查询分析器。</p><p>　　但就是应用程序访问不了，后面我用 telnet 主机 1433 和　telnet IP 1433　测试，居然失败，估计是1433端口的问题</p><p>　　我在服务器端网络实用工具作了设置winsock代理1433端口和tcpip默认端口还是不行，在客户端网络实用工具作了设置别名，还是不行。调了好久，还是没能成功，是不是因为windos　有其他设置或防火墙的设置(客户是用adsl上网的，没装其他防火墙)不能访问1433端口的。</p><p> </p><p> </p><p>　　答：第一步，先确定你的情况是否符合这篇文章的描述：<br /><strong>                                                                  <br />                                                            《SQL Server连接中常见的错误》<br /></strong><br />SQL Server连接中的四个最常见错误:</p><p><strong>　　一."SQL Server 不存在或访问被拒绝"</strong></p><p><strong>　　这个是最复杂的,错误发生的原因比较多,需要检查的方面也比较多.</strong></p><p><strong>　　一般说来,有以下几种可能性:</strong></p><p><strong>　　1,SQL Server名称或IP地址拼写有误</strong></p><p><strong>　　2,服务器端网络配置有误</strong></p><p><strong>　　3,客户端网络配置有误</strong></p><p><strong>　　要解决这个问题,我们一般要遵循以下的步骤来一步步找出导致错误的原因.</strong></p><p><strong>　　============= 首先,检查网络物理连接 =============</strong></p><p><strong>　　ping &lt;服务器IP地址/服务器名称&gt;</strong></p><p><strong>　　如果 ping &lt;服务器IP地址&gt; 不成功,说明物理连接有问题,这时候要检查硬件设备,如网卡,HUB,路由器等.</strong></p><p><strong>　　还有一种可能是由于客户端和服务器之间安装有防火墙软件造成的,比如 ISA Server.防火墙软件可能会屏蔽对 ping,telnet 等的响应</strong></p><p><strong>　　因此在检查连接问题的时候,我们要先把防火墙软件暂时关闭,或者打开所有被封闭的端口.</strong></p><p><strong>　　如果ping &lt;服务器IP地址&gt; 成功而,ping &lt;服务器名称&gt; 失败</strong></p><p><strong>　　则说明名字解析有问题,这时候要检查 DNS 服务是否正常.</strong></p><p><strong>　　有时候客户端和服务器不在同一个局域网里面,这时候很可能无法直接使用服务器名称来标识该服务器,这时候我们可以使用HOSTS文件来进行名字解析,</strong></p><p><strong>　　具体的方法是:</strong></p><p><strong>　　1.使用记事本打开HOSTS文件(一般情况下位于C:\WINNT\system32\drivers\etc).</strong></p><p><strong>　　添加一条IP地址与服务器名称的对应记录,如:</strong></p><p><strong>　　172.168.10.24 myserver</strong></p><p><strong>　　2.或在 SQL Server 的客户端网络实用工具里面进行配置,后面会有详细说明.</strong></p><p><strong>　　============= 其次,使用 telnet 命令检查SQL Server服务器工作状态 =============</strong></p><p><strong>　　telnet &lt;服务器IP地址&gt; 1433</strong></p><p><strong>　　如果命令执行成功,可以看到屏幕一闪之后光标在左上角不停闪动,这说明 SQL Server 服务器工作正常,并且正在监听1433端口的 TCP/IP 连接</strong></p><p><strong>　　如果命令返回"无法打开连接"的错误信息,则说明服务器端没有启动 SQL Server 服务,</strong></p><p><strong>　　也可能服务器端没启用 TCP/IP 协议,或者服务器端没有在 SQL Server 默认的端口1433上监听.</strong></p><p><strong>　　=============接着,我们要到服务器上检查服务器端的网络配置,检查是否启用了命名管道.是否启用了 TCP/IP 协议等等 =============</strong></p><p><strong>　　可以利用 SQL Server 自带的服务器网络使用工具来进行检查.</strong></p><p><strong>　　点击:程序 -- Microsoft SQL Server -- 服务器网络使用工具</strong></p><p><strong>　　打开该工具后,在"常规"中可以看到服务器启用了哪些协议.</strong></p><p><strong>　　一般而言,我们启用命名管道以及 TCP/IP 协议.</strong></p><p><strong>　　点中 TCP/IP 协议,选择"属性",我们可以来检查 SQK Server 服务默认端口的设置</strong></p><p><strong>　　一般而言,我们使用 SQL Server 默认的1433端口.如果选中"隐藏服务器",则意味着客户端无法通过枚举服务器来看到这台服务器,起到了保护的作用,但不影响连接.</strong></p><p><strong>　　============= 接下来我们要到客户端检查客户端的网络配置 =============</strong></p><p><strong>　　我们同样可以利用 SQL Server 自带的客户端网络使用工具来进行检查,</strong></p><p><strong>　　所不同的是这次是在客户端来运行这个工具.</strong></p><p><strong>　　点击:程序 -- Microsoft SQL Server -- 客户端网络使用工具</strong></p><p><strong>　　打开该工具后,在"常规"项中,可以看到客户端启用了哪些协议.</strong></p><p><strong>　　一般而言,我们同样需要启用命名管道以及 TCP/IP 协议.</strong></p><p><strong>　　点击 TCP/IP 协议,选择"属性",可以检查客户端默认连接端口的设置,该端口必须与服务器一致.</strong></p><p><strong>　　单击"别名"选项卡,还可以为服务器配置别名.服务器的别名是用来连接的名称,</strong></p><p><strong>　　连接参数中的服务器是真正的服务器名称,两者可以相同或不同.别名的设置与使用HOSTS文件有相似之处.</strong></p><p><strong>　　通过以上几个方面的检查,基本上可以排除第一种错误.</strong></p><p><strong>　　-----------------------------------------------------------------------------</strong></p><p><strong>　　二."无法连接到服务器,用户xxx登陆失败"</strong></p><p><strong>　　该错误产生的原因是由于SQL Server使用了"仅 Windows"的身份验证方式,</strong></p><p><strong>　　因此用户无法使用SQL Server的登录帐户(如 sa )进行连接.解决方法如下所示:</strong></p><p><strong>　　1.在服务器端使用企业管理器,并且选择"使用 Windows 身份验证"连接上 SQL Server</strong></p><p><strong>　　操作步骤:</strong></p><p><strong>　　在企业管理器中</strong></p><p><strong>　　--右键你的服务器实例(就是那个有绿色图标的)</strong></p><p><strong>　　--编辑SQL Server注册属性</strong></p><p><strong>　　--选择"使用windows身份验证"</strong></p><p><strong>　　--选择"使用SQL Server身份验证"</strong></p><p><strong>　　--登录名输入:sa,密码输入sa的密码</strong></p><p><strong>　　--确定</strong></p><p><strong>　　2.设置允许SQL Server身份登录</strong></p><p><strong>　　操作步骤:</strong></p><p><strong>　　在企业管理器中</strong></p><p><strong>　　--展开"SQL Server组",鼠标右键点击SQL Server服务器的名称</strong></p><p><strong>　　--选择"属性"</strong></p><p><strong>　　--再选择"安全性"选项卡</strong></p><p><strong>　　--在"身份验证"下,选择"SQL Server和 Windows ".</strong></p><p><strong>　　--确定,并重新启动SQL Server服务.</strong></p><p><strong>　　在以上解决方法中,如果在第 1 步中使用"使用 Windows 身份验证"连接 SQL Server 失败,</strong></p><p><strong>　　那就通过修改注册表来解决此问题:</strong></p><p><strong>　　1.点击"开始"-"运行",输入regedit,回车进入注册表编辑器</strong></p><p><strong>　　2.依次展开注册表项,浏览到以下注册表键:</strong></p><p><strong>　　[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\MSSQLServer]</strong></p><p><strong>　　3.在屏幕右方找到名称"LoginMode",双击编辑双字节值</strong></p><p><strong>　　4.将原值从1改为2,点击"确定"</strong></p><p><strong>　　5.关闭注册表编辑器</strong></p><p><strong>　　6.重新启动SQL Server服务.</strong></p><p><strong>　　此时,用户可以成功地使用sa在企业管理器中新建SQL Server注册,</strong></p><p><strong>　　但是仍然无法使用Windows身份验证模式来连接SQL Server.</strong></p><p><strong>　　这是因为在 SQL Server 中有两个缺省的登录帐户:</strong></p><p><strong>　　BUILTIN\Administrators</strong></p><p><strong>　　&lt;机器名&gt;\Administrator 被删除.</strong></p><p><strong>　　要恢复这两个帐户,可以使用以下的方法:</strong></p><p><strong>　　1.打开企业管理器,展开服务器组,然后展开服务器</strong></p><p><strong>　　2.展开"安全性",右击"登录",然后单击"新建登录"</strong></p><p><strong>　　3.在"名称"框中,输入 BUILTIN\Administrators</strong></p><p><strong>　　4.在"服务器角色"选项卡中,选择"System Administrators"</strong></p><p><strong>　　5.点击"确定"退出</strong></p><p><strong>　　6.使用同样方法添加 &lt;机器名&gt;\Administrator 登录.</strong></p><p><strong>　　说明:</strong></p><p><strong>　　以下注册表键:</strong></p><p><strong>　　HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\LoginMode</strong></p><p><strong>　　的值决定了SQL Server将采取何种身份验证模式.</strong></p><p><strong>　　1.表示使用"Windows 身份验证"模式</strong></p><p><strong>　　2.表示使用混合模式(Windows 身份验证和 SQL Server 身份验证).</strong></p><p><strong>　　-----------------------------------------------------------------------------</strong></p><p><strong>　　三.提示连接超时</strong></p><p><strong>　　如果遇到第三个错误,一般而言表示客户端已经找到了这台服务器,并且可以进行连接,</strong></p><p><strong>　　不过是由于连接的时间大于允许的时间而导致出错.</strong></p><p><strong>　　这种情况一般会发生在当用户在Internet上运行企业管理器来注册另外一台同样在Internet上的服务器,</strong></p><p><strong>　　并且是慢速连接时,有可能会导致以上的超时错误.有些情况下,由于局域网的网络问题,也会导致这样的错误.</strong></p><p><strong>　　要解决这样的错误,可以修改客户端的连接超时设置.</strong></p><p><strong>　　默认情况下,通过企业管理器注册另外一台SQL Server的超时设置是 4 秒,</strong></p><p><strong>　　而查询分析器是 15 秒(这也是为什么在企业管理器里发生错误的可能性比较大的原因).</strong></p><p><strong>　　具体步骤为:</strong></p><p><strong>　　企业管理器中的设置:</strong></p><p><strong>　　1.在企业管理器中,选择菜单上的"工具",再选择"选项"</strong></p><p><strong>　　2.在弹出的"SQL Server企业管理器属性"窗口中,点击"高级"选项卡</strong></p><p><strong>　　3.在"连接设置"下的"登录超时(秒)"右边的框中输入一个比较大的数字,如 20.</strong></p><p><strong>　　查询分析器中的设置:</strong></p><p><strong>　　工具 -- 选项 -- 连接 -- 将登录超时设置为一个较大的数字</strong></p><p><strong>　　---------------------------------------------------------------------------------</strong></p><p><strong>　　四.大部分机都用Tcp/ip才能成功，有次我发现用Named Pipes才可以?</strong></p><p><strong>　　回复人: leimin(黄山光明顶)</strong></p><p><strong>　　这是因为在WINDOWS 2000以后的操作系统中，MS为解决SQL SERVER的安全问题将TCP/IP配置</strong></p><p><strong>　　为SQLSERVER的默认连接协议，你可以在CLIENT NETWORK UTILITY中看到TCP/IP和NAME PIPE</strong></p><p><strong>　　的顺序。</strong></p><p><strong>　　你也可以在:</strong></p><p><strong>　　[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\SuperSocketNetLib]</strong></p><p><strong>　　"ProtocolOrder"=hex(7):74,00,63,00,70,00,00,00,00,00</strong></p><p><strong>　　看到默认的协议。</strong></p><p><strong>　　2.怎么在程序中更改Named Pipes ， Tcp/ip ，其sql语句怎么写?</strong></p><p><strong>　　你可以在上面提到的注册表的位置修改:</strong></p><p><strong>　　CLIENT端:</strong></p><p><strong>　　[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\SuperSocketNetLib]</strong></p><p><strong>　　"ProtocolOrder"=hex(7):74,00,63,00,70,00,00,00,00,00</strong></p><p><strong>　　SERVER端:</strong></p><p><strong>　　[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\SuperSocketNetLib]</strong></p><p><strong>　　"ProtocolOrder"=hex(7):74,00,63,00,70,00,00,00,00,00</strong></p><p><br /><br /><br /> </p><p><strong>      </strong>第二步，如果是远程方面的问题，请参看这篇文章：<br /><br /><strong>                                                            《远程连接sql server 服务器的解决方案》<br /><br /></strong>远程连接sql server 2000服务器的解决方案</p><p><strong>　　一 看ping 服务器IP能否ping通。</strong></p><p><strong>　　这个实际上是看和远程sql server 2000服务器的物理连接是否存在。如果不行，请检查网络，查看配置，当然得确保远程sql server 2000服务器的IP拼写正确。</strong></p><p><strong>　　二 在Dos或命令行下输入telnet 服务器IP 端口，看能否连通。</strong></p><p><strong>　　如telnet 202.114.100.100 1433</strong></p><p><strong>　　通常端口值是1433，因为1433是sql server 2000的对于Tcp/IP的默认侦听端口。如果有问题，通常这一步会出问题。通常的提示是“……无法打开连接,连接失败"。</strong></p><p><strong>　　如果这一步有问题，应该检查以下选项。</strong></p><p><strong>　　1 检查远程服务器是否启动了sql server 2000服务。如果没有，则启动。</strong></p><p><strong>　　2 检查服务器端有没启用Tcp/IP协议，因为远程连接(通过因特网)需要靠这个协议。检查方法是，在服务器上打开 开始菜单-&gt;程序-&gt;Microsoft SQL Server-&gt;服务器网络实用工具，看启用的协议里是否有tcp/ip协议，如果没有，则启用它。</strong></p><p><strong>　　3 检查服务器的tcp/ip端口是否配置为1433端口。仍然在服务器网络实用工具里查看启用协议里面的tcp/ip的属性，确保默认端口为1433，并且隐藏服务器复选框没有勾上。</strong></p><p><strong>　　事实上，如果默认端口被修改，也是可以的，但是在客户端做telnet测试时，写服务器端口号时必须与服务器配置的端口号保持一致。如果隐藏服务器复选框被勾选，则意味着客户端无法通过枚举服务器来看到这台服务器，起到了保护的作用，但不影响连接，但是Tcp/ip协议的默认端口将被隐式修改为2433，在客户端连接时必须作相应的改变。</strong></p><p><strong>　　4 如果服务器端操作系统打过sp2补丁，则要对windows防火墙作一定的配置，要对它开放1433端口，通常在测试时可以直接关掉windows防火墙(其他的防火墙也关掉最好)。</strong></p><p><strong>　　5 检查服务器是否在1433端口侦听。如果服务器没有在tcp连接的1433端口侦听，则是连接不上的。检查方法是在服务器的dos或命令行下面输入</strong></p><p><strong>　　netstat -a -n 或者是netstat -an，在结果列表里看是否有类似 tcp 127.0.0.1 1433 listening 的项。如果没有，则通常需要给sql server 2000打上至少sp3的补丁。其实在服务器端启动查询分析器，输入 select @@version 执行后可以看到版本号，版本号在8.0.2039以下的都需要打补丁。</strong></p><p><strong>　　如果以上都没问题，这时你再做telnet 服务器ip 1433 测试，将会看到屏幕一闪之后光标在左上角不停闪动。恭喜你，你马上可以开始在企业管理器或查询分析器连接了。</strong></p><p><strong>　　三 检查客户端设置</strong></p><p><strong>　　程序-&gt;Microsoft SQL Server -&gt; 客户端网络使用工具。像在服务器网络实用工具里一样，确保客户端tcp/ip协议启用，并且默认端口为1433(或其他端口，与服务器端保持一致就行)。</strong></p><p><strong>　　四 在企业管理器里或查询那分析器连接测试</strong></p><p><strong>　　企业管理器-&gt;右键SQlserver组-&gt;新建sqlserver注册-&gt;下一步-&gt;写入远程IP-&gt;下一步-&gt;选Sqlserver登陆-&gt;下一步-&gt;写入登陆名与密码(sa,password)-&gt;下一步-&gt;下一步-&gt;完成</strong></p><p><strong>　　查询分析器-&gt;文件-&gt;连接-&gt;写入远程IP-&gt;写入登录名和密码(sa,password)-&gt;确定</strong></p><p><strong>　　通常建议在查询分析器里做，因为默认情况下，通过企业管理器注册另外一台SQL Server的超时设置是4秒，而查询分析器是15秒。</strong></p><p><strong>　　修改默认连接超时的方法:</strong></p><p><strong>　　企业管理器-&gt;工具-&gt;选项-&gt;在弹出的"SQL Server企业管理器属性"窗口中，点击"高级"选项卡-&gt;连接设置-&gt;在 登录超时(秒) 后面的框里输入一个较大的数字</strong></p><p><strong>　　查询分析器-&gt;工具-&gt;选项-&gt;连接-&gt;在 登录超时(秒) 后面的框里输入一个较大的数字</strong></p><p><strong>　　通常就可以连通了，如果提示错误，则进入下一步。</strong></p><p><strong>　　五 错误产生的原因通常是由于SQL Server使用了"仅 Windows"的身份验证方式，因此用户无法使用SQL Server的登录帐户(如 sa )进行连接。解决方法如下所示:</strong></p><p><strong>　　1 在服务器端使用企业管理器，并且选择"使用 Windows 身份验证"连接上 SQL Server。</strong></p><p><strong>　　2 展开"SQL Server组"，鼠标右键点击SQL Server服务器的名称，选择"属性"，再选择"安全性"选项卡。</strong></p><p><strong>　　3 在"身份验证"下，选择"SQL Server和 Windows "。</strong></p><p><strong>　　4 重新启动SQL Server服务。(在dos或命令行下面net stop mssqlserver停止服务，net start mssqlserver启动服务，也是一种快捷的方法)。</strong></p><p><strong>　　附注:在连接本地服务器时，通常使用的是命名管道协议(在服务器网络实用工具里可以看到启用的协议有这个)，默认端口是445，因此在本地能连通是不能说明什么问题的，连接远程服务器是完全不同的协议)</strong></p><p><br /> </p><p>      第三步：如果上述方法仍不能解决你的问题，请检查你的SQL有没有打补丁,没有的话要打上补丁,检查的方法是在查询分析器中运行:</p><p>　　select @@version</p><p>　　如果出来的版本号是8.00.2039以下,则表明你未安装sp4的补丁,要装上.</p><p>　　SQL补丁下载:</p><p>　　全部补丁的位置(在下载页的中间部分,可以选择语言,以下载和sql server实例语言对应的补丁)</p><p>　　http://www.microsoft.com/downloads/details.aspx?FamilyId=8E2DFC8D-C20E-4446-99A9-B7F0213F8BC5&amp;displaylang=zh-cn</p><p>　　应该安装的是</p><p>　　http://download.microsoft.com/download/9/b/f/9bff6646-2cdb-4069-ada0-548be9cb9338/SQL2000-KB884525-SP4-x86-CHS.EXE</p><p>　　注意下载后,执行的时候是解压,要在解压后的目录中执行setup.bat才是真正的安装</p><p>　　如果你的操作系统是xp,那么在安装xp sp2后,不管以前是否安装过sql sp4,都要再安装一次,并且在防火墙中开启1433端口,否则无法被其他电脑访问.</p><img src ="http://www.blogjava.net/fortune/aggbug/50808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-06-06 16:43 <a href="http://www.blogjava.net/fortune/archive/2006/06/06/50808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何使用links方式安装Eclipse插件</title><link>http://www.blogjava.net/fortune/archive/2006/05/04/44550.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Thu, 04 May 2006 11:10:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/05/04/44550.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/44550.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/05/04/44550.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/44550.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/44550.html</trackback:ping><description><![CDATA[　eclispe想必大家都很熟悉了，一般来说，eclipse插件都是安装在plugins目录下。不过这样一来，当安装了许多插件之后，eclipse变的很大，最主要的是不便于更新和管理众多插件。用links方式安装eclipse插件，可以解决这个问题。<br />　　<br />　　<b>当前配置XP SP1，eclipse3.0.1</b><br />　　<br />　　现在假设我的eclipse安装目录是D:\eclipse，待安装插件目录是D:\plug-in ，我将要安装LanguagePackFeature（语言包）、emf-sdo-xsd-SDK、GEF-SDK、Lomboz这四个插件。<br />　　<br />　　先把这四个插件程序全部放在D:\plug-in目录里，分别解压。如Lomboz3.0.1.zip解压成Lomboz3.0.1目录，这个目录包含一个plugins目录，要先在Lomboz3.0.1目录中新建一个子目录eclipse，然后把plugins目录移动到刚建立的eclipse目录中，即目录结构要是这样的：D:\plug-in\Lomboz3.0.1\eclipse\plugins<br />　　<br />　　Eclipse 将会到指定的目录下去查找 eclipse\features 目录和eclipse\plugins 目录，看是否有合法的功能部件和（或）插件。也就是说，目标目录必须包含一个 \eclipse 目录。如果找到，附加的功能部件和插件在运行期配置是将是可用的，如果链接文件是在工作区创建之后添加的，附加的功能部件和插件会作为新的配置变更来处理。<br />　　<br />　　其它压缩文件解压后若已经包含eclipse\plugins目录，则不需要建立eclipse目录。<br />　　<br />　　然后在 eclipse安装目录D:\eclipse目录中建立一个子目录links，在links目录中建立一个link文件，比如 LanguagePackFeature.link，改文件内容为　path=D:/plug-in/LanguagePackFeature　即这个link文件要对应一个刚解压后的插件目录。<br />　　<br />　　<b>说明：</b><br />　　<br />　　1. 插件可以分别安装在多个自定义的目录中。<br />　　<br />　　2. 一个自定义目录可以安装多个插件。<br />　　<br />　　3. link文件的文件名及扩展名可以取任意名称，比如ddd.txt，myplugin都可以。<br />　　<br />　　4. link文件中path=插件目录的path路径分隔要用\\或是/<br />　　<br />　　5. 在links目录也可以有多个link文件，每个link文件中的path参数都将生效。<br />　　<br />　　6. 插件目录可以使用相对路径。<br />　　<br />　　7. 可以在links目录中建立一个子目录，转移暂时不用的插件到此子目录中，加快eclipse启动。<br />　　<br />　　8.　如果安装后看不到插件，把eclipse 目录下的configuration目录删除，重启即可。 <img src ="http://www.blogjava.net/fortune/aggbug/44550.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-05-04 19:10 <a href="http://www.blogjava.net/fortune/archive/2006/05/04/44550.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>中断JAVA线程</title><link>http://www.blogjava.net/fortune/archive/2006/04/12/40628.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Wed, 12 Apr 2006 05:36:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/04/12/40628.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/40628.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/04/12/40628.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/40628.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/40628.html</trackback:ping><description><![CDATA[在JAVA中，通过其对线程类的内嵌支持，编程人员编写多线程程序是很简易的。然而，在编程人员面前，多线程呈现出了一组新的难题，如果没有被恰当的解决，将导致意外的行为以及细微的、难以发现的错误。在本篇文章中，我们针对这些难题之一：如何中断一个正在运行的线程。 <br /><br />背景<br />中断（Interrupt）一个线程意味着在该线程完成任务之前停止其正在进行的一切，有效地中止其当前的操作。线程是死亡、还是等待新的任务或是继续运行至下一步，就取决于这个程序。<br /><br />虽然初次看来它可能显得简单，但是，你必须进行一些预警以实现期望的结果。你最好还是牢记以下的几点告诫。<br /><br />首先，忘掉Thread.stop方法。虽然它确实停止了一个正在运行的线程，然而，这种方法是不安全也是不受提倡的，这意味着，在未来的JAVA版本中，它将不复存在。<br /><br />一些轻率的家伙可能被另一种方法Thread.interrupt所迷惑。尽管，其名称似乎在暗示着什么，然而，这种方法并不会中断一个正在运行的线程（待会将进一步说明），正如Listing A中描述的那样。它创建了一个线程，并且试图使用Thread.interrupt方法停止该线程。Thread.sleep()方法的调用，为线程的初始化和中止提供了充裕的时间。线程本身并不参与任何有用的操作。<br /><br />Listing A<br />class Example1 extends Thread {<br /><br />  public static void main( String args[] ) throws Exception {<br /><br />    Example1 thread = new Example1();<br /><br />   System.out.println( "Starting thread..." );<br /><br />   thread.start();<br /><br />   Thread.sleep( 3000 );<br /><br />   System.out.println( "Interrupting thread..." );<br /><br />   thread.interrupt();<br /><br />   Thread.sleep( 3000 );<br /><br />   System.out.println( "Stopping application..." );<br /><br />   System.exit( 0 );<br /><br />  }<br /><br /><br />如果你运行了Listing A中的代码，你将在控制台看到以下输出：<br /><br />Starting thread...<br /><br />Thread is running...<br /><br />Thread is running...<br /><br />Thread is running...<br /><br />Interrupting thread...<br /><br />Thread is running...<br /><br />Thread is running...<br /><br />Thread is running...<br /><br />Stopping application...<br /><br />甚至，在Thread.interrupt()被调用后，线程仍然继续运行了一段时间。<br /><br />真正地中断一个线程<br /><br />中断线程最好的，最受推荐的方式是，使用共享变量（shared variable）发出信号，告诉线程必须停止正在运行的任务。线程必须周期性的核查这一变量（尤其在冗余操作期间），然后有秩序地中止任务。Listing B描述了这一方式。<br /><br />Listing B<br />class Example2 extends Thread {<br /><br />  volatile boolean stop = false;<br /><br />  public static void main( String args[] ) throws Exception {<br /><br />    Example2 thread = new Example2();<br /><br />   System.out.println( "Starting thread..." );<br /><br />   thread.start();<br /><br />   Thread.sleep( 3000 );<br /><br />   System.out.println( "Asking thread to stop..." );<br /><br />   thread.stop = true;<br /><br />   Thread.sleep( 3000 );<br /><br />   System.out.println( "Stopping application..." );<br /><br />   System.exit( 0 );<br /><br />  }<br /><br />  public void run() {<br /><br />    while ( !stop ) {<br /><br />     System.out.println( "Thread is running..." );<br /><br />      long time = System.currentTimeMillis();<br /><br />      while ( (System.currentTimeMillis()-time &lt; 1000) &amp;&amp; (!stop) ) {<br /><br />      }<br /><br />    }<br /><br />   System.out.println( "Thread exiting under request..." );<br /><br />  }<br /><br />}<br /><br /> <br /><br /><br />运行Listing B中的代码将产生如下输出（注意线程是如何有秩序的退出的）<br /><br />Starting thread...<br /><br />Thread is running...<br /><br />Thread is running...<br /><br />Thread is running...<br /><br />Asking thread to stop...<br /><br />Thread exiting under request...<br /><br />Stopping application...<br /><br />虽然该方法要求一些编码，但并不难实现。同时，它给予线程机会进行必要的清理工作，这在任何一个多线程应用程序中都是绝对需要的。请确认将共享变量定义成volatile 类型或将对它的一切访问封入同步的块/方法（synchronized blocks/methods）中。<br /><br />到目前为止一切顺利!但是，当线程等待某些事件发生而被阻塞，又会发生什么？当然，如果线程被阻塞，它便不能核查共享变量，也就不能停止。这在许多情况下会发生，例如调用Object.wait()、ServerSocket.accept()和DatagramSocket.receive()时，这里仅举出一些。<br /><br />他们都可能永久的阻塞线程。即使发生超时，在超时期满之前持续等待也是不可行和不适当的，所以，要使用某种机制使得线程更早地退出被阻塞的状态。<br /><br />很不幸运，不存在这样一种机制对所有的情况都适用，但是，根据情况不同却可以使用特定的技术。在下面的环节，我将解答一下最普遍的例子。<br /><br />使用Thread.interrupt()中断线程<br />正如Listing A中所描述的，Thread.interrupt()方法不会中断一个正在运行的线程。这一方法实际上完成的是，在线程受到阻塞时抛出一个中断信号，这样线程就得以退出阻塞的状态。更确切的说，如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞，那么，它将接收到一个中断异常（InterruptedException），从而提早地终结被阻塞状态。<br /><br />因此，如果线程被上述几种方法阻塞，正确的停止线程方式是设置共享变量，并调用interrupt()（注意变量应该先设置）。如果线程没有被阻塞，这时调用interrupt()将不起作用；否则，线程就将得到异常（该线程必须事先预备好处理此状况），接着逃离阻塞状态。在任何一种情况中，最后线程都将检查共享变量然后再停止。Listing C这个示例描述了该技术。<br /><br />Listing C<br />class Example3 extends Thread {<br /><br />  volatile boolean stop = false;<br /><br />  public static void main( String args[] ) throws Exception {<br /><br />   Example3 thread = new Example3();<br /><br />   System.out.println( "Starting thread..." );<br /><br />   thread.start();<br /><br />   Thread.sleep( 3000 );<br /><br />   System.out.println( "Asking thread to stop..." );<br /><br />   thread.stop = true;<br /><br />   thread.interrupt();<br /><br />   Thread.sleep( 3000 );<br /><br />   System.out.println( "Stopping application..." );<br /><br />   System.exit( 0 );<br /><br />  }<br /><br />  public void run() {<br /><br />    while ( !stop ) {<br /><br />     System.out.println( "Thread running..." );<br /><br />      try {<br /><br />      Thread.sleep( 1000 );<br /><br />      } catch ( InterruptedException e ) {<br /><br />      System.out.println( "Thread interrupted..." );<br /><br />      }<br /><br />    }<br /><br />   System.out.println( "Thread exiting under request..." );<br /><br />  }<br /><br />}<br /><br />一旦Listing C中的Thread.interrupt()被调用，线程便收到一个异常，于是逃离了阻塞状态并确定应该停止。运行以上代码将得到下面的输出：<br /><br />Starting thread...<br /><br />Thread running...<br /><br />Thread running...<br /><br />Thread running...<br /><br />Asking thread to stop...<br /><br />Thread interrupted...<br /><br />Thread exiting under request...<br /><br />Stopping application...<br /><br /><br />中断I/O操作<br />然而，如果线程在I/O操作进行时被阻塞，又会如何？I/O操作可以阻塞线程一段相当长的时间，特别是牵扯到网络应用时。例如，服务器可能需要等待一个请求（request），又或者，一个网络应用程序可能要等待远端主机的响应。<br /><br />如果你正使用通道（channels）（这是在Java 1.4中引入的新的I/O API），那么被阻塞的线程将收到一个ClosedByInterruptException异常。如果情况是这样，其代码的逻辑和第三个例子中的是一样的，只是异常不同而已。<br /><br />但是，你可能正使用Java1.0之前就存在的传统的I/O，因为新的I/O是最近才引入，而且要求更多的工作。既然这样，Thread.interrupt()将不起作用，因为线程将不会退出被阻塞状态。Listing D描述了这一行为。尽管interrupt()被调用，线程也不会退出被阻塞状态<br /><br />Listing D<br />import java.io.*;<br /><br />class Example4 extends Thread {<br /><br />  public static void main( String args[] ) throws Exception {<br /><br />    Example4 thread = new Example4();<br /><br />   System.out.println( "Starting thread..." );<br /><br />   thread.start();<br /><br />   Thread.sleep( 3000 );<br /><br />   System.out.println( "Interrupting thread..." );<br /><br />   thread.interrupt();<br /><br />   Thread.sleep( 3000 );<br /><br />   System.out.println( "Stopping application..." );<br /><br />   System.exit( 0 );<br /><br />  }<br /><br />  public void run() {<br /><br />   ServerSocket socket;<br /><br />    try {<br /><br />      socket = new ServerSocket(7856);<br /><br />    } catch ( IOException e ) {<br /><br />     System.out.println( "Could not create the socket..." );<br /><br />      return;<br /><br />    }<br /><br />    while ( true ) {<br /><br />     System.out.println( "Waiting for connection..." );<br /><br />      try {<br /><br />       Socket sock = socket.accept();<br /><br />      } catch ( IOException e ) {<br /><br />      System.out.println( "accept() failed or interrupted..." );<br /><br />      }<br /><br />    }<br /><br />  }<br /><br />}<br /><br /><br />很幸运，Java平台为这种情形提供了一项解决方案，即调用阻塞该线程的套接字的close()方法。在这种情形下，如果线程被I/O操作阻塞，该线程将接收到一个SocketException异常，这与使用interrupt()方法引起一个InterruptedException异常被抛出非常相似。<br /><br />唯一要说明的是，必须存在socket的引用（reference），只有这样close()方法才能被调用。这意味着socket对象必须被共享。Listing E描述了这一情形。运行逻辑和以前的示例是相同的。<br /><br />Listing E<br />import java.net.*;<br />import java.io.*;<br />class Example5 extends Thread {<br />  volatile boolean stop = false;<br />  volatile ServerSocket socket;<br />  public static void main( String args[] ) throws Exception {<br />    Example5 thread = new Example5();<br />   System.out.println( "Starting thread..." );<br />   thread.start();<br />   Thread.sleep( 3000 );<br />   System.out.println( "Asking thread to stop..." );<br />   thread.stop = true;<br />   thread.socket.close();<br />   Thread.sleep( 3000 );<br />   System.out.println( "Stopping application..." );<br />   System.exit( 0 );<br />  }<br />  public void run() {<br />    try {<br />      socket = new ServerSocket(7856);<br />    } catch ( IOException e ) {<br />     System.out.println( "Could not create the socket..." );<br />      return;<br />    }<br />    while ( !stop ) {<br />     System.out.println( "Waiting for connection..." );<br />      try {<br />       Socket sock = socket.accept();<br />      } catch ( IOException e ) {<br />      System.out.println( "accept() failed or interrupted..." );<br />      }<br />    }<br />   System.out.println( "Thread exiting under request..." );<br />  }<br />}<br />以下是运行Listing E中代码后的输出：<br /><br />Starting thread...<br /><br />Waiting for connection...<br /><br />Asking thread to stop...<br /><br />accept() failed or interrupted...<br /><br />Thread exiting under request...<br /><br />Stopping application...<br /><br />多线程是一个强大的工具，然而它正呈现出一系列难题。其中之一是如何中断一个正在运行的线程。如果恰当地实现，使用上述技术中断线程将比使用Java平台上已经提供的内嵌操作更为简单。 <br /><img src ="http://www.blogjava.net/fortune/aggbug/40628.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-04-12 13:36 <a href="http://www.blogjava.net/fortune/archive/2006/04/12/40628.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java线程</title><link>http://www.blogjava.net/fortune/archive/2006/04/12/40558.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Wed, 12 Apr 2006 01:41:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/04/12/40558.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/40558.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/04/12/40558.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/40558.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/40558.html</trackback:ping><description><![CDATA[
		<span class="javascript" id="text162090">在新的JDK5.0中，对thread做了一些改进，我通过阅读一些资料写下了下面的总结，请大家看看。<br /><br />1.创建线程<br />在java中实现多线程有两种方法，一个是直接继承Thread类，一个是实现Runnable接口，但是推荐的是第二种。因为在逻辑上应该要把一个线程要做的事情以及做这个事情的方法分开；对于Thread来讲，它只负责线程的操作，而具体要做的事情就应该放在Runnable中。但不管是那种方式，都要实现public void run()方法，但启动线程用start而不是run。<br /><br />2.终止线程<br />在1.0中，可以用stop方法来终止，但是现在这种方法已经被禁用了，改用interrupt方法。interrupt方法并不是强制终止线程，它只能设置线程的interrupted状态，而在线程中一般使用一下方式：<br />while (!Thread.currentThread().isInterrupted() &amp;&amp; more work to do)<br />{<br />do more work<br />}<br />而被block的线程在被调用interrupt时会产生InterruptException，此时是否终止线程由本线程自己决定。程序的一般形式是：<br />public void run()<br />{<br />try<br />{<br />. . .<br />while (!Thread.currentThread().isInterrupted() &amp;&amp; more work to do)<br />{<br />do more work<br />}<br />}<br />catch(InterruptedException e)<br />{<br />// thread was interrupted during sleep or wait<br />}<br />finally<br />{<br />cleanup, if required<br />}<br />// exiting the run method terminates the thread<br />}<br /><br />Thread.sleep方法也会产生InterruptedException，因此，如果每次在做完一些工作后调用了sleep方法，那么就不用检查isInterrupted，而是直接捕捉InterruptedException。<br /><br />在捕捉到InterruptedException时，如果没有其他的事情可做，最好做一下处理，不能用{}<br />1）<br />void mySubTask()<br />{<br />. . .<br />try { sleep(delay); }<br />catch (InterruptedException e) { Thread().currentThread().interrupt(); }<br />. . .<br />}<br />或是<br />2）<br />void mySubTask() throws InterruptedException<br />{<br />. . .<br />sleep(delay);<br />. . .<br />}<br /><br />3.线程状态<br />New：当使用new创建一个线程时<br />Runnable: 调用start或是从blocked状态出来时<br />Blocked：sleep, block on input/output, try to acquire lock, suspend, wait.<br />Dead: 运行完成或有exception产生。<br /><br />4.线程优先级<br />可以设置线程优先级，但是不能保证高优先级的线程就会被先运行<br /><br />5.线程组<br />可以把多个线程加到一个线程组里面去，这样可以对这些线程进行一些统一的操作，例如<br />ThreadGroup g = new ThreadGroup(groupName）<br />...<br />g.interrupt(); // interrupt all threads in group g<br /><br />6.为Uncaught Exceptions设置Handlers<br />在java 5.0中，可以为线程中产生的unchecked exception设置一个处理器，这个处理器必须实现UncaughtExceptionHandler接口。<br />可以调用线程实例的setUncaughtExceptionHandler方法为每个线程设置一个处理器，也可以调用Thread.setDefaultUncaughtExceptionHandler来为所有的线程设置一个默认的处理器。如果没有给每一个线程设置处理器，那线程会首先使用线程组的处理器，如果还没有再使用默认的处理器。<br /><br />7.Synchronization<br />多线程很重要的一个问题就是同步的问题，如果不解决好同步的问题一个是可能会引起数据的混乱，而且还有可能造成线程的死锁。在Java 5.0之前，用synchronized来解决这个问题，在5.0中加入了一个新的类:ReentrantLock<br /><br />使用lock的基本形式是：<br />myLock.lock(); // a ReentrantLock object<br />try<br />{<br />critical section<br />}<br />finally<br />{<br />myLock.unlock(); // make sure the lock is unlocked even if an exception is thrown<br />}<br /><br />这个锁被称为Reentrant的原因是在一个线程中可以重复多次申请同一个锁，系统会保留加锁的次数，而在解锁的时候也就必须执行相同次数。<br /><br />在一个线程已经得到锁可以执行程序的时候，可能会发现需要的条件还不能满足，这时他就必须等待直到条件满足。但是因为它已经对所需要操作的东西加了锁，其他的线程不能访问，因此它又可能会永远等待下去。现在可以用Condition Object来避免这种情况。<br />sufficientFunds = bankLock.newCondition();<br />如果条件不满足：<br />sufficientFunds.await();<br />这时线程就会释放锁并进入blocked状态，其他线程就有机会执行操作。当其他线程执行完后，就可通知等待的线程继续执行它的操作了：<br />sufficientFunds.signalAll();<br />当然也可以调用singal方法，这样效率会高一些，但是有一定的危险性，因为它的唤醒具有随机性。<br /><br />在5.0之前，采用的是synchronized关键字来进行同步，但是和lock相比它有一些局限性：<br />1. 申请锁的线程不能被interrupt<br />2. 没有timeout设置<br />3. 只有一个隐性的condition条件<br /><br />另外，在申请锁的时候可以用tryLock方法，它会返回一个bool值来表示锁是否申请成功，如果没有成功，程序就可以做其他的事情了。<br /><br />tryLock, await方法都可以被interrupt。<br /><br />java.util.concurrent.locks包中提供了两种锁，一个就是ReentrantLock，另一个是ReentrantReadWriteLock，一般用于多操作远远多于写操作的时候：<br />private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();<br />private Lock readLock = rwl.readLock();<br />private Lock writeLock = rwl.writeLock();<br /><br />8. Callables and Futures<br />实现多线程时一般用的是Runnable接口，但是他有一个问题就是他没有参数和返回值，所以当执行一个线程需要返回一个值的时候就不是很方便了。Callable接口和Runnable差不多，但是他提供了参数和返回值：<br />public interface Callable&lt;V&gt;<br />{<br />V call() throws Exception;<br />}<br />而Future接口可以保留异步执行的值：<br />public interface Future&lt;V&gt;<br />{<br />V get() throws . . .;<br />V get(long timeout, TimeUnit unit) throws . . .;<br />void cancel(boolean mayInterrupt);<br />boolean isCancelled();<br />boolean isDone();<br />}<br /><br />FutureTask可以很方便的把Callable转换成Future和Runnable:<br />Callable&lt;Integer&gt; myComputation = . . .;<br />FutureTask&lt;Integer&gt; task = new FutureTask&lt;Integer&gt;(myComputation);<br />Thread t = new Thread(task); // it's a Runnable<br />t.start();<br />. . .<br />Integer result = task.get(); // it's a Future<br /><br />9.用Executors创建线程池<br />用线程池有两个好处：1. 减少创建线程的开销。2. 控制线程的数量。<br />EXecutors提供了一些方法可以很方便的创建线程池：<br />newCachedThreadPool<br />New threads are created as needed; idle threads are kept for 60 seconds.<br /><br />newFixedThreadPool<br />The pool contains a fixed set of threads; idle threads are kept indefinitely.<br /><br />newSingleThreadExecutor<br />A "pool" with a single thread that executes the submitted tasks sequentially.<br /><br />newScheduledThreadPool<br />A fixed-thread pool for scheduled execution.<br /><br />newSingleThreadScheduledExecutor<br />A single-thread "pool" for scheduled execution.<br /><br />在使用Executors时，先调用这些静态方法创建线程池，得到一个ExecutorService对象，然后用这个对象的submit方法提交你的Runnable或是Callable对象。<br />Future&lt;?&gt; submit(Runnable task)<br />Future&lt;T&gt; submit(Runnable task, T result)<br />Future&lt;T&gt; submit(Callable&lt;T&gt; task)<br />如果不再需要任何提交，就用shutdown方法来关闭线程池。<br /><br />10.在界面中使用多线程<br />对于GUI设计来说，很重要的一个原则就是要及时的给用户反馈，就算是不能立即得到结果，界面也不能停在那里，是用户不知道发生了什么事情，必须让用户随时知道程序在坐什么。所以当程序要执行一段需要消耗比较长时间的操作时，就要使用多线程。<br /><br />但是，有些界面控件并不是线程安全的，在使用这些控件时就要特别注意。在API doc中这些都有注明，使用的时候就可以查一下。<br /><br />如果想在自己另外所创建的线程执行过程中随时更新界面来表示执行进程，要注意的一点是，这个线程并不能直接调用界面控件的方法，而要采用EventQueue类的invokeLater，invokeAndWait方法：<br />EventQueue.invokeLater(new<br />Runnable()<br />{<br />public void run()<br />{<br />label.setText(percentage + "% complete");<br />}<br />}); </span>
		<br />
<img src ="http://www.blogjava.net/fortune/aggbug/40558.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-04-12 09:41 <a href="http://www.blogjava.net/fortune/archive/2006/04/12/40558.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SWT的线程间通信</title><link>http://www.blogjava.net/fortune/archive/2006/04/10/40280.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Mon, 10 Apr 2006 09:29:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/04/10/40280.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/40280.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/04/10/40280.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/40280.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/40280.html</trackback:ping><description><![CDATA[
		<h2> </h2>
		<p>
		</p>
		<p>在SWT中，通常需要开多个线程来执行任务，因为主线程为UI线程，不能用太长的时间来执行某个任务，否则会造成失去响应的假象。<br />SWT的线程通信有几个要注意的地方：<br />1、工作线程访问UI线程。不能在非UI线程中直接访问UI控件的值，要获得或设置控件的值必须通过Display对象的asyncExec()或syncExec()函数，一般的使用方法是：<br /><span style="COLOR: #008080"></span></p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #000000">//代码A：<br /> <br />Display disp  </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000">  Display.getDefault();<br /> </span>
				<span style="COLOR: #0000ff">if</span>
				<span style="COLOR: #000000"> (disp </span>
				<span style="COLOR: #000000">!=</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">null</span>
				<span style="COLOR: #000000"> )  {<br />   disp.asyncExec(<br />    </span>
				<span style="COLOR: #0000ff">new</span>
				<span style="COLOR: #000000">  Runnable()  {<br />    </span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000">  </span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000">  run()  {<br />       </span>
				<span style="COLOR: #008000">//</span>
				<span style="COLOR: #008000"> 在这里设置或获得控件的值 </span>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000"> } <br />} <br />); <br />} </span>
		</div>
		<br />2、内部类与外部类的交流。内部类调用外部类局部变量时，该变量必须是final的，这样在取得控件的值后返回给外部类处理时就比较麻烦。例如，在上面的代码段中，有个匿名内部类实现了Runnable接口，在里面的run()函数里可以访问到UI对象，但是，得到了对象的值怎么告诉外面的代码呢？假如用普通的局部变量传递进去，由于是final的，是不能赋值的，所以需要有一个封装类来把需要返回的变量封装起来，这个封装类是final的，但里面的成员变量是可变的，这样就把内部类里得到的东西传递到了外部，不过似乎比较麻烦，不知道有没有更好的办法。<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">//代码B：<br /><br />class</span><span style="COLOR: #000000"> StringWrapper {<br /></span><span style="COLOR: #0000ff">   public</span><span style="COLOR: #000000"> String uiValue;<br />}<br />StringWrapper sw </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> StringWrapper(); <br />Display disp  </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">  Display.getDefault();<br /> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (disp </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"> )  {<br />   disp.asyncExec(<br />    </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">  Runnable()  {<br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">  </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">  run()  {<br />        sw.uiValue </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> text.getText();</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">假设text是一个文本框对象<br />       </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 在这里设置或获得控件的值 </span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    } <br />   } <br />   ); <br />} <br /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">这里就可以对sw.uiValue的值进行访问</span></div>3、线程间的同步。在上面的代码B中，通过asyncExec()函数来取得控件的值所需要的时间比较长，如果在后面马上访问那些值是得不到的，于是就需要有个同步的问题，即在控件值取得之前先不进行下一步操作。可以通过synchronized块及wait()，notify()机制来实现同步。<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">代码C：</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> StringWrapper {<br />   </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> String uiValue;<br />}<br />StringWrapper sw </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> StringWrapper(); <br />Display disp  </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">  Display.getDefault();<br /> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (disp </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"> )  {<br />   disp.asyncExec(<br />    </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">  Runnable()  {<br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">  </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">  run()  {<br />        </span><span style="COLOR: #0000ff">synchronized</span><span style="COLOR: #000000">(sw){<br />          sw.uiValue </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> text.getText();</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">假设text是一个文本框对象</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">            sw.notify();<br />         }<br />       </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 在这里设置或获得控件的值</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"> <br />    } <br />   } <br />   ); <br />}<br /></span><span style="COLOR: #0000ff">synchronized</span><span style="COLOR: #000000">(sw){<br />  sw.wait();<br />} <br /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">这里就可以对sw.uiValue的值进行访问</span></div><br />但是这里会带来一个问题，假如很快就能取得控件的值，但后面还有很长一段时间才会用到该值，如果把sw.wait()语句放在比较后的地方，就有可能造成死锁，因为sw已经被notify之后才开始wait的，再没有其他线程来notify它了，它就只能一直wait下去……。为了解决这个问题，可以(1)把sw.wait()紧跟在disp.asyncExec()后面；(2)给wait()设置一个timeout参数，到了一定的时间还没有东西notify它，它就自己超时。但这两种办法似乎都比较牵强，没有十足的保证，JDK文档里面有个例子，是用while来判断是否已经达到了要求，如果已经达到了就不再wait。<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">代码D：</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> StringWrapper {<br />   </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> String uiValue;<br />   </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">boolean</span><span style="COLOR: #000000"> isValueSet;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">是否已经取得了控件的值</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">}<br />StringWrapper sw </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> StringWrapper(); <br />sw.isValueSet </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br />Display disp  </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">  Display.getDefault();<br /> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (disp </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"> )  {<br />   disp.asyncExec(<br />    </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">  Runnable()  {<br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">  </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">  run()  {<br />        </span><span style="COLOR: #0000ff">synchronized</span><span style="COLOR: #000000">(sw){<br />          sw.uiValue </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> text.getText();</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">假设text是一个文本框对象</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">            sw.isValueSet </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br />            sw.notify();<br />         }<br />       <span style="COLOR: #008000">//</span><span style="COLOR: #008000"> 在这里设置或获得控件的值</span></span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"> <br />    } <br />   } <br />   ); <br />}<br /></span><span style="COLOR: #0000ff">synchronized</span><span style="COLOR: #000000">(sw){<br />  </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">sw.isValueSet){<br />    </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">{<br />      sw.wait();<br />    }</span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (InterruptedException e){<br />    }<br />  }<br />} <br /></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">这里就可以对sw.uiValue的值进行访问</span></div><img src ="http://www.blogjava.net/fortune/aggbug/40280.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-04-10 17:29 <a href="http://www.blogjava.net/fortune/archive/2006/04/10/40280.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>swt 解决在容器中添加或修改内容时不能及时显示的问题</title><link>http://www.blogjava.net/fortune/archive/2006/04/04/39257.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Tue, 04 Apr 2006 13:38:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/04/04/39257.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/39257.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/04/04/39257.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/39257.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/39257.html</trackback:ping><description><![CDATA[想了很久 （水平太滥）查了半天资料才发现需要在最后添加一个函数layout（）就能解决了<br />比如在composite中就添加一句composite.layout()就OK了，呵呵，是不是很简单。以后不许忘了哦。<img src ="http://www.blogjava.net/fortune/aggbug/39257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-04-04 21:38 <a href="http://www.blogjava.net/fortune/archive/2006/04/04/39257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟我学XML Schema</title><link>http://www.blogjava.net/fortune/archive/2006/03/27/37659.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Mon, 27 Mar 2006 10:01:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/27/37659.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/37659.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/27/37659.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/37659.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/37659.html</trackback:ping><description><![CDATA[
		<div>如何写一个最简单的XML Schema文档呢？ 
<p></p><p>首先，我们写出一个最简单的XML文档.</p><p>hello.xml<br />-------------------<br />&lt;?xml version="1.0"?&gt; <br />&lt;greeting&gt;Hello World!!&lt;/greeting&gt;</p><p>（一个根元素：greeting；且这个元素不含属性，无子元素，内容是字符串。）</p><p>hello.xsd<br />－－－－－－－－－－<br />&lt;?xml version="1.0"?&gt; <br />&lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />  &lt;xsd:element name="greeting" type="xsd:string"/&gt;<br />&lt;/xsd:schema&gt;</p><p>XML Schema文档后缀名是.xsd，完全符合XML语法，根元素是schema，命名空间xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema</font></a>，用元素&lt;element&gt;定义实例文档中的元素，如greeting。<br /></p><div>跟我学XML Schema(2):含子元素的稍复杂Schema文档  
<p></p><p>假设实例文档是如下的：</p><p>customer.xml<br />-----------<br />&lt;customer&gt;<br />  &lt;name&gt;teiki&lt;/name&gt;<br />  &lt;address&gt;No.237, Road Waitan, Shanghai&lt;/address&gt;<br />&lt;/customer&gt;</p><p>则可以写出以下的XML Schema文档：<br />customer.xsd<br />----------------<br />1: &lt;?xml version="1.0"?&gt;<br />2: &lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:   &lt;xsd:element name="customer"&gt;<br />4:    &lt;xsd:complexType&gt;<br />5:      &lt;xsd:sequence&gt;<br />6:        &lt;xsd:element name="name" type="xsd:string"/&gt;<br />7:        &lt;xsd:element name="address" type="xsd:string" /&gt;<br />8:      &lt;/xsd:sequence&gt;<br />9:    &lt;/xsd:complexType&gt;<br />10:  &lt;/xsd:element&gt;<br />11: &lt;/xsd:schema&gt;</p><p>实例文档customer.xml中，&lt;customer&gt;元素含有两个子元素，所以我们在Schema文档中采用ComplexType来定义该元素。</p><p>sequence表示子元素依次出现的顺序。<br /></p><div>跟我学XML Schema(3):含子元素和孙元素的更复杂Schema文档 
<p></p><p>这次我们给出一个更加复杂一些的文档：</p><p>address.xml<br />---------------<br />&lt;customer&gt;<br />  &lt;name&gt;Teiki&lt;/name&gt;<br />  &lt;address&gt;<br />    &lt;!-- address追加一个地址子元素 --&gt;<br />    &lt;prefecture&gt;Zhejiang&lt;/prefecture&gt;<br />    &lt;city&gt;Hangzhou&lt;/city&gt;<br />    &lt;street&gt;Xilu Road, No.121, 7F&lt;/street&gt;<br />  &lt;/address&gt;<br />&lt;/customer&gt;</p><p><br />为此，我们需要一个更加复杂一点的Schema文档：</p><p>address.xsd<br />-----------------<br />1: &lt;?xml version="1.0"?&gt;<br />2: &lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:<br />4:   &lt;xsd:element name="customer"&gt;<br />5:     &lt;xsd:complexType&gt;<br />6:       &lt;xsd:sequence&gt;<br />7:         &lt;xsd:element name="name" type="xsd:string"/&gt;<br />8:         &lt;!-- 追加子元素address--&gt;<br />9:         &lt;xsd:element name="address"&gt;<br />10:          &lt;xsd:complexType&gt;<br />11:            &lt;xsd:sequence&gt;<br />12:              &lt;xsd:element name="prefecture" type="xsd:string"/&gt;<br />13:              &lt;xsd:element name="city" type="xsd:string" /&gt;<br />14:              &lt;xsd:element name="street" type="xsd:string" /&gt;<br />15:            &lt;/xsd:sequence&gt;<br />16:          &lt;/xsd:complexType&gt;<br />17:        &lt;/xsd:element&gt;<br />18:        &lt;!-- end --&gt;<br />19:      &lt;/xsd:sequence&gt;<br />20:    &lt;/xsd:complexType&gt;<br />21:  &lt;/xsd:element&gt;<br />22:<br />23:&lt;/xsd:schema&gt;<br />不过，我们还可以采用ref元素来重新编写这个Schema文档：<br />address2.xsd<br />----------------------<br />1: &lt;?xml version="1.0"?&gt;<br />2: &lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:<br />4:   &lt;xsd:element name="customer"&gt;<br />5:     &lt;xsd:complexType&gt;<br />6:       &lt;xsd:sequence&gt;<br />7:         &lt;xsd:element name="name" type="xsd:string"/&gt;<br />8:         &lt;xsd:element ref="address"/&gt;<br />9:       &lt;/xsd:sequence&gt;<br />10:    &lt;/xsd:complexType&gt;<br />11:  &lt;/xsd:element&gt;<br />12:<br />13:  &lt;xsd:element name="address"&gt;<br />14:    &lt;xsd:complexType&gt;<br />15:      &lt;xsd:sequence&gt;<br />16:        &lt;xsd:element name="prefecture" type="xsd:string"/&gt;<br />17:        &lt;xsd:element name="city" type="xsd:string" /&gt;<br />18:        &lt;xsd:element name="street" type="xsd:string" /&gt;<br />19:      &lt;/xsd:sequence&gt;<br />20:    &lt;/xsd:complexType&gt;<br />21:  &lt;/xsd:element&gt;<br />22:<br />23: &lt;/xsd:schema&gt;<br />使用ref元素可以直接将其指向另一个模块，使文档更加具有可读性。<br />跟我学XML Schema(4):如何定义属性呢？  </p><p></p><p><br />加入实例文档的元素包含属性，怎么办呢？</p><p>customer2.xml<br />---------------<br />&lt;customer id="001718"&gt;<br />  &lt;name&gt;Teiki&lt;/name&gt;<br />  &lt;address&gt;No.237, Road Waitan, Shanghai&lt;/address&gt;<br />&lt;/customer&gt;</p><p>那就这样写Schema文档：<br />customer2.xsd<br />------------------<br />1: &lt;?xml version="1.0"?&gt;<br />2: &lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:<br />4:   &lt;xsd:element name="customer"&gt;<br />5:    &lt;xsd:complexType&gt;<br />6:      &lt;xsd:sequence&gt;<br />7:        &lt;xsd:element name="name" type="xsd:string"/&gt;<br />8:        &lt;xsd:element name="address" type="xsd:string" /&gt;<br />9:      &lt;/xsd:sequence&gt;<br />10:      &lt;!-- 增加属性定义 --&gt;<br />11:      &lt;xsd:attribute name="id" type="xsd:string"/&gt;<br />12:    &lt;/xsd:complexType&gt;<br />13:  &lt;/xsd:element&gt;<br />14:<br />15: &lt;/xsd:schema&gt;</p><p>很简单，在&lt;sequence&gt;元素定义完成后，再用&lt;attribute&gt;元素id。<br /></p><div>跟我学XML Schema(5):如何定义相同子元素的数量？  
<p></p><p>先看这个简单的订购数据实例文档：</p><p>order.xml<br />---------<br />&lt;order&gt;<br />  &lt;orderItem&gt;Accounting Book&lt;/orderItem&gt;<br />  &lt;orderItem&gt;Taxation Book&lt;/orderItem&gt;<br />&lt;/order&gt;</p><p>假设&lt;orderItem&gt;元素，即每次的订购书目不能超过10种，那该怎么写这个Schema文档呢？这里要用到&lt;element&gt;的maxOccurs属性。</p><p>order.xsd<br />--------------------<br />1:&lt;?xml version="1.0"?&gt;<br />2:&lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:<br />4:  &lt;xsd:element name="order"&gt;<br />5:    &lt;xsd:complexType&gt;<br />6:      &lt;xsd:sequence&gt;<br />7:        &lt;xsd:element name="orderItem"   type="xsd:string"  maxOccurs="10" /&gt;<br />8:      &lt;/xsd:sequence&gt;<br />9:    &lt;/xsd:complexType&gt;<br />10:  &lt;/xsd:element&gt;<br />11:<br />12:&lt;/xsd:schema&gt;</p><p>第7行中的maxOccurs属性为10，代表orderItem元素可以最大有10个。如果，不设定元素个数，则可以用maxOccurs="unbounded"来定义.</p><p>类似，如果要定义最小值，可以使用minOccurs，比如下面这句：<br />&lt;xsd:element name="orderItem" type="xsd:string" minOccurs="5" maxOccurs="10"/&gt;<br />这两个属性缺省值都是1。<br /></p><div>跟我学XML Schema(6):如何定义可选项的子元素？ 
<p></p><p>假如上面的订书数据中，可以用书名或者书号任一一种订购，则实例文档可能如下：</p><p>order2.xml<br />-----------------<br />&lt;order&gt;<br />  &lt;orderItem&gt;<br />    &lt;!--书名订购--&gt;<br />    &lt;name&gt;Accounting Book&lt;/name&gt;<br />  &lt;/orderItem&gt;<br />  &lt;orderItem&gt;<br />    &lt;!--书号订购--&gt;<br />    &lt;id&gt;7-5058-3496-7&lt;/id&gt;<br />  &lt;/orderItem&gt;<br />&lt;/order&gt;</p><p>这时书写Schema文档还需要使用choice元素。</p><p>order2.xsd<br />-------------------------<br />1:&lt;?xml version="1.0"?&gt;<br />2:&lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:<br />4:  &lt;xsd:element name="order"&gt;<br />5:    &lt;xsd:complexType&gt;<br />6:      &lt;xsd:sequence&gt;<br />7:        &lt;xsd:element ref="orderItem" maxOccurs="10" /&gt;<br />8:      &lt;/xsd:sequence&gt;<br />9:    &lt;/xsd:complexType&gt;<br />10:  &lt;/xsd:element&gt;<br />11:<br />12:  &lt;xsd:element name="orderItem"&gt;<br />13:    &lt;xsd:complexType&gt;<br />14:      &lt;xsd:choice&gt;<br />15:        &lt;xsd:element name="name" type="xsd:string"/&gt;<br />16:        &lt;xsd:element name="id" type="xsd:string"/&gt;<br />17:      &lt;/xsd:choice&gt;<br />18:    &lt;/xsd:complexType&gt;<br />19:  &lt;/xsd:element&gt;<br />20:<br />21:&lt;/xsd:schema&gt;<br /></p><div>跟我学XML Schema(7):稍微更复杂的可选项子元素 
<p></p><p>再稍微修改一下订书数据的实例文档：</p><p>order3.xml<br />-----------------<br />&lt;order&gt;<br />  &lt;orderItem&gt;<br />    &lt;name&gt;Accounting Book&lt;/name&gt;<br />    &lt;quantity&gt;2&lt;/quantity&gt;<br />  &lt;/orderItem&gt;<br />  &lt;orderItem&gt;<br />    &lt;id&gt;7-5058-3496-7&lt;/id&gt;<br />  &lt;/orderItem&gt;<br />&lt;/order&gt;</p><p>这里假定&lt;quantity&gt;值为1时，缺省。</p><p>如何修改Schema文档呢？</p><p>order3.xsd<br />-----------------<br />1:&lt;?xml version="1.0"?&gt;<br />2:&lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:<br />4:  &lt;xsd:element name="order"&gt;<br />5:    &lt;xsd:complexType&gt;<br />6:      &lt;xsd:sequence&gt;<br />7:        &lt;xsd:element ref="orderItem" maxOccurs="10"/&gt;<br />8:      &lt;/xsd:sequence&gt;<br />9:    &lt;/xsd:complexType&gt;<br />10:  &lt;/xsd:element&gt;<br />11:<br />12:  &lt;xsd:element name="orderItem"&gt;<br />13:    &lt;xsd:complexType&gt;<br />14:      &lt;xsd:sequence&gt;<br />15:        &lt;xsd:choice&gt;<br />16:          &lt;xsd:element name="name" type="xsd:string"/&gt;<br />17:          &lt;xsd:element name="id" type="xsd:string"/&gt;<br />18:        &lt;/xsd:choice&gt;<br />19:        &lt;xsd:element name="quantity" type="xsd:string" minOccurs="0"/&gt;<br />20:      &lt;/xsd:sequence&gt;<br />21:    &lt;/xsd:complexType&gt;<br />22:  &lt;/xsd:element&gt;<br />23:<br />24:&lt;/xsd:schema&gt;</p><p>19行中的quantity最少出现值为0，也就是可以有，也可以没有。<br />当然，也可以直接在&lt;choice&gt;元素中，包含quantity,然后定义它的minOccurs。</p><div>跟我学XML Schema(8):内置简单类型 
<p></p><p>内建于XML Schema的简单类型有44种。他们在XML Schema推荐标准的第二部分中公布，下面这是一张内置类型的层次结构图：</p><p><a class="contentlink" href="http://www.w3.org/TR/2001/PR-xmlschema-2-20010330/type-hierarchy.jpg" target="_blank"><font color="#4455aa">http://www.w3.org/TR/2001/PR-xmlschema-2-20010330/type-hierarchy.jpg</font></a><br /></p><div>跟我学XML Schema(9):自定义简单类型 
<p></p><p>如果内置简单类型的44种还不能满足要求，怎么办呢？下面学习自定义简单类型。(XML的扩展性充分体现在这里)</p><p>例如这个实例文档：</p><p>order4.xml<br />-----------------<br />&lt;order&gt;<br />  &lt;orderItem&gt;<br />    &lt;id&gt;7-5058-3496-7&lt;/id&gt;<br />    &lt;quantity&gt;5&lt;/quantity&gt;<br />  &lt;/orderItem&gt;<br />&lt;/order&gt;</p><p>ID是一个标准的ISBN编码，我们怎么定义这个ISBN编码呢？</p><p>&lt;xsd:simpleType name="idType"&gt;<br />  &lt;xsd:restriction base="xsd:string"&gt;<br />    &lt;xsd:pattern <i>value</i>="\d{1}-\d{4}-\d{4}-\d{1}"/&gt;<br />  &lt;/xsd:restriction&gt;<br />&lt;/xsd:simpleType&gt;</p><p>idType是一个自定义的简单类型。<br />我们对它做了限制：<br />&lt;xsd:restriction base="xsd:string"&gt;代表它是基于一个字符串类型。再用pattern元素来描述该字符串的形式。</p><p><i>value</i>="\d{1}-\d{4}-\d{4}-\d{1}"这是一个正则表达式，关于正则表达式，以后再介绍。嘻嘻！</p><p>利用这个自定义的简单类型，我们可以重新写Schema文档：</p><p>order4.xsd<br />---------------<br />1:&lt;?xml version="1.0"?&gt;<br />2:&lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:<br />4:  &lt;xsd:element name="order"&gt;<br />5:    &lt;xsd:complexType&gt;<br />6:      &lt;xsd:sequence&gt;<br />7:        &lt;xsd:element ref="orderItem" maxOccurs="10"/&gt;<br />8:      &lt;/xsd:sequence&gt;<br />9:    &lt;/xsd:complexType&gt;<br />10:  &lt;/xsd:element&gt;<br />11:<br />12:  &lt;xsd:element name="orderItem"&gt;<br />13:    &lt;xsd:complexType&gt;<br />14:      &lt;xsd:sequence&gt;<br />15:        &lt;xsd:element name="id" type="idType"/&gt;<br />16:        &lt;xsd:element name="quantity" type="xsd:integer"/&gt;<br />17:      &lt;/xsd:sequence&gt;<br />18:    &lt;/xsd:complexType&gt;<br />19:  &lt;/xsd:element&gt;<br />20:  <br />21:  &lt;xsd:simpleType name="idType"&gt;<br />22:    &lt;xsd:restriction base="xsd:string"&gt;<br />23:      &lt;xsd:pattern <i>value</i>="\d{1}-\d{4}-\d{4}-\d{1}"/&gt;<br />24:    &lt;/xsd:restriction&gt;<br />25:  &lt;/xsd:simpleType&gt;<br />26:  <br />27:&lt;/xsd:schema&gt;</p><p><br />假如我们事先确定好ID只有3个，即只有3个ISBN是可选的，那怎么办？我们可以用enumeration元素来进行列举。</p><p>&lt;xsd:simpleType name="idType"&gt;<br />  &lt;xsd:restriction base="xsd:string"&gt;<br />    &lt;xsd:enumeration <i>value</i>="7-5058-3496-7"/&gt;<br />    &lt;xsd:enumeration <i>value</i>="7-5005-6450-3"/&gt;<br />    &lt;xsd:enumeration <i>value</i>="7-3020-6069-7"/&gt;<br />  &lt;/xsd:restriction&gt;<br />&lt;/xsd:simpleType&gt;</p><p><br />再来看订购量quantity的值，如果我们设定其值必须在1－10之间，该怎么办呢？可以这些自定义一个简单类型。</p><p>&lt;xsd:simpleType name="quantityType"&gt;<br />  &lt;xsd:restriction base="xsd:integer"&gt;<br />    &lt;xsd:minInclusive <i>value</i>="1"/&gt;<br />    &lt;xsd:maxInclusive <i>value</i>="10"/&gt;<br />  &lt;/xsd:restriction&gt;<br />&lt;/xsd:simpleType&gt;</p><p>其中，minInclusive,maxInclusive分别代表该类型的取值范围。</p><p>所以最终修改后的Schema文档如下：</p><p>order4-1.xsd<br />----------------------<br />1:&lt;?xml version="1.0"?&gt;<br />2:&lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:<br />4:  &lt;xsd:element name="order"&gt;<br />5:    &lt;xsd:complexType&gt;<br />6:      &lt;xsd:sequence&gt;<br />7:        &lt;xsd:element ref="orderItem" maxOccurs="10"/&gt;<br />8:      &lt;/xsd:sequence&gt;<br />9:    &lt;/xsd:complexType&gt;<br />10:  &lt;/xsd:element&gt;<br />11:<br />12:  &lt;xsd:element name="orderItem"&gt;<br />13:    &lt;xsd:complexType&gt;<br />14:      &lt;xsd:sequence&gt;<br />15:        &lt;xsd:element name="id" type="idType"/&gt;<br />16:        &lt;xsd:element name="quantity" type="quantityType"/&gt;<br />17:      &lt;/xsd:sequence&gt;<br />18:    &lt;/xsd:complexType&gt;<br />19:  &lt;/xsd:element&gt;<br />20:  <br />21:  &lt;xsd:simpleType name="idType"&gt;<br />22:    &lt;xsd:restriction base="xsd:string"&gt;<br />23:      &lt;xsd:enumeration <i>value</i>="7-5058-3496-7"/&gt;<br />    &lt;xsd:enumeration <i>value</i>="7-5005-6450-3"/&gt;<br />    &lt;xsd:enumeration <i>value</i>="7-3020-6069-7"/&gt;<br />26:    &lt;/xsd:restriction&gt;<br />27:  &lt;/xsd:simpleType&gt;<br />28:  <br />29:  &lt;xsd:simpleType name="quantityType"&gt;<br />30:    &lt;xsd:restriction base="xsd:integer"&gt;<br />31:      &lt;xsd:minInclusive <i>value</i>="1"/&gt;<br />32:      &lt;xsd:maxInclusive <i>value</i>="10"/&gt;<br />33:    &lt;/xsd:restriction&gt;<br />34:  &lt;/xsd:simpleType&gt;<br />35:<br />36:&lt;/xsd:schema&gt;<br /></p><div>跟我学XML Schema(10):定义属性 
<p></p><p>最后，我们再来讲讲元素的属性如何在Schema文档中定义。</p><p>比如上面的order.xml实例文档中：</p><p>&lt;order&gt;<br />  &lt;orderItem id="7-5058-3496-7" /&gt;<br />&lt;/order&gt;</p><p>对此，我们在Schema文档中采用一个attribute来定义：</p><p>order.xsd<br />－－－－－－－－－<br />&lt;xsd:element name="orderItem"&gt;<br />  &lt;xsd:complexType&gt;<br />    &lt;xsd:sequence&gt;　　←空元素<br />    &lt;/xsd:sequence&gt;　 <br />    <br />    &lt;!--定义该元素属性--&gt;<br />    &lt;xsd:attribute name="id" type="xsd:string"/&gt;<br />  &lt;/xsd:complexType&gt;<br />&lt;/xsd:element&gt;</p><p>那么，实例文档中该属性值是必须的还是可有可无的呢？我们可以这样限制：</p><p>&lt;xsd:attribute name="id" type="idType" use="required"/&gt;</p><p>这里我们讲id属性类型作为一种自定义数据类型idType。<br />而且，用attribute元素的use属性来定义是否是必须的属性。<br />required是必须值，optional是可选值，prohibited是无属性值。</p><p><br />那么对于属性的缺省值，我们怎么定义呢？<br />比如：<br />&lt;order&gt;<br />  &lt;orderItem id="4-8443-1780-6" quantity="3"/&gt;<br />&lt;/order&gt;</p><p>我们还可以用attribute元素的另一个属性default来定义：<br />&lt;xsd:attribute name="quantity" type="xsd:integer" default="1"/&gt;</p><p>所以，我们可以重新写出一个Schema文档：</p><p>order2.xsd<br />--------------<br />&lt;xsd:element name="orderItem"&gt;<br />  &lt;xsd:complexType&gt;<br />    &lt;xsd:sequence&gt;&lt;/xsd:sequence&gt;<br />    &lt;xsd:attribute name="id" type="idType" use="required"/&gt;<br />    &lt;xsd:attribute name="quantity" type="xsd:integer" default="1"/&gt;<br />  &lt;/xsd:complexType&gt;<br />&lt;/xsd:element&gt;<br /></p><div>上面的属性我们定义我们还可以采用属性组的办法来重新改写Schema文档。 
<p></p><p>order3.xsd<br />----------------<br />1:    &lt;xsd:element name="orderItem"&gt;<br />2:      &lt;xsd:complexType&gt;<br />3:        &lt;xsd:sequence&gt;&lt;/xsd:sequence&gt;<br />4:        &lt;xsd:attributeGroup ref="orderItemAttributes"/&gt;<br />5:      &lt;/xsd:complexType&gt;<br />6:    &lt;/xsd:element&gt;<br />7:<br />8:    &lt;xsd:attributeGroup name="orderItemAttributes"&gt;<br />9:      &lt;xsd:attribute name="id" type="idType" use="required"/&gt;<br />10:      &lt;xsd:attribute name="quantity" type="xsd:integer" default="1"/&gt;<br />11:    &lt;/xsd:attributeGroup&gt;</p><p>这个属性组就不详细解释了，不过，大家一看就清楚了吧。</p><p>最后，我们写一个完整的订书order.xml的Schema文档。<br />1:  &lt;?xml version="1.0"?&gt;<br />2:  &lt;xsd:schema xmlns:xsd="<a class="contentlink" href="http://www.w3.org/2001/XMLSchema&quot;&gt;" target="_blank"><font color="#4455aa">http://www.w3.org/2001/XMLSchema"&gt;</font></a><br />3:<br />4:    &lt;xsd:element name="order"&gt;<br />5:      &lt;xsd:complexType&gt;<br />6:        &lt;xsd:sequence&gt;<br />7:          &lt;xsd:element ref="orderItem" maxOccurs="10"/&gt;<br />8:        &lt;/xsd:sequence&gt;<br />9:      &lt;/xsd:complexType&gt;<br />10:    &lt;/xsd:element&gt;<br />11:<br />12:    &lt;xsd:element name="orderItem"&gt;<br />13:      &lt;xsd:complexType&gt;<br />14:        &lt;xsd:sequence&gt;&lt;/xsd:sequence&gt;<br />15:        &lt;xsd:attributeGroup ref="orderItemAttributes"/&gt;<br />16:      &lt;/xsd:complexType&gt;<br />17:    &lt;/xsd:element&gt;<br />18:<br />19:    &lt;xsd:attributeGroup name="orderItemAttributes"&gt;<br />20:      &lt;xsd:attribute name="id" type="idType" use="required"/&gt;<br />21:      &lt;xsd:attribute name="quantity" type="xsd:integer" default="1"/&gt;<br />22:    &lt;/xsd:attributeGroup&gt;<br />23:<br />24:    &lt;xsd:simpleType name="idType"&gt;<br />25:      &lt;xsd:restriction base="xsd:string"&gt;<br />26:        &lt;xsd:pattern <i>value</i>="\d{1}-\d{4}-\d{4}-\d{1}"/&gt;<br />27:      &lt;/xsd:restriction&gt;<br />28:    &lt;/xsd:simpleType&gt;<br />29:<br />30:  &lt;/xsd:schema&gt;<br /></p></div></div></div></div></div></div></div></div></div></div>
<img src ="http://www.blogjava.net/fortune/aggbug/37659.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-27 18:01 <a href="http://www.blogjava.net/fortune/archive/2006/03/27/37659.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML Schema用法</title><link>http://www.blogjava.net/fortune/archive/2006/03/27/37585.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Mon, 27 Mar 2006 05:03:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/27/37585.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/37585.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/27/37585.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/37585.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/37585.html</trackback:ping><description><![CDATA[
		<font color="#003399">
				<p>你现在应该知道XML只说明数据的结构而并不关心数据是如何具体描述的、数据是否正确。XML文档的强制性结构化需求是通过DTD（文档类型说明）来实现的。那就是本系列文章中先前讲述的主题。在本文里，我们概要介绍DTD所存在的缺点，讨论新型的更为强大的标准XML Schema。</p>
				<p>DTD的麻烦</p>
				<p>使用DTD虽然在指定许可的元素、需要的元素以及给定XML文档中如何组织元素等方面给我们以较大的方便，但是，一旦你想针对特定元素施加数据类型就会遇到麻烦了。DTD规范严格地定义了结构，但只支持相对功能较弱的内容类型规范，而对强制性结构化却无计可施，比如名为Date 的数据如何规定它必须包含有效值呢？ </p>
				<p>这就要指望XML Schema了，XML Schema目前作为建议已经于2001年提交给了W3C ，这意味着它最终将成为一般用途的建议标准。假如你对此感兴趣，你不妨到W3C网站找些官方文档和内容简介之类的材料来看看。注意，其他schema定义也是有的，包括日本的标准RELAX 和微软公司的XDR。可是，XML Schema是唯一受到W3C成为的建议标准，所以我在这篇文章中只对它进行阐述。</p>
				<p>XML Schema不仅可以让你定义XML文档的结构而且还允许你约束文档的内容，这就不同于DTD了。另外，一个 XML Schema自身就是一个XML文档，其基于标签的语法比DTD中的特殊字符要清楚多了。</p>
				<p>
						<br />Schema概述</p>
				<p>XML Schema是用一套预先规定的XML元素和属性创建的，这些元素和属性定义了文档的结构和内容模式。相应的一套精巧的规则（这些规则却很有意思的用DTD来表示）指定了每个Schema元素或者属性的合法用途。如果违反这些规则解析器就会拒绝解析你的Schema以及任何同它相联系的文档。</p>
				<p>现在让就让我们来看看清单A中显示的XML Schema示例，该例对我们以前在清单B中用到的图书目录进行了说明。清单B有了点小改动：作为根元素的catalog现在有了两个新属性，它们通过清单A中的catalog schema与之关联。</p>
				<p>你再看catalog schema，很快你就会注意到它包含了标准的XML头&lt;?xml version = "1.0"?&gt;，这表示schema自己就是一个XML文档。而任何schema的根元素都必须是schema，它有一个或者多个说明自己的属性。在这种情况下，schema的namespace定义属性（xmlns）会定义名称空间为xs，它将用作文档中所有元素的根名称空间。</p>
				<p>
						<br />--------------------------------------------------------------------------------</p>
				<p>什么是名称空间<br />XML把名称空间定义为包装XML元素在一起供以后重用的方式。为了使用XML文档的名称空间中定义的元素，你必须通过xmlns属性声明你希望采用名称空间。你还必须为该名称空间定义快捷方式的前缀（例如xs:）作为你文档中的根元素，从而使得名称空间在文档中都可用。前缀是用于文档的任何导入名称空间的元素的标识符。这一过程就如同在Visual Basic中给库加索引或者导入模块；C++、Java或者.NET下的名称空间也具有同样的含义。</p>
				<p>
						<br />--------------------------------------------------------------------------------</p>
				<p>我们的schema示例中接下来的元素是annotation，它的作用是代表同其父元素有关的文档。annotation可以包含两个子元素之一，或者是documentation或者是appinfo，或者两者都包含进去。前者用于可读的文档，而后者则用来保存供应用程序处理的指令。</p>
				<p>接下来我们定义了两个主要的元素（根元素catalog及其子元素book），它们用在书目文档内，后者采用了两个element元素。这些元素都包含了定义名字的属性和各个元素准许的内容。在这种情况下，catalog元素被定义为catalogtype类型，而book元素则被定义为elementtype类型；这两种类型以后还要在schema文档中被定义。</p>
				<p>什么是类型？<br />我已经说过了，XML Schema可以让你把XML文档中的元素声明为特定的类型，准许解析器检查文档的内容及其结构。XML Schem定义了两种主要的数据类型：预定义简单类型和复杂类型。这两种数据类型之间的主要区别是复杂类型可以象数据一样包含其他元素而简单类型则只能包含数据。简单类型给予了XML Schema低级类型检查能力，允许你把元素定义为图A中的任何类型之一。</p>
				<p>图A</p>
				<p>简单类型 定义</p>
				<p>string 字符串数据。</p>
				<p>boolean 二元类型的True或者False。</p>
				<p>date 历法日期，格式是CCYY-MM-DD。</p>
				<p>dateTime 历法日期和时间。</p>
				<p>time 24小时格式的时间可根据时区调节。</p>
				<p>decimal 任意精度和位数的十进制数。</p>
				<p>integer 整数</p>
				<p>float 标准的32位浮点数。</p>
				<p>
						<br />XML Schema预定义简单类型</p>
				<p>
						<br />你也可以定义自己的简单类型。为了更深入地了解各种XML Schema数据类型，请参看W3C网站上的“XML Schema Part 2: DataTypes”。</p>
				<p>复杂类型由complexType元素定义，它通常至少拥有一个name属性，用在声明其他元素时索引类型，除非它位于某一元素之内（参见下一节）。所有的复杂类型都会包含一个内容定义类型，其主要功能是定义类型能包含的内容模式。某些可用的内容模式请见图B。</p>
				<p>图B</p>
				<p>复杂类型 定义</p>
				<p>sequence 在其定义范围之内的所有元素都必须按顺序出现，范围由minOccurs和 maxOccurs指定。</p>
				<p>choice 其范围内有且只有一个元素必须出现。</p>
				<p>any 定义的任何元素都必须出现。</p>
				<p>simpleContent 这种复杂类型只包含了非嵌套元素。可以通过包含扩展元素的方式扩展先前定义的简单类型。</p>
				<p>complexContent 这种复杂类型只能包含其他元素。可以通过包含扩展元素的方式扩展先前定义的复杂类型。</p>
				<p>attribute 这种复杂类型只能包含命名属性。</p>
				<p>
						<br />一些准许的XML Schema复杂类型</p>
				<p>我们示例schema中的第一个complexType元素定义了booktype类型，你能从文档注释元素中看出，该类型给目录中单一的书建模型。Booktype包含一个sequence元素，通过它告诉解析器这种复杂类型的元素必须按照同样准确的顺序包含出现在sequence标签内出现的所有元素。就booktype而言，元素author、title、genre、price和publish_date都必须出现在 booktype元素之内。</p>
				<p>Description又是怎么一回事呢？它出现在sequence元素内，有没有这个必要呢？当然没有。description元素有一个minOccurs属性，它定义了复杂类型中元素可以出现的最小次数。在这种情况下，minOccurs的值是零，因此description是一个可选的元素。</p>
				<p>author元素也是这样。它有一个maxOccurs属性，但却没有设值，意思是说author元素可以在sequence中出现无限次，显然，一本图书的作者至少有一个但却不一定只有一个。既没有minOccurs也没有maxOccurs属性的元素必须而且仅仅只能在sequence中出现一次，因此，booktype sequence中的所有其他元素都是必要的而且只能出现一次。</p>
				<p>在我们的示例catalog schema中定义的第二个同时也是最后一个复杂类型是catalogtype复杂类型。它也是包含一个以上的sequence，你可以从无界的maxOccurs属性看出这一点。</p>
				<p>深入解释<br />看你的背景知识有多少了，本文用到的示例schema的结构对你来说要不本该如何要不只会叫你发昏，对book和catalog元素不采用正规复杂类型声明来定义catalog schema也是可能的，清单C就是这样。注意，清单C中的complexType元素嵌套在了element元素之内，catalog的sequence元素的子元素具有一个ref属性通过它告诉解析器它有一个引用指向先前定义的book元素。</p>
				<p>我曾经听到很多人这样问：“很好，如果是这样的话，那么你为什么要采用以上那些费工夫的办法呢？”很简单，我们绕来饶去只是为了说明XML Schema的重要一点：它是可扩展的。通过定义类型的方式你就可以在多个文档中重用它们，甚至还可以用不同的schema对其进行扩展，这就像你在开发应用程序的时候重用或者扩展抽象数据类型或对象是一个道理。</p>
				<p>
						<br />工具</p>
				<p>到目前为止，你应该意识到XML Schema的语法并不简单。虽然可以用简单的文本编辑器手工创建schema，不过，这样做也许会叫你累得吐血。为了更好地利用它，你可以采用若干种XML工具，最近出现的一些工具甚至提供了创建XML Schema的图形界面。XML Spy和Cape Clear Studio都是具有XML Schema创建功能的全方位XML综合开发环境。dtd2xs是一种DTD-to-XML的Schema转换工具，它有两种形式：单独运行的应用程序和Java类。同DTD一样，标准的XML Schema定义非常多，你可以根据自己的需要在应用程序的开发中采用。</p>
				<p>
						<br />结论<br />XML Schema具有强制文档内容和结构的能力，它是XML世界中的一种不但重要而且强大的新标准。在这篇文章里，我仅仅浮光掠影地大致解释了其基本原理，但我希望这些阐述能给你打下一个继续前进的基础。</p>
		</font>
<img src ="http://www.blogjava.net/fortune/aggbug/37585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-27 13:03 <a href="http://www.blogjava.net/fortune/archive/2006/03/27/37585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设置 SAX 解析器</title><link>http://www.blogjava.net/fortune/archive/2006/03/26/37502.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Sun, 26 Mar 2006 13:44:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/26/37502.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/37502.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/26/37502.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/37502.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/37502.html</trackback:ping><description><![CDATA[
		<blockquote>本文是技巧文章系列的第一篇文章，这些技巧文章将作为在 Java 编程语言中使用 XML 的综合指南。 我从讨论 SAX API 开始。本篇技巧文章回顾了如何获取 SAX 解析器实例以及如何对该解析器设置各种功能和属性。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>在 Java 中使用 XML 是一个内容相当丰富的主题；可以使用多个 API，而且许多 API 使得使用 XML 简单得如同从文本文档读取行。基于树的 API（如 DOM）展现了一个内存中的 XML 结构，该结构对于 GUI 和编辑器来说是最理想的，基于流的 API（如 SAX）对于只需要获取文档数据的高性能应用程序来说很重要。在本技巧文章系列中，我将从基础知识开始一步步地教您如何在 Java 中使用 XML。同时，您将学习许多甚至连众多专业人士都不知道的诀窍，所以即使您已经具有一些 XML 经验，也应该仔细阅读本教程。 </p>
		<p>我从 SAX（Simple API for XML）开始。虽然该 API 或许是 Java 和 XML API 中最难以掌握的，但它可能也是功能最强的 API。另外，大多数其它 API 实现（象 DOM 解析器、JDOM 和 dom4j 等）都部分地基于 SAX 解析器。对于用 XML 和 Java 语言所做的每一件事情，理解 SAX 会给予您一个良好的开端。特别在本篇技巧文章中，我将讨论如何获取 SAX 解析器实例以及如何对该解析器设置一些基本功能和属性。</p>
		<p>
				<i>
						<b>注</b>：我假设您已经下载了一个符合 SAX 的解析器（如 Apache Xerces-J）（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/xml/tips/x-tipsaxp/index.html#3"><font color="#996699">参考资料</font></a>以获取链接）。Apache 站点有大量关于如何进行设置的信息，但是，基本上您只需要将已下载的 JAR 文件放入 <code>CLASSPATH</code> 中。这些示例假设您的解析器可用。 </i>
		</p>
		<p>
				<a name="0">
						<span class="atitle">
								<font face="Arial" size="4">获取解析器</font>
						</span>
				</a>
		</p>
		<p>使用 SAX 的第一步实际上是获取解析器实例。在 SAX 中，由 <code>org.xml.sax.XMLReader</code> 类的实例表示解析器。我在上一篇技巧文章（“Achieving vendor independence with SAX”— 请参阅 <a href="http://www-128.ibm.com/developerworks/cn/xml/tips/x-tipsaxp/index.html#3"><font color="#996699">参考资料</font></a>）中对它进行了详细讨论，所以我将不会在这里花大量的时间在上面。清单 1 显示了在无需编写与供应商相关的代码的情况下获取新 SAX 解析器实例的正确方法。 </p>
		<br />
		<a name="c1">
				<b>清单 1. 获取 SAX 解析器实例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader(); 
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>通过使用这个方法，您需要将系统属性 <code>org.xml.sax.driver</code> 设置成想要装入的解析器的类名。这是特定于供应商的类；对于 Xerces，它应该是 <code>org.apache.xerces.parsers.SAXParser</code> 。用 <code>-D</code> 开关将这个参数指定给 Java 编译器： </p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">java -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser some.sample.Class
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>当然，您要确保指定的类存在并在类路径上。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/xml/tips/x-tipsaxp/index.html#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="1">
						<span class="atitle">
								<font face="Arial" size="4">功能</font>
						</span>
				</a>
		</p>
		<p>一旦有了解析器实例，就需要配置它。请注意，这与设置解析器来处理 XML 中的错误、内容或结构不同；相反，配置是实际告诉解析器如何操作的过程。您可以打开验证、关闭名称空间检查及扩展实体。这些行为完全独立于特定的 XML 文档，因此涉及与新解析器实例的交互。 </p>
		<p>
				<i>
						<b>注：</b>对于那些过于急燥的人来说（我知道您不是这样的），我当然会处理内容、错误处理及类似的东西。然而，这些主题将在未来的技巧文章中讨论，所以您还得复查。眼下，我们只关注配置、功能和属性。 </i>
		</p>
		<p>可以用两种方法配置解析器：功能和属性。 <b>功能</b>包括打开或关闭特定功能，比如验证。 <b>属性</b>包括设置解析器所使用的特定项的值，如用来验证所有文档的模式位置。我将先讨论功能，然后在下一节研究属性。 </p>
		<p>功能是通过解析器上名为 <code>setFeature()</code> 的方法设置的，这一点并不奇怪。语法类似于清单 2 所示。 </p>
		<br />
		<a name="c2">
				<b>清单 2. 设置 SAX 解析器的功能</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader(); 

String featureName = "some feature URI";
boolean featureOn = true;

try {
  parser.setFeature(featureName, featureOn);
} catch (SAXNotRecognizedException e) {
  System.err.println("Unknown feature specified: " + e.getMessage());
} catch (SAXNotSupportedException e) {
  System.err.println("Unsupported feature specified: " + e.getMessage());
} catch (SAXException e) {
  System.err.println("Error in setting feature: " + e.getMessage());
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这相当清楚，不需要说明；关键是知道可用于 SAX 解析器的常见功能。每个功能均由一个特定的 URI 标识。可以从 SAX 网站在线获得这些 URI 的完整列表（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/xml/tips/x-tipsaxp/index.html#3"><font color="#996699">参考资料</font></a>）。一些最常见的功能是验证和名称空间处理。清单 3 显示了设置这两种属性的示例。 </p>
		<br />
		<a name="c3">
				<b>清单 3. 一些常见功能</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader(); 

try {
  // Turn on validation
  parser.setFeature("http://xml.org/sax/features/validation", true);
  // Ensure namespace processing is on (the default)
  parser.setFeature("http://xml.org/sax/features/namespaces", true);
} catch (SAXNotRecognizedException e) {
  System.err.println("Unknown feature specified: " + e.getMessage());
} catch (SAXNotSupportedException e) {
  System.err.println("Unsupported feature specified: " + e.getMessage());
} catch (SAXException e) {
  System.err.println("Error in setting feature: " + e.getMessage());
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>请注意，虽然解析器有几个标准 SAX 功能，但这些解析器可以自由地添加自己的特定于供应商的功能。例如，Apache Xerces-J 添加了一些考虑动态验证以及遇到致命错误之后继续处理的功能。请参考解析器供应商的文档，以获取相关的功能 URI。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/xml/tips/x-tipsaxp/index.html#main">
																				<b>
																						<font color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="2">
						<span class="atitle">
								<font face="Arial" size="4">属性</font>
						</span>
				</a>
		</p>
		<p>一旦理解了功能，就很容易理解属性。除了属性将对象作为参数而功能获取布尔值外，它们以完全相同的方式操作。我们使用 <code>setProperty()</code> 方法来设置属性，如清单 4 所示。 </p>
		<br />
		<a name="c4">
				<b>清单 4. 设置 SAX 解析器的属性</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader(); 

String propertyName = "some property URI";

try {
  parser.setProperty(propertyName, obj-arg);
} catch (SAXNotRecognizedException e) {
  System.err.println("Unknown property specified: " + e.getMessage());
} catch (SAXNotSupportedException e) {
  System.err.println("Unsupported property specified: " + e.getMessage());
} catch (SAXException e) {
  System.err.println("Error in setting property: " + e.getMessage());
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这里使用相同的错误处理框架，所以您可以容易地在两种类型的配置选项之间复制代码。和功能一样，SAX 提供了一组标准属性，供应商可以添加他们自己的扩展。常见的 SAX 标准的属性考虑到了设置词法处理程序（Lexical Handler）和声明处理程序（Declaration Handler）（我将在以后的技巧文章中讨论这两个处理程序）。像 Apache Xerces 之类的解析器对它们进行了扩展，例如，使它们能够设置输入缓冲区大小以及要在验证中使用的外部模式的位置。清单 5 显示了几个实际使用中的属性。</p>
		<br />
		<a name="c5">
				<b>清单 5. 一些常见属性</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">// Obtain an instance of an XMLReader implementation from a system property
XMLReader parser = org.xml.sax.helpers.XMLReaderFactory.createXMLReader(); 

try {
  // Set the chunk to read in by SAX
  parser.setProperty("http://apache.org/xml/properties/input-buffer-size", 
      new Integer(2048));
  // Set a LexicalHandler
  parser.setProperty("http://xml.org/sax/properties/lexical-handler", 
      new MyLexicalHandler());
} catch (SAXNotRecognizedException e) {
  System.err.println("Unknown feature specified: " + e.getMessage());
} catch (SAXNotSupportedException e) {
  System.err.println("Unsupported feature specified: " + e.getMessage());
} catch (SAXException e) {
  System.err.println("Error in setting feature: " + e.getMessage());
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/fortune/aggbug/37502.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-26 21:44 <a href="http://www.blogjava.net/fortune/archive/2006/03/26/37502.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>xsd的两个例子</title><link>http://www.blogjava.net/fortune/archive/2006/03/26/37498.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Sun, 26 Mar 2006 12:47:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/26/37498.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/37498.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/26/37498.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/37498.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/37498.html</trackback:ping><description><![CDATA[
		<p>noNamspace schema的：<br /><br />&lt;?xml version="1.0" encoding="gb2312"?&gt;<br />&lt;!-- PRODUCTDATA是根元素--&gt;<br />&lt;PRODUCTDATA xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>" xsi:noNamespaceSchemaLocation="F:\XML\2\BookSaleS.XSD"&gt;<br /> &lt;PRODUCT&gt;<br />  &lt;BookTitle&gt;JAVA核心技术&lt;/BookTitle&gt;<br />  &lt;BookISBN&gt;I001&lt;/BookISBN&gt;<br />  &lt;FAuthor&gt;John Sun&lt;/FAuthor&gt;<br />  &lt;LAuthor&gt;May Rose&lt;/LAuthor&gt;<br />  &lt;BookPrice&gt;45&lt;/BookPrice&gt;<br /> &lt;/PRODUCT&gt;<br />&lt;/PRODUCTDATA&gt;</p>
		<p>
				<br />下面是XSD文件（BookSales.xsd）</p>
		<p>&lt;xsd:schema xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>"&gt;<br /> &lt;xsd:element name="PRODUCTDATA" type="PRODATA"/&gt;<br /> &lt;xsd:complexType name="PRODATA"&gt;<br />  &lt;xsd:sequence&gt;<br />   &lt;xsd:element name="PRODUCT" type="PROC"/&gt;<br />  &lt;/xsd:sequence&gt;<br /> &lt;/xsd:complexType&gt;<br /> &lt;xsd:complexType name="PROC"&gt;<br />  &lt;xsd:sequence&gt;<br />   &lt;xsd:element name="BookTitle" type="xsd:string"/&gt;<br />   &lt;xsd:element name="BookISBN" type="xsd:string"/&gt;<br />   &lt;xsd:element name="FAuthor" type="xsd:string"/&gt;<br />   &lt;xsd:element name="LAuthor" type="xsd:string"/&gt;<br />   &lt;xsd:element name="BookPrice" type="xsd:positiveInteger"/&gt;<br />  &lt;/xsd:sequence&gt;<br /> &lt;/xsd:complexType&gt;<br />&lt;/xsd:schema&gt;<br /><br />有命名空间的：<br />&lt;?xml version="1.0" encoding="GBK"?&gt;<br />&lt;qqq:MOVIEINFO xmlns:qqq="n" xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>" xsi:schemaLocation="n<br />F:\4\4.2\Movie.xsd"&gt;<br /> &lt;MOVIES&gt;<br />  &lt;MOVIE ID="Q0024"&gt;<br />   &lt;MOVIETYPE&gt;<br />    &lt;ROMANTIC&gt;浪漫&lt;/ROMANTIC&gt;<br />   &lt;/MOVIETYPE&gt;<br />   &lt;MOVIEDATE&gt;2003-12-12&lt;/MOVIEDATE&gt;<br />   &lt;MOVIENAME&gt;人鬼情未了&lt;/MOVIENAME&gt;<br />   &lt;PLAYACTORS&gt;<br />    &lt;PLAYACTOR&gt;Tom1&lt;/PLAYACTOR&gt;<br />    &lt;PLAYACTOR&gt;Tom2&lt;/PLAYACTOR&gt;<br />    &lt;PLAYACTOR&gt;Tom3&lt;/PLAYACTOR&gt;<br />    &lt;PLAYACTOR&gt;Tom3&lt;/PLAYACTOR&gt;<br />   &lt;/PLAYACTORS&gt;<br />   &lt;DIRECT&gt;Tom Jone&lt;/DIRECT&gt;<br />   &lt;HORTATION&gt;100万&lt;/HORTATION&gt;<br />  &lt;/MOVIE&gt;<br />  &lt;MOVIE ID="Q0404"&gt;<br />   &lt;MOVIETYPE&gt;<br />    &lt;COMEDY&gt;浪漫&lt;/COMEDY&gt;<br />   &lt;/MOVIETYPE&gt;<br />   &lt;MOVIEDATE&gt;2003-12-12&lt;/MOVIEDATE&gt;<br />   &lt;MOVIENAME&gt;人鬼情未了&lt;/MOVIENAME&gt;<br />   &lt;PLAYACTORS&gt;<br />    &lt;PLAYACTOR&gt;Tom1&lt;/PLAYACTOR&gt;<br />    &lt;PLAYACTOR&gt;Tom2&lt;/PLAYACTOR&gt;<br />    &lt;PLAYACTOR&gt;Tom3&lt;/PLAYACTOR&gt;<br />    &lt;PLAYACTOR&gt;Tom3&lt;/PLAYACTOR&gt;<br />   &lt;/PLAYACTORS&gt;<br />   &lt;DIRECT&gt;Tom Jone&lt;/DIRECT&gt;<br />   &lt;HORTATION&gt;100万&lt;/HORTATION&gt;<br />  &lt;/MOVIE&gt;<br /> &lt;/MOVIES&gt;<br />&lt;/qqq:MOVIEINFO&gt;</p>
		<p>
				<br />XSD文件：(Movie.xsd)</p>
		<p>&lt;s:schema xmlns:s="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>" targetNamespace="n" xmlns:a="n"&gt;<br /> &lt;s:include schemaLocation="Id.xsd"/&gt;<br /> &lt;s:element name="MOVIEINFO" type="a:suType"/&gt;<br /> &lt;s:complexType name="suType"&gt;<br />  &lt;s:sequence&gt;<br />   &lt;s:element name="MOVIES" type="a:ppType"/&gt;<br />  &lt;/s:sequence&gt;<br /> &lt;/s:complexType&gt;<br /> &lt;s:complexType name="ppType"&gt;<br />  &lt;s:sequence&gt;<br />   &lt;s:element name="MOVIE" type="a:uuType" maxOccurs="5"/&gt;<br />  &lt;/s:sequence&gt;<br /> &lt;/s:complexType&gt;<br /> &lt;s:complexType name="uuType"&gt;<br />  &lt;s:sequence&gt;<br />   &lt;s:element name="MOVIETYPE" type="a:prd"/&gt;<br />   &lt;s:element name="MOVIEDATE" type="s:string"/&gt;<br />   &lt;s:element name="MOVIENAME" type="s:string"/&gt;<br />   &lt;s:element name="PLAYACTORS" type="a:pod"/&gt;<br />   &lt;s:element name="DIRECT" type="s:string"/&gt;<br />   &lt;s:element name="HORTATION" type="s:string"/&gt;<br />  &lt;/s:sequence&gt;<br />  &lt;s:attribute name="ID" type="a:ppp"/&gt;<br /> &lt;/s:complexType&gt;<br /> &lt;s:complexType name="prd"&gt;<br />  &lt;s:choice&gt;<br />   &lt;s:element name="DROLLNESS" type="s:string"/&gt;<br />   &lt;s:element name="ROMANTIC" type="s:string"/&gt;<br />   &lt;s:element name="COMEDY" type="s:string"/&gt;<br />   &lt;s:element name="DRAMA" type="s:string"/&gt;<br />   &lt;s:element name="ACTION" type="s:string"/&gt;<br />  &lt;/s:choice&gt;<br /> &lt;/s:complexType&gt;<br /> &lt;s:complexType name="pod"&gt;<br />  &lt;s:sequence&gt;<br />   &lt;s:element name="PLAYACTOR" type="s:string" maxOccurs="5"/&gt;<br />  &lt;/s:sequence&gt;<br /> &lt;/s:complexType&gt;<br />&lt;/s:schema&gt;</p>
		<p>XSD文件：（ID.xsd）</p>
		<p>&lt;xsd:schema targetNamespace="n" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>"&gt;<br /> &lt;xsd:simpleType name="ppp"&gt;<br />  &lt;xsd:restriction base="xsd:string"&gt;<br />   &lt;xsd:pattern value="[Q]{1}\d{4}"/&gt;<br />  &lt;/xsd:restriction&gt;<br /> &lt;/xsd:simpleType&gt;<br />&lt;/xsd:schema&gt;<br /></p>
<img src ="http://www.blogjava.net/fortune/aggbug/37498.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-26 20:47 <a href="http://www.blogjava.net/fortune/archive/2006/03/26/37498.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>给XML文件定义DTD </title><link>http://www.blogjava.net/fortune/archive/2006/03/24/37150.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Fri, 24 Mar 2006 02:13:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/24/37150.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/37150.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/24/37150.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/37150.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/37150.html</trackback:ping><description><![CDATA[
		<table class="tablenormal">
				<tbody>
						<tr>
								<td valign="top" height="150">
										<!--帖子评价 -->
										<!--是否正解 -->
										<!--内容 -->近来研究XML，发现有必要对XML文件有更细致的了解<br />找来些东东，很早了，希望有用。。。<br /><br />    DTD实际上可以看作一个或多个XML文件的模板，这些XML文件中的元素、元素的属性、元素的排列方式/顺序、元素能够包含的内容等，都必须符合DTD中的定义。XML文件中的元素，即我们所创建的标记，是根据我们应用的实际情况来创建的。想要创建一份完整性高、适应性广的DTD是非常困难的，因为各行各业都有他们自己的行业特点，所以DTD通常是以某种应用领域为定义的范围，如：医学、建筑、工商、行政。DTD定义的元素含盖范围越广泛，那么就越复杂。<br /><br />    DTD可以是一个完全独立的文件，也可以在XML文件中直接设定。所以，DTD分为外部DTD（在XML文件中调用另外已经编辑好的DTD）和内部DTD（在XML文件中直接设定DTD）两种。比如，有几十家相互联系的、合作伙伴关系的公司、厂商，他们相互之间的交换电子文档都是用XML文档。那么我们可以将这些XML文档的DTD放在某个地方，让所有交换的XML文档都使用此DTD，这是最方便的做法，同时也适用于公司内部的XML文件使用。<br /><br />内部DTD<br /><br />内部DTD是在XML文件的文件序言区域中定义的。语法：<br /><br />〈!DOCTYPE element-name[........<br /><br />]〉  <br /><br /><br />〈!DOCTYPE ：表示开始设定DTD，注意DOCUTYPE是大写。<br /><br />Element-name ：指定此DTD的根元素的名称，一个XML文件只能有一个根元素。注意，如果 XML文件使用了DTD，那么文件中的根元素就在这里指定。<br /><br />[.........]〉 ：在[ ]标记里面定义XML文件使用元素，然后用〉结束DTD的定义。<br /><br />下面，我们来看一下怎样给XML文件定义DTD，请见例1。<br /><br />例1中的DTD定义区可以看作是一个DTD定义的大概框架，为其他XML文件定义DTD，结构和例1的DTD差不多，只是可能需要添加、删除或者更改一些东西而已。在DTD定义的中间是元素设定，这是一个DTD的最主要部分，其主要语法如下：<br /><br />〈!ELEMENT element-name element-definition〉  <br /><br /><br />〈!ELEMENT：表示开始元素设置，注意此处ELEMENT关键字是大写。<br /><br />element-name：表示要设置的元素的名称。<br /><br />element-definition：指明要对此元素进行怎样的定义，就是说〈元素〉...〈/元素〉之间能够包含什么内容，是其他元素还是一般性的文字。<br /><br />在例1中，大家可以看到，〈!ELEMENT 参考资料 (书籍)〉这个元素设定是声明了“参考资料”这个元素，并且它是作为“书籍”这个元素的父元素。〈!ELEMENT 书籍 (名称,作者,价格)〉这个元素设定声明了“书籍”这个元素，并且它是作为“名称”、“作者”、“价格”这三个元素的父元素。而〈!ELEMENT 名称 (#PCDATA)〉这个元素设定声明了“名称”这个元素，但是此元素仅仅包含一般文字，是基本元素，这是由#PCDATA关键字定义的。<br /><br />在元素设置中，如果元素包含多个子元素，如：〈!ELEMENT 书籍 (名称,作者,价格)〉这种含多个子元素的声明，那么“名称”、“作者”、“价格”这些标记在XML文件中必须以上面排列的顺序出现，每个标记必须而且只能够出现一次。如果在设定元素时，按照〈!ELEMENT 书籍ANY〉，这样在元素下就可以包含任意被设定过的元素，出现的次数和顺序也不受限制，并且在该元素下，除了可以包含子元素以外，还能够包含一般的文字。有时候，在XML文件中，一个标记可能多次出现（或者不出现），那么我们除了在它们的父元素中用ANY关键字之外，还可以在元素的旁边加上特定的符号来控制标记出现的次数。这些符号见表1。<br /><br />表1  符号<br />代表标记出现的次数<br /><br />？<br />不出现或只出现一次 <br /><br />*<br />不出现或可出现多次<br /><br />+<br />必须出现一次以上<br /><br />无符号<br />只能出现一次<br /><br /><br />例如：〈!ELEMENT 参考资料(书籍,报纸+,杂志?,网站)〉这个元素设定，“书籍”标记在XML文件中可以不出现或者出现多次；“报纸”标记必须出现一次以上；“杂志”标记可以不出现或只出现一次；而“网站”标记必须出现而且只能出现一次。<br /><br />在一些父元素的声明中，有可能它包含的子元素是在多个子元素中选择一个来使用，那么我们声明此父元素时，就可以把它声明成选择性元素，例如：〈!ELEMENT 配偶 (妻子|丈夫)〉。可供选择的子元素用“|”分隔，这样，我们在XML文件中可以这样写：<br /><br />〈配偶〉<br /><br />〈丈夫〉张三〈/丈夫〉<br /><br />〈/配偶〉  <br /><br /><br />只从中选择一个子元素。<br /><br />在我们的XML文件中，还可能包括很多“空元素”，即：元素是单独存在的，没有〈/元素〉这样的结束标记。那么在DTD中是用EMPTY关键字来声明的。如：〈!ELEMENT 元素名 EMPTY〉。在XML文件中，空元素不需要结束标记，但必须以〈/空元素名〉这样的写法。<br /><br />在DTD中，还可以声明一些称为Entity的东西，让DTD和XML文件使用。我们可以把Entity看作是一个常量，它有一定的值。在DTD中，Entity的声明语法为：〈!ENTITY entity-name entity-definition〉。例如：我们在DTD中声明〈!ENTITY PC "(#PCDATA)"〉 ，那么在后面的元素设定中，就可以使用这个Entity来代替“(#PCDATA)”这个字符串，如：〈!ELEMENT 作者 (#PCDATA)〉可以写成〈!ELEMENT 作者 &amp;&amp;PC;〉。引用Entity的时候，必须要在Entity名称前面加上“&amp;&amp;”符号，后面加上“；”符号。<br /><br />在例1中，〈!ATTLIST 价格 货币单位 CDATA #REQUIRED〉这一句是设定元素的属性，关于元素属性设置的语法为：〈!ATTLIST element-name attribute-name Type Default-value〉 。其中，〈!ATTLIST是开始属性的设定（注意大小写）。element-name是指明此属性设定是针对什么元素的；attribute-name是设定的属性的名称；Type是该属性的属性值的类别，属性值有多种，可以是一般的文字，或从几种属性值中取一种等，属性值的种类见表2。Default-value是指该属性的内定值种类，有四种不同的属性内定值（见表3）。<br /><br />下面我们举几个例子来看一下几个常用的元素属性的设定。例：<br /><br />〈!ATTLIST 姓名 性别 (男|女) "男"〉 <br /><br />此元素属性设定是为“姓名”这个元素设定一个名为“性别”的属性，此属性的属性值类别是Enumerated，取值范围为“男”或者“女”（用“|”分隔）。如果在XML文件中没有为此属性赋值，那么就取值为“男”，因为属性内定值是一个字符串“男”。<br /><br />〈!ATTLIST 姓名 号码 ID #REQUIRED〉<br /><br />该属性设定是为“姓名”元素设定一个名为“号码”的属性，属性值类别是ID，意味着在XML文件中为此属性赋值的时候，值在此XML文件中是唯一的，如在同一份XML文件中出现下面的XML语句：<br /><br />〈姓名 号码="1234567"〉张三〈/姓名〉<br /><br />〈姓名 号码="1234567"〉李四〈/姓名〉<br /><br />注意：“号码”属性的值重复了，这样，在解析过程中将会出现错误信息。此属性设定中的属性内定值为#REQUIRED，表示这个属性在XML文件的〈姓名〉标记中必须出现，否则解析会发生错误。<br /><br />〈!ATTLIST 电话号码 国家代码 CDATA #FIX "86"〉 <br /><br />该属性设定是为“电话号码”这个元素设定一个名为“国家代码”的属性，该属性的值是一般的文字。在〈电话号码〉标记中不能够设定该属性，因为这个属性被设为具有固定值的属性（#FIX关键字），解析器会自动地将该属性以及值“86”加到〈电话号码〉标记中。<br /><br />表2  属性值类别<br />描述 <br /><br />cdata<br />属性值仅仅是一般的文字。 <br /><br />enumerated<br />列出该属性的取值范围，一次只能有一个属性值能够赋予属性。 <br /><br />nmtoken<br />表示属性值只能由字母、数字、下划线、. 、：、-这些符号组成。 <br /><br />nmtokens<br />表示属性值能够由多个nmtoken组成，每个nmtoken之间用空格隔开。 <br /><br />id<br />该属性在xml文件中是唯一的，常用来表示人的身份证号码。 <br /><br />idref<br />表示该属性值是参考了另一个id属性。 <br /><br />idrefs<br />表示该属性值是参考了多个id属性，这些id属性的值用空格隔开。 <br /><br />entity<br />表示该属性的设定值是一个外部的entity，如一个图片文件。 <br /><br />entities<br />该属性值包含了多个外部entity，不同的entity之间用空格隔开。 <br /><br />notation<br />属性值是在dtd中声明过的notation（声明用什么应用软件解读某些二进制文件，如图片）。<br /><br /><br />在XML的规范中，还规定了两个内定的属性，即：xml:space和xml:lang ，内定的属性名称以xml:开头，而你自己定义的属性名不能以xml:开头，否则在解析时会发生错误。<br /><br />我们前面已经讲过，空白格在XML文件是有含义的，xml:space属性就是来设置解析器将XML文件中的空白格传给应用程序后的处理方法。xml:space是一个Enumerated类型的属性，只能够在default和preserver之间取值。xml:space="defaule"表示解析器将空白格传递给应用程序后，由应用程序内定的方法来处理这些空白格。如果没有设定xml:space属性，则解析器会默认用default来设定该属性。xml:space="preserver"是表示解析器将空白格传递给应用程序后，要求应用程序保留这些空白格。<br /><br />xml:lang属性是用来设置标记中的文字信息是使用哪种语言，ISO-639规定了不同语言的代表缩写，如：xml:lang="en" 表示英文；xml:lang="la"表示拉丁文；xml:lang="zh" 表示中文资料；xml:lang="zh-CN" 表示中文（简体）；xml:lang="zh-TW" 表示中文（繁体）。系统内定是xml:lang="en"，即标记中间的文字信息都是英文。<br /><br />外部DTD<br /><br />外部DTD是一个独立于XML文件的文件，实际上也是一个文本文件，只是使用.dtd为文件扩展名。因为外部DTD独立于XML文件，那么它可以供多个XML文件使用，就像用同一个模板可以写出多个不同内容的文件一样，这多个XML文件因为是引用同一个外部DTD，所以它们的结构大致相同。<br /><br />外部DTD的创建方式、语法和内部DTD是一样的，把例1的内部DTD的例子用外部DTD来写，文件如下所示。文件存为后缀名为 .dtd的文件。<br /><br />〈?xml version="1.0" encoding="GB2312" ?〉<br /><br />〈!ELEMENT 参考资料 (书籍*)〉<br /><br />〈!ELEMENT 书籍 (名称,作者,价格)〉<br /><br />〈!ELEMENT 名称 (#PCDATA)〉<br /><br />〈!ELEMENT 作者 (#PCDATA)〉<br /><br />〈!ELEMENT 价格 (#PCDATA)〉<br /><br />〈!ATTLIST 价格 货币单位 CDATA #REQUIRED〉  <br /><br /><br />除了没有内部DTD中的〈!DOCTYPE 参考资料 [.....]〉语句外，其他都一样。而且有关元素数目、排列顺序、空元素设定、选择性元素、Entity声明、属性设定等都和内部DTD是一样的。<br /><br />XML文件使用〈!DOCTYPE element-name SYSTEM DTD-URL〉或者〈!DOCTYPE element-name PUBLIC DTD-name DTD-URL〉来引用创建好的外部DTD文件。<br /><br />表3  属性内定值<br />描述<br /><br />#required<br />表示在标记中必须出现此属性。 <br /><br />#implied<br />标记中可以不出现此属性。 <br /><br />#fix<br />属性的值是固定的某个值。 <br /><br />字符串<br />标记中如没有指定属性的值，那么此字符串就是此属性的值。<br /><br /><br />此语句必须位于XML文件的文件序言区，其中，〈!DOCTYPE表示开始声明应用外部DTD；element-name是指该DTD的根元素的名称；SYSTEM是指该外部DTD文件是私有的，即我们自己创建的，没有公开发行，只是个人或在公司内部或者几个合作单位之间使用；而PUBIC关键字是指该外部DTD是公用的，经过了公开讨论，用PUBLIC的DTD都有一个逻辑名称——DTD-name，我们必须在调用时指明这个逻辑名称。DTD-URL是用URL的方式指明外部DTD文件的位置。例如，我们这份DTD文件存放在URL为：http://www.xml.com/这个地方，文件名为ckzl.dtd。那么在XML文件中的声明如下：<br /><br />〈?xml version="1.0" encoding="GB2312" ?〉<br /><br />〈!DOCTYPE 参考资料 SYSTEM "http://www.xml.com/ckzl.dtd"〉<br /><br />...  <br /><br /><br />Schema简介<br /><br />DTD的语法相当复杂，并且它不符合XML文件的标准，自成一个体系。上面的介绍也仅仅是作了一个简介，目的是帮助大家能读懂DTD文件以及在必要时创建简单的DTD文件，因为现在很多的XML应用是建立在DTD之上的。<br /><br />另外，一个代替DTD的就是W3C定义的Schema，Schema相对于DTD的明显好处是XML Schema文档本身也是XML文档，而不是像DTD一样使用自成一体的语法。这就方便了用户和开发者，因为可以使用相同的工具来处理XML Schema和其他XML信息，而不必专门为Schema使用特殊工具。Schema简单易懂，懂得XML语法、规则的人都可以立刻理解它。Schema的概念提出已久，但W3C的标准最近才出来，相应的应用支持尚未完善，但采用Schema已成为XML发展的一个趋势。<br /><br /><br /><br />例1<br /><br />DTD定义区:<br /><br />〈?xml version="1.0" encoding="GB2312" ?〉<br /><br />〈!DOCTYPE 参考资料 [<br /><br />〈!ELEMENT 参考资料 (书籍)〉<br /><br />〈!ELEMENT 书籍 (名称,作者,价格)〉<br /><br />〈!ELEMENT 名称 (#PCDATA)〉<br /><br />〈!ELEMENT 作者 (#PCDATA)〉<br /><br />〈!ELEMENT 价格 (#PCDATA)〉<br /><br />〈!ATTLIST 价格 货币单位 CDATA #REQUIRED〉<br /><br />]〉<br /><br />〈参考资料〉<br /><br />〈书籍〉<br /><br />〈名称〉XML入门精解〈/名称〉<br /><br />〈作者〉张三〈/作者〉<br /><br />〈价格 货币单位="人民币"〉20.00〈/价格〉<br /><br />〈/书籍〉<br /><br />〈书籍〉<br /><br />〈名称〉XML语法〈/名称〉<br /><br />〈!-- 即将出版 --〉<br /><br />〈作者〉李四〈/作者〉<br /><br />〈价格 货币单位="人民币"〉18.00〈/价格〉<br /><br />〈/书籍〉<br /><br />〈/参考资料〉 </td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/fortune/aggbug/37150.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-24 10:13 <a href="http://www.blogjava.net/fortune/archive/2006/03/24/37150.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>标题：Xml文档验证—基础篇</title><link>http://www.blogjava.net/fortune/archive/2006/03/23/37094.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Thu, 23 Mar 2006 14:01:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/23/37094.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/37094.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/23/37094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/37094.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/37094.html</trackback:ping><description><![CDATA[
		<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">
				<font class="f14">
						<font color="#000099">
								<b>一、Xml可扩展性的优势与隐患 </b>
						</font>
						<br />
						<br />　　从Xml（Extensible Markup Language可扩展标记语言）这个名字就可以知道，Xml是易于扩展的。的确，作为一种描述"元数据"的标记语言，Xml规范虽然为构建Xml文档提供了一些基本语法，但是并没有定义确切的标记，任何人都能够根据需要使用自定义的元素和属性为Xml文档提供结构信息以扩充标记集。 <br /><br />　　Xml的可扩展是不难理解的，作为一种新标记语言，Xml语言提供了一个可扩展的、强有力的标准来描述数据，使得数据可以在应用程序中使用或在不同平台、不同应用中交换。Xml只关心如何描述数据，并不指定如何为一个最终用户或者系统显示数据。（当然，你可以通过Xml相关的其他技术如XPath、XSlt或者程序语言来操纵和显示这些数据）。 <br /><br />　　在这一点上，Xml与同样继承自SGML（Standard Generalized Markup Language 标准通用标记语言）并且也是SGML子集的Html有很大的不同。Html的目的是通过一个（例如一个浏览器）来显示数据，你只能使用那些预先定义的特定标记。例如，要建立一个链接，你必须使用&lt;a&gt;标记，并且，你只能在这个标记内使用"href"属性指定链接目标所在的位置；同样，要在Html中导入一幅图象，你也只能使用&lt;img&gt;标记，并且只能在这个标记中使用"src"属性指定图象文件的路径。其他Html的元素和属性也一样，它们都被预定义了特定的名称。 <br /><br />　　Xml这种允许自由地创建标记和属性的特点为应用带来了极大的方便。根据应用需要，你可以为那些标记指定更有意义的、自描述的名称而不用一味遵循那些有可能并不合适的某种限制。比如，你大可用&lt;Link&gt;取代&lt;a&gt;标记，用"path"取代"href"属性使链接一目了然。放心，这在Xml规范中是允许的。 <br /><br />　　实际上也正是由于Xml可扩展的优点，Xml文档在各个领域（如科技词典、法律词汇表、医学词汇表、计算机词汇表、公用电话交换网络词汇等）的标准化建设中得到了广泛的应用。 <br /><br />　　这种定制Xml文档标记的"自由"无疑具有明显的优势，并且在特定的环境下的确是这样。然而， Xml文档很多时候被用于数据交换，Xml为标记那些可以在应用程序之间以平台无关的方式进行交换的数据提供了一种非常有用而且可以扩展的框架。它被广泛地用于在应用程序对象之间、不同平台应用中，甚至是Internet上交换数据。这个时候，创建你自己的Xml文档元素和属性名字的能力确实需要付出一定的代价，当你想要与其他的不熟悉你的文当结构的客户或者应用程序交换Xml文档时，这种代价尤为突出。所有这些参与者（平台、应用程序及人）都能正确使用这些Xml文档吗？它们中的自定义标记能够被识别吗？ <br /><br />　　乍看起来，这样似乎已经导致了混乱。毕竟，如果每个人都可以使用不遵循任何命名规范的标记来创建Xml文档，其他人怎么能够使用这些文档呢？ <br /><br /><br />　　<font color="#000099"><b>二、Xml验证-自由的相对性 </b></font><br />　　看来，完全遵循xml规范的格式正确的文档并不总能满足需要。许多情况下还需要保证文档的有效性。这时，一种"元数据"文档被创建来定义这个Xml文档中包含什么样的元素、属性和其他项目。有三种这样的"元数据"文档，它们是DTD、XML-DR Schema以及W3C Schema，它们定义了一个Xml文档必须遵循什么样的结构才是有效的。通过定义Xml文档的结构，应用能够在执行任何计算和转换之前对文档进行验证。 <br /><br />　　现在很清楚了，你尽可以在xml文档中自定义所需要的标记以描述数据，任何想使用这个文档的人也可以使用它，只要你为他们提供一个文档是如何组织以及使用什么样的标记描述数据的定义即可！由于XSD Schema是万维网联盟W3C的推荐标准，下面的验证均只针对它展开。 <br /><br /><br /><br />　　<font color="#000099"><b>三、从Xml文档内部引用Xml Schema验证 </b></font><br />　　在创建了一个Xml Schema文档之后，就可以用它来验证xml文档的有效性了。做起来很简单，只需要在xml文档根元素内引用该schema文件就可以了。不过，根据xml schema文档是否包含targetNamespace属性，xml文档内的引用有以下两种方式： <br /><br />　<font color="#0480fb">　1、使用noNamespceSchemaLocation属性引用schema文件 </font><br /><br />　　当xml schema文档不包括targetNamespace属性时，应当通过xml文档根元素的noNamespaceSchemaLocation属性及W3C的schmea实例命名空间(xmlns:xsi="http://www.w3.org/2001/XMLScheam-instance")来引用名xml schema文件。下面的例子引用不包含"targetNamespace"属性的名为"noTargetNS.xsd"的架构文件： </font>
		</span>
		<table width="100%" border="0">
				<tbody>
						<tr>
								<td width="100%" bgcolor="#ffffff">
										<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">
												<font class="f14">&lt;?xml version="1.0" encoding="utf-8" ?&gt;<br />&lt;Employees Xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance<br />"xsi:noNamespaceSchemaLocation="noTargetNS.xsd"&gt;<br />&lt;Name&gt;LinY&lt;/Name&gt;<br />&lt;Age&gt;42&lt;/Age&gt;<br />&lt;/Employees&gt;</font>
										</span>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 20pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">
						<font class="f14">
								<br />
								<br />　<font color="#0480fb">　2、使用schemaLocation属性引用schema文件 </font><br /><br />　　然而，如果xml schmea文件包含了一个targetNamespace 属性，在xml文档中就将通过schemaLocation属性而不是noNamespaceSchemaLocation属性来引用schema文档。而且，这个属性所指定的值必须是完整的。它需要包含以空格分开的两部分，前一部分是Uri，这个Uri与schema文档的targetNamespace属性内部引用的Uri是一致的；后一部分是schema文件完整路径及名称。另外，Xml文档的根元素也必须声明schema实例名字空间(xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance")，下面的例子引用包含"targetNamespace"属性的名为yesTargetNS.xsd架构文件： </font>
				</span>
		</p>
		<table width="100%" border="0">
				<tbody>
						<tr>
								<td width="100%" bgcolor="#ffffff">
										<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">
												<font class="f14">&lt;?Xml version="1.0" encoding="utf-8" ?&gt;<br />&lt;Employees Xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />xsi:schemaLocation="http://www.tuha.net yesTargetNS.xsd"<br />Xmlns="http://www.tuha.net"&gt;<br />&lt;Name&gt;XiaoM&lt;/Name&gt;<br />&lt;Age&gt;25&lt;/Age&gt;<br />&lt;/Employees&gt;</font>
										</span>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 20pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">
						<font class="f14">
								<br />　　在xml文档内部正确地引用schema文件之后，在解析xml文档时将执行验证。 <br /><br />　　<b><font color="#000099">四、在Visual Studio.Net IDE中使用Xml Schmea验证 </font></b><br /><br />　　Visual Studio.Net IDE为使用xml架构提供了丰富的支持。其集成的xml架构设计器，能够以组件拖放的方式创建xml架构文档；集成的xml文档设计器，能够基于现有xml文档创建xml架构。这之后，你可以关联xml文档和xml架构文件并执行xml文档的正确性及有效性验证操作。这样做时，你只需要作简单的代码修改甚至不用手写一行代码就能完整文档验证的所有工作。 <br /><br />　<font color="#0480fb">　1、创建xml架构 </font><br />　　可以通过任何文本编辑器创建xml架构文件，显然，这样做比较麻烦的，你必须熟知架构文档的规范。作为补充，Visual Studio.Net IDE中提供了好几种创建Xml架构文档的简单方式。使用Xml 架构设计器，从工具箱中拖入你需要的节点元素组件，就可以完成xml架构文档创建的绝大部分工作（如果你不需要修改节点数据类型的话，这也是创建xml架构文件的全部工作）。特别地，如果你已经创建了xml文档，你可以基于现有 XML 文件创建架构，通过简单的操作，就可以生成此xml文档应遵循的xml架构文件： <br />　　◇将Xml源文档（.xml 文件）加载到"Xml设计器"中。 <br />　　◇从IDE菜单栏中选择"XML"菜单项并单击"创建架构"。 <br />　　就这么简单，查看项目"所有文件"，你会发现，与xml文档同名的 XML 架构（.xsd 文件）生成了。 <br /><br />　　不过，以这种方法产生xml架构时，所有数据类型都被默认设置为 xsd:string类型，因此，可能需要修改它们以符合 Xml文档的需要。 <br /><br />　　<font color="#0480fb">2、关联xml文档和xml架构文件 </font><br /><br />　　如果已经创建了xml源文件和Xml架构文件，要使该xml架构文件对xml文档发生作用，必须将xml源文件和xml架构文件关联起来。在Visual Studio.Net IDE（集成开发环境）中，实现这一关联非常简单，通过定义Xml文件的targetSchema属性就可以完成： <br />　　◇将Xml 文件加载到"Xml 设计器"中。 <br />　　◇切换到"Xml"视图模式。 <br />　　◇在属性窗口中，从"targetSchema"属性的下拉列表中选择与名字空间相关联的的架构文件。 <br /><br />　　这时你应该会注意到，targetSchema属性的下拉框将列出该项目包括的所有xml架构及一些建议的规范，包括相应的名字空间。这同时也告诉我们，如果所需要的xml架构并不包含在该项目中，你将需要在这里键入将用于验证 XML 文档的架构的统一资源标识符 (URI)。 <br /><br />　　完成这几步后，返回查看你的xml源文件，会发现，在根元素内，xml架构以默认名字空间被引用。 <br /><br />　　附带说明一下，清除targetSchema属性的内容就可以移除xml文档与xml架构间的关联。 <br /><br />　　<font color="#0480fb">3、执行验证操作 </font><br />　　将xml架构文件与 Xml源文件关联后，"Xml 设计器"的验证功能可以检查Xml文件是否有效： <br />　　◇将要检查的 XML 文件加载到"XML 设计器"中。 <br />　　◇从"XML"菜单选择"验证 Xml 数据"。 <br /><br />　　这时，执行验证操作。这一过程也同时检查xml文档的正确性，如果发现错误，状态栏将予以指示。如果发生有效性错误，系统将提示"发现验证错误"并在"任务列表"中提供详细说明，否则，系统提示"未找到验证错误"而通过验证。 </font>
				</span>
		</p>
<img src ="http://www.blogjava.net/fortune/aggbug/37094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-23 22:01 <a href="http://www.blogjava.net/fortune/archive/2006/03/23/37094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实战SWT布局</title><link>http://www.blogjava.net/fortune/archive/2006/03/23/37067.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Thu, 23 Mar 2006 09:00:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/23/37067.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/37067.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/23/37067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/37067.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/37067.html</trackback:ping><description><![CDATA[
		<strong>标准的SWT布局类<br /></strong>FillLayout：在容器中以相同的大小单行或单列的排列组件<br />RowLayout：以单行或多行的方式使用几个选项(fill,wrap,spacing,justify,type)定制组件的排列方式<br />GridLayout：类似于swing的GridLayout的方式以格子的方式排列组件<br />FormLayout（SWT 2.0的新特性）：通过定义组件四个边的“粘贴”位置来排列组件，被引用的相对的组件可以父组件，也可以是同一容器中的其它组件。<br />在SWT中，可以由用户自定义布局类。<br /><br />在简单的布局中，使用FillLayout和RowLayout也许就够用了，也比较简单。但是通常的布局都比较复杂，而且要求很精确。无论复杂程度如何，都可以由GridLayout或FormLayout来完成。通常GridLayout与FormLayout可以做成同样的效果，但是使用FormLayout更有效，不会像GridLayout产生resize导致的布局错位，也更简单。下面通过一个例子简单介绍FormLayout的使用。<br /><br /><b>布局效果</b><br /><img src="http://www.javaresearch.org/members/efly/formlayout.jpg" /><br /><br /><b>布局实施</b><br />1.首先定义窗口和它的空白边<br />Display.getDefault().dispose();  //移去平台核心启动画面<br />        display = new Display();<br />        shell = new Shell(display, SWT.TITLE);<br />        FormLayout layout = new FormLayout();<br />        layout.marginHeight = 10;<br />        layout.marginWidth = 20;<br />        shell.setLayout(layout);<br />        shell.setText("用户登录");<br /><br />2.创建窗口上的元素，其中下面的两个button由一个使用RowLayout的组件来包容。<br />        name = new Label(shell, SWT.NONE);<br />        name.setText("用户名");<br />        nameText = new Text(shell, SWT.SINGLE | SWT.BORDER);<br />        pass = new Label(shell, SWT.NONE);<br />        pass.setText("密码");<br />        passText = new Text(shell, SWT.SINGLE | SWT.BORDER);<br />        passText.setEchoChar('*');<br />        passText.setTabs(2);<br />        bottom = new Composite(shell, SWT.NONE);<br />        RowLayout rowLayout = new RowLayout();<br />        rowLayout.justify = true;  //justify定义组件在容器中分散开，效果类似于swing的FlowLayout<br />        bottom.setLayout(rowLayout);<br /><br />3.定义name标签的位置。它的顶边离父组件（窗口shell）的空白边距离是父组件clientArea（除空白边以外的空间）高度(height)的15%，偏移的点数(points)为0。<br />FormData data = new FormData();<br />        data.top = new FormAttachment(15, 0);<br />        name.setLayoutData(data);<br /><br />4.定义name文本输入的位置。它的顶边在name标签的中心位置（这不是正确的表达，但程序是这样解释，事实上它的中心位置与name标签在同一条水平线上），左边距name标签的右边有10个点。<br />data = new FormData();<br />        data.top = new FormAttachment(name, 0, SWT.CENTER);<br />        data.left = new FormAttachment(name, 10, SWT.RIGHT);<br />        nameText.setLayoutData(data);<br /><br />5.定义pass标签的位置。它的顶边距name标签的底边有10个点数的偏移。<br />data = new FormData();<br />        data.top = new FormAttachment(name, 10, SWT.BOTTOM);<br />        pass.setLayoutData(data);<br /><br />6.定义pass文本输入的位置。它的顶边在name标签的中心位置（同上），左边与name文本框的左边对齐。<br />data = new FormData();<br />        data.top = new FormAttachment(pass, 0, SWT.CENTER);<br />        data.left = new FormAttachment(nameText, 0, SWT.LEFT);<br />        passText.setLayoutData(data);<br /><br />7.定义bottom组件的位置。它的顶边距pass标签的底边15个点数，左边与pass标签的左边对齐，右边与pass文本输入的右边对齐。<br />        data = new FormData();<br />        data.top = new FormAttachment(pass, 15, SWT.BOTTOM);<br />        data.left = new FormAttachment(pass, 0, SWT.LEFT);<br />        data.right = new FormAttachment(passText, 0, SWT.RIGHT);<br />        bottom.setLayoutData(data);<br /><br /><b>完整的源码</b><br />import org.eclipse.swt.SWT;<br />import org.eclipse.swt.events.SelectionAdapter;<br />import org.eclipse.swt.events.SelectionEvent;<br />import org.eclipse.swt.graphics.Rectangle;<br />import org.eclipse.swt.layout.FormAttachment;<br />import org.eclipse.swt.layout.FormData;<br />import org.eclipse.swt.layout.FormLayout;<br />import org.eclipse.swt.layout.RowLayout;<br />import org.eclipse.swt.widgets.Button;<br />import org.eclipse.swt.widgets.Composite;<br />import org.eclipse.swt.widgets.Display;<br />import org.eclipse.swt.widgets.Label;<br />import org.eclipse.swt.widgets.Shell;<br />import org.eclipse.swt.widgets.Text;<br /><br />import cn.com.efly.clientframe.core.Hook;<br /><br />/**<br /> * @author efly<br /> * @version 1.0.0,11/22/02<br /> */<br />public final class LoginUI {<br />    private Display display;<br />    private Shell shell;<br />    private Composite bottom;<br />    private Label name;<br />    private Label pass;<br />    private Text nameText;<br />    private Text passText;<br />    private Button ok;<br />    private Button exit;<br />    private Rectangle clientArea;<br />    private RootHook rootHook;<br /><br />    public LoginUI(Hook hook) {<br />        rootHook = (RootHook) hook;<br />    }<br /><br />    /**<br />     * 显示登陆界面<br />     */<br />    public void show() {<br />        Display.getDefault().dispose();<br />        display = new Display();<br />        clientArea = display.getClientArea();<br />        shell = new Shell(display, SWT.TITLE);<br />        FormLayout layout = new FormLayout();<br />        layout.marginHeight = 10;<br />        layout.marginWidth = 20;<br />        shell.setLayout(layout);<br />        shell.setText("用户登录");<br /><br />        name = new Label(shell, SWT.NONE);<br />        name.setText("用户名");<br />        nameText = new Text(shell, SWT.SINGLE | SWT.BORDER);<br />        pass = new Label(shell, SWT.NONE);<br />        pass.setText("密码");<br />        passText = new Text(shell, SWT.SINGLE | SWT.BORDER);<br />        passText.setEchoChar('*');<br />        passText.setTabs(2);<br />        bottom = new Composite(shell, SWT.NONE);<br />        RowLayout rowLayout = new RowLayout();<br />        rowLayout.justify = true;<br />        bottom.setLayout(rowLayout);<br />        ok = new Button(bottom, SWT.PUSH);<br />        ok.setText("确定");<br />        ok.addSelectionListener(new SelectionAdapter() {<br />            public void widgetSelected(SelectionEvent event) {<br />                ok();<br />            }<br />        });<br />        exit = new Button(bottom, SWT.PUSH);<br />        exit.setText("取消");<br />        exit.addSelectionListener(new SelectionAdapter() {<br />            public void widgetSelected(SelectionEvent event) {<br />                cancel();<br />            }<br />        });<br /><br />        FormData data = new FormData();<br />        data.top = new FormAttachment(15, 0);<br />        name.setLayoutData(data);<br /><br />        data = new FormData();<br />        data.top = new FormAttachment(name, 0, SWT.CENTER);<br />        data.left = new FormAttachment(name, 10, SWT.RIGHT);<br />        nameText.setLayoutData(data);<br /><br />        data = new FormData();<br />        data.top = new FormAttachment(name, 10, SWT.BOTTOM);<br />        pass.setLayoutData(data);<br /><br />        data = new FormData();<br />        data.top = new FormAttachment(pass, 0, SWT.CENTER);<br />        data.left = new FormAttachment(nameText, 0, SWT.LEFT);<br />        passText.setLayoutData(data);<br /><br />        data = new FormData();<br />        data.top = new FormAttachment(pass, 15, SWT.BOTTOM);<br />        data.left = new FormAttachment(pass, 0, SWT.LEFT);<br />        data.right = new FormAttachment(passText, 0, SWT.RIGHT);<br />        bottom.setLayoutData(data);<br /><br />        shell.pack();<br />        Rectangle shellBounds = shell.getBounds();<br />        shell.setLocation(<br />            (clientArea.width - shellBounds.width) / 2,<br />            (clientArea.height - shellBounds.height) / 2);<br /><br />        shell.open();<br /><br />        while (!shell.isDisposed()) {<br />            if (!display.readAndDispatch())<br />                display.sleep();<br />        }<br />    }<br /><br />    private void dispose() {<br />        display.dispose();<br /><br />    }<br /><br />    private void cancel() {<br />        dispose();<br />    }<br /><br />    private void ok() {<br />        verify();<br />    }<br /><br />    private void verify() {<br />        rootHook.runPlatform();<br />    }<br /><br />        public static void main(String[]){<br />                new LoginUI(null).show();<br />        }<br />}<br /><img src ="http://www.blogjava.net/fortune/aggbug/37067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-23 17:00 <a href="http://www.blogjava.net/fortune/archive/2006/03/23/37067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dom4j 学习笔记 </title><link>http://www.blogjava.net/fortune/archive/2006/03/22/36891.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Wed, 22 Mar 2006 09:50:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/22/36891.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/36891.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/22/36891.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/36891.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/36891.html</trackback:ping><description><![CDATA[
		<div class="postbody">
				<p>Dom4j 学习笔记<br />The dom4j Project Homepage: <a href="http://www.dom4j.org/">http://www.dom4j.org</a></p>
				<p>Loading XML Data<br />以下代码从File中或一个URL中读取一个XML文件，并产生一个Document对象。一个Document对象表示了内存中的一棵XML树，可以在这个XML树中进行遍历、查询、修改等操作。</p>
				<p>
						<br />import java.io.*;<br />import java.net.*;<br />import org.dom4j.Document;<br />import org.dom4j.DocumentException;<br />import org.dom4j.io.SAXReader;</p>
				<p>public class XMLLoader {<br />    <br />    private Document doc = null;<br />    <br />    public void parseWithSAX(File file)<br />    throws MalformedURLException, DocumentException {<br />        SAXReader xmlReader = new SAXReader();<br />        this.doc = xmlReader.read(file);<br />        return;<br />    }<br />    <br />    public void parseWithSAX(URL url)<br />    throws MalformedURLException, DocumentException {<br />        SAXReader xmlReader = new SAXReader();<br />        this.doc = xmlReader.read(url);<br />        return;<br />    }<br />}<br />        <br />QName and Namespace<br />QName对象表示了一个XML元素或属性的qualified name，即一个namespace和一个local name的二元组。</p>
				<p>Namespace对象表示了QName二元组中的namespace部分，它由prefix和URI两部分组成。</p>
				<p>
						<br />/******************** SAMPLE XML FILE *************************<br />  &lt;heavyz:Sample<br />    xmlns:heavyz="<a href="http://www.heavyzheng.com/schema/sample.xsd">http://www.heavyzheng.com/schema/sample.xsd</a>"&gt;<br />    &lt;heavyz:HelloWorld/&gt;<br />  &lt;/heavyz:Sample&gt;<br />  *************************************************************/<br />  <br />public void printRootQNameInfo(Document doc) {<br />    Element root = doc.getRootElement();<br />    QName qname = root.getQName();<br />    System.out.println("local name      : " + qname.getName());<br />    System.out.println("namespace prefix: " + qname.getNamespacePrefix());<br />    System.out.println("namespace URI   : " + qname.getNamespaceURI());<br />    System.out.println("qualified name  : " + qname.getQualifiedName());<br />    return;<br />}</p>
				<p>/************************* OUTPUT *****************************<br />  localname       : Sample<br />  namespace prefix: heavyz<br />  namespace URI   : <a href="http://www.heavyzheng.com/schema/sample.xsd">http://www.heavyzheng.com/schema/sample.xsd</a><br />  qualified name  : heavyz:Sample<br />  *************************************************************/<br />        <br />可以调用Namespace(String prefix, String uri)构造方法构造一个新的Namespace对象；也可以调用Namespace.get(String prefix, String uri)静态方法获得一个新的Namespace对象。</p>
				<p>可以调用QName(String name)构造方法构造一个没有namespace的qualified name；或者调用QName(String name, Namespace namespace)构造方法构造一个有namespace的qualified name。</p>
				<p>Navigating Through an XML Tree<br />对Document对象调用getRootElement()方法可以返回代表根节点的Element对象。拥有了一个Element对象后，可以对该对象调用elementIterator()方法获得它的子节点的Element对象们的一个iterator。使用(Element)iterator.next()方法遍历一个iterator并把每个取出的元素转化为Element类型。</p>
				<p>通过递归的方法，以下代码可以根据Document对象打印出完整的XML树。</p>
				<p>
						<br />public void printXMLTree(Document doc) {<br />    Element root = doc.getRootElement();<br />    printElement(root,0);<br />    return;<br />}<br />    <br />private void printElement(Element element, int level) {<br />    // print indent<br />    for (int i=0; i&lt;level; i++) {<br />        System.out.print(" ");<br />    }<br />    System.out.println(element.getQualifiedName());<br />    Iterator iter = element.elementIterator();<br />    while (iter.hasNext()) {<br />        Element sub = (Element)iter.next();<br />        printElement(sub,level+2);<br />    }<br />    return;<br />}<br />        <br />Getting Information from an Element<br />可以通过Element类提供的方法访问一个XML元素中含有的信息： Method Comment <br />getQName() 元素的QName对象 <br />getNamespace() 元素所属的Namespace对象 <br />getNamespacePrefix() 元素所属的Namespace对象的prefix <br />getNamespaceURI() 元素所属的Namespace对象的URI <br />getName() 元素的local name <br />getQualifiedName() 元素的qualified name <br />getText() 元素所含有的text内容，如果内容为空则返回一个空字符串而不是null <br />getTextTrim() 元素所含有的text内容，其中连续的空格被转化为单个空格，该方法不会返回null <br />attributeIterator() 元素属性的iterator，其中每个元素都是Attribute对象 <br />attributeValue() 元素的某个指定属性所含的值 <br />elementIterator() 元素的子元素的iterator，其中每个元素都是Element对象 <br />element() 元素的某个指定（qualified name或者local name）的子元素 <br />elementText() 元素的某个指定（qualified name或者local name）的子元素中的text信息 <br />getParent 元素的父元素 <br />getPath() 元素的XPath表达式，其中父元素的qualified name和子元素的qualified name之间使用"/"分隔 <br />isTextOnly() 是否该元素只含有text或是空元素 <br />isRootElement() 是否该元素是XML树的根节点 </p>
				<p>
						<br />要取出Element对象中某个属性的信息，可以调用attributeIterator()方法获得一个Attribute对象的iterator，然后再遍历它。也可以直接调用attributeValue()方法获得指定属性的值。该方法接受四种类型的参数： </p>
				<p>attributeValue(QName qname)：通过指定qualified name获得属性值，如果无法找到指定的属性，则返回null。 <br />attributeValue(QName qname, String defaultValue)：通过指定qualified name获得属性值，如果无法找到指定的属性，则返回defaultValue。 <br />attributeValue(String name)：通过指定local name获得属性值，而忽略属性的namespace，如果无法找到指定的属性，则返回null。 <br />attributeValue(String name, String defaultValue)：通过指定local name获得属性值，而忽略属性的namespace，如果无法找到指定的属性，则返回defaultValue。 </p>
				<p>对于一个Attribute对象，可以使用它的以下方法访问其中的信息： Method Comment <br />getQName() 属性的QName对象 <br />getNamespace() 属性所属的Namespace对象 <br />getNamespacePrefix() 属性所属的Namespace对象的prefix <br />getNamespaceURI() 属性所属的Namespace对象的URI <br />getName() 属性的local name <br />getQualifiedName() 属性的qualified name <br />getValue() 属性的值 </p>
				<p>
						<br />Writing an XML Tree to OutputStream<br />Dom4j通过XMLWriter将由Document对象表示的XML树写入一个文件，并使用OutputFormat格式对象指定写入的风格和编码方法。调用OutputFormat.createPrettyPrint()方法可以获得一个默认的pretty print风格的格式对象。对OutputFormat对象调用setEncoding()方法可以指定XML文件的编码方法。</p>
				<p>
						<br />public void writeTo(OutputStream out, String encoding)<br />throws UnsupportedEncodingException, IOException {<br />    OutputFormat format = OutputFormat.createPrettyPrint();<br />    format.setEncoding("gb2312");<br />    XMLWriter writer = new XMLWriter(System.out,format);<br />    writer.write(doc);<br />    writer.flush();<br />    return;<br />}<br />        <br />Creating an XML Tree<br />使用DocumentFactory对象创建一个空的Document对象。DocumentFactory对象由DocumentFactory.getInstance()静态方法产生。对Document对象调用addElement()方法将创建XML根节点，并将该节点返回。也可以手工创建一个Element对象并调用Document.setRootElement()方法把它设置为根节点</p>
				<p>
						<br />import org.dom4j.DocumentFactory;<br />import org.dom4j.Document;<br />import org.dom4j.Element;</p>
				<p>public class XMLSaver {<br />    <br />    private DocumentFactory factory = null;<br />    private Document doc = null;<br />    private Element root = null;<br />    <br />    public XMLSaver() {<br />        factory = DocumentFactory.getInstance();<br />        doc = factory.createDocument();<br />    }<br />    <br />    public Element generateRoot(String name) {<br />        root = doc.addElement(name);<br />        return root;<br />    }<br />    <br />    public Element generateRoot(QName qname) {<br />        root = doc.addElement(qname);<br />        return root;<br />    }<br />    <br />    public Element generateRoot(Element element) {<br />        doc.setRootElement(element);<br />        root = element;<br />        return root;<br />    }<br />}<br />        <br />Adding Information into an Element<br />Element通过addElement()为自己增加一个子节点到当前所有子节点的后面。该方法可以接受三种不同类型的参数：(QName qname)、(String name)或者(String qualifiedName, String namespaceURI)。该方法返回增加的子节点的Element对象。</p>
				<p>Element通过addAttribute()为自己增加属性。该方法可以接受两种不同类型的参数：(QName qname, String value)或者(String name, String value)。该方法返回自身的Element对象。</p>
				<p>Element通过addText()为自己增加文本内容。该方法只接受String类型参数，并返回自身的Element对象。</p>
				<p>
						<br />public void addAuthors(Element bookElement) {</p>
				<p>    Element author1 = bookElement.addElement("author");<br />    author1.addAttribute("name","Toby");<br />    author1.addAttribute("location","Germany");<br />    author1.addText("Tobias Rademacher");</p>
				<p>    Element author2 = bookElement.addElement("author");<br />    author2.addAttribute("name","James");<br />    author2.addAttribute("name","UK");<br />    author2.addText("James Strachan");<br />    <br />    return;<br />}<br />        <br />Deleting Elements and Attributes<br />要删除XML树上的一棵子树，首先要找到该子树的根节点，然后对该节点调用detach()方法。注意：如果对根节点调用了detach()方法，将导致该XML树不再完整（一个XML文件需要有且仅有一个根节点）。</p>
				<p>
						<br />public void deleteSubtree(Element subtreeRoot) {<br />    subtreeRoot.detach();<br />    return;<br />}<br />        <br />要清除Element下的所有子节点（包括Element和text），可以对该Element调用clearContent()方法。该方法不会清除Element的属性。</p>
				<p>要清除Element下的某个Attribute，首先要获得该Attribute对象，然后把它作为参数调用Element的remove()方法。</p>
				<p>Updating an Attribute<br />要更新一个属性的内容，首先要获得该Attribute对象，然后可以调用setNamespace()方法更新它所属的namespace；调用setValue()方法更新它的属性值。</p>
				<p>Updating an Element's Text<br />可以对一个Element对象调用isTextOnly()方法判断它是否只含有text或者是空节点。对Element对象调用addText()方法将把一个字符串附加到Element中，但不会修改它原来拥有的text或者子节点。如果Element是isTextOnly()，要修改原来含有的text，可以先调用clearContent()，再调用addText()并把新值传入。</p>
				<p>
						<br />public void updateText(Element element, String newText) {<br />    if (element.isTextOnly()) {<br />        element.clearContent();<br />        element.addText(newText);<br />    }<br />    return;<br />}</p>
		</div>
<img src ="http://www.blogjava.net/fortune/aggbug/36891.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-22 17:50 <a href="http://www.blogjava.net/fortune/archive/2006/03/22/36891.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 domj4 API 创建与修改 XML 文档</title><link>http://www.blogjava.net/fortune/archive/2006/03/20/36453.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Mon, 20 Mar 2006 14:20:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/20/36453.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/36453.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/20/36453.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/36453.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/36453.html</trackback:ping><description><![CDATA[
		<span class="postbody">
				<font size="2">
						<span style="FONT-WEIGHT: bold">使用 domj4 API 创建与修改 XML 文档</span>
						<br />级别：入门 <br /><br />Deepak Vohra (dvohra09@yahoo.com) <br />Web 开发人员 <br />2004 年 4 月 <br /><br />dom4j 是一种解析 XML 文档的开放源代码 XML 框架。本文介绍如何使用包含在 dom4j 中的解析器创建并修改 XML 文档。 <br />dom4j API 包含一个解析 XML 文档的工具。本文中将使用这个解析器创建一个示例 XML 文档。清单 1 显示了这个示例 XML 文档，catalog.xml。 <br /><br />清单 1. 示例 XML 文档（catalog.xml） <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />&lt;catalog&gt; <br />&lt;!--An XML Catalog--&gt; <br />&lt;?target instruction?&gt; <br />  &lt;journal title="XML Zone" <br />                  publisher="IBM developerWorks"&gt; <br /><br />&lt;article level="Intermediate" date="December-2001"&gt; <br /> &lt;title&gt;Java configuration with XML Schema&lt;/title&gt; <br /> &lt;author&gt; <br />     &lt;firstname&gt;Marcello&lt;/firstname&gt; <br />     &lt;lastname&gt;Vitaletti&lt;/lastname&gt; <br /> &lt;/author&gt; <br />  &lt;/article&gt; <br />  &lt;/journal&gt; <br />&lt;/catalog&gt;</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">然后使用同一个解析器修改 catalog.xml，清单 2 是修改后的 XML 文档，catalog-modified.xml。 <br /><br />清单 2. 修改后的 XML 文档（catalog-modified.xml） <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />&lt;catalog&gt; <br />&lt;!--An XML catalog--&gt; <br />&lt;?target instruction?&gt; <br />  &lt;journal title="XML Zone" <br />                   publisher="IBM developerWorks"&gt; <br /><br />&lt;article level="Introductory" date="October-2002"&gt; <br /> &lt;title&gt;Create flexible and extensible XML schemas&lt;/title&gt; <br /> &lt;author&gt; <br />     &lt;firstname&gt;Ayesha&lt;/firstname&gt; <br />     &lt;lastname&gt;Malik&lt;/lastname&gt; <br /> &lt;/author&gt; <br />  &lt;/article&gt; <br />  &lt;/journal&gt; <br />&lt;/catalog&gt;</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">与 W3C DOM API 相比，使用 dom4j 所包含的解析器的好处是 dom4j 拥有本地的 XPath 支持。DOM 解析器不支持使用 XPath 选择节点。 <br /><br />本文包括以下几个部分： <br /><br />预先设置 <br />创建文档 <br />修改文档 <br />预先设置 <br />这个解析器可以从 </font>
				<a href="http://dom4j.org/" target="_blank">
						<font color="#006699" size="2">http://dom4j.org</font>
				</a>
				<font size="2"> 获取。通过设置使 dom4j-1.4/dom4j-full.jar 能够在 classpath 中访问，该文件中包括 dom4j 类、XPath 引擎以及 SAX 和 DOM 接口。如果已经使用了 JAXP 解析器中包含的 SAX 和 DOM 接口，向 classpath 中增加 dom4j-1.4/dom4j.jar。dom4j.jar 包括 dom4j 类和 XPath 引擎，但是不含 SAX 与 DOM 接口。 <br /><br />创建文档 <br />本节讨论使用 dom4j API 创建 XML 文档的过程，并创建示例 XML 文档 catalog.xml。 <br /><br />使用 import 语句导入 dom4j API 类： <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">import org.dom4j.Document; <br />import org.dom4j.DocumentHelper; <br />import org.dom4j.Element;</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">使用 DocumentHelper 类创建一个文档实例。DocumentHelper 是生成 XML 文档节点的 dom4j API 工厂类。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">Document document = DocumentHelper.createDocument();</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">使用 addElement() 方法创建根元素 catalog。 addElement() 用于向 XML 文档中增加元素。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">Element catalogElement = document.addElement("catalog");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">在 catalog 元素中使用 addComment() 方法添加注释“An XML catalog”。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">catalogElement.addComment("An XML catalog");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">在 catalog 元素中使用 addProcessingInstruction() 方法增加一个处理指令。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">catalogElement.addProcessingInstruction("target","text");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">在 catalog 元素中使用 addElement() 方法增加 journal 元素。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">Element journalElement =  catalogElement.addElement("journal");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">使用 addAttribute() 方法向 journal 元素添加 title 和 publisher 属性。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">journalElement.addAttribute("title", "XML Zone"); <br />         journalElement.addAttribute("publisher", "IBM developerWorks");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">向 article 元素中添加 journal 元素。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">Element articleElement=journalElement.addElement("article");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">为 article 元素增加 level 和 date 属性。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">articleElement.addAttribute("level", "Intermediate"); <br />      articleElement.addAttribute("date", "December-2001");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">向 article 元素中增加 title 元素。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">Element titleElement=articleElement.addElement("title");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">使用 setText() 方法设置 article 元素的文本。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">titleElement.setText("Java configuration with XML Schema");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">在 article 元素中增加 author 元素。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">Element authorElement=articleElement.addElement("author");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">在 author 元素中增加 firstname 元素并设置该元素的文本。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">Element  firstNameElement=authorElement.addElement("firstname"); <br />     firstNameElement.setText("Marcello");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">在 author 元素中增加 lastname 元素并设置该元素的文本。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">Element lastNameElement=authorElement.addElement("lastname"); <br />     lastNameElement.setText("Vitaletti");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">可以使用 addDocType() 方法添加文档类型说明。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">document.addDocType("catalog", null,"file://c:/Dtds/catalog.dtd");</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">这样就向 XML 文档中增加文档类型说明： <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">&lt;!DOCTYPE catalog SYSTEM "file://c:/Dtds/catalog.dtd"&gt;</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">如果文档要使用文档类型定义（DTD）文档验证则必须有 Doctype。 <br /><br />XML 声明 &lt;?xml version="1.0" encoding="UTF-8"?&gt; 自动添加到 XML 文档中。 <br /><br />清单 3 所示的例子程序 XmlDom4J.java 用于创建 XML 文档 catalog.xml。 <br /><br />清单 3. 生成 XML 文档 catalog.xml 的程序（XmlDom4J.java） <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">import org.dom4j.Document; <br />import org.dom4j.DocumentHelper; <br />import org.dom4j.Element; <br />import org.dom4j.io.XMLWriter; <br />import java.io.*; <br /><br />public class XmlDom4J{ <br /><br />public void generateDocument(){ <br />Document document = DocumentHelper.createDocument(); <br />     Element catalogElement = document.addElement("catalog"); <br />     catalogElement.addComment("An XML Catalog"); <br />     catalogElement.addProcessingInstruction("target","text"); <br />     Element journalElement =  catalogElement.addElement("journal"); <br />     journalElement.addAttribute("title", "XML Zone"); <br />     journalElement.addAttribute("publisher", "IBM developerWorks"); <br /><br /><br />     Element articleElement=journalElement.addElement("article"); <br />     articleElement.addAttribute("level", "Intermediate"); <br />     articleElement.addAttribute("date", "December-2001"); <br />     Element  titleElement=articleElement.addElement("title"); <br />     titleElement.setText("Java configuration with XML Schema"); <br />     Element authorElement=articleElement.addElement("author"); <br />     Element  firstNameElement=authorElement.addElement("firstname"); <br />     firstNameElement.setText("Marcello"); <br />     Element lastNameElement=authorElement.addElement("lastname"); <br />     lastNameElement.setText("Vitaletti"); <br /><br />     document.addDocType("catalog", <br />                           null,"file://c:/Dtds/catalog.dtd"); <br />    try{ <br />    XMLWriter output = new XMLWriter( <br />            new FileWriter( new File("c:/catalog/catalog.xml") )); <br />        output.write( document ); <br />        output.close(); <br />        } <br />     catch(IOException e){System.out.println(e.getMessage());} <br />} <br /><br />public static void main(String[] argv){ <br />XmlDom4J dom4j=new XmlDom4J(); <br />dom4j.generateDocument(); <br />} <br />} <br /></td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">这一节讨论了创建 XML 文档的过程，下一节将介绍使用 dom4j API 修改这里创建的 XML 文档。 <br /><br />修改文档 <br />这一节说明如何使用 dom4j API 修改示例 XML 文档 catalog.xml。 <br /><br />使用 SAXReader 解析 XML 文档 catalog.xml： <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">SAXReader saxReader = new SAXReader(); <br /> Document document = saxReader.read(inputXml);</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">SAXReader 包含在 org.dom4j.io 包中。 <br /><br />inputXml 是从 c:/catalog/catalog.xml 创建的 java.io.File。使用 XPath 表达式从 article 元素中获得 level 节点列表。如果 level 属性值是“Intermediate”则改为“Introductory”。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">List list = document.selectNodes("//article/@level" ); <br />      Iterator iter=list.iterator(); <br />        while(iter.hasNext()){ <br />            Attribute attribute=(Attribute)iter.next(); <br />               if(attribute.getValue().equals("Intermediate")) <br />               attribute.setValue("Introductory"); <br />       }</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">获取 article 元素列表，从 article 元素中的 title 元素得到一个迭代器，并修改 title 元素的文本。 <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">list = document.selectNodes("//article" ); <br />     iter=list.iterator(); <br />   while(iter.hasNext()){ <br />       Element element=(Element)iter.next(); <br />      Iterator iterator=element.elementIterator("title"); <br />   while(iterator.hasNext()){ <br />   Element titleElement=(Element)iterator.next(); <br />   if(titleElement.getText().equals("Java configuration with XML Schema")) <br />     titleElement.setText("Create flexible and extensible XML schema"); <br /><br />    }} <br /> </td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">通过和 title 元素类似的过程修改 author 元素。 <br /><br />清单 4 所示的示例程序 Dom4JParser.java 用于把 catalog.xml 文档修改成 catalog-modified.xml 文档。 <br /><br />清单 4. 用于修改 catalog.xml 的程序（Dom4Jparser.java） <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="90%" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<span class="genmed">
												<b>
														<font size="2">代码:</font>
												</b>
										</span>
								</td>
						</tr>
						<tr>
								<td class="code">import org.dom4j.Document; <br />import org.dom4j.Element; <br />import org.dom4j.Attribute; <br />import java.util.List; <br />import java.util.Iterator; <br />import org.dom4j.io.XMLWriter; <br />import java.io.*; <br />import org.dom4j.DocumentException; <br />import org.dom4j.io.SAXReader; <br /><br />public class Dom4JParser{ <br /><br /> public void modifyDocument(File inputXml){ <br /><br />  try{ <br />   SAXReader saxReader = new SAXReader(); <br />   Document document = saxReader.read(inputXml); <br /><br />   List list = document.selectNodes("//article/@level" ); <br />   Iterator iter=list.iterator(); <br />   while(iter.hasNext()){ <br />    Attribute attribute=(Attribute)iter.next(); <br />    if(attribute.getValue().equals("Intermediate")) <br />      attribute.setValue("Introductory"); <br /><br />       } <br />    <br />   list = document.selectNodes("//article/@date" ); <br />   iter=list.iterator(); <br />   while(iter.hasNext()){ <br />    Attribute attribute=(Attribute)iter.next(); <br />    if(attribute.getValue().equals("December-2001")) <br />      attribute.setValue("October-2002"); <br /><br />       } <br /><br />   list = document.selectNodes("//article" ); <br />   iter=list.iterator(); <br />   while(iter.hasNext()){ <br />    Element element=(Element)iter.next(); <br />    Iterator iterator=element.elementIterator("title"); <br />      while(iterator.hasNext()){ <br />        Element titleElement=(Element)iterator.next(); <br />        if(titleElement.getText().equals("Java configuration with XML <br /><br />      Schema")) <br />        titleElement.setText("Create flexible and extensible XML schema"); <br /><br />                                          } <br /><br />                                } <br /><br />    list = document.selectNodes("//article/author" ); <br />    iter=list.iterator(); <br />     while(iter.hasNext()){ <br />     Element element=(Element)iter.next(); <br />     Iterator iterator=element.elementIterator("firstname"); <br />     while(iterator.hasNext()){ <br />      Element firstNameElement=(Element)iterator.next(); <br />      if(firstNameElement.getText().equals("Marcello")) <br />      firstNameElement.setText("Ayesha"); <br />                                     } <br /><br />                              } <br /><br />    list = document.selectNodes("//article/author" ); <br />    iter=list.iterator(); <br />     while(iter.hasNext()){ <br />      Element element=(Element)iter.next(); <br />      Iterator iterator=element.elementIterator("lastname"); <br />     while(iterator.hasNext()){ <br />      Element lastNameElement=(Element)iterator.next(); <br />      if(lastNameElement.getText().equals("Vitaletti")) <br />      lastNameElement.setText("Malik"); <br /><br />                                  } <br /><br />                               } <br />     XMLWriter output = new XMLWriter( <br />      new FileWriter( new File("c:/catalog/catalog-modified.xml") )); <br />     output.write( document ); <br />     output.close(); <br />   } <br />  <br />  catch(DocumentException e) <br />                 { <br />                  System.out.println(e.getMessage()); <br />                            } <br /><br />  catch(IOException e){ <br />                       System.out.println(e.getMessage()); <br />                    } <br /> } <br /><br /> public static void main(String[] argv){ <br /><br />  Dom4JParser dom4jParser=new Dom4JParser(); <br />  dom4jParser.modifyDocument(new File("c:/catalog/catalog.xml")); <br /><br />                                        } <br /><br />   }</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">这一节说明了如何使用 dom4j 中的解析器修改示例 XML 文档。这个解析器不使用 DTD 或者模式验证 XML 文档。如果 XML 文档需要验证，可以解释用 dom4j 与 JAXP SAX 解析器。 <br /><br />结束语 <br />包含在 dom4j 中的解析器是一种用于解析 XML 文档的非验证性工具，可以与JAXP、Crimson 或 Xerces 集成。本文说明了如何使用该解析器创建和修改 XML 文档。 <br /><br />参考资料 <br /><br />请访问 dom4j Web 站点，那里有一个很有用的 FAQ。 <br /><br />阅读 XML.com 上的文章“dom4j: the flexible XML framework for Java”。 <br /><br />通过 Dennis Sosnoski 的 developerWorks 文章“文档模型，第一部分：性能”（2001 年9 月）和“Java 文档模型的用法”（2002 年 2 月）进一步研究 dom4j。 <br /><br />通过 Elliotte Rusty Harold 的“Processing XML with Java”了解如何编制读写 XML 文档的 Java 程序。 <br /><br />在 developerWorks XML 和 Web 服务专区可以找到更多的 XML 资源。也可以订阅每周一期的 Web 服务/XML 技巧新闻邮件。 <br /><br />在 developerWorks Developer Bookstore 可以找到各种关于 XML 的书籍。 <br /><br />了解如何才能成为一名 IBM 认证的 XML 及相关技术的开发人员。 </font>
				<br />
				<span class="postbody">
						<font size="2">CSDN上的参考。 <br /></font>
						<a href="http://dev.csdn.net/develop/article/22/22753.shtm" target="_blank">
								<font color="#006699" size="2">http://dev.csdn.net/develop/article/22/22753.shtm</font>
						</a>
						<br />
				</span>
		</span>
<img src ="http://www.blogjava.net/fortune/aggbug/36453.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-20 22:20 <a href="http://www.blogjava.net/fortune/archive/2006/03/20/36453.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dom4j使用简介</title><link>http://www.blogjava.net/fortune/archive/2006/03/20/36428.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Mon, 20 Mar 2006 13:03:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/20/36428.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/36428.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/20/36428.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/36428.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/36428.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Dom4j																				is an easy to use, open source library for working with XML, XPath and XSLT on the Java platform using the Java Collections Framework and with full support for DOM, SAX ...&nbsp;&nbsp;<a href='http://www.blogjava.net/fortune/archive/2006/03/20/36428.html'>阅读全文</a><img src ="http://www.blogjava.net/fortune/aggbug/36428.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-20 21:03 <a href="http://www.blogjava.net/fortune/archive/2006/03/20/36428.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于dom4j</title><link>http://www.blogjava.net/fortune/archive/2006/03/20/36414.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Mon, 20 Mar 2006 12:08:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/20/36414.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/36414.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/20/36414.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/36414.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/36414.html</trackback:ping><description><![CDATA[今天就简单介绍一下处理XML文档的常用东西，关于xml document的话，w3c的document结构确实让人感到头痛，所以很多开发者都转向使用其他的document对象。其中dom4j是一个成功的开源项目，从java的对象概念的角度出发，按照通常的使用规范来处理xml文档，可以说，在java社区里，dom4j使用的最为广泛了，以下是dom4j的官方地址：<a href="http://www.dom4j.org/">http://www.dom4j.org/</a>。如，众所周知的o/r mapping工具hibernate就是使用dom4j来解释xml文档的（ejb3.0就是基于hibernate实现的），由此可见，dom4j的使用广泛之处。dom4j的一个最大的实用之处是支持XPath表达式的查询，这样，我们可以在dom4j的Document结构中使用这种简单的表达式就可以快速找到我们需要的某个元素了。
<p>      下载dom4j开发包：<a href="http://sourceforge.net/project/showfiles.php?group_id=16035">http://sourceforge.net/project/showfiles.php?group_id=16035</a>。在前言我已说过，由于都采用了使用类似的发布框架，所以对程序员来说极为容易上手。下载完dom4j之后，在dom4j的docs/cookbook.html里有详细的入门手册，而在src/samples里面则是一些样例，src/test文件夹里面是JUnit的测试例子。这些东西都已经很详细的介绍了怎样进行入门介绍。这里，我打算小结一下dom4j的Document结构：</p><p>      首先，要明白的是dom4j是基于面向接口的样式来实现处理xml文档的，这种方法在面向对象的领域里特别常见。使用的常用接口都封装在org.dom4j包里，而怎样读取xml文档呢？则是使用一系列的api函数，这些常用方法都封装在org.dom4j.io。</p><p>（1）从面向对象的角度来看，dom4j对XML的文档结构进行了封装，从一个文档的角度来说（我们不考虑内存中的数据结构的话），可以简单的把一个XML文档就当做一个org.dom4j.Document：</p><p>         我们现在使用dom4j的Document结构，而不是使用w3c的Document结构，读取一个文件，在内存中构造一个Document结构：Document doc=new SAXReader().read(new File("...")); 就可以获得一个Document结构。注意，dom4j同时也对w3c的Document结构，SAX Event的支持，具体的使用可以参看docs/cookbook.html中的内容。这里不一一介绍。</p><p>（2）获得一个dom4j的Document结构之后，从面向对象的角度，我们自然而然的想起的是XML中的element，dom4j根据这种想法对这些进行了封装org.dom4j.Element类就是对这些进行了封装，从Document中获得Element：</p><p>         首先获得一个root元素，Element root=doc.getRootElement();而其他的元素也可以根据这个root元素来获得。</p><p>（4）一个元素的属性的话，则是Attribute，在Element类中，有非常容易操作的方法添加于获得Attribute，addAttritue();attribute()等函数原型都提供了操作。</p><p>（5）dom4j同时也提供了在内存中的数据结构的构造，不降低处理的灵活性。如：Node就是对一个xml文档树的节点的封装，而Branch则是对一个树的分支的封装，通过使用这些，可以灵活的按照树的结构来处理xml文档。敏感的朋友可能会注意到，Document和Element都是Node与Branch的子类，这种不同功能的领域的封装可以按照对象的处理与数据结构的结合，灵活的处理xml文档。</p><p>         以上是一点简单的介绍入门dom4j的Document结构，详细的请看docs/cookbook.html文件，里面太详细了，：-）。</p><img src ="http://www.blogjava.net/fortune/aggbug/36414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-20 20:08 <a href="http://www.blogjava.net/fortune/archive/2006/03/20/36414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java串口编程（起步</title><link>http://www.blogjava.net/fortune/archive/2006/03/03/33401.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Fri, 03 Mar 2006 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/03/03/33401.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/33401.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/03/03/33401.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/33401.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/33401.html</trackback:ping><description><![CDATA[1. SerialBean<BR>SerialBean是本类库与其他应用程序的接口。该类库中定义了SerialBean的构造方法以及初始化串口，从串口读取数据，往串口写入数据以及关闭串口的函数。具体介绍如下： <BR><BR>public SerialBean(int PortID)<BR>本函数构造一个指向特定串口的SerialBean，该串口由参数PortID所指定。PortID = 1 表示COM1，PortID = 2 表示COM2，由此类推。<BR><BR>public int Initialize()<BR>本函数初始化所指定的串口并返回初始化结果。如果初始化成功返回1，否则返回-1。初始化的结果是该串口被SerialBean独占性使用，其参数被设置为9600, N, 8, 1。如果串口被成功初始化，则打开一个进程读取从串口传入的数据并将其保存在缓冲区中。<BR><BR>public String ReadPort(int Length)<BR>本函数从串口(缓冲区)中读取指定长度的一个字符串。参数Length指定所返回字符串的长度。<BR><BR>public void WritePort(String Msg)<BR>本函数向串口发送一个字符串。参数Msg是需要发送的字符串。<BR><BR>public void ClosePort()<BR>本函数停止串口检测进程并关闭串口。<BR>package serial;<BR>&nbsp;import java.io.*;<BR>&nbsp;import java.util.*;<BR>&nbsp;import javax.comm.*;<BR>&nbsp;/**<BR>&nbsp; *<BR>&nbsp; * This bean provides some basic functions to implement full dulplex<BR>&nbsp; * information exchange through the srial port.<BR>&nbsp; *<BR>&nbsp; */<BR>&nbsp;public class SerialBean<BR>&nbsp;{<BR>&nbsp; &nbsp;static String PortName;<BR>&nbsp; &nbsp;CommPortIdentifier portId;<BR>&nbsp; &nbsp;SerialPort serialPort;<BR>&nbsp; &nbsp;static OutputStream out;<BR>&nbsp; &nbsp;static InputStream &nbsp;in;<BR>&nbsp; &nbsp;SerialBuffer SB;<BR>&nbsp; &nbsp;ReadSerial &nbsp; RT;<BR>&nbsp; &nbsp; &nbsp;/**<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * Constructor<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * @param PortID the ID of the serial to be used. 1 for COM1,<BR>&nbsp; &nbsp; &nbsp; * 2 for COM2, etc.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; */<BR>&nbsp; &nbsp; &nbsp;public SerialBean(int PortID)<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;PortName = "COM" + PortID;<BR>&nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;/**<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * This function initialize the serial port for communication. It startss a<BR>&nbsp; &nbsp; &nbsp; * thread which consistently monitors the serial port. Any signal capturred<BR>&nbsp; &nbsp; &nbsp; * from the serial port is stored into a buffer area.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; */<BR>&nbsp; &nbsp; &nbsp;public int Initialize()<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;int InitSuccess = 1;<BR>&nbsp; &nbsp; &nbsp; &nbsp;int InitFail &nbsp; &nbsp;= -1;<BR>&nbsp; &nbsp; &nbsp;try<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;portId = CommPortIdentifier.getPortIdentifier(PortName);<BR>&nbsp; &nbsp; &nbsp; &nbsp;try<BR>&nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;serialPort = (SerialPort)<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;portId.open("Serial_Communication", 2000);<BR>&nbsp; &nbsp; &nbsp; &nbsp;} catch (PortInUseException e)<BR>&nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return InitFail;<BR>&nbsp; &nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp; &nbsp;//Use InputStream in to read from the serial port, and OutputStream<BR>&nbsp; &nbsp; &nbsp; &nbsp;//out to write to the serial port.<BR>&nbsp; &nbsp; &nbsp; &nbsp;try<BR>&nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;in &nbsp;= serialPort.getInputStream();<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;out = serialPort.getOutputStream();<BR>&nbsp; &nbsp; &nbsp; &nbsp;} catch (IOException e)<BR>&nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return InitFail;<BR>&nbsp; &nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp; &nbsp;//Initialize the communication parameters to 9600, 8, 1, none.<BR>&nbsp; &nbsp; &nbsp; &nbsp;try<BR>&nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; serialPort.setSerialPortParams(9600,<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SerialPort.DATABITS_8,<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SerialPort.STOPBITS_1,<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SerialPort.PARITY_NONE);<BR>&nbsp; &nbsp; &nbsp; &nbsp;} catch (UnsupportedCommOperationException e)<BR>&nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return InitFail;<BR>&nbsp; &nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;} catch (NoSuchPortException e)<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;return InitFail;<BR>&nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;// when successfully open the serial port, &nbsp;create a new serial buffer,<BR>&nbsp; &nbsp; &nbsp;// then create a thread that consistently accepts incoming signals from<BR>&nbsp; &nbsp; &nbsp;// the serial port. Incoming signals are stored in the serial buffer.<BR>&nbsp; &nbsp; &nbsp;SB = new SerialBuffer();<BR>&nbsp; &nbsp; &nbsp;RT = new ReadSerial(SB, in);<BR>&nbsp; &nbsp; &nbsp;RT.start();<BR>&nbsp; &nbsp; &nbsp;// return success information<BR>&nbsp; &nbsp; &nbsp;return InitSuccess;<BR>&nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;/**<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * This function returns a string with a certain length from the incomin<BR>&nbsp; &nbsp; &nbsp; * messages.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * @param Length The length of the string to be returned.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; */<BR>&nbsp; &nbsp; &nbsp;public String ReadPort(int Length)<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;String Msg;<BR>&nbsp; &nbsp; &nbsp; &nbsp;Msg = SB.GetMsg(Length);<BR>&nbsp; &nbsp; &nbsp; &nbsp;return Msg;<BR>&nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;/**<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * This function sends a message through the serial port.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * @param Msg The string to be sent.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; */<BR>&nbsp; &nbsp; &nbsp;public void WritePort(String Msg)<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;int c;<BR>&nbsp; &nbsp; &nbsp; &nbsp;try<BR>&nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for (int i = 0; i &lt; Msg.length(); i++)<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;out.write(Msg.charAt(i));<BR>&nbsp; &nbsp; &nbsp; &nbsp;} catch (IOException e) &nbsp;{}<BR>&nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;/**<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * This function closes the serial port in use.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; */<BR>&nbsp; &nbsp; &nbsp;public void ClosePort()<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;RT.stop();<BR>&nbsp; &nbsp; &nbsp; &nbsp;serialPort.close();<BR>&nbsp; &nbsp; &nbsp;}<BR>&nbsp;}<BR>
<DIV style="MARGIN: 4px 8px 0px" firstchar="">2. SerialBuffer <BR><BR>SerialBuffer是本类库中所定义的串口缓冲区，它定义了往该缓冲区中写入数据和从该缓冲区中读取数据所需要的函数。 <BR><BR>public synchronized String GetMsg(int Length)<BR>本函数从串口(缓冲区)中读取指定长度的一个字符串。参数Length指定所返回字符串的长度。<BR><BR>public synchronized void PutChar(int c)<BR>本函数望串口缓冲区中写入一个字符，参数c 是需要写入的字符。<BR><BR>在往缓冲区写入数据或者是从缓冲区读取数据的时候，必须保证数据的同步，因此GetMsg和PutChar函数均被声明为synchronized并在具体实现中采取措施实现的数据的同步。<BR>package serial;<BR>&nbsp;/**<BR>&nbsp; *<BR>&nbsp; * This class implements the buffer area to store incoming data from the serial<BR>&nbsp; * port.<BR>&nbsp; *<BR>&nbsp; */<BR>&nbsp;public class SerialBuffer<BR>&nbsp;{<BR>&nbsp; &nbsp;private String Content = "";<BR>&nbsp; &nbsp;private String CurrentMsg, TempContent;<BR>&nbsp; &nbsp;private boolean available = false;<BR>&nbsp; &nbsp;private int LengthNeeded = 1;<BR>&nbsp; &nbsp; &nbsp;/**<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * This function returns a string with a certain length from the incomin<BR>&nbsp; &nbsp; &nbsp; * messages.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * @param Length The length of the string to be returned.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; */<BR>&nbsp; &nbsp;public synchronized String GetMsg(int Length)<BR>&nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp;LengthNeeded = Length;<BR>&nbsp; &nbsp; &nbsp;notifyAll();<BR>&nbsp; &nbsp; &nbsp;if (LengthNeeded &gt; Content.length())<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;available = false;<BR>&nbsp; &nbsp; &nbsp; &nbsp;while (available == false)<BR>&nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;try<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;wait();<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} catch (InterruptedException e) { }<BR>&nbsp; &nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;CurrentMsg &nbsp;= Content.substring(0, LengthNeeded);<BR>&nbsp; &nbsp; &nbsp;TempContent = Content.substring(LengthNeeded);<BR>&nbsp; &nbsp; &nbsp;Content = TempContent;<BR>&nbsp; &nbsp; &nbsp;LengthNeeded = 1;<BR>&nbsp; &nbsp; &nbsp;notifyAll();<BR>&nbsp; &nbsp; &nbsp;return CurrentMsg;<BR>&nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;/**<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * This function stores a character captured from the serial port to the<BR>&nbsp; &nbsp; &nbsp; * buffer area.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * @param t The char value of the character to be stored.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; */<BR>&nbsp; &nbsp;public synchronized void PutChar(int c)<BR>&nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp;Character d = new Character((char) c);<BR>&nbsp; &nbsp; &nbsp;Content = Content.concat(d.toString());<BR>&nbsp; &nbsp; &nbsp;if (LengthNeeded &lt; Content.length())<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;available = true;<BR>&nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;notifyAll();<BR>&nbsp; &nbsp;}<BR>&nbsp;}<BR>&nbsp;&nbsp;&nbsp;3. ReadSerial<BR>ReadSerial是一个进程，它不断的从指定的串口读取数据并将其存放到缓冲区中。 <BR><BR>public ReadSerial(SerialBuffer SB, InputStream Port)<BR>本函数构造一个ReadSerial进程，参数SB指定存放传入数据的缓冲区，参数Port指定从串口所接收的数据流。<BR><BR>public void run()<BR>ReadSerial进程的主函数，它不断的从指定的串口读取数据并将其存放到缓冲区中。<BR>package serial;<BR>&nbsp;import java.io.*;<BR>&nbsp;/**<BR>&nbsp; *<BR>&nbsp; * This class reads message from the specific serial port and save<BR>&nbsp; * the message to the serial buffer.<BR>&nbsp; *<BR>&nbsp; */<BR>&nbsp;public class ReadSerial extends Thread<BR>&nbsp;{<BR>&nbsp; &nbsp;private SerialBuffer ComBuffer;<BR>&nbsp; &nbsp;private InputStream ComPort;<BR>&nbsp; &nbsp; &nbsp;/**<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * Constructor<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; * @param SB The buffer to save the incoming messages.<BR>&nbsp; &nbsp; &nbsp; * @param Port The InputStream from the specific serial port.<BR>&nbsp; &nbsp; &nbsp; *<BR>&nbsp; &nbsp; &nbsp; */<BR>&nbsp; &nbsp;public ReadSerial(SerialBuffer SB, InputStream Port)<BR>&nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp;ComBuffer = SB;<BR>&nbsp; &nbsp; &nbsp;ComPort = Port;<BR>&nbsp; &nbsp;}<BR>&nbsp; &nbsp;public void run()<BR>&nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp;int c;<BR>&nbsp; &nbsp; &nbsp;try<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;while (true)<BR>&nbsp; &nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;c = ComPort.read();<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ComBuffer.PutChar(c);<BR>&nbsp; &nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;} catch (IOException e) {}<BR>&nbsp; &nbsp;}<BR>&nbsp;}<BR>4. SerialExample<BR>SerialExample是本类库所提供的一个例程。它所实现的功能是打开串口COM1，<BR>对其进行初始化，从串口读取信息对其进行处理后将处理结果发送到串口。 <BR>import serial.*;<BR>&nbsp;import java.io.*;<BR>&nbsp;/**<BR>&nbsp; *<BR>&nbsp; * This is an example of how to use the SerialBean. It opens COM1 and reads<BR>&nbsp; * six messages with different length form the serial port.<BR>&nbsp; *<BR>&nbsp; */<BR>&nbsp;class SerialExample<BR>&nbsp;{<BR>&nbsp; &nbsp;public static void main(String[] args)<BR>&nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp;//TO DO: Add your JAVA codes here<BR>&nbsp; &nbsp; &nbsp;SerialBean SB = new SerialBean(1);<BR>&nbsp; &nbsp; &nbsp;String Msg;<BR>&nbsp; &nbsp; &nbsp;SB.Initialize();<BR>&nbsp; &nbsp; &nbsp;for (int i = 5; i &lt;= 10; i++)<BR>&nbsp; &nbsp; &nbsp;{<BR>&nbsp; &nbsp; &nbsp; &nbsp;Msg = SB.ReadPort(i);<BR>&nbsp; &nbsp; &nbsp; &nbsp;SB.WritePort("Reply: " + Msg);<BR>&nbsp; &nbsp; &nbsp;}<BR>&nbsp; &nbsp; &nbsp;SB.ClosePort();<BR>&nbsp; &nbsp;}<BR>&nbsp;}<BR>　本类库中使用了Java Communication API (javax.comm)。这是一个Java扩展类库，<BR>并不包括在标准的Java SDK当中。如果你尚未安装这个扩展类库的话，你应该从<BR>Sun公司的Java站点下载这个类库并将其安装在你的系统上。在所下载的包里面包括<BR>一个安装说明，如果你没有正确安装这个类库及其运行环境的话，运行这个程序的时候<BR>你会找不到串口。<BR>正确安装Java Communication API并将上述程序编译通过以后，<BR>你可以按如下方法测试这个程序。如果你只有一台机器，你可以利用一条<BR>RS-232电缆将COM1和COM2连接起来，在COM1上运行SerialExample，<BR>在COM2上运行Windows提供的超级终端程序。如果你有两台机器的话，<BR>你可以利用一条RS-232电缆将两台机器的COM1(或者是COM2)连接起来，在一端运行例程，<BR>另外一端运行Windows提供的超级终端程序。如果有必要的话，可以对SerialExample中<BR>所声明的串口进行相应改动。 <BR>本程序在Windows 2000 + Java SDK 1.3环境下编译通过并成功运行。 <BR></DIV><img src ="http://www.blogjava.net/fortune/aggbug/33401.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-03-03 11:00 <a href="http://www.blogjava.net/fortune/archive/2006/03/03/33401.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>xml新手入门</title><link>http://www.blogjava.net/fortune/archive/2006/02/28/32832.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Tue, 28 Feb 2006 05:35:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/28/32832.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/32832.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/28/32832.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/32832.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/32832.html</trackback:ping><description><![CDATA[1.什么是 XML？&nbsp;&nbsp;<BR>可扩展标记语言（Extensible Markup Language，XML）提供了一种标记内容的方式，可以添加关于数据用途的信息。信息使用 XML 存储之后，称为解析器的应用程序就能够可靠地提取相关信息，并根据不同的需要处理。<BR><BR><BR><BR>2.XML 可用来做什么？&nbsp;&nbsp;<BR>XML 可用于各种不同的应用程序，但其实质是：XML 是一种表示数据的方式。有时候数据是为数据库准备的，有些时候则是供人阅读的。与这两方面应用相关的技术，比如数据验证和 XML 转换也已经随着 XML 自身一起发展起来。<BR><BR>XML 包括验证或者确认的能力、文档结构和文档（在某种意义上的）内容。验证文档有助于防止数据与期望具有特定结构的应用程序进行交互时出现问题，当 XML 与非 XML 的遗留系统交互时这一点尤其有用。最初的 XML 1.0 推荐标准包括对文档类型定义（Document Type Definitions，DTD）的支持，DTD 提供了一些验证能力。W3C XML Schemas 扩展了这种功能，并提供了一种更加类似 XML 的语法。<BR><BR>可通过多种方式使用 XML 封装的数据。一种常见的处理方式是通过使用可扩展样式表语言转换（Extensible Stylesheet Language Transformations，XSLT），开发人员可以使用 XSLT 定义对 XML 文档的操作，以生成特定的结果。这种动态转换信息的能力允许从单个源文档产生多种输出，无论输出到不同的数据库还是输出到不同的浏览器。<BR><BR>XSL 格式化对象（XSL Formatting Objects，XSL-FO）是一种强大而灵活的格式化数据的 XML 词汇表，常与 XSLT 结合使用，把 XML 和 HTML 转化成 PDF（可移植文档格式）。<BR><BR><BR>3.如何在应用程序开发中使用 XML？&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;开发 XML 应用程序时常用到几种模型。您可以使用根据这些模型创建的 API 来分析和操纵 XML 结构，这些模型可以是基于对象的，如文档对象模型（Document Object Model，DOM）和 JDOM；也可以是基于事件的，如 Simple API for XML（SAX）。另外，Java API for XML Parsing（JAXP）提供了使用 DOM、SAX 和 XSLT 处理 XML 文档的通用接口。<BR><BR>其中最常用的 API 是 DOM，在这种模型里文档的每个成分被描述成特定类型的节点。这些节点按照父子关系组织。各种不同的语言中都有 DOM API 的绑定，如 Java、C++、Perl 和 Python。<BR><BR>SAX 是第二种应用最广的 API。和基于对象的 DOM 模型不同，SAX 是一种基于事件的模型，把文档转化成一系列回调，如 startElement()。<BR><BR>因为 XML 实质上是一种简单的文本，任何人都可以创建处理 XML 的 API。事实上，SAX 并不是由正式的组织创建的，而是由 XML-DEV 邮件列表的成员完成的。由松散组织创建的另一种 API 是 JDOM――它是基于对象的。JDOM 和 DOM 类似，但是和 Java 语言的联系更密切。<BR><BR><BR>4.使用的 XML 语言有哪些？&nbsp;&nbsp;<BR>&nbsp;&nbsp; XML 的优势在于它能够在多种环境中使用。大量涌现的各种 XML 词汇表，使人们能够立即互相理解。三种最常用的词汇表是可扩展超文本标记语言（Extensible HyperText Markup Language，XHTML）、资源定义框架（Resource Definition Framework，RDF）和可缩放向量图形（Scalable Vector Graphics，SVG）。<BR><BR>XHTML 是 XML 形式的 HTML 修订版。XHTML 文档就是遵守 XML 规则的 HTML 文档。同时，从业务和表示两方面定义了其他的 XML 词汇表：RDF 提供了一种向 XML 文档添加信息的方式；SVG 提供了一种使用 XML 指定图形元素的方式（因为 SVG 是基于文本的 XML，不仅可用于动态生成图形，还可用于动画和脚本）；语音可扩展标记语言（Voice Extensible Markup Language，Voice XML）则用于电话菜单和其他语音相关的系统。<BR><BR>大体上了解 XML 之后，使用特定的词汇表只需要理解它所包含的各种元素和属性，以及它所表示的含义。<BR><BR>5. XML 和 Web 服务的关系？&nbsp;&nbsp;<BR>XML 是构建 Web 服务的理想基础，因为它促进了易于标准化和易于理解的消息创建。<BR><BR>6.如何提高 XML 技能？&nbsp;&nbsp;<BR>一旦理解了使用 XML 的基础知识，您会发现有很多需要提高的地方，最好的办法就是慢慢进步。<BR><img src ="http://www.blogjava.net/fortune/aggbug/32832.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-28 13:35 <a href="http://www.blogjava.net/fortune/archive/2006/02/28/32832.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java国际化——资源包的使用</title><link>http://www.blogjava.net/fortune/archive/2006/02/27/32647.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Mon, 27 Feb 2006 06:51:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/27/32647.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/32647.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/27/32647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/32647.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/32647.html</trackback:ping><description><![CDATA[<H4>资源包</H4><BR>在编写应用<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>的时候，需要面对的一个问题是如何来处理与locale相关的一些信息。比如，页面上的一些静态文本就希望能够以用户习惯的语言显示。最原始的做法是将这些信息硬编码到<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>中（可能是一大串判断语句），但是这样就将<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>代码和易变的locale信息捆绑在一起，以后如果需要修改locale信息或者添加其它的locale信息，你就不得不重新修改代码。而资源包可以帮助你解决这个问题，它通过将可变的locale信息放入资源包中来达到两者分离的目的。应用<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>可以自动地通过当前的locale设置到相应的资源包中取得所要的信息。资源包的概念类似于<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>Windows</FONT></A>编程人员使用的资源文件</A>（rc文件</A>）。<BR><BR>一般来说，资源包需要完成两个功能：和具体的locale进行绑定以及读取locale相关信息。<BR><BR>
<H5>ResourceBundle类</H5><BR>你可以把资源包看作为一个由许多成员（子类）组成的大家庭，其中每个成员关联到不同的locale对象，那它是如何完成关联功能的呢？<BR><BR>资源包中的每个成员共享一个被称作基名（base&nbsp;name）的名称，然后在此基础上根据一定的命名规范进行扩展。下面就列出了一些成员的名称：<BR>&nbsp;&nbsp;&nbsp;&nbsp;LabelResources<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LabelResources_de<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LabelResources_de_CH<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LabelResources_de_CH_UNIX<BR>可见这些子类依据这样的命名规范：baseName_language_country_variant，其中language等几个变量就是你在构造Locale类时所使用的。而资源包正是通过这个符合命名规范的名称来和locale进行关联的，比如LabelResource_de_CH就对应于由德语（de）和瑞士（CH）组成的locale对象。<BR><BR>当你的应用<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>需要查找特定locale对象关联的资源包时，它可以调用ResourceBundle的getBundle方法，并将locale对象作为参数传入。<BR>
<DIV class=codeStyle>
<OL>
<LI>
<LI><FONT color=#ff0000>Locale</FONT>&nbsp;currentLocale&nbsp;=&nbsp;<B><FONT color=#0000ff>new</FONT></B>&nbsp;<FONT color=#ff0000>Locale</FONT>(<FONT color=#ff33ff>"de"</FONT>,&nbsp;<FONT color=#ff33ff>"CH"</FONT>,&nbsp;<FONT color=#ff33ff>"UNIX"</FONT>); 
<LI><FONT color=#ff0000>ResourceBundle</FONT>&nbsp;myResources&nbsp;= 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<FONT color=#ff0000>ResourceBundle</FONT>.getBundle(<FONT color=#ff33ff>"LabelResources"</FONT>,&nbsp;currentLocale);</LI></OL></DIV><BR>如果该locale对象匹配的资源包子类找不到，getBundle将试着查找最匹配的一个子类。具体的查找策略是这样的：getBundle使用基名，locale对象和缺省的locale来生成一个候选资源包名称序列。如果特定locale对象的语言代码、国家代码和可选变量都是空值，则基名是唯一的候选资源包名称。否则的话，具体locale对象（language1，country1和variant1）和缺省locale（language2，country2和variant2）将产生如下的序列：<BR>
<UL><BR>
<LI>baseName&nbsp;+&nbsp;"_"&nbsp;+&nbsp;language1&nbsp;+&nbsp;"_"&nbsp;+&nbsp;country1&nbsp;+&nbsp;"_"&nbsp;+&nbsp;variant1<BR>
<LI>baseName&nbsp;+&nbsp;"_"&nbsp;+&nbsp;language1&nbsp;+&nbsp;"_"&nbsp;+&nbsp;country1&nbsp;<BR>
<LI>baseName&nbsp;+&nbsp;"_"&nbsp;+&nbsp;language1&nbsp;<BR>
<LI>baseName&nbsp;+&nbsp;"_"&nbsp;+&nbsp;language2&nbsp;+&nbsp;"_"&nbsp;+&nbsp;country2&nbsp;+&nbsp;"_"&nbsp;+&nbsp;variant2&nbsp;<BR>
<LI>baseName&nbsp;+&nbsp;"_"&nbsp;+&nbsp;language2&nbsp;+&nbsp;"_"&nbsp;+&nbsp;country2&nbsp;<BR>
<LI>baseName&nbsp;+&nbsp;"_"&nbsp;+&nbsp;language2&nbsp;<BR>
<LI>baseName&nbsp;<BR></LI></UL><BR>然后，getBundle方法按照产生的序列依次查找匹配的资源包子类并对结果子类初始化。首先，它将寻找类名匹配候选资源包名称的类，如果找到将创建该类的一个实例，我们称之为结果资源包。否则，getBundle方法将寻找对应的资源文件</A>，它通过候选资源包名称来获得资源文件</A>的完整路径（将其中的“.”替换为“/”，并加上“.properties”后缀），如果找到匹配文件</A>，getBundle方法将利用该资源文件</A>来创建一个PropertyResourceBundle实例，也就是最终的结果资源包。与此同时，getBundle方法会将这些资源包实例缓存起来供以后使用。<BR><BR>如果没有找到结果资源包，该方法将抛出MissingResourceException异常。所以为了防止异常的抛出，一般来说都需要至少实现一个基名资源包子类。<BR><BR><B>注意：基名参数必须是一个完整的类名称（比如LabelResources，resource.LabelResources等），就相当于你引用一个类时需要指定完整的类路径。但是，为了和以前的版本保持兼容，在使用PropertyResourceBundles时也允许使用“/”来代替“.”表示路径。</B><BR><BR>比如你有以下这些资源类和资源文件</A>：MyResources.class，&nbsp;MyResources_fr_CH.properties，&nbsp;MyResources_fr_CH.class，&nbsp;MyResources_fr.properties，&nbsp;MyResources_en.properties，&nbsp;MyResources_es_ES.class。你利用以下的locale设置来调用getBundle方法，你将会得到不同的结果资源包（假设缺省locale为Locale(“en”,&nbsp;“UK”)），请参考表13.4。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;表13.4&nbsp;locale设置与结果资源包<BR>locale设置&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;结果资源包<BR>Locale("fr",&nbsp;"CH")&nbsp;&nbsp;&nbsp;&nbsp;MyResources_fr_CH.class<BR>Locale("fr",&nbsp;"FR")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyResources_fr.properties<BR>Locale("de",&nbsp;"DE")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyResources_en.properties<BR>Locale("en",&nbsp;"US")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyResources_en.properties<BR>Locale("es",&nbsp;"ES")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyResources_es_ES.class<BR><BR>创建了具体的资源包子类实例以后，就需要获得具体的信息。信息在资源包中是以键值对的方式存储的，表13.5列出的是LabelResources.properties文件</A>的内容。<BR><BR>表13.5&nbsp;LabelResources.properties<BR>
<DIV class=codeStyle>
<OL>
<LI>
<LI>#&nbsp;This&nbsp;is&nbsp;LabelResources.properties&nbsp;file 
<LI>greetings&nbsp;=&nbsp;您好！ 
<LI>farewell&nbsp;=&nbsp;再见。 
<LI>inquiry&nbsp;=&nbsp;您好吗？</LI></OL></DIV><BR>其中等号左边的字符</A>串表示主键，它们是唯一的。为了获得主键对应的值，你可以调用ResourceBundle类的getString方法，并将主键作为参数。此外，文件</A>中以“#”号开头的行表示注释行。<BR><BR>
<H5>ListResourceBundle和PropertyResourceBundle子类</H5><BR>抽象类ResourceBundle具有两个子类：ListResourceBundle和PropertyResourceBundle，它们表示资源包子类两种不同的实现方式。<BR><BR>PropertyResourceBundle是和资源文件</A>配对使用的，一个属性文件</A>就是一个普通的文本文件</A>，你只需要为不同的locale设置编写不同名称的资源文件</A>。但是，在资源文件</A>中只能包含字符</A>串，如果需要存储其它类型对象，你可以使用ListResourceBundle。<BR><BR>ListResourceBundle是将键值对信息保存在类中的列表中，而且你必须实现ListResourceBundle的具体子类。<BR><BR>如果ListResourceBundle和PropertyResourceBundle不能够满足你的需要，你可以实现自己的ResourceBundle子类，你的子类必须覆盖两个方法：handleGetObject和getKeys。<BR><BR>
<H5>使用资源文件</A></H5><BR>使用资源包最简单的方法就是利用资源文件</A>，利用资源文件</A>一般需要以下几个步骤：<BR>1、创建一个缺省的资源文件</A><BR>为了防止找不到资源文件</A>，你最好实现一个缺省的资源文件</A>，该文件</A>的名称为资源包的基名加上.properties后缀。<BR>2、创建所需的资源文件</A><BR>为你准备支持的locale设置编写对应的资源文件</A>。<BR>3、设置locale<BR>你必须在<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>中的某个地方提供locale的设置或者切换功能，或者将其放入配置文件</A>中。<BR>4、根据locale设置创建资源包<BR>ResourceBundle&nbsp;resource&nbsp;=<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ResourceBundle.getBundle("LabelBundle",currentLocale);<BR>5、通过资源包获取locale相关信息<BR>String&nbsp;value&nbsp;=&nbsp;resource.getString("welcome");<BR><BR><B>注意：在使用基名的时候，特别要注意给出完整的类名（或者路径名），比如你的应用<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>所在的类包为org.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>research.j2seimproved.i18n，而你的资源文件</A>在你的应用<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>下的resource子目录中，那你的基名就应该是org.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>research.j2seimproved.i18n.resource.LabelBundleBundle而不是resource.LabelBundleBundle。<BR></B><BR><BR>
<H5>使用ListResourceBundle</H5><BR>使用ListResourceBundle和使用资源文件</A>的步骤基本上一样，只不过你需要用ListResourceBundle子类来替换相应的资源文件</A>。比如你的应用<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>的基名是LabelBundle，而且准备支持Locale("en","US")和Locale("zh","CN")，那你需要提供以下几个<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>Java</FONT></A>文件</A>，注意类名和locale的对应关系。<BR>LabelBundle_en_US.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A><BR>LabelBundle_zh_CN.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A><BR>LabelBundle.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>（缺省类）<BR><BR>代码13.3列出的是LabelBundle_zh_CN.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>的源代码，相对于资源文件</A>中“key&nbsp;=&nbsp;value”的写法，在此文件</A>中你首先利用键值对来初始化一个二维数组，并在getContents方法中返回该数组。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>代码13.3：LabelBundle_zh_CN.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A><BR>
<DIV class=codeStyle>
<OL>
<LI><FONT color=#246398></FONT>
<LI><B><FONT color=#0000ff>package</FONT></B>&nbsp;org.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>research.j2seimproved.i18n;<B><FONT color=#0000ff>import</FONT></B>&nbsp; 
<LI>
<LI><A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>.util.<B><A class=wordstyle href="http://blog.cnbie.com/source/jdk142/<a%20target=" _blank?><FONT color=#246398>java</FONT></A></A>/util/ListResourceBundle.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>.html" target="_blank"&gt;<FONT class=classLink><U>ListResourceBundle</U></FONT></A></B>; 
<LI>
<LI><B><FONT color=#0000ff>public</FONT></B>&nbsp;<B><FONT color=#0000ff>class</FONT></B>&nbsp;LabelBundle_zh_CN&nbsp;<B><FONT color=#0000ff>extends</FONT></B>&nbsp;<FONT color=#ff0000>ListResourceBundle</FONT>&nbsp;{&nbsp;&nbsp;&nbsp; 
<LI>&nbsp;&nbsp;<B><FONT color=#0000ff>public</FONT></B>&nbsp;<B><A class=wordstyle href="http://blog.cnbie.com/source/jdk142/<a%20target=" _blank?><FONT color=#246398>java</FONT></A></A>/lang/Object.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>.html" target="_blank"&gt;<FONT class=classLink><U>Object</U></FONT></A></B>[][]&nbsp;getContents()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;<B><FONT color=#0000ff>return</FONT></B>&nbsp;contents;&nbsp;&nbsp;&nbsp; 
<LI>&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp; 
<LI>
<LI>&nbsp;&nbsp;<B><FONT color=#0000ff>private</FONT></B>&nbsp;<B><A class=wordstyle href="http://blog.cnbie.com/source/jdk142/<a%20target=" _blank?><FONT color=#246398>java</FONT></A></A>/lang/Object.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>.html" target="_blank"&gt;<FONT class=classLink><U>Object</U></FONT></A></B>[][]&nbsp;contents&nbsp;=&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;{<FONT color=#ff33ff>"title"</FONT>,&nbsp;<FONT color=#ff33ff>"称谓"</FONT>},&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;{<FONT color=#ff33ff>"surname"</FONT>,&nbsp;<FONT color=#ff33ff>"姓"</FONT>},&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;{<FONT color=#ff33ff>"firstname"</FONT>,&nbsp;<FONT color=#ff33ff>"名"</FONT>},&nbsp;&nbsp;&nbsp; 
<LI>&nbsp;&nbsp;}; 
<LI>}</LI></OL></DIV><BR><BR>创建完资源类以后，同样需要设置locale以及根据locale来创建资源包。在通过资源包获取具体值的时候，你不能再使用getString方法，而应该调用getObject方法，而且由于getObject方法返回一个Object对象，你还需要进行正确的类型转换。其实，为了你的<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>通用性，我们建议在使用资源文件</A>的时候你也应该调用getObject方法，而不是getString方法。<BR>
<DIV class=codeStyle>
<OL>
<LI>
<LI>&nbsp;&nbsp;&nbsp;&nbsp;<B><A class=wordstyle href="http://blog.cnbie.com/source/jdk142/<a%20target=" _blank?><FONT color=#246398>java</FONT></A></A>/lang/String.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>.html" target="_blank"&gt;<FONT class=classLink><U>String</U></FONT></A></B>&nbsp;title&nbsp;=&nbsp;(<B><A class=wordstyle href="http://blog.cnbie.com/source/jdk142/<a%20target=" _blank?><FONT color=#246398>java</FONT></A></A>/lang/String.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>.html" target="_blank"&gt;<FONT class=classLink><U>String</U></FONT></A></B>)resource.getObject(<FONT color=#ff33ff>"title"</FONT>);</LI></OL></DIV><BR>关于ListResourceBundle的详细使用，可以参考本书所附代码中国际化一节的ListResourceBundleSample.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A><A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>。<BR><BR>
<H5>MessageFormat类</H5><BR>上面我们讲到利用资源文件</A>来分离代码和可变的信息。但是在实际过程中，有些信息并不能够完全事先定义好，其中可能会用到运行时的一些结果，最典型例子的就是错误提示代码，比如提示某个输入必须在一定范围内。利用上面所讲的资源文件</A>并不能够很好地解决这个问题，所以<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>Java</FONT></A>中引入了MessageFormat类。<BR><BR>MessageFormat提供一种语言无关的方式来组装消息，它允许你在运行时刻用指定的参数来替换掉消息字符</A>串中的一部分。你可以为MessageFormat定义一个模式，在其中你可以用占位符来表示变化的部分，比如你有这样一句话：<BR><BR>您好，<U>peachpi</U>！欢迎来到<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>Java</FONT></A>研究组织网站！当前时间是：<U>2003-8-1&nbsp;16:43:12。</U><BR><BR>其中斜体带下划线的部分为可变化的，你需要根据当前时间和不同的登录用户来决定最终的显示。我们用占位符来表示这些变化的部分，可以得到下面这个模式：<BR><BR>您好，{0}！欢迎来到<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>Java</FONT></A>研究组织网站！当前时间是：{1,date}&nbsp;{1,time}。<BR><BR>占位符的格式为{&nbsp;ArgumentIndex&nbsp;,&nbsp;FormatType&nbsp;,&nbsp;FormatStyle&nbsp;}，详细说明可以参考MessageFormat的API说明文档。这里我们定义了两个占位符，其中的数字对应于传入的参数数组中的索引，{0}占位符被第一个参数替换，{1}占位符被第二个参数替换，依此类推。<BR>最多可以设置10个占位符，而且每个占位符可以重复出现多次，而且格式可以不同，比如{1,date}和{1,time}。而通过将这些模式定义放到不同的资源文件</A>中，就能够根据不同的locale设置，得到不同的模式定义，并用参数动态替换占位符。<BR><BR>下面我们就以MessageFormatSample.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A><A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>程序</FONT></A></A>（源文件</A>见本书所附代码）为例，来详细说明其中的每个步骤。<BR>1、找出可变的部分，并据此定义模式，将模式放入不同的资源文件</A>中。<BR>比如针对上面的模式，定义了下面两个资源文件</A>：<BR>MessagesBundle_en_US.properties<BR>Welcome&nbsp;=&nbsp;Hi,&nbsp;{0}!&nbsp;Welcome&nbsp;to&nbsp;<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>Java</FONT></A>&nbsp;Research&nbsp;Organization!<BR>MessagesBundle_zh_CN.properties<BR>Welcome&nbsp;=&nbsp;您好，{0}！欢迎来到<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>Java</FONT></A>研究组织网站！<BR><BR>2、创建MessageFormat对象，并设置其locale属性。<BR>
<DIV class=codeStyle>
<OL>
<LI>
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<FONT color=#ff0000>MessageFormat</FONT>&nbsp;formatter&nbsp;=&nbsp;<B><FONT color=#0000ff>new</FONT></B>&nbsp;<FONT color=#ff0000>MessageFormat</FONT>(<FONT color=#ff33ff>""</FONT>); 
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formatter.setLocale(currentLocale);</LI></OL></DIV><BR>3、从资源包中得到模式定义，以及设置参数。<BR>
<DIV class=codeStyle>
<OL>
<LI>
<LI>messages&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<FONT color=#ff0000>ResourceBundle</FONT>.getBundle( 
<LI>&nbsp;&nbsp;<FONT color=#ff33ff>"org.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>research.j2seimproved.i18n.resource.MessagesBundle"</FONT>,currentLocale); 
<LI><B><A class=wordstyle href="http://blog.cnbie.com/source/jdk142/<a%20target=" _blank?><FONT color=#246398>java</FONT></A></A>/lang/Object.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>.html" target="_blank"&gt;<FONT class=classLink><U>Object</U></FONT></A></B>[]&nbsp;testArgs&nbsp;=&nbsp;{<FONT color=#ff33ff>"peachpi"</FONT>,<B><FONT color=#0000ff>new</FONT></B>&nbsp;<FONT color=#ff0000>Date</FONT>()};</LI></OL></DIV><BR>4、利用模式定义和参数进行格式化。<BR>
<DIV class=codeStyle>
<OL>
<LI>
<LI>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<B><A class=wordstyle href="http://blog.cnbie.com/source/jdk142/<a%20target=" _blank?><FONT color=#246398>java</FONT></A></A>/lang/System.<A class=wordstyle href="http://www.itlove.net/" target=_blank><FONT color=#246398>java</FONT></A></A>.html" target="_blank"&gt;<FONT class=classLink><U>System</U></FONT></A></B>.out.println(formatter.format(messages.getString(<FONT color=#ff33ff>"welcome"</FONT>),testArgs));</LI></OL></DIV><BR><BR>
<H5>关于资源包的组织</H5><BR>一般来说，你是按照资源的用途来组织资源包的，比如会把所有的页面按钮的信息放入一个名为ButtonResources的资源包中。在实际的应用过程中，以下几个原则可以帮你决定如何组织资源包：<BR>1、要易于维护。<BR>2、最好不要将所有的信息都放入一个资源包中，因为这样资源包载入内存时将会很耗时。<BR>3、最好将一个大的资源包分为几个小的资源包，这样可以在使用的时候才导入必须的资源，减少内存消耗。<BR><img src ="http://www.blogjava.net/fortune/aggbug/32647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-27 14:51 <a href="http://www.blogjava.net/fortune/archive/2006/02/27/32647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 关于线程的停止问题</title><link>http://www.blogjava.net/fortune/archive/2006/02/27/32641.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Mon, 27 Feb 2006 06:45:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/27/32641.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/32641.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/27/32641.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/32641.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/32641.html</trackback:ping><description><![CDATA[多线程是<A class=wordstyle href="http://www.itlove.net/" target=_blank>java</A></A>的一个优势，<A class=wordstyle href="http://www.itlove.net/" target=_blank>java</A></A>使得<A class=wordstyle href="http://www.itlove.net/" target=_blank>程序</A></A>员可以很方便的进行多线程<A class=wordstyle href="http://www.itlove.net/" target=_blank>程序</A></A><A class=wordstyle href="http://www.itlove.net/" target=_blank>开发</A>。获得更好的性能。<BR>关于多线程的概念以及一般的多线程编程，比如如何以及为何实现runnable接口，为何stop()会被Deprecated掉等等，这个请看matrix之前的多线程编程基础或者sun的<A class=wordstyle href="http://www.itlove.net/" target=_blank>java</A></A>文档。<BR>关于多线程编程，有几点这里要提到的：<BR>1。既然stop()是不被推荐的，那么我们如何停止一个线程呢？直接kill吗？在这里，笔者总结一种比较通用也比较稳定的方法：<BR><BR>class threadtest extend Thread{<BR>//skip some code..<BR><BR><BR>boolean runflag=true; <BR><BR>public synchronized void stopthread()<BR>{<BR>runflag=false; <BR>}<BR><BR>public synchronized boolean getrunflag()<BR>{<BR>return runflag; <BR>} <BR><BR>public void run() {<BR>runflag=true;<BR>try {<BR>while (getrunflag()) {<BR>code1；<BR>code2； <BR>//put your code here<BR>}<BR>}<BR>}<BR>catch (IOException e) {<BR>e.printStackTrace();<BR>}<BR>System.out.println(this.getClass().getName()+" stopped");<BR>}<BR><BR>//skip some code..<BR>} <BR><BR><BR>这样，每当需要停止该线程时，只需调用stopthread()即可。<BR><BR>这里有两点需要注意：<BR><BR>1）我们用了一个同步方法getrunflag()来得到当前的状态，为什么用这个方法而不是直接使用while(runflag)呢？<BR>这个是因为在<A class=wordstyle href="http://www.itlove.net/" target=_blank>java</A></A>的多线程模型中，有一个公共的对象存储区，但是每个对象都有自己的私有备份，当一个线程改变了状态，jvm并不能保证这个线程改变过的变量即时更新公共对象存储区的状态，可能(可能性不大)造成问题。<BR>所以建议有好的设计习惯，采用同步方法来获得当前的runflag值。<BR><BR>2）还有一点，特别是涉及<A class=wordstyle href="http://www.itlove.net/" target=_blank>网络</A></A>的多线程，如果发生了<A class=wordstyle href="http://www.itlove.net/" target=_blank>网络</A></A>阻塞(在while循环里面发生)，那么，即使runflag状态比如改变成false，由于<A class=wordstyle href="http://www.itlove.net/" target=_blank>程序</A></A>被阻塞，线程用这种方法是永远都不会被停止的。<BR>举个例子：比如上面的<A class=wordstyle href="http://www.itlove.net/" target=_blank>程序</A></A>，如果code1是一段<A class=wordstyle href="http://www.itlove.net/" target=_blank>网络</A></A>程式，如果在code1发生了阻塞，阻塞的意义就是得不到请求的<BR>资源，在无限期等待，这个时候，runflag状态的变化对while循环是起不了作用的，线程不会被停止。<BR>笔者曾经参与多个涉及到获取<A class=wordstyle href="http://www.itlove.net/" target=_blank>网络</A></A>资源的<A class=wordstyle href="http://www.itlove.net/" target=_blank>java</A></A>程式，经常遇到因为<A class=wordstyle href="http://www.itlove.net/" target=_blank>网络</A></A>的阻塞引起的线程问题。<BR>如果你的程式可能涉及到<A class=wordstyle href="http://www.itlove.net/" target=_blank>网络</A></A>阻塞，或者有可能发生某种消息接受的阻塞。那么，请不要用这种方法来停止线程。具体方法请看笔者另外一片文章：高级多线程编程(二)-多线程中的监控与超时问题。<BR><img src ="http://www.blogjava.net/fortune/aggbug/32641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-27 14:45 <a href="http://www.blogjava.net/fortune/archive/2006/02/27/32641.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java图形用户界面设计（转</title><link>http://www.blogjava.net/fortune/archive/2006/02/24/32312.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Fri, 24 Feb 2006 09:26:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/24/32312.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/32312.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/24/32312.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/32312.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/32312.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD width="100%">
<H1>&nbsp;</H1>
<P id=subtitle>深入了解布局管理器</P><IMG class=display-img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=1></TD>
<TD class=no-print width=192><IMG height=18 alt=developerWorks src="http://www-128.ibm.com/developerworks/i/dw.gif" width=192></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR vAlign=top>
<TD width=10><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></TD>
<TD width="100%">
<TABLE class=no-print cellSpacing=0 cellPadding=0 width=160 align=right border=0>
<TBODY>
<TR>
<TD width=10><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></TD>
<TD>
<TABLE cellSpacing=0 cellPadding=0 width=150 border=0>
<TBODY>
<TR>
<TD class=v14-header-1-small></TD></TR></TBODY></TABLE>
<TABLE class=v14-gray-table-border cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=no-padding width=150>
<TABLE cellSpacing=0 cellPadding=0 width=143 border=0><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8> 
<FORM name=email action=https://www-130.ibm.com/developerworks/secure/email-it.jsp>
<SCRIPT language=JavaScript type=text/javascript>
<!--
document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt=""/></td><td width="16"><img src="//www.ibm.com/i/v14/icons/em.gif" height="16" width="16" vspace="3" alt="将此页作为电子邮件发送" /></td><td width="122"><p><a class="smallplainlink" href="javascript:document.email.submit();"><b>将此页作为电子邮件发送</b></a></p></td></tr>');
//-->
</SCRIPT>
&nbsp; 
<TBODY>
<TR vAlign=top>
<TD width=8><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8></TD>
<TD width=16></TD>
<TD width=122>
<P><A class=smallplainlink href="javascript:document.email.submit();"><B><FONT color=#5c81a7 size=2>将此页作为电子邮件送</FONT></B></A></P></TD></TR><NOSCRIPT><tr valign="top"><td width="8"><img alt="" height="1" width="8" src="//www.ibm.com/i/c.gif"/></td><td width="16"><img alt="" width="16" height="16" src="//www.ibm.com/i/c.gif"/></td><td class="small" width="122"><p><span class="ast">未显示需要 JavaScript 的文档选项</span></p></td></tr></NOSCRIPT></FORM></TBODY></TABLE></TD></TR></TBODY></TABLE><BR>
<TABLE cellSpacing=0 cellPadding=0 width=150 border=0>
<TBODY>
<TR>
<TD class=v14-header-1-small>对此页的评价</TD></TR></TBODY></TABLE>
<TABLE class=v14-gray-table-border cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=no-padding width=150>
<TABLE cellSpacing=0 cellPadding=0 width=143 border=0>
<TBODY>
<TR vAlign=top>
<TD width=8><IMG height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8></TD>
<TD><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/d_bold.gif" width=16 vspace=3 border=0></TD>
<TD width=125>
<P><A class=smallplainlink href="http://www-128.ibm.com/developerworks/cn/java/l-javagui/index.html#rate"><B><FONT color=#996699 size=2>帮助我们改进这些内容</FONT></B></A></P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR></TD></TR></TBODY></TABLE>
<P>2002 年 7 月 05 日</P>
<BLOCKQUOTE>本文试图通过作者自己的开发经历介绍一些具体的应用实例，希望能给那些曾经象作者一样苦闷的Java痴迷者一些帮助。</BLOCKQUOTE>
<P><A name=1><SPAN class=atitle><FONT face=Arial size=4>前言</FONT></SPAN></A></P>
<P><FONT face=Arial size=4></FONT>
<P>随着Internet的飞速发展，Java技术也得到了越来越广泛的应用。而无论我们是采用J2SE、J2EE还是J2ME，GUI都是不能回避的问题。现在的应用软件越来越要求界面友好、功能强大而又使用简单。而众所周知，在Java中进行GUI设计相对于其跨平台、多线程等特性的实现要复杂和麻烦许多。这也是很多Java程序员抱怨的事情。但GUI已经成为程序发展的方向，所以我们也必须了解Java的GUI设计方法和特点。其实，采用Java提供的布局管理器接口和相应的布局管理类，我们也可以做出相当漂亮的界面来，当然实现起来肯定要比VB麻烦许多。本文试图通过自己的开发经历介绍一些具体的应用实例，希望能给那些曾经象我一样苦闷的Java痴迷者一些帮助。</P><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/l-javagui/index.html#main"><B><FONT color=#996699>回页首</FONT></B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=2><SPAN class=atitle><FONT face=Arial size=4>Java中的布局管理器</FONT></SPAN></A></P>
<P><FONT face=Arial size=4></FONT>
<P><A name=N1004E><SPAN class=smalltitle><STRONG><FONT face=Arial>2.1 为什么要使用布局</FONT></STRONG></SPAN></A></P>
<P><STRONG><FONT face=Arial></FONT></STRONG>
<P>在实际编程中，我们每设计一个窗体，都要往其中添加若干组件。为了管理好这些组件的布局，我们就需要使用布局管理器。比如说，设计一个简单的计算器，或一个文本编辑器等等。这些组件是让JVM 自己任意安排呢？还是按照一定的位置关系进行规范的安排呢？当然应该选择后者。将加入到容器的组件按照一定的顺序和规则放置，使之看起来更美观，这就是布局。在Java中，布局由布局管理器 (LayoutManager) 来管理。那么，我们在什么时候应该使用布局管理器？应选择哪种布局管理器？又该怎样使用布局管理器呢？</P>
<P>如果你写的是GUI程序，在使用AWT/Swing组件时就不应硬性设置组件的大小和位置，而应该使用Java的布局管理器（LayoutManager）来设置和管理可视组件的大小和位置，否则就有可能造成布局混乱。不信，你可以新建一个Frame（或JFrame），通过setBounds()方法往其中添加几个Button（或JButton），一旦你将窗体拉大或缩小时，你会发现组件的排列完全不是按你所预想的那样。为了解决这个问题，即当窗体（或容器）缩放时，组件位置也随之合理调整，我们就需要使用布局管理器。</P>
<P>为此，我们首先要知道Java的布局方式，Java提供的API中有些什么布局管理器，它们的布局特点是什么。</P>
<P><A name=N1005F><SPAN class=smalltitle><STRONG><FONT face=Arial>2.2 Java的布局方式</FONT></STRONG></SPAN></A></P>
<P><STRONG><FONT face=Arial></FONT></STRONG>
<P>我们都知道，Java的GUI界面定义是由AWT类包和Swing类包来完成的。它在布局管理上采用了容器和布局管理分离的方案。也就是说，容器只管将其他组件放入其中，而不管这些组件是如何放置的。对于布局的管理交给专门的布局管理器类（LayoutManager）来完成。</P>
<P>现在我们来看Java中布局管理器的具体实现。我们前面说过，Java中的容器类（Container），它们只管加入组件（Component），也就是说，它只使用自己的add()方法向自己内部加入组件。同时他记录这些加入其内部的组件的个数，可以通过container.getComponentCount()方法类获得组件的数目，通过container.getComponent(i)来获得相应组件的句柄。然后LayoutManager类就可以通过这些信息来实际布局其中的组件了。</P>
<P>Java已经为我们提供了几个常用的布局管理器类，例如： FlowLayout、BorderLayout、GridLayout、GridBagLayout等。下面列表说明它们的布局特点：</P>
<TABLE width="60%" border=1>
<TBODY>
<TR>
<TD>包</TD>
<TD>类</TD>
<TD>特点</TD></TR>
<TR>
<TD>java.awt</TD>
<TD>CardLayout</TD>
<TD>将组件象卡片一样放置在容器中，在某一时刻只有一个组件可见</TD></TR>
<TR>
<TD>java.awt</TD>
<TD>FlowLayout</TD>
<TD>将组件按从左到右而后从上到下的顺序依次排列，一行不能放完则折到下一行继续放置</TD></TR>
<TR>
<TD>java.awt</TD>
<TD>GridLayout</TD>
<TD>形似一个无框线的表格，每个单元格中放一个组件</TD></TR>
<TR>
<TD>java.awt</TD>
<TD>BorderLayout</TD>
<TD>将组件按东、南、西、北、中五个区域放置，每个方向最多只能放置一个组件</TD></TR>
<TR>
<TD>java.awt</TD>
<TD>GridBagLayout</TD>
<TD>非常灵活，可指定组件放置的具体位置及占用单元格数目</TD></TR>
<TR>
<TD>Javax.swing</TD>
<TD>BoxLayout</TD>
<TD>就像整齐放置的一行或者一列盒子，每个盒子中一个组件</TD></TR>
<TR>
<TD>Javax.swing</TD>
<TD>SpringLayout</TD>
<TD>根据一组约束条件放置子组件</TD></TR>
<TR>
<TD>Javax.swing</TD>
<TD>ScrollPaneLayout</TD>
<TD>专用于JScrollPane，含一个Viewport，一个行头、一个列头、两个滚动条和四个角组件</TD></TR>
<TR>
<TD>Javax.swing</TD>
<TD>OverlayLayout</TD>
<TD>以彼此覆盖的形式叠置组件</TD></TR>
<TR>
<TD>Javax.swing</TD>
<TD>ViewportLayout</TD>
<TD>JViewport的默认布局管理器</TD></TR></TBODY></TABLE>
<P>事实上，在大多数情况下，综合运用好这些布局管理器已可以满足需要。当然对于特殊的具体应用，我们可以通过实现LayoutManager或LayoutManager2接口来定义自己的布局管理器。下面我们通过几个实例来了解几个常用的布局管理器的使用方法。</P><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/l-javagui/index.html#main"><B><FONT color=#996699>回页首</FONT></B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=3><SPAN class=atitle><FONT face=Arial size=4>GUI设计应用实例</FONT></SPAN></A></P>
<P><FONT face=Arial size=4></FONT>
<P><A name=N10104><SPAN class=smalltitle><STRONG><FONT face=Arial>3.1 FlowLayout/GridLayout/BorderLayout的应用实例</FONT></STRONG></SPAN></A></P>
<P><STRONG><FONT face=Arial></FONT></STRONG>
<P><STRONG>3.1.1应用背景</STRONG> </P>
<P>假设我们要编写一个简单的计算器JApplet，其基本界面如下：</P><BR><A name=N10117><B></A><BR><IMG height=295 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-javagui/1.gif" width=420> <BR>
<P><B>3.1.2解决方法</B> </P>
<P>通过其界面要求可知，我们可以通过将"BackSpace"和"Clear"JButton放置在一个JPanel（1）中，采用FlowLayout布局；将显示结果的JTextField和该JPanel一起放置到另外一个JPanel（2），采用GridLayout布局；而将其它的JButton则放置在另外一个JPanel（3）中，采用GridLayout布局；再将JPanel（2）和JPanel（3）加入该JApplet，即可实现界面需求。具体实现方法如下：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console">/**以FlowLayout布局JPanel（1）*/
JPanel p1 = new JPanel(new FlowLayout()); //默认组件从居中开始
//加入"BackSpace"和"Clear"JButton
p1.add(backButton);    
p1.add(clearButton);
/**以GridLayout布局JPanel（2）*/
JPanel p2 = new JPanel(new GridLayout(2, 1));   //放置2行，每行1个组件
//加入显示结果的JTextField和JPanel（1）
p2.add(displayField);  
p2.add(p1);
/**以GridLayout布局JPanel（3）*/
JPanel p3 = new JPanel(new GridLayout(4, 5));   //放置4行，每行5个组件
String buttonStr = "789/A456*B123-C0.D+=";
for (int i = 0; i &lt; buttonStr.length(); i++)
this.addButton(p3, buttonStr.substring(i, i + 1));
	
//addButton方法
	private void addButton(Container c, String s)
    {
        JButton b = new JButton(s);
        if (s.equals("A"))
            b.setText("sqrt");
        else if (s.equals("B"))
            b.setText("1/x");
        else if (s.equals("C"))
            b.setText("%");
        else if (s.equals("D"))
            b.setText("+/-");
        b.setForeground(Color.blue);
        c.add(b);
        b.addActionListener(this);
    }
/**以BorderLayout布局JApplet*/
	this.setLayout(new BorderLayout());
this.add(p2, "North");
this.add(p3, "Center");
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>这样，就一切OK啦。具体的实现代码可参见附件中的CalculateApplet.java文件。</P>
<P><A name=N10133><SPAN class=smalltitle><FONT face=Arial>3.2 带工具栏和状态栏的GridLayout/BorderLayout应用实例</FONT></SPAN></A></P>
<P><FONT face=Arial></FONT>
<P><B>3.2.1实际问题</B> </P>
<P>在很多情况下我们需要动态设置工具栏和状态栏，看下面的应用实例：</P><BR><A name=N10146><B></A><BR><IMG height=406 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-javagui/2.gif" width=470> <BR>
<P>以上是在视图的工具栏和状态栏都被复选的时候，以下分别为某一个没选或都未选的情况。</P><BR><A name=N10157><B></A><BR><IMG height=370 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-javagui/3.gif" width=470> <BR>
<P><B>3.2.2解决方法</B> </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console">	/**工具栏JToolBar采用从左开始的FlowLayout布局*/
JToolBar toolBar = new JToolBar();	
toolBar.setBorderPainted(false); //不画边界
    toolBar.setLayout(new FlowLayout(FlowLayout.LEFT));
	
/**窗体采用动态的BorderLayout布局，通过获取工具栏或状态栏的复选标记进行界面的动态调整*/
JSplitPane splitPane = new JSplitPane();
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); //设置统计窗口分隔条的方向
splitPane.setDividerLocation(300); 	//设置分隔条的位置
splitPane.setOneTouchExpandable(true);
JCheckBoxMenuItem toolBarItem = new JCheckBoxMenuItem("工具栏(T)", true);
    JLabel statusLabel = new JLabel("当前统计目标:");
    JCheckBoxMenuItem statusBarItem = new JCheckBoxMenuItem("状态栏(S)", true);

/**设置系统窗体布局并动态设置工具栏和状态栏*/
    private void setLayout()
    {
        if (toolBarItem.getState() &amp;&amp;' statusBarItem.getState())
        {
            this.getContentPane().add(BorderLayout.NORTH, toolBar);
            this.getContentPane().add(BorderLayout.CENTER, splitPane);
            this.getContentPane().add(BorderLayout.SOUTH, statusLabel);
        }
        else if (toolBarItem.getState() &amp;&amp; !statusBarItem.getState())
        {
            this.getContentPane().add(BorderLayout.NORTH, toolBar);
            this.getContentPane().remove(statusLabel);
        }
        else if (statusBarItem.getState() &amp;&amp; !toolBarItem.getState())
        {
            this.getContentPane().add(BorderLayout.SOUTH, statusLabel);
            this.getContentPane().remove(toolBar);
        }
        else if (!toolBarItem.getState() &amp;&amp; !statusBarItem.getState())
        {
            this.getContentPane().remove(toolBar);
            this.getContentPane().remove(statusLabel);
        }
        this.show(); //添加或移去组件后刷新界面
    }
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>通过该方法即可实现界面的动态刷新与调整。</P>
<P><A name=N10170><SPAN class=smalltitle><FONT face=Arial>3.3 GridBagLayout应用实例</FONT></SPAN></A></P>
<P><FONT face=Arial></FONT>
<P><B>3.3.1实际问题</B> </P>
<P>GridBagLayout是Java API提供的一个较复杂的布局管理器，利用好它可以解决许多实际编程中的令人烦恼的界面设计问题。看下面的界面应用实例：</P><BR><A name=N10183><B></A><BR><IMG height=359 alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-javagui/5.gif" width=602> <BR>
<P><B>3.3.2解决方法</B> </P>
<P>这个界面的设计比较复杂，涉及多个标签域（JLabel）、文本域（JTextField、JTextArea），且标签域的大小还不一样，如附件标签；并当窗体缩放时，标签域的大小应不改变，而文本域则必须自适应缩放。如何来实现呢？请看下面的代码：（工具栏的实现不再赘述）</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console">/**系统的界面布局实现*/
GridBagConstraints gridBag = new GridBagConstraints();
gridBag.fill = GridBagConstraints.HORIZONTAL;  //以水平填充方式布局
    gridBag.weightx = 0;  //行长不变
    gridBag.weighty = 0;  //列高不变
    fromLabel.setForeground(Color.blue);
    fromLabel.setFont(new Font("Alias", Font.BOLD, 16));
    this.add(fromLabel, gridBag, 0, 1, 1, 1);  //指定发信人标签位置
    receiveLabel.setForeground(Color.blue);
    receiveLabel.setFont(new Font("Alias", Font.BOLD, 16));
    this.add(receiveLabel, gridBag, 0, 2, 1, 1); //指定收信人标签位置及大小
    ccLabel.setForeground(Color.blue);
    ccLabel.setFont(new Font("Alias", Font.BOLD, 16));
    this.add(ccLabel, gridBag, 0, 3, 1, 1); //指定抄送人标签位置及大小
    subjectLabel.setForeground(Color.blue);
    subjectLabel.setFont(new Font("Alias", Font.BOLD, 16));
    his.add(subjectLabel, gridBag, 0, 4, 1, 1); //指定主题标签位置及大小
    accessoryLabel.setForeground(Color.blue);
    accessoryLabel.setFont(new Font("Alias", Font.BOLD, 16));
    this.add(accessoryLabel, gridBag, 0, 5, 1, 1); //指定附件标签位置及大小

    gridBag.weightx = 100; //行自适应缩放
    gridBag.weighty = 0;//列高不变
    fromField.setText("admin@watermelon.com");
   	this.add(fromField, gridBag, 1, 1, 2, 1); //指定发信人文本域（JTextField）位置及大小
    this.add(receiveField, gridBag, 1, 2, 2, 1); //指定收信人文本域（JTextField）位置及大小
    this.add(ccField, gridBag, 1, 3, 2, 1); //指定抄送人文本域（JTextField）位置及大小
    this.add(subjectField, gridBag, 1, 4, 2, 1); //指定主题文本域（JTextField）位置及大小
    accessoryArea.setEditable(false); 
//设置不显示水平滚动条（该JTextArea置于JScrollPane中）
accessoryScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    this.add(accessoryScroll, gridBag, 1, 5, 2, 1); //指定附件文本区（JTextArea）位置及大小

    gridBag.fill = GridBagConstraints.BOTH;//采用全填充方式布局
    gridBag.weightx = 100;//行自适应缩放
    gridBag.weighty = 100;//列自适应缩放
    mailArea.setBackground(Color.blue);
    mailArea.setForeground(Color.yellow);
    mailArea.setTabSize(4);
    //指定信件主体区（JTextArea）的位置及大小。（该JTextArea也置于JScrollPane中）
	this.add(scroll, gridBag, 0, 6, 3, 1);

	在上面用到一个方法add()，这个方法是自己定义的：
private void add(Component c, GridBagConstraints gbc, int x, int y, int w, int h)
    {
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.gridheight = h;
        gbc.gridwidth = w;
        this.getContentPane().add(c, gbc);
    }
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR>
<P>在用到GridBagLayout布局管理器的组件添加方法中，都可以重用它。事实上，你还可以在方法最前面加一个参数Container cn，而将方法中的this相应的改为cn，就可以通用于所有需要使用GridBagLayout进行布局管理的容器中。在下面的复杂例程中我们就会用到。</P>
<P><A name=N1019F><SPAN class=smalltitle><FONT face=Arial>3.4 综合多个布局的复杂应用实例</FONT></SPAN></A></P>
<P><FONT face=Arial></FONT>
<P><B>3.4.1实际问题</B> </P>
<P>请看下面的实际应用界面要求：</P><BR><A name=N101B2><B>（图3.4-1）</B></A><BR><IMG height=310 alt=图3.4-1 src="http://www-128.ibm.com/developerworks/cn/java/l-javagui/6.gif" width=495> <BR><BR><A name=N101C1><B>（图3.4-2）</B></A><BR><IMG height=310 alt=图3.4-2 src="http://www-128.ibm.com/developerworks/cn/java/l-javagui/7.gif" width=495> <BR><BR><A name=N101D0><B>（图3.4-3）</B></A><BR><IMG height=310 alt=图3.4-3 src="http://www-128.ibm.com/developerworks/cn/java/l-javagui/8.gif" width=496> <BR>
<P>在这个具体应用中，底部的JButton组是确定的，但JTabbedPane的每一个选项都不同，如何实现呢？</P>
<P><B>3.4.2解决方案</B> </P>
<P>首先我们可以采用BorderLayout确定主题对话框的布局方式，实现方法如下：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE class=section>
<FONT face="Lucida Console">JTabbedPane dbTabPane = new JTabbedPane();
…… //下面需要用到的JButton等组件变量定义（或声明）
private void initLayout()
{
initDBTabPane();//初始化JTabbedPane:DBTabPane组件
    this.getContentPane().add(BorderLayout.CENTER, dbTabPane);
	//将JTabbedPane组件：dbTabPane布局于JDialog对话框的中间
        initButtonPanel();//初始化JPanel:ButtonPanel组件
        this.getContentPane().add(BorderLayout.SOUTH, buttonPanel);
	//将JPanel组件：buttonPanel布局于JDialog对话框的底部（南面）
    }

private void initDBTabPane()
{
        JPanel loginPanel = new JPanel(new GridLayout(10, 1));
//为保证两个JCheckBox组件位于顶端，设置为共10行，每行一个组件的布局，但只
//放置界面要求的两个组件，这样就保持了界面的美观，否则如定义为
//Gridlayout(2,1)则会使两个组件居中，而且中间会隔开较长的距离。
pwdBox.setMnemonic('P');
        loginPanel.add(pwdBox);
        dspBox.setMnemonic('D');
        loginPanel.add(dspBox);
        dbTabPane.add("Login", loginPanel); //设置"Login"JPanel（图3.4-1）的布局
        needRadio.setMnemonic('N');
        allRadio.setMnemonic('A');
        cacheRadio.setMnemonic('U');
        radioPanel.setBorder(new TitledBorder("Load Option"));//加上边界标题
        radioPanel.add(needRadio);
        radioPanel.add(allRadio);
        radioPanel.add(cacheRadio);
//以上为加入需要的JRadioButton组件到指定的JPanel: radioPanel
        queryPanel.add(radioPanel);//加入含JRadioButton组的JPanel到queryPanel
        reqBox.setMnemonic('R');
        boxPanel.add(reqBox);
        saveBox.setMnemonic('S');
        boxPanel.add(saveBox);
        autoBox.setMnemonic('t');
        boxPanel.add(autoBox);
//以上为加入需要的JCheckBox组到指定的JPanel：boxPanel
        queryPanel.add(boxPanel); //加入含JCheckBox组的JPanel到queryPanel
        dbTabPane.add("Query", queryPanel);//设置"Query"JPanel（图3.4-2）的布局
        initDrvPanel();
    }

/**设置"Drivers"JPanel（图3.4-3）的布局*/
private void initDrvPanel()
{
        gridBag.fill = GridBagConstraints.HORIZONTAL;
        gridBag.weightx = 100;
        gridBag.weighty = 0;
        tipLabel.setForeground(Color.black);
        this.add(drvPanel, tipLabel, gridBag, 0, 0, 4, 1);
        urlLabel.setForeground(Color.black);
        this.add(drvPanel, urlLabel, gridBag, 0, 5, 4, 1);
        urlField.setEditable(false);
        this.add(drvPanel, urlField, gridBag, 0, 6, 4, 1);
        gridBag.weightx = 0;
        gridBag.weighty = 0;
        addButton.setMnemonic('A');
        this.add(drvPanel, addButton, gridBag, 3, 1, 1, 1);
        editButton.setMnemonic('E');
        this.add(drvPanel, editButton, gridBag, 3, 2, 1, 1);
        removeButton.setMnemonic('R');
        this.add(drvPanel, removeButton, gridBag, 3, 3, 1, 1);
        gridBag.fill = GridBagConstraints.BOTH;
        gridBag.weightx = 100;
        gridBag.weighty = 100;
       	//设置JTable组件：drvTable的从0到7行第0列的值
for (int i = 0; i &lt; 8; i++)
       		drvTable.setValueAt(drvStrs[i],i,0); 
//设置JTable的列头
drvTable.getColumn(drvTable.getColumnName(0)).setHeaderValue("All Drivers");
        drvTable.setShowGrid(false);//设置不显示网格线
        this.add(drvPanel, drvScroll, gridBag, 0, 1, 3, 4);
        dbTabPane.add("Drivers", drvPanel);
   }

/**初始化底部JButton组的布局*/
private void initButtonPanel()
    {
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
//从右边开始进行FlowLayout布局
okButton.setMnemonic('O');
        buttonPanel.add(okButton);
        cancelButton.setMnemonic('C');
        buttonPanel.add(cancelButton);
        helpButton.setMnemonic('H');
        buttonPanel.add(helpButton);
    }

/**给指定的容器cn在指定的（x,y）位置放置指定大小（宽度=w,高度=h）的组件c*/
private void add(Container cn, Component c, GridBagConstraints gbc, int x, int y, int w, int h)
{
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.gridwidth = w;
        gbc.gridheight = h;
        cn.add(c, gbc);
    }
</FONT></CODE></PRE></TD></TR></TBODY></TABLE><BR><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><FONT face="Lucida Console"><IMG height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"></FONT></TD></TR></TBODY></TABLE>
<TABLE class=no-print cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD vAlign=center><FONT face="Lucida Console"><IMG height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><BR></FONT></TD>
<TD vAlign=top align=right><A class=fbox href="http://www-128.ibm.com/developerworks/cn/java/l-javagui/index.html#main"><B><FONT color=#996699>回页首</FONT></B></A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<P><A name=4><SPAN class=atitle><FONT face=Arial size=4>结束语</FONT></SPAN></A></P>
<P><FONT face=Arial size=4></FONT>
<P>以上是本人在两年多J2EE应用开发中，总结的关于用Java进行GUI设计的一些经验，希望能给曾经象我一样迷惘，但依旧对Java一往情深，至今仍在摸索探求Java GUI设计捷径的朋友一些启示。更希望借此机会抛砖引玉，与更多的朋友进行交流与探讨。其实，在Java中所有的布局管理器都要实现一个接口，即LayoutManager Inerface或者是它的一个子接口LayoutManager2 Interface，后者用于更复杂的布局管理。如果在实际应用中，觉得Java API提供的这些布局管理器仍不够用，你完全可以自己来实现其中某一个接口的方法，从而为你自己的具体GUI应用设计提供更好的布局管理。</P></B></B></B></B></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/fortune/aggbug/32312.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-24 17:26 <a href="http://www.blogjava.net/fortune/archive/2006/02/24/32312.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SWT多线程问题</title><link>http://www.blogjava.net/fortune/archive/2006/02/21/31826.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Tue, 21 Feb 2006 09:01:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/21/31826.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/31826.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/21/31826.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/31826.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/31826.html</trackback:ping><description><![CDATA[<SPAN style="FONT-FAMILY: 宋体">多线程问题：</SPAN><SPAN lang=EN-US>SWT</SPAN><SPAN style="FONT-FAMILY: 宋体">使用</SPAN><SPAN lang=EN-US>Display</SPAN><SPAN style="FONT-FAMILY: 宋体">类来维护</SPAN><SPAN lang=EN-US>GUI</SPAN><SPAN style="FONT-FAMILY: 宋体">及其使用的系统资源。它禁止用户在其他线程下访问</SPAN><SPAN lang=EN-US>GUI</SPAN><SPAN style="FONT-FAMILY: 宋体">资源。例如：</SPAN> 
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US>public void run() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; butt.setText("test");<BR>&nbsp;&nbsp;&nbsp; }<BR></SPAN><SPAN style="FONT-FAMILY: 宋体">这样的写法会导致非法线程异常。如果需要在其他线程下访问</SPAN><SPAN lang=EN-US>GUI</SPAN><SPAN style="FONT-FAMILY: 宋体">资源可以使用如下方法：</SPAN><SPAN lang=EN-US><BR>Display.getCurrent().asyncExec(new Thread () {<BR>&nbsp;&nbsp;&nbsp; public void run() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; butt.setText("test");<BR>&nbsp;&nbsp;&nbsp; }<BR>})<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></P>
<UL>
<LI><SPAN lang=EN-US style="FONT-FAMILY: Wingdings"><SPAN><SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN lang=EN-US>Display</SPAN><SPAN style="FONT-FAMILY: 宋体">提供同步异步方法分别是</SPAN><SPAN lang=EN-US>: syncExec(Runnable)</SPAN><SPAN style="FONT-FAMILY: 宋体">和</SPAN><SPAN lang=EN-US>asyncExec(Runnable)</SPAN><SPAN style="FONT-FAMILY: 宋体">。</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN> </LI></UL>
<UL>
<LI><SPAN lang=EN-US style="FONT-FAMILY: Wingdings"><SPAN><SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">对于</SPAN><SPAN lang=EN-US>Display</SPAN><SPAN style="FONT-FAMILY: 宋体">，在同一个线程里，不能申明</SPAN><SPAN lang=EN-US>2</SPAN><SPAN style="FONT-FAMILY: 宋体">个</SPAN><SPAN lang=EN-US>Display</SPAN><SPAN style="FONT-FAMILY: 宋体">实例。同样的，一个</SPAN><SPAN lang=EN-US>Display</SPAN><SPAN style="FONT-FAMILY: 宋体">实例也不能跨线程使用。也就是说，如果你要在另外一个线程中显示一个窗体，你必须另外创建一个</SPAN><SPAN lang=EN-US>Display</SPAN><SPAN style="FONT-FAMILY: 宋体">实例。不然会导致异常。)</SPAN> </LI></UL>
<P>线程问题 <BR><BR>　　在任何操作平台的GUI系统中，对构件或一些图形API的访问操作都要被严格同步并串行化。例如，在一个图形界面中的按键构件可被设成可用状态(enable)或禁用状态(disable)，正常的处理方式是，用户对按键状态设置操作都要被放入到GUI系统的事件处理队列中（这意味着访问操作被串行化），然后依次处理（这意味着访问操作被同步）。想象当按键可用状态的设置函数还没有执行结束的时候，程序就希望再设置该按键为禁用状态，势必会引起冲突。实际上，这种操作在任何GUI系统都会触发异常。 <BR><BR>　　Java语言本身就提供了多线程机制，这种机制对GUI编程来说是不利的，它不能保证图形构件操作的同步与串行化。SWT采用了一种简单而直接的方式去适应本地GUI系统对线程的要求：在SWT中，通常存在一个被称为"用户线程"的唯一线程，只有在这个线程中才能调用对构件或某些图形API的访问操作。如果在非用户线程中程序直接调用这些访问操作，那么SWTExcepiton异常会被抛出。但是SWT也在*.widget.Display类中提供了两个方法可以间接的在非用户线程的进行图形构件的访问操作，这是通过的syncExec(Runnable)和asyncExec(Runnable)这两个方法去实现的。例如： <BR><BR>//此时程序运行在一个非用户线程中，并且希望在构件panel上加入一个按键。<BR><BR>Display.getCurrent().asyncExec(new Runnable() {<BR>　public void run() {<BR>　　Button butt = new Button(panel,SWT.PUSH);<BR>　　butt.setText("Push");<BR>　}<BR>}); <BR><BR>　　方法syncExec()和asyncExec()的区别在于前者要在指定的线程执行结束后才返回，而后者则无论指定的线程是否执行都会立即返回到当前线程。 <BR></P><img src ="http://www.blogjava.net/fortune/aggbug/31826.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-21 17:01 <a href="http://www.blogjava.net/fortune/archive/2006/02/21/31826.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SWT和多线程结合使用的问题释疑</title><link>http://www.blogjava.net/fortune/archive/2006/02/21/31788.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Tue, 21 Feb 2006 05:42:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/21/31788.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/31788.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/21/31788.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/31788.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/31788.html</trackback:ping><description><![CDATA[<P></P>
<P>SWT作为JAVA开源世界的优秀图形库，已经得到了很多java爱好者的青睐。我最近也在使用swt开发一些应用程序。我发现多线程中使用swt需要额外的技巧。</P>
<P>情形：<BR>&nbsp;&nbsp;&nbsp;&nbsp;单击一个按钮，然后新开一个线程来执行一个复杂的任务。任务执行完时，弹出一个对话框提示任务执行完毕。</P>
<P>示例1：</P>
<P>package&nbsp;threadandui;</P>
<P>import&nbsp;org.eclipse.swt.SWT;<BR>import&nbsp;org.eclipse.swt.widgets.Display;<BR>import&nbsp;org.eclipse.swt.widgets.MessageBox;<BR>import&nbsp;org.eclipse.swt.widgets.Shell;<BR>import&nbsp;org.eclipse.swt.widgets.Button;<BR>import&nbsp;org.eclipse.swt.events.SelectionAdapter;<BR>import&nbsp;org.eclipse.swt.events.SelectionEvent;</P>
<P>public&nbsp;class&nbsp;TestSwt1&nbsp;extends&nbsp;Shell&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;Shell&nbsp;shell;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[])&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Display&nbsp;display&nbsp;=&nbsp;Display.getDefault();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell&nbsp;=&nbsp;new&nbsp;TestSwt1(display,&nbsp;SWT.SHELL_TRIM);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell.open();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell.layout();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(!shell.isDisposed())&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!display.readAndDispatch())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display.sleep();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;TestSwt1(Display&nbsp;display,&nbsp;int&nbsp;style)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(display,&nbsp;style);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createContents();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;void&nbsp;createContents()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setText("SWT&nbsp;Application1");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setSize(500,&nbsp;375);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;Button&nbsp;button&nbsp;=&nbsp;new&nbsp;Button(this,&nbsp;SWT.NONE);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button.addSelectionListener(new&nbsp;SelectionAdapter()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;widgetSelected(SelectionEvent&nbsp;e)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;MyThread().start();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button.setBounds(80,&nbsp;50,&nbsp;85,&nbsp;25);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button.setText("start");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;void&nbsp;checkSubclass()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;MyThread&nbsp;extends&nbsp;Thread{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run(){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//complex&nbsp;task<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i=0;i&nbsp;&lt;&nbsp;10000;i++){<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(i);<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//display&nbsp;a&nbsp;dialog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox&nbsp;mb&nbsp;=&nbsp;new&nbsp;MessageBox(shell);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mb.setMessage("Task&nbsp;ended!");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mb.open();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}</P>
<P>该程序在单击start按钮后会有异常：<BR>Exception&nbsp;in&nbsp;thread&nbsp;"Thread-0"&nbsp;org.eclipse.swt.SWTException:&nbsp;Invalid&nbsp;thread&nbsp;access<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.eclipse.swt.SWT.error(SWT.java:2691)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.eclipse.swt.SWT.error(SWT.java:2616)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.eclipse.swt.SWT.error(SWT.java:2587)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.eclipse.swt.widgets.Widget.error(Widget.java:381)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:284)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.eclipse.swt.widgets.Dialog.checkParent(Dialog.java:154)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.eclipse.swt.widgets.Dialog.&lt;init&gt;(Dialog.java:116)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.eclipse.swt.widgets.MessageBox.&lt;init&gt;(MessageBox.java:81)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.eclipse.swt.widgets.MessageBox.&lt;init&gt;(MessageBox.java:54)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;threadandui.TestSwt1$MyThread.run(TestSwt1.java:70)</P>
<P>为什么会有异常？没有参考书，没有人指导，你是就此罢休呢，还是刨根问底？我想知道答案，那我该怎么做呢？<BR>请注意，swt是开源的，代码就是你最好的参考书，最好的指导老师！</P>
<P>查看swt源代码：at&nbsp;org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:284)</P>
<P>/*245*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;void&nbsp;checkWidget&nbsp;()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>/*246*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Display&nbsp;display&nbsp;=&nbsp;this.display;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>/*247*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(display&nbsp;==&nbsp;null)&nbsp;error&nbsp;(SWT.ERROR_WIDGET_DISPOSED);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>/*248*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(display.thread&nbsp;!=&nbsp;Thread.currentThread&nbsp;())&nbsp;error&nbsp;(SWT.ERROR_THREAD_INVALID_ACCESS);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>/*249*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;((state&nbsp;&amp;&nbsp;DISPOSED)&nbsp;!=&nbsp;0)&nbsp;error&nbsp;(SWT.ERROR_WIDGET_DISPOSED);</P>
<P>/*250*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>第248行有判断“display.thread&nbsp;!=&nbsp;Thread.currentThread&nbsp;()”。显然，在我们的示例中他们是不相等的。因为，MessageBox处在新创建的线程中，而display</P>
<P>则处在main线程中。可见我们需要在新线程中创建一个display给MessageBox使用。“示例2”给出了答案。</P>
<P><BR>示例2;<BR>/*<BR>*&nbsp;Created&nbsp;on&nbsp;2005-5-26<BR>*<BR>*&nbsp;TODO&nbsp;To&nbsp;change&nbsp;the&nbsp;template&nbsp;for&nbsp;this&nbsp;generated&nbsp;file&nbsp;go&nbsp;to<BR>*&nbsp;Window&nbsp;-&nbsp;Preferences&nbsp;-&nbsp;Java&nbsp;-&nbsp;Code&nbsp;Style&nbsp;-&nbsp;Code&nbsp;Templates<BR>*/<BR>package&nbsp;threadandui;</P>
<P>import&nbsp;org.eclipse.swt.SWT;<BR>import&nbsp;org.eclipse.swt.widgets.Display;<BR>import&nbsp;org.eclipse.swt.widgets.MessageBox;<BR>import&nbsp;org.eclipse.swt.widgets.Shell;<BR>import&nbsp;org.eclipse.swt.widgets.Button;<BR>import&nbsp;org.eclipse.swt.events.SelectionAdapter;<BR>import&nbsp;org.eclipse.swt.events.SelectionEvent;</P>
<P>/**<BR>*&nbsp;@author&nbsp;jiangjunping<BR>*<BR>*&nbsp;TODO&nbsp;To&nbsp;change&nbsp;the&nbsp;template&nbsp;for&nbsp;this&nbsp;generated&nbsp;type&nbsp;comment&nbsp;go&nbsp;to<BR>*&nbsp;Window&nbsp;-&nbsp;Preferences&nbsp;-&nbsp;Java&nbsp;-&nbsp;Code&nbsp;Style&nbsp;-&nbsp;Code&nbsp;Templates<BR>*/<BR>public&nbsp;class&nbsp;TestSwt2&nbsp;extends&nbsp;Shell&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;Shell&nbsp;shell;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[])&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Display&nbsp;display&nbsp;=&nbsp;Display.getDefault();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell&nbsp;=&nbsp;new&nbsp;TestSwt2(display,&nbsp;SWT.SHELL_TRIM);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell.open();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell.layout();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(!shell.isDisposed())&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!display.readAndDispatch())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display.sleep();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;TestSwt2(Display&nbsp;display,&nbsp;int&nbsp;style)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(display,&nbsp;style);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createContents();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;void&nbsp;createContents()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setText("SWT&nbsp;Application2");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setSize(500,&nbsp;375);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;Button&nbsp;button&nbsp;=&nbsp;new&nbsp;Button(this,&nbsp;SWT.NONE);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button.addSelectionListener(new&nbsp;SelectionAdapter()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;widgetSelected(SelectionEvent&nbsp;e)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;MyThread().start();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button.setBounds(80,&nbsp;50,&nbsp;85,&nbsp;25);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button.setText("start");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;void&nbsp;checkSubclass()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;MyThread&nbsp;extends&nbsp;Thread{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run(){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//complex&nbsp;task<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i=0;i&nbsp;&lt;&nbsp;50000;i++){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(i);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//display&nbsp;a&nbsp;dialog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Display&nbsp;display&nbsp;=&nbsp;new&nbsp;Display();//new&nbsp;display<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Shell&nbsp;shell2&nbsp;=&nbsp;new&nbsp;Shell(display);//added&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox&nbsp;mb&nbsp;=&nbsp;new&nbsp;MessageBox(shell2);//use&nbsp;new&nbsp;display&nbsp;created&nbsp;in&nbsp;the&nbsp;current&nbsp;thread<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mb.setMessage("Task&nbsp;ended!");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mb.open();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display.dispose();//added<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}</P>
<P><BR>好了，程序正常了！</P><img src ="http://www.blogjava.net/fortune/aggbug/31788.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-21 13:42 <a href="http://www.blogjava.net/fortune/archive/2006/02/21/31788.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java多线程</title><link>http://www.blogjava.net/fortune/archive/2006/02/21/31746.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Tue, 21 Feb 2006 02:07:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/21/31746.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/31746.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/21/31746.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/31746.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/31746.html</trackback:ping><description><![CDATA[一：理解多线程<BR><BR>多线程是这样一种机制，它允许在程序中并发执行多个指令流，每个指令流都称为一个线程，彼此间互相独立。&nbsp;<BR><BR>线程又称为轻量级进程，它和进程一样拥有独立的执行控制，由操作系统负责调度，区别在于线程没有独立的存储空间，而是和所属进程中的其它线程共享一个存储空间，这使得线程间的通信远较进程简单。<BR><BR>多个线程的执行是并发的，也就是在逻辑上“同时”，而不管是否是物理上的“同时”。如果系统只有一个CPU，那么真正的“同时”是不可能的，但是由于CPU的速度非常快，用户感觉不到其中的区别，因此我们也不用关心它，只需要设想各个线程是同时执行即可。<BR><BR>多线程和传统的单线程在程序设计上最大的区别在于，由于各个线程的控制流彼此独立，使得各个线程之间的代码是乱序执行的，由此带来的线程调度，同步等问题，将在以后探讨。<BR><BR>二：在Java中实现多线程<BR><BR>我们不妨设想，为了创建一个新的线程，我们需要做些什么？很显然，我们必须指明这个线程所要执行的代码，而这就是在Java中实现多线程我们所需要做的一切！<BR><BR>真是神奇！Java是如何做到这一点的？通过类！作为一个完全面向对象的语言，Java提供了类&nbsp;java.lang.Thread&nbsp;来方便多线程编程，这个类提供了大量的方法来方便我们控制自己的各个线程，我们以后的讨论都将围绕这个类进行。&nbsp;<BR><BR>那么如何提供给&nbsp;Java&nbsp;我们要线程执行的代码呢？让我们来看一看&nbsp;Thread&nbsp;类。Thread&nbsp;类最重要的方法是&nbsp;run()&nbsp;，它为Thread&nbsp;类的方法&nbsp;start()&nbsp;所调用，提供我们的线程所要执行的代码。为了指定我们自己的代码，只需要覆盖它！<BR><BR>方法一：继承&nbsp;Thread&nbsp;类，覆盖方法&nbsp;run()<BR><BR>我们在创建的&nbsp;Thread&nbsp;类的子类中重写&nbsp;run()&nbsp;,加入线程所要执行的代码即可。<BR>下面是一个例子：<BR><BR>public&nbsp;class&nbsp;MyThread&nbsp;extends&nbsp;Thread&nbsp;{<BR><BR>int&nbsp;count=&nbsp;1,&nbsp;number;<BR><BR>public&nbsp;MyThread(int&nbsp;num)&nbsp;{<BR><BR>number&nbsp;=&nbsp;num;<BR><BR>System.out.println("创建线程&nbsp;"&nbsp;+&nbsp;number);<BR><BR>}<BR><BR>public&nbsp;void&nbsp;run()&nbsp;{<BR><BR><BR>while(true)&nbsp;{<BR><BR>System.out.println("线程&nbsp;"&nbsp;+&nbsp;number&nbsp;+&nbsp;":计数&nbsp;"&nbsp;+&nbsp;count);<BR><BR>if(++count==&nbsp;6)&nbsp;return;<BR><BR>}<BR><BR>}<BR><BR>public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[])&nbsp;{<BR><BR>for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;5;&nbsp;i++)&nbsp;new&nbsp;MyThread(i+1).start();<BR><BR>}<BR><BR>}<BR><BR><BR>这种方法简单明了，符合大家的习惯，但是，它也有一个很大的缺点，那就是如果我们的类已经从一个类继承（如小程序必须继承自&nbsp;Applet&nbsp;类），则无法再继承&nbsp;Thread&nbsp;类，这时如果我们又不想建立一个新的类，应该怎么办呢？<BR><BR>我们不妨来探索一种新的方法：我们不创建&nbsp;Thread&nbsp;类的子类，而是直接使用它，那么我们只能将我们的方法作为参数传递给&nbsp;Thread&nbsp;类的实例，有点类似回调函数。但是&nbsp;Java&nbsp;没有指针，我们只能传递一个包含这个方法的类的实例。那么如何限制这个类必须包含这一方法呢？当然是使用接口！（虽然抽象类也可满足，但是需要继承，而我们之所以要采用这种新方法，不就是为了避免继承带来的限制吗？）<BR><BR><BR>Java&nbsp;提供了接口&nbsp;java.lang.Runnable&nbsp;来支持这种方法。<BR><BR>方法二：实现&nbsp;Runnable&nbsp;接口<BR><BR><BR>Runnable&nbsp;接口只有一个方法&nbsp;run()，我们声明自己的类实现&nbsp;Runnable&nbsp;接口并提供这一方法，将我们的线程代码写入其中，就完成了这一部分的任务。<BR><BR>但是&nbsp;Runnable&nbsp;接口并没有任何对线程的支持，我们还必须创建&nbsp;Thread&nbsp;类的实例，这一点通过&nbsp;Thread&nbsp;类的构造函数<BR>public&nbsp;Thread(Runnable&nbsp;target);来实现。<BR><BR>下面是一个例子：<BR><BR>public&nbsp;class&nbsp;MyThread&nbsp;implements&nbsp;Runnable&nbsp;{<BR><BR>int&nbsp;count=&nbsp;1,&nbsp;number;<BR><BR>public&nbsp;MyThread(int&nbsp;num)&nbsp;{<BR><BR>number&nbsp;=&nbsp;num;<BR><BR>System.out.println("创建线程&nbsp;"&nbsp;+&nbsp;number);<BR><BR>}<BR><BR>public&nbsp;void&nbsp;run()&nbsp;{<BR><BR>while(true)&nbsp;{<BR><BR>System.out.println("线程&nbsp;"&nbsp;+&nbsp;number&nbsp;+&nbsp;":计数&nbsp;"&nbsp;+&nbsp;count);<BR><BR>if(++count==&nbsp;6)&nbsp;return;<BR><BR>}&nbsp;<BR><BR>}<BR><BR>public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[])&nbsp;{<BR><BR>for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;5;&nbsp;i++)&nbsp;new&nbsp;Thread(new&nbsp;MyThread(i+1)).start();<BR><BR>}<BR><BR>}<BR><BR><BR>严格地说，创建&nbsp;Thread&nbsp;子类的实例也是可行的，但是必须注意的是，该子类必须没有覆盖&nbsp;Thread&nbsp;类的&nbsp;run&nbsp;方法，否则该线程执行的将是子类的&nbsp;run&nbsp;方法，而不是我<BR><BR>们用以实现Runnable&nbsp;接口的类的&nbsp;run&nbsp;方法，对此大家不妨试验一下。<BR><BR>使用&nbsp;Runnable&nbsp;接口来实现多线程使得我们能够在一个类中包容所有的代码，有利于封装，它的缺点在于，我们只能使用一套代码，若想创建多个线程并使各个线程执行不同的代码，则仍必须额外创建类，如果这样的话，在大多数情况下也许还不如直接用多个类分别继承&nbsp;Thread&nbsp;来得紧凑。<BR><BR><BR>综上所述，两种方法各有千秋，大家可以灵活运用。<BR><BR>下面让我们一起来研究一下多线程使用中的一些问题。<BR><BR>三：线程的四种状态<BR><BR>1.&nbsp;新状态：线程已被创建但尚未执行（start()&nbsp;尚未被调用）。<BR><BR>2.&nbsp;可执行状态：线程可以执行，虽然不一定正在执行。CPU&nbsp;时间随时可能被分配给该线程，从而使得它执行。<BR><BR>3.&nbsp;死亡状态：正常情况下&nbsp;run()&nbsp;返回使得线程死亡。调用&nbsp;stop()或&nbsp;destroy()&nbsp;亦有同样效果，但是不被推荐，前者会产生异常，后者是强制终止，不会释放锁。<BR><BR>4.&nbsp;阻塞状态：线程不会被分配&nbsp;CPU&nbsp;时间，无法执行。<BR><BR>四：线程的优先级&nbsp;<BR><BR>线程的优先级代表该线程的重要程度，当有多个线程同时处于可执行状态并等待获得&nbsp;CPU&nbsp;时间时，线程调度系统根据各个线程的优先级来决定给谁分配&nbsp;CPU&nbsp;时间，优先级高的线程有更大的机会获得&nbsp;CPU&nbsp;时间，优先级低的线程也不是没有机会，只是机会要小一些罢了。<BR><BR><BR>你可以调用&nbsp;Thread&nbsp;类的方法&nbsp;getPriority()&nbsp;和&nbsp;setPriority()来存取线程的优先级，线程的优先级界于1(MIN_PRIORITY)和10(MAX_PRIORITY)之间，缺省是5(NORM_PRIORITY)。<BR><BR><BR>五：线程的同步<BR><BR>由于同一进程的多个线程共享同一片存储空间，在带来方便的同时，也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突，有效避免了同一个数据对象被多个线程同时访问。<BR><BR><BR>由于我们可以通过&nbsp;private&nbsp;关键字来保证数据对象只能被方法访问，所以我们只需针对方法提出一套机制，这套机制就是&nbsp;synchronized&nbsp;关键字，它包括两种用法：synchronized&nbsp;方法和&nbsp;synchronized&nbsp;块。<BR><BR><BR>1.&nbsp;synchronized&nbsp;方法：通过在方法声明中加入&nbsp;synchronized关键字来声明&nbsp;synchronized&nbsp;方法。如：<BR><BR>public&nbsp;synchronized&nbsp;void&nbsp;accessVal(int&nbsp;newVal);<BR><BR><BR>synchronized&nbsp;方法控制对类成员变量的访问：每个类实例对应一把锁，每个&nbsp;synchronized&nbsp;方法都必须获得调用该方法的类实例的锁方能执行，否则所属线程阻塞，方<BR><BR>法一旦执行，就独占该锁，直到从该方法返回时才将锁释放，此后被阻塞的线程方能获得该锁，重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例，其所有声明为&nbsp;synchronized&nbsp;的成员函数中至多只有一个处于可执行状态（因为至多只有一个能够获得该类实例对应的锁），从而有效避免了类成员变量的访问冲突（只要所有可能访问类成员变量的方法均被声明为&nbsp;synchronized）。<BR><BR><BR>在&nbsp;Java&nbsp;中，不光是类实例，每一个类也对应一把锁，这样我们也可将类的静态成员函数声明为&nbsp;synchronized&nbsp;，以控制其对类的静态成员变量的访问。<BR>synchronized&nbsp;方法的缺陷：若将一个大的方法声明为synchronized&nbsp;将会大大影响效率，典型地，若将线程类的方法&nbsp;run()&nbsp;声明为&nbsp;synchronized&nbsp;，由于在线程的整个生命期内它一直在运行，因此将导致它对本类任何&nbsp;synchronized&nbsp;方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中，将其声明为&nbsp;synchronized&nbsp;，并在主方法中调用来解决这一问题，但是&nbsp;Java&nbsp;为我们提供了更好的解决办法，那就是&nbsp;synchronized&nbsp;块。<BR><BR>2.&nbsp;synchronized&nbsp;块：通过&nbsp;synchronized关键字来声明synchronized&nbsp;块。语法如下：&nbsp;<BR>synchronized(syncObject)&nbsp;{<BR>//允许访问控制的代码<BR>}<BR><BR><BR>synchronized&nbsp;块是这样一个代码块，其中的代码必须获得对象&nbsp;syncObject&nbsp;（如前所述，可以是类实例或类）的锁方能执行，具体机制同前所述。由于可以针对任意代码块，且可任意指定上锁的对象，故灵活性较高。<BR><BR><BR>六：线程的阻塞<BR><BR><BR>为了解决对共享存储区的访问冲突，Java&nbsp;引入了同步机制，现在让我们来考察多个线程对共享资源的访问，显然同步机制已经不够了，因为在任意时刻所要求的资源不一定已经准备好了被访问，反过来，同一时刻准备好了的资源也可能不止一个。为了解决这种情况下的访问控制问题，Java&nbsp;引入了对阻塞机制的支持。<BR><BR><BR>阻塞指的是暂停一个线程的执行以等待某个条件发生（如某资源就绪），学过操作系统的同学对它一定已经很熟悉了。Java&nbsp;提供了大量方法来支持阻塞，下面让我们逐一分析。<BR><BR><BR>1.&nbsp;sleep()&nbsp;方法：sleep()&nbsp;允许&nbsp;指定以毫秒为单位的一段时间作为参数，它使得线程在指定的时间内进入阻塞状态，不能得到CPU&nbsp;时间，指定的时间一过，线程重新进入可执行状态。<BR><BR>典型地，sleep()&nbsp;被用在等待某个资源就绪的情形：测试发现条件不满足后，让线程阻塞一段时间后重新测试，直到条件满足为止。<BR><BR><BR>2.&nbsp;suspend()&nbsp;和&nbsp;resume()&nbsp;方法：两个方法配套使用，suspend()使得线程进入阻塞状态，并且不会自动恢复，必须其对应的resume()&nbsp;被调用，才能使得线程重新进入可执行状态。典型地，suspend()&nbsp;和&nbsp;resume()&nbsp;被用在等待另一个线程产生的结果的情形：测试发现结果还没有产生后，让线程阻塞，另一个线程产生了结果后，调用&nbsp;resume()&nbsp;使其恢复。<BR><BR><BR>3.&nbsp;yield()&nbsp;方法：yield()&nbsp;使得线程放弃当前分得的&nbsp;CPU&nbsp;时间，但是不使线程阻塞，即线程仍处于可执行状态，随时可能再次分得&nbsp;CPU&nbsp;时间。调用&nbsp;yield()&nbsp;的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程。<BR><BR><BR>4.&nbsp;wait()&nbsp;和&nbsp;notify()&nbsp;方法：两个方法配套使用，wait()&nbsp;使得线程进入阻塞状态，它有两种形式，一种允许&nbsp;指定以毫秒为单位的一段时间作为参数，另一种没有参数，前者当对应的&nbsp;notify()&nbsp;被调用或者超出指定时间时线程重新进入可执行状态，后者则必须对应的&nbsp;notify()&nbsp;被调用。<BR><BR>初看起来它们与&nbsp;suspend()&nbsp;和&nbsp;resume()&nbsp;方法对没有什么分别，但是事实上它们是截然不同的。区别的核心在于，前面叙述的所有方法，阻塞时都不会释放占用的锁（如果占用了的话），而这一对方法则相反。<BR><BR><BR>上述的核心区别导致了一系列的细节上的区别。<BR><BR>首先，前面叙述的所有方法都隶属于&nbsp;Thread&nbsp;类，但是这一对却直接隶属于&nbsp;Object&nbsp;类，也就是说，所有对象都拥有这一对方法。初看起来这十分不可思议，但是实际上却是很自然的，因为这一对方法阻塞时要释放占用的锁，而锁是任何对象都具有的，调用任意对象的&nbsp;wait()&nbsp;方法导致线程阻塞，并且该对象上的锁被释放。而调用&nbsp;任意对象的notify()方法则导致因调用该对象的&nbsp;wait()&nbsp;方法而阻塞的线程中随机选择的一个解除阻塞（但要等到获得锁后才真正可执行）。<BR><BR>其次，前面叙述的所有方法都可在任何位置调用，但是这一对方法却必须在&nbsp;synchronized&nbsp;方法或块中调用，理由也很简单，只有在synchronized&nbsp;方法或块中当前线程才占有锁，才有锁可以释放。同样的道理，调用这一对方法的对象上的锁必须为当前线程所拥有，这样才有锁可以释放。因此，这一对方法调用必须放置在这样的&nbsp;synchronized&nbsp;方法或块中，该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件，则程序虽然仍能编译，但在运行时会出现IllegalMonitorStateException&nbsp;异常。<BR><BR><BR>wait()&nbsp;和&nbsp;notify()&nbsp;方法的上述特性决定了它们经常和synchronized&nbsp;方法或块一起使用，将它们和操作系统的进程间通信机制作一个比较就会发现它们的相似性：synchronized方法或块提供了类似于操作系统原语的功能，它们的执行不会受到多线程机制的干扰，而这一对方法则相当于&nbsp;block&nbsp;和wakeup&nbsp;原语（这一对方法均声明为&nbsp;synchronized）。它们的结合使得我们可以实现操作系统上一系列精妙的进程间通信的算法（如信号量算法），并用于解决各种复杂的线程间通信问题。<BR><BR><BR>关于&nbsp;wait()&nbsp;和&nbsp;notify()&nbsp;方法最后再说明两点：<BR><BR>第一：调用&nbsp;notify()&nbsp;方法导致解除阻塞的线程是从因调用该对象的&nbsp;wait()&nbsp;方法而阻塞的线程中随机选取的，我们无法预料哪一个线程将会被选择，所以编程时要特别小心，避免因这种不确定性而产生问题。<BR><BR>第二：除了&nbsp;notify()，还有一个方法&nbsp;notifyAll()&nbsp;也可起到类似作用，唯一的区别在于，调用&nbsp;notifyAll()&nbsp;方法将把因调用该对象的&nbsp;wait()&nbsp;方法而阻塞的所有线程一次性全部解除阻塞。当然，只有获得锁的那一个线程才能进入可执行状态。<BR><BR><BR>谈到阻塞，就不能不谈一谈死锁，略一分析就能发现，suspend()&nbsp;方法和不指定超时期限的&nbsp;wait()&nbsp;方法的调用都可能产生死锁。遗憾的是，Java&nbsp;并不在语言级别上支持死锁的避免，我们在编程中必须小心地避免死锁。<BR><BR><BR>以上我们对&nbsp;Java&nbsp;中实现线程阻塞的各种方法作了一番分析，我们重点分析了&nbsp;wait()&nbsp;和&nbsp;notify()&nbsp;方法，因为它们的功能最强大，使用也最灵活，但是这也导致了它们的效率较低，较容易出错。实际使用中我们应该灵活使用各种方法，以便更好地达到我们的目的。<BR><BR><BR>七：守护线程<BR><BR><BR>守护线程是一类特殊的线程，它和普通线程的区别在于它并不是应用程序的核心部分，当一个应用程序的所有非守护线程终止运行时，即使仍然有守护线程在运行，应用程序也将终止，反之，只要有一个非守护线程在运行，应用程序就不会终止。守护线程一般被用于在后台为其它线程提供服务。<BR><BR><BR>可以通过调用方法&nbsp;isDaemon()&nbsp;来判断一个线程是否是守护线程，也可以调用方法&nbsp;setDaemon()&nbsp;来将一个线程设为守护线程。<BR><BR><BR>八：线程组<BR><BR><BR>线程组是一个&nbsp;Java&nbsp;特有的概念，在&nbsp;Java&nbsp;中，线程组是类ThreadGroup&nbsp;的对象，每个线程都隶属于唯一一个线程组，这个线程组在线程创建时指定并在线程的整个生命期内都不能更改。你可以通过调用包含&nbsp;ThreadGroup&nbsp;类型参数的&nbsp;Thread&nbsp;类构造函数来指定线程属的线程组，若没有指定，则线程缺省地隶属于名为&nbsp;system&nbsp;的系统线程组。<BR><BR><BR>在&nbsp;Java&nbsp;中，除了预建的系统线程组外，所有线程组都必须显式创建。<BR><BR><BR>在&nbsp;Java&nbsp;中，除系统线程组外的每个线程组又隶属于另一个线程组，你可以在创建线程组时指定其所隶属的线程组，若没有指定，则缺省地隶属于系统线程组。这样，所有线程组组成了一棵以系统线程组为根的树。<BR><BR><BR>Java&nbsp;允许我们对一个线程组中的所有线程同时进行操作，比如我们可以通过调用线程组的相应方法来设置其中所有线程的优先级，也可以启动或阻塞其中的所有线程。<BR><BR><BR>Java&nbsp;的线程组机制的另一个重要作用是线程安全。线程组机制允许我们通过分组来区分有不同安全特性的线程，对不同组的线程进行不同的处理，还可以通过线程组的分层结构来支持不对等安全措施的采用。Java&nbsp;的&nbsp;ThreadGroup&nbsp;类提供了大量的方法来方便我们对线程组树中的每一个线程组以及线程组中的每一个线程进行操作。<BR><BR><BR>九：总结<BR><BR><BR>在这一讲中，我们一起学习了&nbsp;Java&nbsp;多线程编程的方方面面，包括创建线程，以及对多个线程进行调度、管理。我们深刻认识到了多线程编程的复杂性，以及线程切换开销带来的多线程程序的低效性，这也促使我们认真地思考一个问题：我们是否需要多线程？何时需要多线程？<BR><BR><BR>多线程的核心在于多个代码块并发执行，本质特点在于各代码块之间的代码是乱序执行的。我们的程序是否需要多线程，就是要看这是否也是它的内在特点。<BR><BR><BR>假如我们的程序根本不要求多个代码块并发执行，那自然不需要使用多线程；假如我们的程序虽然要求多个代码块并发执行，但是却不要求乱序，则我们完全可以用一个循环来简单高效地实现，也不需要使用多线程；只有当它完全符合多线程的特点时，多线程机制对线程间通信和线程管理的强大支持才能有用武之地，这时使用多线程才是值得的。<BR><img src ="http://www.blogjava.net/fortune/aggbug/31746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-21 10:07 <a href="http://www.blogjava.net/fortune/archive/2006/02/21/31746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jar文件包及jar命令祥解</title><link>http://www.blogjava.net/fortune/archive/2006/02/17/31122.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Fri, 17 Feb 2006 00:58:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/17/31122.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/31122.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/17/31122.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/31122.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/31122.html</trackback:ping><description><![CDATA[<DIV align=center><B>JAR文件包及jar命令详解</B></DIV>
<P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><FONT color=#808080><BR><BR>常常在网上看到有人询问：如何把&nbsp;java&nbsp;程序编译成&nbsp;.exe&nbsp;文件。通常回答只有两种，一种是制作一个可执行的&nbsp;JAR&nbsp;文件包，然后就可以像.chm&nbsp;文档一样双击运行了；而另一种是使用&nbsp;JET&nbsp;来进行&nbsp;编译。但是&nbsp;JET&nbsp;是要用钱买的，而且据说&nbsp;JET&nbsp;也不是能把所有的&nbsp;Java&nbsp;程序都编译成执行文件，性能也要打些折扣。所以，使用制作可执行&nbsp;JAR&nbsp;文件包的方法就是最佳选择了，何况它还能保持&nbsp;Java&nbsp;的跨平台特性。</P>
<P>　　下面就来看看什么是&nbsp;JAR&nbsp;文件包吧：</P>
<P>　　1.&nbsp;JAR&nbsp;文件包</P>
<P>　　JAR&nbsp;文件就是&nbsp;Java&nbsp;Archive&nbsp;File，顾名思意，它的应用是与&nbsp;Java&nbsp;息息相关的，是&nbsp;Java&nbsp;的一种文档格式。JAR&nbsp;文件非常类似&nbsp;ZIP&nbsp;文件——准确的说，它就是&nbsp;ZIP&nbsp;文件，所以叫它文件包。JAR&nbsp;文件与&nbsp;ZIP&nbsp;文件唯一的区别就是在&nbsp;JAR&nbsp;文件的内容中，包含了一个&nbsp;META-INF/MANIFEST.MF&nbsp;文件，这个文件是在生成&nbsp;JAR&nbsp;文件的时候自动创建的。举个例子，如果我们具有如下目录结构的一些文件：</P>
<P>　　==</P>
<P>　　`--&nbsp;test</P>
<P>　　　&nbsp;`--&nbsp;Test.class</P>
<P>　　把它压缩成&nbsp;ZIP&nbsp;文件&nbsp;test.zip，则这个&nbsp;ZIP&nbsp;文件的内部目录结构为：</P>
<P>　　test.zip</P>
<P>　　`--&nbsp;test</P>
<P>　　　&nbsp;`--&nbsp;Test.class</P>
<P>　　如果我们使用&nbsp;JDK&nbsp;的&nbsp;jar&nbsp;命令把它打成&nbsp;JAR&nbsp;文件包&nbsp;test.jar，则这个&nbsp;JAR&nbsp;文件的内部目录结构为：</P>
<P>　　test.jar</P>
<P>　　|--&nbsp;META-INF</P>
<P>　　|　&nbsp;`--&nbsp;MANIFEST.MF</P>
<P>　　`--&nbsp;test</P>
<P>　　　　`--Test.class</P>
<P>　　2.&nbsp;创建可执行的&nbsp;JAR&nbsp;文件包</P>
<P>　　制作一个可执行的&nbsp;JAR&nbsp;文件包来发布你的程序是&nbsp;JAR&nbsp;文件包最典型的用法。</P>
<P>　　Java&nbsp;程序是由若干个&nbsp;.class&nbsp;文件组成的。这些&nbsp;.class&nbsp;文件必须根据它们所属的包不同而分级分目录存放；运行前需要把所有用到的包的根目录指定给&nbsp;CLASSPATH&nbsp;环境变量或者&nbsp;java&nbsp;命令的&nbsp;-cp&nbsp;参数；运行时还要到控制台下去使用&nbsp;java&nbsp;命令来运行，如果需要直接双击运行必须写&nbsp;Windows&nbsp;的批处理文件&nbsp;(.bat)&nbsp;或者&nbsp;Linux&nbsp;的&nbsp;Shell&nbsp;程序。因此，许多人说，Java&nbsp;是一种方便开发者苦了用户的程序设计语言。</P>
<P>　　其实不然，如果开发者能够制作一个可执行的&nbsp;JAR&nbsp;文件包交给用户，那么用户使用起来就方便了。在&nbsp;Windows&nbsp;下安装&nbsp;JRE&nbsp;(Java&nbsp;Runtime&nbsp;Environment)&nbsp;的时候，安装文件会将&nbsp;.jar&nbsp;文件映射给&nbsp;javaw.exe&nbsp;打开。那么，对于一个可执行的&nbsp;JAR&nbsp;文件包，用户只需要双击它就可以运行程序了，和阅读&nbsp;.chm&nbsp;文档一样方便&nbsp;(.chm&nbsp;文档默认是由&nbsp;hh.exe&nbsp;打开的)。那么，现在的关键，就是如何来创建这个可执行的&nbsp;JAR&nbsp;文件包。</P>
<P>　　创建可执行的&nbsp;JAR&nbsp;文件包，需要使用带&nbsp;cvfm&nbsp;参数的&nbsp;jar&nbsp;命令，同样以上述&nbsp;test&nbsp;目录为例，命令如下：</P>
<P>jar&nbsp;cvfm&nbsp;test.jar&nbsp;manifest.mf&nbsp;test</P>
<P>　　这里&nbsp;test.jar&nbsp;和&nbsp;manifest.mf&nbsp;两个文件，分别是对应的参数&nbsp;f&nbsp;和&nbsp;m，其重头戏在&nbsp;manifest.mf。因为要创建可执行的&nbsp;JAR&nbsp;文件包，光靠指定一个&nbsp;manifest.mf&nbsp;文件是不够的，因为&nbsp;MANIFEST&nbsp;是&nbsp;JAR&nbsp;文件包的特征，可执行的&nbsp;JAR&nbsp;文件包和不可执行的&nbsp;JAR&nbsp;文件包都包含&nbsp;MANIFEST。关键在于可执行&nbsp;JAR&nbsp;文件包的&nbsp;MANIFEST，其内容包含了&nbsp;Main-Class&nbsp;一项。这在&nbsp;MANIFEST&nbsp;中书写格式如下：</P>
<P>　　Main-Class:&nbsp;可执行主类全名(包含包名)</P>
<P>　　例如，假设上例中的&nbsp;Test.class&nbsp;是属于&nbsp;test&nbsp;包的，而且是可执行的类&nbsp;(定义了&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[])&nbsp;方法)，那么这个&nbsp;manifest.mf&nbsp;可以编辑如下：</P>
<P>Manifest-Version: 1.0&nbsp;&nbsp; <BR>Main-Class:&nbsp;test.Test&nbsp;&lt;回车&gt;</P>
<P>　　这个&nbsp;manifest.mf&nbsp;可以放在任何位置，也可以是其它的文件名，只需要有&nbsp;Main-Class:&nbsp;test.Test&nbsp;一行，且该行以一个回车符结束即可。创建了&nbsp;manifest.mf&nbsp;文件之后，我们的目录结构变为：</P>
<P>　　==</P>
<P>　　|--&nbsp;test</P>
<P>　　|　&nbsp;`--&nbsp;Test.class</P>
<P>　　`--&nbsp;manifest.mf</P>
<P>　　这时候，需要到&nbsp;test&nbsp;目录的上级目录中去使用&nbsp;jar&nbsp;命令来创建&nbsp;JAR&nbsp;文件包。也就是在目录树中使用“==”表示的那个目录中，使用如下命令：</P>
<P>jar&nbsp;cvfm&nbsp;test.jar&nbsp;manifest.mf&nbsp;test</P>
<P>　　之后在“==”目录中创建了&nbsp;test.jar，这个&nbsp;test.jar&nbsp;就是执行的&nbsp;JAR&nbsp;文件包。运行时只需要使用&nbsp;java&nbsp;-jar&nbsp;test.jar&nbsp;命令即可。</P>
<P>　　需要注意的是，创建的&nbsp;JAR&nbsp;文件包中需要包含完整的、与&nbsp;Java&nbsp;程序的包结构对应的目录结构，就像上例一样。而&nbsp;Main-Class&nbsp;指定的类，也必须是完整的、包含包路径的类名，如上例的&nbsp;test.Test；而且在没有打成&nbsp;JAR&nbsp;文件包之前可以使用&nbsp;java&nbsp;&lt;类名&gt;&nbsp;来运行这个类，即在上例中&nbsp;java&nbsp;test.Test&nbsp;是可以正确运行的&nbsp;(当然要在&nbsp;CLASSPATH&nbsp;正确的情况下)。</P>
<P></P>
<P><BR>　　3.&nbsp;jar&nbsp;命令详解</P>
<P>　　jar&nbsp;是随&nbsp;JDK&nbsp;安装的，在&nbsp;JDK&nbsp;安装目录下的&nbsp;bin&nbsp;目录中，Windows&nbsp;下文件名为&nbsp;jar.exe，Linux&nbsp;下文件名为&nbsp;jar。它的运行需要用到&nbsp;JDK&nbsp;安装目录下&nbsp;lib&nbsp;目录中的&nbsp;tools.jar&nbsp;文件。不过我们除了安装&nbsp;JDK&nbsp;什么也不需要做，因为&nbsp;SUN&nbsp;已经帮我们做好了。我们甚至不需要将&nbsp;tools.jar&nbsp;放到&nbsp;CLASSPATH&nbsp;中。</P>
<P>　　使用不带任何的&nbsp;jar&nbsp;命令我们可以看到&nbsp;jar&nbsp;命令的用法如下：</P>
<P>　　jar&nbsp;{ctxu}[vfm0M]&nbsp;[jar-文件]&nbsp;[manifest-文件]&nbsp;[-C&nbsp;目录]&nbsp;文件名&nbsp;...</P>
<P>　　其中&nbsp;{ctxu}&nbsp;是&nbsp;jar&nbsp;命令的子命令，每次&nbsp;jar&nbsp;命令只能包含&nbsp;ctxu&nbsp;中的一个，它们分别表示：</P>
<P>　　　-c　创建新的&nbsp;JAR&nbsp;文件包</P>
<P>　　　-t　列出&nbsp;JAR&nbsp;文件包的内容列表</P>
<P>　　　-x　展开&nbsp;JAR&nbsp;文件包的指定文件或者所有文件</P>
<P>　　　-u　更新已存在的&nbsp;JAR&nbsp;文件包&nbsp;(添加文件到&nbsp;JAR&nbsp;文件包中)</P>
<P>　　　　　[vfm0M]&nbsp;中的选项可以任选，也可以不选，它们是&nbsp;jar&nbsp;命令的选项参数</P>
<P>　　　-v　生成详细报告并打印到标准输出</P>
<P>　　　-f　指定&nbsp;JAR&nbsp;文件名，通常这个参数是必须的</P>
<P>　　　-m　指定需要包含的&nbsp;MANIFEST&nbsp;清单文件</P>
<P>　　　-0　只存储，不压缩，这样产生的&nbsp;JAR&nbsp;文件包会比不用该参数产生的体积大，但速度更快</P>
<P>　　　-M　不产生所有项的清单（MANIFEST〕文件，此参数会忽略&nbsp;-m&nbsp;参数</P>
<P>　　　　　[jar-文件]&nbsp;即需要生成、查看、更新或者解开的&nbsp;JAR&nbsp;文件包，它是&nbsp;-f&nbsp;参数的附属参数</P>
<P>　　　　　[manifest-文件]&nbsp;即&nbsp;MANIFEST&nbsp;清单文件，它是&nbsp;-m&nbsp;参数的附属参数</P>
<P>　　　　　[-C&nbsp;目录]&nbsp;表示转到指定目录下去执行这个&nbsp;jar&nbsp;命令的操作。它相当于先使用&nbsp;cd&nbsp;命令转该目录下再执行不带&nbsp;-C&nbsp;参数的&nbsp;jar&nbsp;命令，它只能在创建和更新&nbsp;JAR&nbsp;文件包的时候可用。　　</P>
<P>　　文件名&nbsp;...&nbsp;指定一个文件/目录列表，这些文件/目录就是要添加到&nbsp;JAR&nbsp;文件包中的文件/目录。如果指定了目录，那么&nbsp;jar&nbsp;命令打包的时候会自动把该目录中的所有文件和子目录打入包中。</P>
<P>　　下面举一些例子来说明&nbsp;jar&nbsp;命令的用法：</P>
<P>　　1)&nbsp;jar&nbsp;cf&nbsp;test.jar&nbsp;test</P>
<P>　　该命令没有执行过程的显示，执行结果是在当前目录生成了&nbsp;test.jar&nbsp;文件。如果当前目录已经存在&nbsp;test.jar，那么该文件将被覆盖。</P>
<P>　　2)&nbsp;jar&nbsp;cvf&nbsp;test.jar&nbsp;test</P>
<P>　　该命令与上例中的结果相同，但是由于&nbsp;v&nbsp;参数的作用，显示出了打包过程，如下：</P>
<P>　　标明清单(manifest)</P>
<P>　　增加：test/(读入=&nbsp;0)&nbsp;(写出=&nbsp;0)(存储了&nbsp;0%)</P>
<P>　　增加：test/Test.class(读入=&nbsp;7)&nbsp;(写出=&nbsp;6)(压缩了&nbsp;14%)</P>
<P>　　3)&nbsp;jar&nbsp;cvfM&nbsp;test.jar&nbsp;test</P>
<P>　　该命令与&nbsp;2)&nbsp;结果类似，但在生成的&nbsp;test.jar&nbsp;中没有包含&nbsp;META-INF/MANIFEST&nbsp;文件，打包过程的信息也略有差别：</P>
<P>　　增加：test/(读入=&nbsp;0)&nbsp;(写出=&nbsp;0)(存储了&nbsp;0%)</P>
<P>　　增加：test/Test.class(读入=&nbsp;7)&nbsp;(写出=&nbsp;6)(压缩了&nbsp;14%)</P>
<P>　　4)&nbsp;jar&nbsp;cvfm&nbsp;test.jar&nbsp;manifest.mf&nbsp;test</P>
<P>　　运行结果与&nbsp;2)&nbsp;相似，显示信息也相同，只是生成&nbsp;JAR&nbsp;包中的&nbsp;META-INF/MANIFEST&nbsp;内容不同，是包含了&nbsp;manifest.mf&nbsp;的内容</P>
<P>　　5)&nbsp;jar&nbsp;tf&nbsp;test.jar</P>
<P>　　在&nbsp;test.jar&nbsp;已经存在的情况下，可以查看&nbsp;test.jar&nbsp;中的内容，如对于&nbsp;2)&nbsp;和&nbsp;3)&nbsp;生成的&nbsp;test.jar&nbsp;分别应该此命令，结果如下；</P>
<P>　　对于&nbsp;2)</P>
<P>　　META-INF/</P>
<P>　　META-INF/MANIFEST.MF</P>
<P>　　test/</P>
<P>　　test/Test.class</P>
<P>　　对于&nbsp;3)</P>
<P>　　test/</P>
<P>　　test/Test.class</P>
<P>　　6)&nbsp;jar&nbsp;tvf&nbsp;test.jar</P>
<P>　　除显示&nbsp;5)&nbsp;中显示的内容外，还包括包内文件的详细信息，如：</P>
<P>　　0&nbsp;Wed&nbsp;Jun&nbsp;19&nbsp;15:39:06&nbsp;GMT&nbsp;2002&nbsp;META-INF/</P>
<P>　　86&nbsp;Wed&nbsp;Jun&nbsp;19&nbsp;15:39:06&nbsp;GMT&nbsp;2002&nbsp;META-INF/MANIFEST.MF</P>
<P>　　0&nbsp;Wed&nbsp;Jun&nbsp;19&nbsp;15:33:04&nbsp;GMT&nbsp;2002&nbsp;test/</P>
<P>　　7&nbsp;Wed&nbsp;Jun&nbsp;19&nbsp;15:33:04&nbsp;GMT&nbsp;2002&nbsp;test/Test.class</P>
<P>　　7)&nbsp;jar&nbsp;xf&nbsp;test.jar</P>
<P>　　解开&nbsp;test.jar&nbsp;到当前目录，不显示任何信息，对于&nbsp;2)&nbsp;生成的&nbsp;test.jar，解开后的目录结构如下：</P>
<P>　　==</P>
<P>　　|--&nbsp;META-INF</P>
<P>　　|　&nbsp;`--&nbsp;MANIFEST</P>
<P>　　`--&nbsp;test</P>
<P>　　　　`--Test.class</P>
<P>jar&nbsp;xvf&nbsp;test.jar</P>
<P>　　运行结果与&nbsp;7)&nbsp;相同，对于解压过程有详细信息显示，如：</P>
<P>　　创建：META-INF/</P>
<P>　　展开：META-INF/MANIFEST.MF</P>
<P>　　创建：test/</P>
<P>　　展开：test/Test.class</P>
<P>　　9)&nbsp;jar&nbsp;uf&nbsp;test.jar&nbsp;manifest.mf</P>
<P>　　在&nbsp;test.jar&nbsp;中添加了文件&nbsp;manifest.mf，此使用&nbsp;jar&nbsp;tf&nbsp;来查看&nbsp;test.jar&nbsp;可以发现&nbsp;test.jar&nbsp;中比原来多了一个&nbsp;manifest。这里顺便提一下，如果使用&nbsp;-m&nbsp;参数并指定&nbsp;manifest.mf&nbsp;文件，那么&nbsp;manifest.mf&nbsp;是作为清单文件&nbsp;MANIFEST&nbsp;来使用的，它的内容会被添加到&nbsp;MANIFEST&nbsp;中；但是，如果作为一般文件添加到&nbsp;JAR&nbsp;文件包中，它跟一般文件无异。</P>
<P>　　10)&nbsp;jar&nbsp;uvf&nbsp;test.jar&nbsp;manifest.mf</P>
<P>　　与&nbsp;9)&nbsp;结果相同，同时有详细信息显示，如：</P>
<P>　　增加：manifest.mf(读入=&nbsp;17)&nbsp;(写出=&nbsp;19)(压缩了&nbsp;-11%)</P>
<P>　　4.&nbsp;关于&nbsp;JAR&nbsp;文件包的一些技巧</P>
<P>　　1)&nbsp;使用&nbsp;unzip&nbsp;来解压&nbsp;JAR&nbsp;文件</P>
<P>　　在介绍&nbsp;JAR&nbsp;文件的时候就已经说过了，JAR&nbsp;文件实际上就是&nbsp;ZIP&nbsp;文件，所以可以使用常见的一些解压&nbsp;ZIP&nbsp;文件的工具来解压&nbsp;JAR&nbsp;文件，如&nbsp;Windows&nbsp;下的&nbsp;WinZip、WinRAR&nbsp;等和&nbsp;Linux&nbsp;下的&nbsp;unzip&nbsp;等。使用&nbsp;WinZip&nbsp;和&nbsp;WinRAR&nbsp;等来解压是因为它们解压比较直观，方便。而使用&nbsp;unzip，则是因为它解压时可以使用&nbsp;-d&nbsp;参数指定目标目录。</P>
<P>　　在解压一个&nbsp;JAR&nbsp;文件的时候是不能使用&nbsp;jar&nbsp;的&nbsp;-C&nbsp;参数来指定解压的目标的，因为&nbsp;-C&nbsp;参数只在创建或者更新包的时候可用。那么需要将文件解压到某个指定目录下的时候就需要先将这具&nbsp;JAR&nbsp;文件拷贝到目标目录下，再进行解压，比较麻烦。如果使用&nbsp;unzip，就不需要这么麻烦了，只需要指定一个&nbsp;-d&nbsp;参数即可。如：</P>
<P>　　unzip&nbsp;test.jar&nbsp;-d&nbsp;dest/</P>
<P>　　2)&nbsp;使用&nbsp;WinZip&nbsp;或者&nbsp;WinRAR&nbsp;等工具创建&nbsp;JAR&nbsp;文件</P>
<P>　　上面提到&nbsp;JAR&nbsp;文件就是包含了&nbsp;META-INF/MANIFEST&nbsp;的&nbsp;ZIP&nbsp;文件，所以，只需要使用&nbsp;WinZip、WinRAR&nbsp;等工具创建所需要&nbsp;ZIP&nbsp;压缩包，再往这个&nbsp;ZIP&nbsp;压缩包中添加一个包含&nbsp;MANIFEST&nbsp;文件的&nbsp;META-INF&nbsp;目录即可。对于使用&nbsp;jar&nbsp;命令的&nbsp;-m&nbsp;参数指定清单文件的情况，只需要将这个&nbsp;MANIFEST&nbsp;按需要修改即可。</P>
<P>　　3)&nbsp;使用&nbsp;jar&nbsp;命令创建&nbsp;ZIP&nbsp;文件</P>
<P>　　有些&nbsp;Linux&nbsp;下提供了&nbsp;unzip&nbsp;命令，但没有&nbsp;zip&nbsp;命令，所以需要可以对&nbsp;ZIP&nbsp;文件进行解压，即不能创建&nbsp;ZIP&nbsp;文件。如要创建一个&nbsp;ZIP&nbsp;文件，使用带&nbsp;-M&nbsp;参数的&nbsp;jar&nbsp;命令即可，因为&nbsp;-M&nbsp;参数表示制作&nbsp;JAR&nbsp;包的时候不添加&nbsp;MANIFEST&nbsp;清单，那么只需要在指定目标&nbsp;JAR&nbsp;文件的地方将&nbsp;.jar&nbsp;扩展名改为&nbsp;.zip&nbsp;扩展名，创建的就是一个不折不扣的&nbsp;ZIP&nbsp;文件了，如将上一节的第&nbsp;3)&nbsp;个例子略作改动：</P>
<P>　　jar&nbsp;cvfM&nbsp;test.zip&nbsp;test <BR></P></FONT><img src ="http://www.blogjava.net/fortune/aggbug/31122.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-17 08:58 <a href="http://www.blogjava.net/fortune/archive/2006/02/17/31122.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用java,tomcat,mysql时对机器的设置</title><link>http://www.blogjava.net/fortune/archive/2006/02/17/31123.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Fri, 17 Feb 2006 00:58:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/17/31123.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/31123.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/17/31123.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/31123.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/31123.html</trackback:ping><description><![CDATA[<P>对windows已经无可奈何了......无休止的重装系统我都麻木了，只好把一些资料好好收集下.....（下次重装还能用的上）<BR><BR>感谢网上的许多前辈的经验总结，为了帮助象我一样的初学者在此总结了不少作者的经验，非常感谢他们的无私奉献精神，也希望更多的人把这种精神发扬光大，以下软件下载连接地址无法显示的话，请直接到官方网站下载即可！<BR>&nbsp;<BR>软件下载<BR>Mysql<BR>下载版本：mysql-4.1.13-win32.zip(Windows downloads) <BR><A href="http://dev.mysql.com/downloads/mysql/4.1.html"><U><FONT color=#000000>http://dev.mysql.com/downloads/mysql/4.1.html</FONT></U></A></P>
<P>JDBC驱动<BR>下载版本：mysql-connector-java-3.1.10.zip<BR><A href="http://dev.mysql.com/downloads/connector/j/3.1.html"><U><FONT color=#000000>http://dev.mysql.com/downloads/connector/j/3.1.html</FONT></U></A></P>
<P>下载j2sdk<BR>下载版本：jdk-1_5_0_04-windows-i586-p.exe<BR><A href="http://java.sun.com/j2se/1.5.0/download.jsp"><U><FONT color=#000000>http://java.sun.com/j2se/1.5.0/download.jsp</FONT></U></A></P>
<P>下载tomcat<BR>下载版本: jakarta-tomcat-5.5.9.exe<BR><A href="http://jakarta.apache.org/site/downloads/downloads_tomcat-5.cgi"><U><FONT color=#000000>http://jakarta.apache.org/site/downloads/downloads_tomcat-5.cgi</FONT></U></A></P>
<P>安装,配置j2sdk：</P>
<P>执行j2sdk安装程序，按默认设置进行安装，也可自定义路径，但需修改下面的配置</P>
<P>配置j2sdk:</P>
<P>配置环境变量:</P>
<P>我的电脑-&gt;属性-&gt;高级-&gt;环境变量-&gt;系统变量中添加以下环境变量： <BR>JAVA_HOME=C:\Program Files\Java\jdk1.5.0_04<BR>CLASSPATH=%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;<BR>path=%JAVA_HOME%\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem</P>
<P>写一个简单的java程序来测试J2SDK是否已安装成功： <BR>public class hello<BR>{ <BR>&nbsp;public static void main(String args[])<BR>&nbsp;{ <BR>&nbsp;System.out.println("Hello"); <BR>&nbsp;} <BR>} </P>
<P>将程序保存为文件名为hello.java的文件。 </P>
<P>打开命令提示符窗口，进入到hello.java所在目录，键入下面的命令 <BR>javac hello.java <BR>java hello <BR>此时若打印出来hello则安装成功，若没有打印出这句话，仔细检查以上配置是否正确。<BR>注意系统文件夹选项中应确定“隐藏已知文件类型的扩展名”不勾选（我的电脑—工具—查看） </P>
<P>安装,配置tomcat<BR>执行tomcat安装程序，按默认设置进行安装，也可自定义路径，但需修改下面的配置</P>
<P>我的电脑-&gt;属性-&gt;高级-&gt;环境变量-&gt;系统变量中添加以下环境变量<BR>CATALINA_HOME=C:\Program Files\Apache Software Foundation\Tomcat 5.5<BR>CATALINA_BASE=C:\Program Files\Apache Software Foundation\Tomcat 5.5 </P>
<P>修改环境变量中的classpath，把tomat安装目录下的common\lib下的servlet-api.jar添加到classpath中去，<BR>修改后的classpath如下： <BR>classpath=%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\lib\servlet-api.jar;</P>
<P>启动tomcat，在IE中访问<A href="http://localhost:8080/"><U><FONT color=#000000>http://localhost:8080</FONT></U></A>，若看到tomcat的欢迎页面的话说明安装成功。</P>
<P>安装mysql<BR>解压缩mysql-4.1.13-win32.zip，运行setup.exe<BR>首先出现的是安装向导欢迎界面,直接点击“Next”<BR>继续，选择安装类型,选择“自定义”custom安装，然后点“Next”下一步，出现自定义安装界面<BR>选择安装路径：C:\MySQL Server 4.1(可自定义)<BR>点“OK”返回到自定义安装界面，路径已改为设置的路径<BR>点“Next”，准备开始安装<BR>点“Install”开始安装<BR>完成后出现创建MySQL.com帐号的界面<BR>如果是首次使用MySQL，选“Create anew free MySQL.com accout”<BR>点“Next”，输入你的Email地址和自己设定的用于登录MySQL.com的密码<BR>填完后点“Next”进入第二步<BR>填写姓名等相关信息，填完点“Next”，进入第三步<BR>填完电话号码、公司名称等信息后，点“Next”，<BR>然后出现预览你刚才填的信息的界面，点“Next”出现安装完成界面<BR>注意，这里有个配置向导的选项（Configure the MySQL Server now），<BR>建议勾选立即配置你的MySQL。许多说安装完MySQL后无法启动，原因就在于没有配置MySQL。<BR>点击“Finish”完成安装，并开始配置MySQL<BR>点“Next”，进入配置类型选择页面。选“Detailed configuration”(详细配置)<BR>点“Next”，进入服务类型选择页面。选“Developer Machine”（开发者机器），这样占用系统的资源不会很多<BR>点“Next”后，进入数据库用法选择页面。选择“Multifunctional Database”<BR>点“Next”，进入选择InnoDB数据存放位置页面<BR>不用更改设置，直接放在Installation Path安装目录里即可，然后点“Next”，选择MySQL的同时联接数<BR>选择“Manual Setting”，设置为100(根据自己需要，酌情设置)<BR>点“Next”，配置MySQL在TCP/IP通讯环境中的端口选择默认的3306端口即可。<BR>点“Next”，选择MySQL中的字符设置<BR>注意，这里的选择将会影响你是否能在MySQL中使用中文。选择gb2312字符集以便支持简体中文<BR>点“Next”，设置Windows服务选项<BR>注意，这里的选择很关键。<BR>“Install As Windows Service”一定要勾选，这是将MySQL作为Windows的服务运行。<BR>“Service Name”就用默认的“MySQL”<BR>下面的“Launch the MySQL Server automatically”一定要勾选，这样Windows启动时，MySQL就会自动启动服务，要不然就要手工启动MySQL。<BR>许多人说安装MySQL后无法启动、无法连接、出现10061错误，原因就在这里。<BR>点“Next”，设置根帐号root的登录密码<BR>“Modify Security Settings”是设置根帐号的密码，输入你设定的密码即可。<BR>“Create An Anonymous Account”是创建一个匿名帐号，这样会导致未经授权的用户非法访问你的数据库，有安全隐患，建议不要勾选。<BR>点“Next”，MySQL配置向导将依据你上面的所有设定配置MySQL，以便MySQL的运行符合你的需要<BR>点“Execute”开始配置，当出现“Service started successfully”时，说明你的配置完成，MySQL服务启动成功<BR>点“Finish”完成，整个MySQL的配置完成，剩下的就是用MySQL客户端连接MySQL服务器，然后使用了。</P>
<P><BR>安装JDBC驱动：<BR>解压缩mysql-connector-java-3.1.10.zip<BR>将要使用的是mysql-connector-java-3.1.10-bin-g.jar和mysql-connector-java-3.1.10-bin.jar</P>
<P>配置<BR>在C:\Program Files\Java目录下建立mysqlforjdbc子目录，进入该目录将mysql-connector-java-3.1.10-bin.jar到该目录下<BR>进入C:\Program Files\Java\jdk1.5.0_04\lib目录将mysql-connector-java-3.1.10-bin-g.jar拷贝到该目录下<BR>然后配置classpath，追加%JAVA_HOME%\lib\mysql-connector-java-3.1.10-bin-g.jar;C:\Program Files\Java\mysqlforjdbc\mysql-connector-java-3.1.10-bin.jar;到该环境变量中去<BR>追加以后环境变量如下：<BR>CLASSPATH=%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;C:\Program Files\Apache Software Foundation\Tomcat5.5\common\lib\servlet-api.jar;%JAVA_HOME%\lib\mysql-connector-java-3.1.10-bin-g.jar;C:\Program Files\Java\mysqlforjdbc\mysql-connector-java-3.1.10-bin.jar;<BR>配置这个的目的是让java应用程序找到连接mysql的驱动．</P>
<P><BR>查看并启动MySQL服务<BR>在Windows XP下安装完MySQL后，它就已经自动启动服务了，并且在开始菜单中有其客户端的快捷方式连接<BR>可以通过Windows的服务管理器查看。“开始”－“运行”，输入“services.msc”，回车。<BR>弹出Windows的服务管理器，然后就可以看见服务名为“mysql”的服务项了，其右边标明“已启动”<BR>在开始菜单-所有程序-MySQL-MySQL Server 4.1-MySQL Command Line Client用客户端的快捷方式连接<BR>输入安装是设置的密码即可</P>
<P><BR>数据库的使用</P>
<P>Mysql安装完毕以后，在开始菜单-所有程序-MySQL-MySQL Server 4.1-MySQL Command Line Client用客户端的快捷方式连接<BR>输入安装时设置的密码</P>
<P>使用mysql的基本命令(在mysql命令行编辑每输入完命令后最后一定要有分号)<BR>显示数据库：show databases;<BR>使用数据库：use 数据库名；</P>
<P><BR>建库<BR>在mysql里建一个数据库first，以及在数据库里建一个表about<BR>命令：create database first;</P>
<P>为数据库设置权限（用户和密码）<BR>命令：grant all privileges on first.* to <A href="mailto:test@localhost"><U><FONT color=#000000>test@localhost</FONT></U></A> identified by&nbsp; “123456”;<BR>当你执行完这个命令以后，只要你再以用户名：test,密码：123456登录时你就只可以对first这个数据库操作，这样避开使用root<BR>输入命令：use first;<BR>使用first数据库；</P>
<P>在first库中建表<BR>命令：create table about(id int(8) primary key,name varchar(10));</P>
<P>在表中假如数据：<BR>命令：insert into&nbsp; about values('xyw1026','laojiang');</P>
<P>退出<BR>命令：exit</P>
<P></P>
<P>JSP连接mysql<BR>在C:\Program Files\Apache Software Foundation\Tomcat5.5\webapps目录下建立子目录myapp<BR>进入C:\Program Files\Apache Software Foundation\Tomcat5.5\webapps\myapp目录下<BR>用记事本编写一个文件保存为first.jsp<BR>代码如下：<BR>&lt;%@ page contentType="text/html;charset=gb2312"%&gt; <BR>&lt;%@ page import="java.sql.*"%&gt; <BR>&lt;html&gt; <BR>&lt;body&gt; <BR>&lt;%Class.forName("org.gjt.mm.mysql.Driver").newInstance(); <BR>String url ="jdbc:mysql://localhost/softforum?user=soft&amp;password=soft1234&amp;useUnicode=true&amp;characterEncoding=8859_1" <BR>//first为你的数据库名 <BR>Connection conn= DriverManager.getConnection(url); <BR>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <BR>String sql="select * from first"; <BR>ResultSet rs=stmt.executeQuery(sql); <BR>while(rs.next()) {%&gt; <BR>您的第一个字段内容为：&lt;%=rs.getString(1)%&gt; <BR>您的第二个字段内容为：&lt;%=rs.getString(2)%&gt; <BR>&lt;%}%&gt; <BR>&lt;%out.print("数据库操作成功，恭喜你");%&gt; <BR>&lt;%rs.close(); <BR>stmt.close(); <BR>conn.close(); <BR>%&gt; <BR>&lt;/body&gt; <BR>&lt;/html&gt;</P>
<P>在浏览器中输入：<BR><A href="http://127.0.0.1:8080/myapp/first.jsp"><U><FONT color=#000000>http://127.0.0.1:8080/myapp/first.jsp</FONT></U></A><BR>若出现：<BR>id|num<BR>0 |laojiang</P>
<P>数据库操作成功，恭喜你</P>
<P>表示配置成功</P>
<P></P>
<P><BR>进入C:\Program Files\Apache Software Foundation\Tomcat5.5\webapps\myapp目录<BR>在myapp目录下新建一个目录WEB-INF，注意，目录名称是区分大小写的； <BR>在WEB-INF下用记事本新建一个文件，命名为web.xml，内容如下： </P>
<P>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt; </P>
<P>&lt;!DOCTYPE web-app <BR>PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" <BR>"<A href="http://java.sun.com/dtd/web-app_2_3.dtd"><U><FONT color=#000000>http://java.sun.com/dtd/web-app_2_3.dtd</FONT></U></A>"&gt; </P>
<P>&lt;web-app&gt; <BR>&lt;display-name&gt;My Web Application&lt;/display-name&gt; <BR>&lt;description&gt; <BR>A application for test. <BR>&lt;/description&gt; <BR>&lt;/web-app&gt; </P>
<P>在myapp下用记事本新建一个测试的jsp页面，文件名为index.jsp，文件内容如下： </P>
<P>&lt;html&gt;&lt;body&gt;&lt;center&gt; <BR>Now time is: &lt;%=new java.util.Date()%&gt; <BR>&lt;/center&gt;&lt;/body&gt;&lt;/html&gt; </P>
<P><BR>重启Tomcat <BR>打开浏览器，输入<A href="http://localhost:8080/myapp/index.jsp"><U><FONT color=#000000>http://localhost:8080/myapp/index.jsp</FONT></U></A> <BR>看到当前时间的话说明成功安装。 </P>
<P></P>
<P>建立自己的Servlet： <BR>用记事本新建一个servlet程序，文件名为HelloWorld.java，文件内容如下： </P>
<P>import java.io.*;<BR>import javax.servlet.*;<BR>import javax.servlet.http.*;<BR>public class HelloWorld extends HttpServlet<BR>{<BR>public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException<BR>{</P>
<P>response.setContentType("text/html"); <BR>PrintWriter out = response.getWriter();<BR>out.println("&lt;html&gt;&lt;head&gt;&lt;title&gt;");<BR>out.println("This is my first Servlet");<BR>out.println("&lt;/title&gt;&lt;/head&gt;&lt;body&gt;");<BR>out.println("&lt;h1&gt;Hello,World!&lt;/h1&gt;");<BR>out.println("&lt;/body&gt;&lt;/html&gt;");</P>
<P>}<BR>} </P>
<P><BR>编译 <BR>将HelloWorld.java剪切到C:\Program Files\Apache Software Foundation\Tomcat5.5\common\classes目录下<BR>命令行方式下输入： <BR>cd C:\Program Files\Apache Software Foundation\Tomcat5.5\common\classes<BR>javac HelloWorld.java <BR>用javac HelloWorld.java来编译这个文件，如果出现无法import javax.servlet.*<BR>则将C:\Program Files\Apache Software Foundation\Tomcat5.5\common\lib目录下的servlet-api.jar文件拷贝并添加到<BR>C:\Program Files\Java\jre1.5.0_04\lib\ext目录中去就可以了</P>
<P>然后在C:\Program Files\Apache Software Foundation\Tomcat5.5\common\classes下会产生一个编译后的servlet文件：HelloWorld.class<BR>用记事本打开C:\Program Files\Apache Software Foundation\Tomcat5.5\webapps\ROOT\WEB-INF目录下的web.xml如下所示，添加后的内容如下: <BR>.<BR>.<BR>.<BR>&lt;!-- JSPC servlet mappings start --&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;servlet&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;org.apache.jsp.index_jsp&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;org.apache.jsp.index_jsp&lt;/servlet-class&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/servlet&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;servlet-mapping&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;org.apache.jsp.index_jsp&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/index.jsp&lt;/url-pattern&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/servlet-mapping&gt;</P>
<P>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; &lt;servlet&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;HelloWorld&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;HelloWorld&lt;/servlet-class&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/servlet&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;servlet-mapping&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;HelloWorld&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/servlet/HelloWorld&lt;/url-pattern&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/servlet-mapping&gt;</P>
<P>&lt;!-- JSPC servlet mappings end --&gt;</P>
<P>&lt;/web-app&gt;</P>
<P>这段话中的servlet这一段声明了你要调用的Servlet，而servlet-mapping则是将声明的servlet“映射”到/servlet/HelloWorld地址上 </P>
<P>启动Tomcat，启动浏览器，输入<A href="http://localhost:8080//servlet/HelloWorld"><U><FONT color=#000000>http://localhost:8080//servlet/HelloWorld</FONT></U></A> 如果看到输出HelloWorld！就说明编写的servlet成功了。 <BR>注意：修改了web.xml以及新加了class，都要重启Tomcat </P>
<P><BR>也可以在自己创建的目录下测试如：<BR>将HelloWorld.class拷贝到C:\Program Files\Apache Software Foundation\Tomcat5.5\webapps\myapp\WEB-INF\classes目录下<BR>其中classes目录若没有就创建一个<BR>用记事本打开C:\Program Files\Apache Software Foundation\Tomcat5.5\webapps\myapp\WEB-INF目录下的web.xml如下所示，修改后的内容如下: <BR>.<BR>.<BR>.<BR>&lt;!-- JSPC servlet mappings start --&gt;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; &lt;servlet&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;HelloWorld&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;HelloWorld&lt;/servlet-class&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/servlet&gt;</P>
<P>&nbsp;&nbsp;&nbsp; &lt;servlet-mapping&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;HelloWorld&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/servlet/HelloWorld&lt;/url-pattern&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/servlet-mapping&gt;</P>
<P>&lt;!-- JSPC servlet mappings end --&gt;</P>
<P>&lt;/web-app&gt;</P>
<P><BR>启动Tomcat，启动浏览器，输入<A href="http://localhost:8080/myapp/servlet/HelloWorld"><U><FONT color=#000000>http://localhost:8080/myapp/servlet/HelloWorld</FONT></U></A> 如果看到输出HelloWorld！就说明编写的servlet成功了。 <BR>注意：修改了web.xml以及新加了class，都要重启Tomcat </P>
<P><BR>建立自己的javaBean： </P>
<P>用记事本新建一个java程序，文件名为TestBean.java，文件内容如下： <BR>package test; <BR>public class TestBean{ <BR>private String name = null; <BR>public TestBean(String strName_p){ <BR>this.name=strName_p; <BR>} <BR>public void setName(String strName_p){ <BR>this.name=strName_p; <BR>} <BR>public String getName(){ <BR>return this.name; <BR>} <BR>} </P>
<P>编译 <BR>将TestBean.java放在c:\test下，使用如下命令编译： <BR>C:\test&gt;javac TestBean.java <BR>然后在c:\Test下会产生一个编译后的bean文件：TestBean.class <BR>将TestBean.class文件剪切到C:\Program Files\Apache Software Foundation\Tomcat5.5\webapps\myapp\WEB-INF\classes\test目录下，<BR>若无某些子目录则创建一个 </P>
<P>新建一个TestBean.jsp文件，文件内容为： <BR>&lt;%@ page import="test.TestBean" %&gt; <BR>&lt;html&gt;&lt;body&gt;&lt;center&gt; <BR>&lt;% <BR>TestBean testBean=new TestBean("This is a test java bean."); <BR>%&gt; <BR>Java bean name is: &lt;%=testBean.getName()%&gt; <BR>&lt;/center&gt;&lt;/body&gt;&lt;/html&gt; </P>
<P>重启Tomcat，启动浏览器，输入<A href="http://localhost:8080/myapp/TestBean.jsp"><U><FONT color=#000000>http://localhost:8080/myapp/TestBean.jsp</FONT></U></A> 如果看到输出Java bean name is: This is a test java bean<BR>就说明编写的javaBean成功了。</P><img src ="http://www.blogjava.net/fortune/aggbug/31123.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-17 08:58 <a href="http://www.blogjava.net/fortune/archive/2006/02/17/31123.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse3.1下JFace和SWT工程环境配置方法</title><link>http://www.blogjava.net/fortune/archive/2006/02/17/31120.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Fri, 17 Feb 2006 00:57:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/17/31120.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/31120.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/17/31120.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/31120.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/31120.html</trackback:ping><description><![CDATA[假设eclipse目录为d:\eclipse已经建好一个名为MyProject的工程，下面将介绍如何为该工程设置正确的环境以使用JFace/SWT开发GUI程序。<BR><BR>1.为SWT创建类路径变量。在Eclipse中右键选中MyProject，选择Properties，选择左侧的Java Build Path，选择Libraries，点击Add Variable，来添加各种变量，用它们来表示编译时所需的各个库(*.jar)。继续Configure Variables，然后点击New按钮，添加路径变量，name：SWT_LIB，file：d:/eclipse/plugins/org.eclipse.swt.win32.win32.x86_3.1.0.jar。<BR><BR>2.用上面相同的方法，创建JFACE_LIB变量，name: JFACE_LIB，file: d:/eclipse/plugins/org.eclipse.jface_3.1.0.jar；创建BOOT_LIB变量，name: BOOT_LIB，file: d:/eclipse/plugins/org.eclipse.core.boot_3.0.0.jar；创建RUNTIME_LIB变量，name: RUNTIME_LIB，file: d:/eclipse/plugins/org.eclipse.core.runtime_3.1.0.jar；创建WORKBENCH_LIB变量，name: WORKBENCH_LIB，file: d:/eclipse/plugins/org.eclipse.ui.workbench_3.1.0.jar。<BR><BR>3.在Properties/Java Build Path/Libraries中点击Add Variable，选中刚才添加的几个变量，加入到工程中。<BR><BR>4.解压d:/eclipse/plugins/org.eclipse.swt.win32.win32.x86_3.1.0.jar，将其中的swt-win32-3135.dll拷贝到$PATH环境变量指向的目录。<BR><img src ="http://www.blogjava.net/fortune/aggbug/31120.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-17 08:57 <a href="http://www.blogjava.net/fortune/archive/2006/02/17/31120.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java事件（转）</title><link>http://www.blogjava.net/fortune/archive/2006/02/17/31119.html</link><dc:creator>fortune</dc:creator><author>fortune</author><pubDate>Fri, 17 Feb 2006 00:56:00 GMT</pubDate><guid>http://www.blogjava.net/fortune/archive/2006/02/17/31119.html</guid><wfw:comment>http://www.blogjava.net/fortune/comments/31119.html</wfw:comment><comments>http://www.blogjava.net/fortune/archive/2006/02/17/31119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fortune/comments/commentRss/31119.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fortune/services/trackbacks/31119.html</trackback:ping><description><![CDATA[在学了这么久的JAVA事件总觉的有点搞不清，我想是没有总结的原因吧。下面我将我的几个小例子来更清的了解一下JAVA事件。JAVA事件无非就是键盘事件，鼠标事件，按钮等事件。专业点可以分为语义事件（按钮等到事件）和低层事件（键盘事件，鼠标事件）；下面我简要的总结一下： 1、鼠标事件：点鼠标按钮事它会调用三个监听器方法：mousePressed,mouseReleased,mouseClicked.<BR>鼠标事件提供了mousePressed,mouseClicked,mouseDragged,mouseEntered,mouseExited， mouseUp，mouseDown，mouseDrag等事件。下面介绍一个鼠标一例子：<BR>import java.awt.*;<BR>import java.applet.Applet;<BR>public class CountClick extends Applet<BR>{int CurrentMarks=0;<BR>int a,b;<BR>public boolean mouseDown(Event evt,int x,int y)//鼠标按下时做的事<BR>{ CurrentMarks++;//计录按下次数<BR>repaint();//刷新面版<BR>a=x;//得到鼠标的横坐标<BR>b=y;//得到鼠标的竖坐标<BR>return true;<BR>}<BR>public void paint(Graphics g)<BR>{ g.drawString(" "+CurrentMarks,10,10);//打印按下次数<BR>g.drawString(" "+a,10,30);//打印鼠标的横坐标<BR>g.drawString(" "+b,10,20);//打印鼠标的坚坐标<BR>}<BR>}<BR>//&lt;applet code="CountClick.class" width="200" height="100"&gt;&lt;/applet&gt; <BR>2、键盘事件：如果我们希望使用键盘获得输入信息，就必须处理键盘事件。我们可以用在Conponent的keyDown来实现。如下例子：<BR>import java.applet.Applet;import java.awt.*;<BR>{ char Presskey;<BR>public boolean keyDown(Event evt, int key)<BR>{ Presskey=(char)key;//记录你按下的键<BR>repaint(); return true;<BR>}<BR>public void paint(Graphics g)<BR>{ g.drawString(Presskey,10,10); }//打印你按下的键值<BR>}<BR>3、铵钮等事件：这方面的内容比较多，通过一个例子做一个简单的介绍。<BR>//*******2004年，11月8日**************//<BR>//*******小豆子对事件进一步了解******//<BR>//*******注意Repaint()方法的使用******//<BR>//**通过本程序对JAVA的数据隐藏有了一近一步的了解***///<BR>//*******继续努力。gogogogogo******//<BR>import java.awt.*;<BR>import java.applet.Applet;<BR>import java.awt.event.*;<BR>public class Awtactiontest2 extends Applet implements ItemListener ,ActionListener<BR>//实现ItemListener ,ActionListener接口<BR>{<BR>int num = 5;<BR>Choice ch=new Choice ();<BR>Button one=new Button("one");<BR>Button two=new Button("two"); <BR>Button three=new Button("three");<BR>Image aa[];<BR>Image a;<BR>public void init()<BR>{<BR>aa = new Image[num];<BR>for(int i = 0; i &lt; num; i++)//把图片的路径加到数组中存储<BR>{<BR>aa[i] = getImage(getDocumentBase(),"A"+(i+1)+".JPG");<BR>}<BR>num=4;//给一个初值<BR>this.setBackground(Color.white);<BR>ch. addItem("A1.JPG" );<BR>ch. addItem ("A2.JPG" );<BR>ch. addItem ("A3.JPG" );<BR>ch. addItem ("A4.JPG" );<BR>add (ch);<BR>a = getImage(getDocumentBase(),"A1.JPG");//对a一个初值；<BR>add (one);<BR>add (two);<BR>add (three);<BR>ch.addItemListener(this);//注意把ItemListener接口implements进来<BR>one.addActionListener(this);//注意把ActionListener接口implements进来<BR>two.addActionListener(this);<BR>three.addActionListener(this);<BR>}<BR>public void itemStateChanged (ItemEvent e)<BR>{<BR><BR>a = getImage(getDocumentBase(),ch.getSelectedItem ());<BR>repaint();<BR>}<BR>public void actionPerformed(ActionEvent e)<BR>{<BR>if(e.getSource()==one)<BR>{<BR>num=1;<BR>repaint();//对程序刷新<BR>}<BR>if(e.getSource()==two)<BR>{<BR>num=2;<BR>repaint();<BR>}<BR>if(e.getSource()==three)<BR>{<BR>num=3;<BR>repaint();<BR>}<BR>}<BR>public void paint(Graphics g)<BR>{<BR>//g.drawImage(aa[i],0,0,this);<BR><BR>int w=a.getWidth(this);<BR>int h=a.getHeight(this);<BR>// g.drawLine(100,1,200,500);<BR>try{ <BR>g.drawImage(a,20,300,10+w,20+h,this);//要抓异常，如果图片找不到呢<BR>g.drawImage(aa[num],50,50,200,200,this);<BR>}<BR>catch(Exception e)<BR>{<BR>System.out.println(e);<BR>}<BR>}<BR>public boolean handleEvent(Event ewt)//关窗体,我原以为这个可以把死循环给关了，其它不然.一样的关不了程序<BR>{<BR>if(ewt.id==Event.WINDOW_DESTROY)<BR>System.exit(0);<BR>else <BR>return super.handleEvent(ewt);<BR>return true;<BR>}<BR>}<BR>//&lt;Applet code="Awtactiontest2.class" width=400 height=500&gt;&lt;/applet&gt;<BR><BR><img src ="http://www.blogjava.net/fortune/aggbug/31119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fortune/" target="_blank">fortune</a> 2006-02-17 08:56 <a href="http://www.blogjava.net/fortune/archive/2006/02/17/31119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>