<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>tao of yue &#187; 搜索结果  &#187;  sso</title>
	<atom:link href="http://niyue.com/?s=sso&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://niyue.com</link>
	<description>literally, "way" or "path"</description>
	<lastBuildDate>Sun, 18 Apr 2010 03:28:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>static关键字的含义</title>
		<link>http://niyue.com/2006/09/23/static%e5%85%b3%e9%94%ae%e5%ad%97%e7%9a%84%e5%90%ab%e4%b9%89/</link>
		<comments>http://niyue.com/2006/09/23/static%e5%85%b3%e9%94%ae%e5%ad%97%e7%9a%84%e5%90%ab%e4%b9%89/#comments</comments>
		<pubDate>Sat, 23 Sep 2006 07:23:25 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=197</guid>
		<description><![CDATA[在许多编程语言里面都可以见到static这个关键字,虽然很常见,但是对于它的具体含义我却一直不是很了解,为什么这个要叫做static而不是其他?比如在C,C++,Java,C#里面都有这个关键字,说明这个关键字的字面意思应该是能够表明它的含义的(否则不会这么巧大家都用这个关键字),但是这个关键字的含义又不是那么简单可以望文生义,今天自己花了一些时间看了看,有了个相对清晰的了解.
这个Q&#038;A(What does the keyword &#8217;static&#8217; mean?)是我最开始找到的资料,问的问题是我想问的,但是答案确不是.
The static keyword denotes that a member variable, or method, can be accessed without requiring an instantiation of the class to which it belongs.
它说明了static关键字所表示的结果含义,但是没有说明为什么代表这个含义使用了static这个关键字.而这个含义其实是有一定编程经验的人都知道的,大家都这么用,但是不知道为什么这个是叫static而不是其他的.
我又继续看了一些资料(参见下面的参考文献),自己总结了一下:

static这个关键字想要表达的是变量或者方法等的生命周期,而不是访问的作用域的控制,这可以和public,private(Java等语言)这些关键字区分开来.
static这个关键字的字面含义&#8221;静态&#8221;说明了由static声明的变量或者函数等的生命周期控制信息的存放地点&#8211;静态数据存储区域.

接下来我详细的解释这两点:

static声明的往往是一个用做全局的变量,类实例等.这个&#8221;全局&#8221;主要说的是通过static声明,声明的变量等可以增大其生命周期到某个全局的范围,比如Java类里面声明了一个static的变量,则它的生命周期和这个类相同&#8211;贯穿程序运行的全过程.因为不会消亡,所以你在引用这一static变量的时候只会引用到同一个变量,看起来就是一个类级别的变量(从结果看起来这样理解也可以,类似与Ruby中的@@来声明变量,但这样很容易知其然而不知所以然).在c语言中并没有类的概念,因此这种说法就不大行得通.在c语言中声明了一个static的变量之后,这一变量的生命周期就可以跨越声明它的文件中的所有函数,当然,这个时候的含义可能也包括了访问控制的含义在里面,但是我理解更主要的还是生命周期的改变.
生命周期控制数据的存放地点.要理解这一点,首先要知道有哪些地方可以用来存储程序中使用的数据.对于这一点,文献[1][2]讲述的很清楚,大家可以参考,我就不重复了.主要讲一下随机存储器RAM中的三种存储方式栈,堆,静态存储(stack,heap,static storage).看到这里,大家应该都知道由static声明的话,生命周期相关的信息会存在哪里了吧,至于static这个名字是怎么来的,也不用多说了.对Java来说,

一般的不是由static声明的变量,如果是原始的数据类型,会直接保存在stack上,如果是通过new得到的对象实例,这一对象的引用会保存在堆栈上,其实际的数据会保存在heap上,如果这一变量相关的数据被pop出栈,那么这一变量的生命周期也就结束了.如果是对象的话,其在堆上的对应内存也会被释放,这以后就再也无法访问这一对象了.
如果是由static声明的变量,不是在stack上存放引用等信息,而是在静态存储区域存放,这样即使堆栈内容变化也不会影响这些变量的创建或者消亡,从而可以不实例化一个类直接通过静态存储区域找到这一变量使用.


这些就是我的一个小结,有部分是我自己的理解,可能不是很正确,请大家指教.
Update: 文献[9]是一篇写的很好的文章,我对static声明函数的含义可能有些曲解,大家可以参考文献[9]最后的static函数及其扩展分析.
参考文献:

对象保存在哪里? http://www.qsl.net/bd5hag/JavaCourse/Lesson2/2_9_1.htm
c storage class http://www.phim.unibe.ch/comp_doc/c_manual/C/SYNTAX/storage_class.html#static
Static Variable in Wikipedia http://en.wikipedia.org/wiki/Static_variable
Local Variable  in Wikipedia http://en.wikipedia.org/wiki/Local_variable
Call Stack in Wikipedia http://en.wikipedia.org/wiki/Call_stack
this and static keyword, Thinking in Java  [...]]]></description>
			<content:encoded><![CDATA[<p>在许多编程语言里面都可以见到static这个关键字,虽然很常见,但是对于它的具体含义我却一直不是很了解,为什么这个要叫做static而不是其他?比如在C,C++,Java,C#里面都有这个关键字,说明这个关键字的字面意思应该是能够表明它的含义的(否则不会这么巧大家都用这个关键字),但是这个关键字的含义又不是那么简单可以望文生义,今天自己花了一些时间看了看,有了个相对清晰的了解.</p>
<p>这个<a href="http://www.javacoffeebreak.com/faq/faq0010.html">Q&#038;A</a>(What does the keyword &#8217;static&#8217; mean?)是我最开始找到的资料,问的问题是我想问的,但是答案确不是.</p>
<blockquote><p>The static keyword denotes that a member variable, or method, can be accessed without requiring an instantiation of the class to which it belongs.</p></blockquote>
<p>它说明了static关键字所表示的结果含义,但是没有说明为什么代表这个含义使用了static这个关键字.而这个含义其实是有一定编程经验的人都知道的,大家都这么用,但是不知道为什么这个是叫static而不是其他的.<br />
我又继续看了一些资料(参见下面的参考文献),自己总结了一下:</p>
<ol>
<li>static这个关键字想要表达的是变量或者方法等的生命周期,而不是访问的作用域的控制,这可以和public,private(Java等语言)这些关键字区分开来.</li>
<li>static这个关键字的字面含义&#8221;静态&#8221;说明了由static声明的变量或者函数等的生命周期控制信息的存放地点&#8211;静态数据存储区域.</li>
</ol>
<p>接下来我详细的解释这两点:</p>
<ol>
<li>static声明的往往是一个用做全局的变量,类实例等.这个&#8221;全局&#8221;主要说的是通过static声明,声明的变量等可以增大其生命周期到某个全局的范围,比如Java类里面声明了一个static的变量,则它的生命周期和这个类相同&#8211;贯穿程序运行的全过程.因为不会消亡,所以你在引用这一static变量的时候只会引用到同一个变量,看起来就是一个类级别的变量(从结果看起来这样理解也可以,类似与Ruby中的@@来声明变量,但这样很容易知其然而不知所以然).在c语言中并没有类的概念,因此这种说法就不大行得通.在c语言中声明了一个static的变量之后,这一变量的生命周期就可以跨越声明它的文件中的所有函数,当然,这个时候的含义可能也包括了访问控制的含义在里面,但是我理解更主要的还是生命周期的改变.</li>
<li>生命周期控制数据的存放地点.要理解这一点,首先要知道有哪些地方可以用来存储程序中使用的数据.对于这一点,文献[1][2]讲述的很清楚,大家可以参考,我就不重复了.主要讲一下随机存储器RAM中的三种存储方式栈,堆,静态存储(stack,heap,static storage).看到这里,大家应该都知道由static声明的话,生命周期相关的信息会存在哪里了吧,至于static这个名字是怎么来的,也不用多说了.对Java来说,</li>
<ol>
<li>一般的不是由static声明的变量,如果是原始的数据类型,会直接保存在stack上,如果是通过new得到的对象实例,这一对象的引用会保存在堆栈上,其实际的数据会保存在heap上,如果这一变量相关的数据被pop出栈,那么这一变量的生命周期也就结束了.如果是对象的话,其在堆上的对应内存也会被释放,这以后就再也无法访问这一对象了.</li>
<li>如果是由static声明的变量,不是在stack上存放引用等信息,而是在静态存储区域存放,这样即使堆栈内容变化也不会影响这些变量的创建或者消亡,从而可以不实例化一个类直接通过静态存储区域找到这一变量使用.</li>
</ol>
</ol>
<p>这些就是我的一个小结,有部分是我自己的理解,可能不是很正确,请大家指教.</p>
<p>Update: 文献[9]是一篇写的很好的文章,我对static声明函数的含义可能有些曲解,大家可以参考文献[9]最后的static函数及其扩展分析.</p>
<p>参考文献:</p>
<ol>
<li><a href="http://www.qsl.net/bd5hag/JavaCourse/Lesson2/2_9_1.htm">对象保存在哪里?</a> http://www.qsl.net/bd5hag/JavaCourse/Lesson2/2_9_1.htm</li>
<li><a href="http://www.phim.unibe.ch/comp_doc/c_manual/C/SYNTAX/storage_class.html#static">c storage class</a> http://www.phim.unibe.ch/comp_doc/c_manual/C/SYNTAX/storage_class.html#static</li>
<li><a href="http://en.wikipedia.org/wiki/Static_variable">Static Variable in Wikipedia</a> http://en.wikipedia.org/wiki/Static_variable</li>
<li><a href="http://en.wikipedia.org/wiki/Local_variable">Local Variable  in Wikipedia</a> http://en.wikipedia.org/wiki/Local_variable</li>
<li><a href="http://en.wikipedia.org/wiki/Call_stack">Call Stack in Wikipedia</a> http://en.wikipedia.org/wiki/Call_stack</li>
<li><a href="http://columnist.chinabyte.com/xufeng.cq/149/2183649.shtml">this and static keyword, Thinking in Java </a> http://columnist.chinabyte.com/xufeng.cq/149/2183649.shtml</li>
<li><a href="http://www.csdn.net/develop/Article/20/20219.shtm">小议static</a> http://www.csdn.net/develop/Article/20/20219.shtm</li>
<li><a href="http://www.javacoffeebreak.com/faq/faq0010.html">What does the keyword &#8217;static&#8217; mean?</a> http://www.javacoffeebreak.com/faq/faq0010.html</li>
<li><a href="http://home.zhuonline.net/archives/2005/09/staticqa.html">static关键字Q/A</a> http://home.zhuonline.net/archives/2005/09/staticqa.html</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2006/09/23/static%e5%85%b3%e9%94%ae%e5%ad%97%e7%9a%84%e5%90%ab%e4%b9%89/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[转]语义Web的应用报告</title>
		<link>http://niyue.com/2005/05/28/%e8%bd%ac%e8%af%ad%e4%b9%89web%e7%9a%84%e5%ba%94%e7%94%a8%e6%8a%a5%e5%91%8a/</link>
		<comments>http://niyue.com/2005/05/28/%e8%bd%ac%e8%af%ad%e4%b9%89web%e7%9a%84%e5%ba%94%e7%94%a8%e6%8a%a5%e5%91%8a/#comments</comments>
		<pubDate>Fri, 27 May 2005 18:22:33 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[semanticweb]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=145</guid>
		<description><![CDATA[转自  刘升平的blog
语义Web的应用报告
Filed under:

语义Web应用

― orangebench(刘升平) @ 1:06 am
下面有对SW应用的全面分析，并且选出了两个最有代表性的应用：Semantic blogging和
Semantic Portal, 有详细的需求分析，实现描述，源代码。
Workpackage 12.1: Open demonstrators
12.1.1 Open demonstrators: Semantic web applications &#8211; analysis and selection (pdf), (html) Appendix: Application survey (pdf), (html)
12.1.2 Semantic blogging and bibliographies &#8211; requirements specification (pdf), (html)
12.1.3 Demo 1 Implementation (pdf), (html)
12.1.4 Semantic Blogging &#8211; Lessons Learnt (pdf), (html)
12.1.5 Semantic Portals &#8211; Requirements [...]]]></description>
			<content:encoded><![CDATA[<p>转自  <a href="http://blog.w3china.org/~orangebench">刘升平的blog</a></p>
<h3><a rel="bookmark" title="语义Web的应用报告" href="http://blog.w3china.org/~orangebench/index.php?p=31">语义Web的应用报告</a></h3>
<div>Filed under:</p>
<ul>
<li><a title="View all posts in 语义Web应用" href="http://blog.w3china.org/~orangebench/index.php?cat=7">语义Web应用</a></li>
</ul>
<p>― orangebench(刘升平) @ 1:06 am</p></div>
<div>下面有对SW应用的全面分析，并且选出了两个最有代表性的应用：Semantic blogging和<br />
Semantic Portal, 有详细的需求分析，实现描述，源代码。</p>
<p><a href="http://www.w3.org/2001/sw/Europe/plan/workpackages/live/esw-wp-12.1.html"><font color="#4455aa">Workpackage 12.1: Open demonstrators</font></a></p>
<p>12.1.1 Open demonstrators: Semantic web applications &#8211; analysis and selection (<a href="http://www.w3.org/2001/sw/Europe/reports/pdf/12.1.1.pdf"><font color="#4455aa">pdf</font></a>), (<a href="http://www.w3.org/2001/sw/Europe/reports/chosen_demos_rationale_report/hp-applications-selection.html"><font color="#4455aa">html</font></a>) Appendix: Application survey (<a href="http://www.w3.org/2001/sw/Europe/reports/pdf/12.1.1.appendixA.pdf"><font color="#4455aa">pdf</font></a>), (<a href="http://www.w3.org/2001/sw/Europe/reports/chosen_demos_rationale_report/hp-applications-survey.html"><font color="#4455aa">html</font></a>)<br />
12.1.2 Semantic blogging and bibliographies &#8211; requirements specification (<a href="http://www.w3.org/2001/sw/Europe/reports/pdf/12.1.2.pdf"><font color="#4455aa">pdf</font></a>), (<a href="http://www.w3.org/2001/sw/Europe/reports/requirements-demo-1/hp-requirements-specification.html"><font color="#4455aa">html</font></a>)<br />
12.1.3 Demo 1 Implementation (<a href="http://www.w3.org/2001/sw/Europe/reports/pdf/12.1.3.pdf"><font color="#4455aa">pdf</font></a>), (<a href="http://www.w3.org/2001/sw/Europe/reports/demo_1_impl/"><font color="#000050">html</font></a>)<br />
12.1.4 Semantic Blogging &#8211; Lessons Learnt (<a href="http://www.w3.org/2001/sw/Europe/reports/pdf/12.1.4.pdf"><font color="#4455aa">pdf</font></a>), (<a href="http://www.w3.org/2001/sw/Europe/reports/demo_1_report/"><font color="#000050">html</font></a>)<br />
12.1.5 Semantic Portals &#8211; Requirements Specification (<a href="http://www.w3.org/2001/sw/Europe/reports/pdf/12.1.5.pdf"><font color="#4455aa">pdf</font></a>), (<a href="http://www.w3.org/2001/sw/Europe/reports/requirements-demo-2/"><font color="#000050">html</font></a>)<br />
12.1.6 Semantic Portals Demonstrator, (<a href="http://www.w3.org/2001/sw/Europe/reports/demo_2_impl/"><font color="#000050">html</font></a>)</div>
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2005/05/28/%e8%bd%ac%e8%af%ad%e4%b9%89web%e7%9a%84%e5%ba%94%e7%94%a8%e6%8a%a5%e5%91%8a/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java界技术名人堂</title>
		<link>http://niyue.com/2005/04/18/java%e7%95%8c%e6%8a%80%e6%9c%af%e5%90%8d%e4%ba%ba%e5%a0%82/</link>
		<comments>http://niyue.com/2005/04/18/java%e7%95%8c%e6%8a%80%e6%9c%af%e5%90%8d%e4%ba%ba%e5%a0%82/#comments</comments>
		<pubDate>Sun, 17 Apr 2005 16:30:47 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[other]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=130</guid>
		<description><![CDATA[

Java界技术名人堂
    上次在某个blog上面看到过一个关于Java人仕的综合介绍,人列了不少,不过讲的比较没有规律并且不是很全.今天在赛迪网上看到了这些资料,但是阅读起来很不方便,这里为其修改了其链接上的错误并将原来分散的资源做了一个综合.想知道更多的人还可以看看TheServerSide上面的这篇文章: Who&#8217;s Who in the Enterprise Java World? Make your opinion known! 里面断断续续的也讲了不少人^_^
A









Adrian Colyer
IBM的AspectJ DeveloperJava研究项目负责人，同时也是Eclipse上AspectJ项目的领导者。AspectJ项目起源于帕洛阿尔托（Palo Alto）研究中心（缩写为PARC）。该中心由Xerox集团资助，Gregor Kiczales领导，从1997年开始致力于AspectJ的开发，1998年第一次发布给外部用户，2001年发布1.0 release。为了推动AspectJ技术和社团的发展，PARC在2003年3月正式将AspectJ项目移交给了Eclipse组织，因为AspectJ的发展和受关注程度大大超出了PARC的预期，他们已经无力继续维持它的发展。
AspectJ是用于实现面向方面编程（AOP）的Java语言扩展。通过分离各种正交问题，AspectJ使得开发者能够更轻松地解决大型软件系统中常见的一些棘手问题，如日志记录、错误处理之类。
AspectJ项目经过近十年的发展，对于AOP的具体实现已经相当成熟，但其仍存在诸如过于复杂、破坏封装、需要专门的Java编译器等缺点。在接收了AspectJ项目之后，Eclipse项目组已经把AspectJ集成在Eclipse Java开发环境中。通过这样的集成，Eclipse IDE将可以提供对AOP的支持，并弥补AspectJ本身的一些不足之处。




B












Ben Galbraith
AOP活跃人士，其在TSSJS2005（全称：The ServerSide Java Symposium）上关于“AJax Toy”的演讲被与会者认为颇有新意。AJAX是Asynchronous JavaScript + XML的缩写，而且AJax可以很好的和JSF的Component结合起来，开发者不需要成为AJax方面的专家。








Benjamin Renaud
BEA的副CTO。BEA是企业级平台中间件的领导厂商，其2002财年收入达到9.34亿美元，在全球拥有超过15,000家企业用户。1995年，BEA收购Tuexdo联机事物处理监视器［Tuxedo online transaction processing（OLTP） monitor］，并由此而进入平台中间件市场。1998年又收购了WebLogic，而WebLogic技术随后在1999年成为Java应用服务器领域中的领导者。








Bill Burke
JBoss组织首席架构师，EJB 3.0专家组里的JBoss代表。JBoss是一个用纯Java编写、开放源代码、遵循J2EE规范的应用服务器软件，它遵循LGPL开放源码协议。JBoss起初只是一个EJB容器，后来逐步发展成为一个具有复杂功能的应用服务器。现在，最高的版本是4.0。它从创建到现在，经历了4年的发展历程。JBoss组织是一家位于美国亚特兰大的商业服务组织。他们为JBoss应用服务器提供技术支持和顾问咨询。








Bob McWhirter
Groovy和Drools的开发者。Groovy是一种敏捷开发语言，完全以Java编程API为基础，于2004年3月底获得批准。Groovy还是与JRE兼容的一种脚本语言，使用了Java开发人员最熟悉的功能和库（将它们放到了一个敏捷开发框架中）。Groovy具有使开发人员不用编译、允许动态类型、使合成结构容易、脚本可在普通Java应用程序中使用、提供shell解析器等特性，这使其成为一种特别容易学习和使用的语言，不管是有经验的Java开发人员还是刚接触Java平台的人，都可以快速掌握。有些人说它可能会永久性地改变开发人员看待和使用Java平台的方式。
Drools是Bob McWhirter开发的开源项目，是Charles Forgy Rete算法的一个增强的Java语言实现，放在The Codehaus上。Rete算法是Charles Forgy在1979年发明的，是目前用于生产系统的效率最高的算法（除了私有的Rete II）。Rete是唯一的、效率与执行规则数目无关的决策支持算法。Rete应用于生产系统已经有很多年了，但在Java开源软件中并没有得到广泛应用。
除了应用了Rete核心算法、开源软件和100%的Java实现外，Drools还提供了很多有用的特性。其中包括实现了JSR94 API和创新的规则语义系统，这个语义系统可用来编写描述规则的语言。目前，Drools提供了三种语义模块，即Python模块、Java模块和Groovy模块。



C








Cedric Beust
EJB 3专家组的成员，也是其他一些流行的开源项目（例如EJBGen和Doclipse）的创造者。目前是BEA的Weblogic架构师。EJBGen是一种EJB 2.0原始码生成器，它能够从一个EJB bean类生成本地界面/远端界面、本地主界面/远端主界面、主键类和部署描述符。
Doclipse是一个Eclipse下的JavaDoc插件。
Java中的包（Package）其实指的就是目录，它是为了更好地管理Java类（Class）和接口（Interface）。Java语言的包可以被另一个Java开发包所使用。
EJB是SUN公司倡导的基于JAVA的组件构架，是J2EE中的主要技术之一。EJB定义了一个集成的编程模型和标准的API接口，是实现服务器端应用服务的组件。








Cliff Schmidt
Cliff Schmidt，标准和开源策略产品经理，也是Apache蜂巢项目负责人。蜂巢计划(Project Beehive)是一个基于 WebLogic [...]]]></description>
			<content:encoded><![CDATA[<p align="left">
<p><font size="2" /></p>
<p align="center"><font size="2"><a href="http://tech.ccidnet.com/pub/article/c2575_a237349_p1.html">Java界技术名人堂</a></font></p>
<p><font size="2">    上次在某个blog上面看到过一个关于Java人仕的综合介绍,人列了不少,不过讲的比较没有规律并且不是很全.今天在<a href="http://tech.ccidnet.com/index.htm">赛迪网</a>上看到了这些资料,但是阅读起来很不方便,这里为其修改了其链接上的错误并将原来分散的资源做了一个综合.想知道更多的人还可以看看TheServerSide上面的这篇文章: <a href="http://www.theserverside.com/news/thread.tss?thread_id=23627">Who&#8217;s Who in the Enterprise Java World? Make your opinion known!</a> 里面断断续续的也讲了不少人^_^</font></p>
<p align="left"><em><font size="4"><strong>A</strong></font></em></p>
<p align="center">
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419393.jpg" /></a><br />
<strong>Adrian Colyer</strong></td>
<td style="width: 81%">IBM的AspectJ DeveloperJava研究项目负责人，同时也是Eclipse上AspectJ项目的领导者。AspectJ项目起源于帕洛阿尔托（Palo Alto）研究中心（缩写为PARC）。该中心由Xerox集团资助，Gregor Kiczales领导，从1997年开始致力于AspectJ的开发，1998年第一次发布给外部用户，2001年发布1.0 release。为了推动AspectJ技术和社团的发展，PARC在2003年3月正式将AspectJ项目移交给了Eclipse组织，因为AspectJ的发展和受关注程度大大超出了PARC的预期，他们已经无力继续维持它的发展。</p>
<p>AspectJ是用于实现面向方面编程（AOP）的Java语言扩展。通过分离各种正交问题，AspectJ使得开发者能够更轻松地解决大型软件系统中常见的一些棘手问题，如日志记录、错误处理之类。</p>
<p>AspectJ项目经过近十年的发展，对于AOP的具体实现已经相当成熟，但其仍存在诸如过于复杂、破坏封装、需要专门的Java编译器等缺点。在接收了AspectJ项目之后，Eclipse项目组已经把AspectJ集成在Eclipse Java开发环境中。通过这样的集成，Eclipse IDE将可以提供对AOP的支持，并弥补AspectJ本身的一些不足之处。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" />
<em><strong><font size="4">B</font></strong></em></td>
</tr>
</table>
<p align="center">
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<p align="left">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419421.jpg" /></a><br />
<strong>Ben Galbraith</strong></td>
<td style="width: 81%">AOP活跃人士，其在TSSJS2005（全称：The ServerSide Java Symposium）上关于“AJax Toy”的演讲被与会者认为颇有新意。AJAX是Asynchronous JavaScript + XML的缩写，而且AJax可以很好的和JSF的Component结合起来，开发者不需要成为AJax方面的专家。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419421.jpg" /></a><br />
<strong>Benjamin Renaud</strong></td>
<td style="width: 81%">BEA的副CTO。BEA是企业级平台中间件的领导厂商，其2002财年收入达到9.34亿美元，在全球拥有超过15,000家企业用户。1995年，BEA收购Tuexdo联机事物处理监视器［Tuxedo online transaction processing（OLTP） monitor］，并由此而进入平台中间件市场。1998年又收购了WebLogic，而WebLogic技术随后在1999年成为Java应用服务器领域中的领导者。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419405.jpg" /></a><br />
<strong>Bill Burke</strong></td>
<td style="width: 81%">JBoss组织首席架构师，EJB 3.0专家组里的JBoss代表。JBoss是一个用纯Java编写、开放源代码、遵循J2EE规范的应用服务器软件，它遵循LGPL开放源码协议。JBoss起初只是一个EJB容器，后来逐步发展成为一个具有复杂功能的应用服务器。现在，最高的版本是4.0。它从创建到现在，经历了4年的发展历程。JBoss组织是一家位于美国亚特兰大的商业服务组织。他们为JBoss应用服务器提供技术支持和顾问咨询。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419421.jpg" /></a><br />
<strong>Bob McWhirter</strong></td>
<td style="width: 81%">Groovy和Drools的开发者。Groovy是一种敏捷开发语言，完全以Java编程API为基础，于2004年3月底获得批准。Groovy还是与JRE兼容的一种脚本语言，使用了Java开发人员最熟悉的功能和库（将它们放到了一个敏捷开发框架中）。Groovy具有使开发人员不用编译、允许动态类型、使合成结构容易、脚本可在普通Java应用程序中使用、提供shell解析器等特性，这使其成为一种特别容易学习和使用的语言，不管是有经验的Java开发人员还是刚接触Java平台的人，都可以快速掌握。有些人说它可能会永久性地改变开发人员看待和使用Java平台的方式。</p>
<p>Drools是Bob McWhirter开发的开源项目，是Charles Forgy Rete算法的一个增强的Java语言实现，放在The Codehaus上。Rete算法是Charles Forgy在1979年发明的，是目前用于生产系统的效率最高的算法（除了私有的Rete II）。Rete是唯一的、效率与执行规则数目无关的决策支持算法。Rete应用于生产系统已经有很多年了，但在Java开源软件中并没有得到广泛应用。</p>
<p>除了应用了Rete核心算法、开源软件和100%的Java实现外，Drools还提供了很多有用的特性。其中包括实现了JSR94 API和创新的规则语义系统，这个语义系统可用来编写描述规则的语言。目前，Drools提供了三种语义模块，即Python模块、Java模块和Groovy模块。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /><em><strong><font size="4">C</font></strong></em></p>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419427.jpg" /></a><br />
<strong>Cedric Beust</strong></td>
<td style="width: 81%">EJB 3专家组的成员，也是其他一些流行的开源项目（例如EJBGen和Doclipse）的创造者。目前是BEA的Weblogic架构师。EJBGen是一种EJB 2.0原始码生成器，它能够从一个EJB bean类生成本地界面/远端界面、本地主界面/远端主界面、主键类和部署描述符。</p>
<p>Doclipse是一个Eclipse下的JavaDoc插件。</p>
<p>Java中的包（Package）其实指的就是目录，它是为了更好地管理Java类（Class）和接口（Interface）。Java语言的包可以被另一个Java开发包所使用。</p>
<p>EJB是SUN公司倡导的基于JAVA的组件构架，是J2EE中的主要技术之一。EJB定义了一个集成的编程模型和标准的API接口，是实现服务器端应用服务的组件。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419427.jpg" /></a><br />
<strong>Cliff Schmidt</strong></td>
<td style="width: 81%">Cliff Schmidt，标准和开源策略产品经理，也是Apache蜂巢项目负责人。蜂巢计划(Project Beehive)是一个基于 WebLogic Workshop应用框架的用于 J2EE&#038;SOA 应用的开源项目。该框架本身是独立的，但要依靠WebLogic来运行。 在2004年5月，BEA宣布该框架以后的所有开发都是开放源码的，这就是Apache蜂巢项目，名为Beehive。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419427.jpg" /></a><br />
<strong>Craig McClanahan</strong></td>
<td style="width: 81%">Craig McClanahan目前是SUN公司的高级工程师，主要从事J2EE的WEB层的工作。主要参加的开放源码有：</p>
<p>1．Catalina Servlet Container：主要的开发人员，该Servlet Container是Apache软件基金的Jarkarta 中的TOMCAT 4.x和5.x版中的核心部分。</p>
<p>2．Struts： 发起人和主要的开发人员，2000年该项目转为Apache软件基金的Jarkarta项目，该框架目前成为采用Java Servlet 和JSP技术构件Web应用的最流行的框架。</p>
<p>3．Digester：发起人和主要的开发人员，本来该项目是为Struts中处理配置文件的一些功能类，后来觉得不错，就转成Apache软件基金的Jarkarta项目的Common中的一个组件项目。</p>
<p>4．JavaServer Faces（JSR-127）, 和SUN公司的Ed Burns一起负责该标准。</p>
<p>著作：《Struts in action》</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
</table>
<p><em><strong><font size="4">D</font></strong></em></p>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<p align="left">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419429.jpg" /></a><br />
<strong>David Nuescheler</strong></td>
<td style="width: 81%">Day Software的CTO，也是Java Content Repository（Java内容录仓库）JCR 170专家组负责人。Java Content Repository是一个寻址内容仓库的标准化API建议。2002年2月，该建议提交到JCR(Java Community Process)，JCR专家组于2003年下半年完成最终草案。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419429.jpg" /></a><br />
<strong>Dion Almaer</strong></td>
<td style="width: 81%">TSS主编、中间件公司首席架构师、JDO专家组成员。Middleware Company (www.middleware-company.com)即中间件公司是领先的EJB/J2EE和B2B技术培训机构之一。Middleware Company还构建和维护一流的在线J2EE社区TheServerSide.com。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419429.jpg" /></a><br />
<strong>Doug Cutting</strong></td>
<td style="width: 81%">TSS的CEO、MiddleWare公司CEO、《Mastering EJB》作者。他是一位资深全文索引/检索专家，曾经是V-Twin搜索引擎（Apple的Copland操作系统的成就之一）的主要开发者，后在Excite担任高级系统架构设计师，目前从事于一些INTERNET底层架构的研究。他贡献出的Lucene的目标是为各种中小型应用程序加入全文检索功能。Lucene不是一个完整的全文索引应用，而是是一个用Java写的全文索引引擎工具包，它可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能。早先发布在作者自己的www.lucene.com，后来发布在SourceForge，2001年年底成为APACHE基金会jakarta的一个子项目：http://jakarta.apache.org/lucene/</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /><em><strong><font size="4">E</font></strong></em></p>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<p align="left">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419431.jpg" /></a><br />
<strong>Erich Gamma</strong></td>
<td style="width: 81%">经典书籍《Design Patterns（设计模式）》（Addison-Wesley，1995）的四位作者之一，Eclipse的总设计师，并且是EclipseJava开发工具（JDT）项目的领导人。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419431.jpg" /></a><br />
<strong>Edward Burns</strong></td>
<td style="width: 81%">JSF 1.2规格主导者。SPEC是System PerformanceEvaluation Cooperative的缩写，是几十家世界知名计算机大厂商所支持的非盈利的合作组织，旨在开发共同认可的标准基准程序。</p>
<p>SPEC基准程序是由SPEC开发的一组用于计算机性能综合评价的程序。以对VAX11/780机的测试结果作为基数，其他计算机的测试结果以相对于这个基数的比率来表示。SPEC基准程序能较全面地反映机器性能，有一定的参考价值。</p>
<p>SPEC版本1.0是1989年10月宣布的，是一套复杂的基准程序集，主要用于测试与工程和科学应用有关的数值密集型的整数和浮点数方面的计算。源程序超过15万行，包含10个测试程序，使用的数据量比较大，分别测试应用的各个方面。</p>
<p>SPEC基准程序测试结果一般以SPECmark（SPEC分数）、SPECint（SPEC整数）和SPECfp（SPEC浮点数）来表示。其中SPEC分数是10个程序的几何平均值，SPEC整数是4个整数程序的几何平均值，SPEC浮点数是6个浮点程序的集合平均值。</p>
<p>1992年在原来SPECint89和SPECfp89的基础上增加了两个整数测试程序和8个浮点数测试程序，因此SPECint92由6个程序组成，SPECfp92由14个程序组成。这20个基准程序是基于不同的应用写成的，主要测量32位cpu、主存储器、编译器和操作系统的性能。</p>
<p>参加这个组织的主要成员有：IBM,AT&#038;T,BULL,Compag，CDC,DG,DEC,Fujitsu，HP，Intel，MIPS,Motorola，SGI,SUN和Unisys等。1995年，这些厂商又共同推出了SPECint95和SPECfp95作为最新的测试标准程序。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /><em><strong><font size="4">F</font></strong></em></p>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419433.jpg" /></a><br />
<strong>Floyd Marinescu</strong></td>
<td style="width: 81%">《EJB Design Patterns》作者。他架构、建置并执行了TheServerSide.com（知名J2EE社区）。他写了无以计数的文章并且经常在Java研讨会上发表演说。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" />
<p align="left"><em><strong><font size="4">G</font></strong></em></p>
<p align="left">
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419445.jpg" /></a><br />
<strong>Gavin King</strong></td>
<td style="width: 81%">Hibernate的作者，EJB3.0专家委员会成员，JBoss核心成员之一，也是《Hibernate in Action》一书的作者。Gavin King 1974年出生于澳大利亚，现在居住在澳大利亚默尔本市。Hibernate 是Java平台上的一种流行的、容易使用的开放源代码对象关系（OR）映射框架。Hibernate诞生在2001年11月，在短短的两年多时间就发展成为Java世界主流的持久层框架软件，令人侧目。Hibernate是一个雄心勃勃的项目，它的目标是成为Java中管理持续性数据问题的一种完整的解决方案。它协调应用与关系数据库的交互，让开发者解放出来专注于手边的业务问题。Hibernate是一种非强迫的解决方案。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419443.jpg" /></a><br />
<strong>Gregor Hohpe</strong></td>
<td style="width: 81%">《Enterprise Integration Patterns》作者，目前在ThoughtWorks工作。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419443.jpg" /></a><br />
<strong>Gregor Kiczales</strong></td>
<td style="width: 81%">人称AOP之父，是其领导了开发AOP和AspectJ的PARC团队。他是知名的AOP传教士，并且致力于建立同时给实践者和研究者服务的社区。他在开发高级编程技术并把这些技术传授给开发者方面有二十年的经验，是ANSI CLOS设计团队的成员，同时还是CLOS参考实现的作者，以及《The Art of Metaobject Protocol》（MIT出版社，1991）的作者之一。他现在是British Columbia大学软件设计方面的Sierra System教授。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419443.jpg" /></a><br />
<strong>Graham Hamilton</strong></td>
<td style="width: 81%">Sun副总裁，J2SE1.3、1.4、5.0项目领导人。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /><em><strong><font size="4">H</font></strong></em></p>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419447.jpg" /></a><br />
<strong>Hani Suleiman</strong></td>
<td style="width: 81%">OSWorkflow开发者，BileBlog的作者。osworkflow是一个轻量级的又极为灵活的工作流引擎，较容易和其它架构做整合。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419451.jpg" /></a><br />
<strong>Howard Lewis Ship</strong></td>
<td style="width: 81%">HLS的Blog：http://howardlewisship.com/blog/Tapestry和Hivemind的开发者，《Tapestry in Action》作者。</p>
<p>Tapestry是类似WebForms机制的Java Web Framework，Hivemind是一个微内核的IoC容器，Tapestry和Hivemind都是Apache Foundation Software旗下的软件。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /><em><strong><font size="4">J</font></strong></em></p>
<table width="491" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419453.jpg" /></a><br />
<strong>James Strachan</strong></td>
<td style="width: 81%">Geronimo的发起者之一，Jakarta项目管理委员会成员，N多JSR expert group的成员。Geronimo是Apache软件基金会为了创造一个兼容J2EE的容器，而整理出来的一个新成果。</p>
<p>Jakarta是一个Sun公司支持的开源项目。它的最终目标是创造一个质量达到了那些商业解决方案要求的免费J2EE服务器端解决方案。Tomcat应用程序是整个项目的主要部分，并且在很多人看来，它几乎就等同于整个的Jakarta项目。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419453.jpg" /></a><br />
<strong>Jason Careria</strong></td>
<td style="width: 81%">Webwork2，Xwork核心的开发者。WebWork2.x前身是Rickard Oberg开发的WebWork，但现在WebWork已经被拆分成了XWork1和WebWork2两个项目。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419453.jpg" /></a><br />
<strong>Jason Hunter</strong></td>
<td style="width: 81%">Apache基金会管理员，《Java Servlet Programming》作者，Xquery，Jdom等的开发者。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419453.jpg" /></a><br />
<strong>John Crupi</strong></td>
<td style="width: 81%">Sun Java Center系统架构师，目前专著于SOA。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419453.jpg" /></a><br />
<strong>Jonathan Bruce</strong></td>
<td style="width: 81%">JDBC规格主导人。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419453.jpg" /></a><br />
<strong>Joshua Bloch</strong></td>
<td style="width: 81%">《Effective Java》作者，前java平台核心开发者，目前在google。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419453.jpg" /></a><br />
<strong>Jon Tirsen</strong></td>
<td style="width: 81%">Nanning的首席开发者，PicoContainer和NanoContainer活跃开发者，目前在ThoughtWorks工作，Damage Control的项目领导者之一。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419455.jpg" /></a><br />
<strong>Juergen Hoeler</strong></td>
<td style="width: 81%">Juergen Hoeler是SpringFramework的共同作者之一，与Rod Johnson共同发起和创造了SpringFramework。SpringFramework中Hibernate相关的API是由Juergen Hoeler完成的。对于喜欢使用Spring/Hibernate架构的程序员来说一定对这部分非常熟悉。Juergen Hoeler也是《J2EE Development without EJB》一书的共同作者之一。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
</table>
<p><em><strong><font size="4">K</font></strong></em></td>
</tr>
</table>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419457.jpg" /></a><br />
<strong>Kent Beck</strong></td>
<td style="width: 81%">设计模式的开创者之一。XP[eXtreme Programming（极限编程）]和TDD的创始人，xUnit的开发者。是《The Smalltalk Best Practice Patterns》、《Extreme Programming Explained》和《Planning Extreme Programming（与Martin Fowler合著）》等书的作者。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" />
<em><strong><font size="4">L</font></strong></em></td>
</tr>
</table>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419461.jpg" /></a><br />
<strong>Linda DeMichiel</strong></td>
<td style="width: 81%">EJB 3.0规格主导者，在SUN工作。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
</table>
<p><em><strong><font size="4">M</font></strong></em></p>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419463.jpg" /></a><br />
<strong>Marc Fleury</strong></td>
<td style="width: 81%">博士，1968年生于巴黎。马克原先在太阳微视（法国）从事过销售工作。毕业于法国声名显赫的Ecole Poly技术学院的他，同时也是伞兵队的前任上尉。后来，马克从巴黎高等师范学校获得理论物理专业的硕士和博士学位。在从事物理方面的研究过程中，他也在麻省理工学院做过X射线激光器方面的访问学者。目前，马克是JBoss公司，即一个坐落在亚特兰大郊外的、提供优质服务的公司的总裁。JBoss公司，由Marc Fleury领衔的、由世界范围内100多位开发者组成的公司。他们分发各种用途的J2EE工具，并且致力于将JBoss发展为J2EE平台中的主流企业Java应用服务器。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419515.jpg" /></a><br />
<strong>Mark Hapner</strong></td>
<td style="width: 81%">Mark Hapner不仅是J2EE 1.4规范的主导者，还是Web Service协同工作组织中Sun公司的代表。简而言之，他是Sun驱动J2EE技术趋势的关键人物。Mark于1996年加 入Sun的Java软件公司，参与JDBC API的开发。接着，他撰写了EJB规范和JMS规范。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419463.jpg" /></a><br />
<strong>Martin Fowler</strong></td>
<td style="width: 81%">从80年代开始，他就一直从事软件开发的工作。他写过四本软件开发方面的书。《分析模式》是对他商业建模的经验的收集回顾，其中有很多重要的商业对象开发模式。《UML Disilled》是对UML符号、语意以及迭代式开发过程的概览，在1998年获得软件开发生产力奖金，现在已经出到了第二版。《Refactoring》描述了如何以可控的、快速的方式改变现有软件的设计。他最近与Kent Beck合写的《Planning Extreme Programming》则描述了如何进行XP设计。这四本书被全世界的软件开发者奉为经典，尤其是后两本，让软件开发者们看到了快速、灵活的软件开发的可能性。他所描述的重构技术和基于重构的XP方法，被称为“软件开发史上的一次风暴”。Martin Fowler在许多软件开发的国际性会议上做过演讲。他还是OOPSLA、软件开发委员会、UML世界、XP2001、TOOLS等几个协会的会员。同时，他还是“分布式运算”杂志的专栏作家。现在，他又为“软件开发”杂志做顾问，同时还为“IEEE软件”写一个设计专栏。目前是ThoughtWorks（系统集成及顾问公司）的CEO。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419463.jpg" /></a><br />
<strong>Matt Raible</strong></td>
<td style="width: 81%">1997年毕业于Denver大学，获得俄语、国际商业和经济学位。《Spring live》一书的作者。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419463.jpg" /></a><br />
<strong>Mike Cannon-Brookes</strong></td>
<td style="width: 81%">OpenSymphony及Atlassian的开发者，《Java Open Source programing》一书的作者。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /><em><strong><font size="4">P</font></strong></em></p>
<table width="449" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419469.jpg" /></a><br />
<strong>Pat Lightbody</strong></td>
<td style="width: 81%">Webwork的开发者。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419469.jpg" /></a><br />
<strong>Patrick Linskey</strong></td>
<td style="width: 81%">JDO活跃人士，JDO2.0，EJB3.0专家组成员。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
</table>
<p><em><strong><font size="4">R</font></strong></em></p>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419471.jpg" /></a><br />
<strong>Rick Ross</strong></td>
<td style="width: 81%">Javalobby公司创建人。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419473.jpg" /></a><br />
<strong>Rickard Oberg</strong></td>
<td style="width: 81%">Xdoclet及Webwork的开发者，Jboss的前架构师，目前主要研究AOP。Oberg是瑞典Java编程竞赛“Software Reuse Cafe”的两度折桂者，这使得他成为瑞典最好的Java程序员之一。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419471.jpg" /></a><br />
<strong>Robin Roos</strong></td>
<td style="width: 81%">JDO2.0活跃人士，《Java Data Object》一书的作者。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419475.jpg" /></a><br />
<strong>Rod Johnson</strong></td>
<td style="width: 81%">Rod Johnson在2002年出版了一本非常畅销的J2EE书籍《Expert One-on-One J2EE Design and Development》，阐述了J2EE开发的方方面面的经验和设计，同时他根据本书的思路，开发了SpringFramework。如今SpringFramework是最流行的轻量级Java IoC容器。Rod本人也是Servlet2.4和JDO2.0专家委员会成员，他同时也是一位经验丰富的技术咨询专家。Rod开了一家咨询公司，提供SpringFramework的技术支持和培训。Rod Johnson也是反EJB方面一个代表人物，他创建的Spring的最终目标是取代EJB。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
</table>
<p><em><strong><font size="4">S</font></strong></em></p>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419479.jpg" /></a><br />
<strong>Scott Ambler</strong></td>
<td style="width: 81%">Scott W. Ambler是Ronin International的总裁，该公司是一家专门提供面向对象过程指导、体系结构建模和Enterprise JavaBean（EJB）开发的咨询企业。他自己著作了或者与其他人合著了几本有关面向对象开发的书籍，包括最近出版的《The Object Primer 2nd Edition》。可以通过scott.ambler@ronin-intl.com与他联系，他的网站位于www.ambysoft.com。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419479.jpg" /></a><br />
<strong>Sergey Dmitriev</strong></td>
<td style="width: 81%">Jetbrains公司CEO，Intelij IDEA的开发者。Sergey Dmitriev认为，我们今天把领域问题映射成通用编程语言如Java、C#，就像把C语言用汇编代码表达出来一样如在石器时代。所以我们需要可以随意制造贴近问题域的DSL。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" />
<font size="4"><em><strong>T</strong></em></font></td>
</tr>
</table>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419483.jpg" /></a><br />
<strong>Ted Neward</strong></td>
<td style="width: 81%">Ted Neward是Manning出版社元老级的作者，Manning最早出版的书正是Ted Neward的《Core OWL》与《Advanced OWL》（一本入门，一本进阶）。有趣的是，当Ted Neward的OWL这两本书快出版时，Borland居然宣布停止开发OWL。Ted Neward花了这么多心血，居然换来这样的结果。OWL本来市场就很小，又被Borland宣布死刑，Ted Neward的这两本书卖得奇惨。后来，Ted Neward转向Java，在Manning出版了一本很受好评的《Effective Enterprise Java》。接着，Ted Neward开始和O&#8217;Reilly合作，出版了好几本与他人合著的.NET书，包括了《C# in a Nutshell》、《VB.NET Core Classes in a Nutshell》、《C# Language Packet Reference》、《Shared Source CLI Essentials》。其中，《Shared Source CLI Essentials》一书是剖析Rotor的第一本书，2003年三月底出版。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
</table>
</td>
</tr>
</table>
<p><em><strong><font size="4">V</font></strong></em></td>
</tr>
</table>
<table width="90%" border="0" align="center">
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
<tr>
<td style="width: 19%">
<p align="center"><a href="mailto:jiaoxq@staff.ccidnet.com"><img src="http://tech.ccidnet.com/pub/attachment/2005/4/419467.jpg" /></a><br />
<strong>Vincent Massol</strong></td>
<td style="width: 81%">Vincent Massol是Jakarta Cactus测试框架的创建者，也是Maven和MockObjects开发团队的活跃参与者。他是Pivolis的CTO，还是一位敏捷软件开发专家。《Junit in action》一书的作者。</td>
</tr>
<tr>
<td colspan="2">
<hr size="1" /></td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p align="center">
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2005/04/18/java%e7%95%8c%e6%8a%80%e6%9c%af%e5%90%8d%e4%ba%ba%e5%a0%82/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tomcat中用web.xml控制Web应用详解！</title>
		<link>http://niyue.com/2005/03/16/tomcat%e4%b8%ad%e7%94%a8webxml%e6%8e%a7%e5%88%b6web%e5%ba%94%e7%94%a8%e8%af%a6%e8%a7%a3%ef%bc%81/</link>
		<comments>http://niyue.com/2005/03/16/tomcat%e4%b8%ad%e7%94%a8webxml%e6%8e%a7%e5%88%b6web%e5%ba%94%e7%94%a8%e8%af%a6%e8%a7%a3%ef%bc%81/#comments</comments>
		<pubDate>Wed, 16 Mar 2005 02:29:00 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=114</guid>
		<description><![CDATA[1 定义头和根元素部署描述符文件就像所有XML文件一样，必须以一个XML头开始。这个头声明可以使用的XML版本并给出文件的字符编码。
DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本（如2.2或2.3）并指定管理此文件其余部分内容的语法的DTD(Document Type Definition，文档类型定义)。
所有部署描述符文件的顶层（根）元素为web-app。请注意，XML元素不像HTML，他们是大小写敏感的。因此，web-App和WEB-APP都是不合法的，web-app必须用小写。
2 部署描述符文件内的元素次序
XML元素不仅是大小写敏感的，而且它们还对出现在其他元素中的次序敏感。例如，XML头必须是文件中的第一项，DOCTYPE声明必须是第二项，而web-app元素必须是第三项。在web-app元素内，元素的次序也很重要。服务器不一定强制要求这种次序，但它们允许（实际上有些服务器就是这样做的）完全拒绝执行含有次序不正确的元素的Web应用。这表示使用非标准元素次序的web.xml文件是不可移植的。
下面的列表给出了所有可直接出现在web-app元素内的合法元素所必需的次序。例如，此列表说明servlet元素必须出现在所有servlet-mapping元素之前。请注意，所有这些元素都是可选的。因此，可以省略掉某一元素，但不能把它放于不正确的位置。
l icon icon元素指出IDE和GUI工具用来表示Web应用的一个和两个图像文件的位置。
l display-name display-name元素提供GUI工具可能会用来标记这个特定的Web应用的一个名称。
l description description元素给出与此有关的说明性文本。
l context-param context-param元素声明应用范围内的初始化参数。
l filter 过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联。
l filter-mapping 一旦命名了一个过滤器，就要利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。
l listener servlet API的版本2.3增加了对事件监听程序的支持，事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类。
l servlet 在向servlet或JSP页面制定初始化参数或定制URL时，必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。
l servlet-mapping 服务器一般为servlet提供一个缺省的URL：http://host/webAppPrefix/servlet/ServletName。但是，常常会更改这个URL，以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时，使用servlet-mapping元素。
l session-config 如果某个会话在一定时间内未被访问，服务器可以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveInterval方法明确设置单个会话对象的超时值，或者可利用session-config元素制定缺省超时值。
l mime-mapping 如果Web应用具有想到特殊的文件，希望能保证给他们分配特定的MIME类型，则mime-mapping元素提供这种保证。
l welcom-file-list welcome-file-list元素指示服务器在收到引用一个目录名而不是文件名的URL时，使用哪个文件。
l error-page error-page元素使得在返回特定HTTP状态代码时，或者特定类型的异常被抛出时，能够制定将要显示的页面。
l taglib taglib元素对标记库描述符文件（Tag Libraryu Descriptor file）指定别名。此功能使你能够更改TLD文件的位置，而不用编辑使用这些文件的JSP页面。
l resource-env-ref resource-env-ref元素声明与资源相关的一个管理对象。
l resource-ref resource-ref元素声明一个资源工厂使用的外部资源。
l security-constraint security-constraint元素制定应该保护的URL。它与login-config元素联合使用
l login-config 用login-config元素来指定服务器应该怎样给试图访问受保护页面的用户授权。它与sercurity-constraint元素联合使用。
l security-role security-role元素给出安全角色的一个列表，这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。分别地声明角色可使高级IDE处理安全信息更为容易。
l env-entry env-entry元素声明Web应用的环境项。
l ejb-ref ejb-ref元素声明一个EJB的主目录的引用。
l ejb-local-ref ejb-local-ref元素声明一个EJB的本地主目录的应用。
3 分配名称和定制的UL
在web.xml中完成的一个最常见的任务是对servlet或JSP页面给出名称和定制的URL。用servlet元素分配名称，使用servlet-mapping元素将定制的URL与刚分配的名称相关联。
3.1 分配名称
为了提供初始化参数，对servlet或JSP页面定义一个定制URL或分配一个安全角色，必须首先给servlet或JSP页面一个名称。可通过servlet元素分配一个名称。最常见的格式包括servlet-name和servlet-class子元素（在web-app元素内），如下所示：
&#60;servlet&#62;
&#60;servlet-name&#62;Test&#60;/servlet-name&#62;
&#60;servlet-class&#62;moreservlets.TestServlet&#60;/servlet-class&#62;
&#60;/servlet&#62;
这表示位于WEB-INF/classes/moreservlets/TestServlet的servlet已经得到了注册名Test。给servlet一个名称具有两个主要的含义。首先，初始化参数、定制的URL模式以及其他定制通过此注册名而不是类名引用此servlet。其次,可在URL而不是类名中使用此名称。因此，利用刚才给出的定义，URL [...]]]></description>
			<content:encoded><![CDATA[<p>1 定义头和根元素部署描述符文件就像所有XML文件一样，必须以一个XML头开始。这个头声明可以使用的XML版本并给出文件的字符编码。<br />
DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本（如2.2或2.3）并指定管理此文件其余部分内容的语法的DTD(Document Type Definition，文档类型定义)。<br />
所有部署描述符文件的顶层（根）元素为web-app。请注意，XML元素不像HTML，他们是大小写敏感的。因此，web-App和WEB-APP都是不合法的，web-app必须用小写。</p>
<p>2 部署描述符文件内的元素次序</p>
<p>XML元素不仅是大小写敏感的，而且它们还对出现在其他元素中的次序敏感。例如，XML头必须是文件中的第一项，DOCTYPE声明必须是第二项，而web-app元素必须是第三项。在web-app元素内，元素的次序也很重要。服务器不一定强制要求这种次序，但它们允许（实际上有些服务器就是这样做的）完全拒绝执行含有次序不正确的元素的Web应用。这表示使用非标准元素次序的web.xml文件是不可移植的。<br />
下面的列表给出了所有可直接出现在web-app元素内的合法元素所必需的次序。例如，此列表说明servlet元素必须出现在所有servlet-mapping元素之前。请注意，所有这些元素都是可选的。因此，可以省略掉某一元素，但不能把它放于不正确的位置。<br />
l icon icon元素指出IDE和GUI工具用来表示Web应用的一个和两个图像文件的位置。<br />
l display-name display-name元素提供GUI工具可能会用来标记这个特定的Web应用的一个名称。<br />
l description description元素给出与此有关的说明性文本。<br />
l context-param context-param元素声明应用范围内的初始化参数。<br />
l filter 过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联。<br />
l filter-mapping 一旦命名了一个过滤器，就要利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。<br />
l listener servlet API的版本2.3增加了对事件监听程序的支持，事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类。<br />
l servlet 在向servlet或JSP页面制定初始化参数或定制URL时，必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。<br />
l servlet-mapping 服务器一般为servlet提供一个缺省的URL：<a href="http://host/webAppPrefix/servlet/ServletName">http://host/webAppPrefix/servlet/ServletName</a>。但是，常常会更改这个URL，以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时，使用servlet-mapping元素。<br />
l session-config 如果某个会话在一定时间内未被访问，服务器可以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveInterval方法明确设置单个会话对象的超时值，或者可利用session-config元素制定缺省超时值。<br />
l mime-mapping 如果Web应用具有想到特殊的文件，希望能保证给他们分配特定的MIME类型，则mime-mapping元素提供这种保证。<br />
l welcom-file-list welcome-file-list元素指示服务器在收到引用一个目录名而不是文件名的URL时，使用哪个文件。<br />
l error-page error-page元素使得在返回特定HTTP状态代码时，或者特定类型的异常被抛出时，能够制定将要显示的页面。<br />
l taglib taglib元素对标记库描述符文件（Tag Libraryu Descriptor file）指定别名。此功能使你能够更改TLD文件的位置，而不用编辑使用这些文件的JSP页面。<br />
l resource-env-ref resource-env-ref元素声明与资源相关的一个管理对象。<br />
l resource-ref resource-ref元素声明一个资源工厂使用的外部资源。<br />
l security-constraint security-constraint元素制定应该保护的URL。它与login-config元素联合使用<br />
l login-config 用login-config元素来指定服务器应该怎样给试图访问受保护页面的用户授权。它与sercurity-constraint元素联合使用。<br />
l security-role security-role元素给出安全角色的一个列表，这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。分别地声明角色可使高级IDE处理安全信息更为容易。<br />
l env-entry env-entry元素声明Web应用的环境项。<br />
l ejb-ref ejb-ref元素声明一个EJB的主目录的引用。<br />
l ejb-local-ref ejb-local-ref元素声明一个EJB的本地主目录的应用。</p>
<p>3 分配名称和定制的UL</p>
<p>在web.xml中完成的一个最常见的任务是对servlet或JSP页面给出名称和定制的URL。用servlet元素分配名称，使用servlet-mapping元素将定制的URL与刚分配的名称相关联。<br />
3.1 分配名称<br />
为了提供初始化参数，对servlet或JSP页面定义一个定制URL或分配一个安全角色，必须首先给servlet或JSP页面一个名称。可通过servlet元素分配一个名称。最常见的格式包括servlet-name和servlet-class子元素（在web-app元素内），如下所示：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;</p>
<p>这表示位于WEB-INF/classes/moreservlets/TestServlet的servlet已经得到了注册名Test。给servlet一个名称具有两个主要的含义。首先，初始化参数、定制的URL模式以及其他定制通过此注册名而不是类名引用此servlet。其次,可在URL而不是类名中使用此名称。因此，利用刚才给出的定义，URL <a href="http://host/webAppPrefix/servlet/Test">http://host/webAppPrefix/servlet/Test</a> 可用于 <a href="http://host/webAppPrefix/servlet/moreservlets.TestServlet">http://host/webAppPrefix/servlet/moreservlets.TestServlet</a> 的场所。<br />
请记住：XML元素不仅是大小写敏感的，而且定义它们的次序也很重要。例如，web-app元素内所有servlet元素必须位于所有servlet-mapping元素（下一小节介绍）之前，而且还要位于5.6节和5.11节讨论的与过滤器或文档相关的元素（如果有的话）之前。类似地，servlet的servlet-name子元素也必须出现在servlet-class之前。5.2节&#8221;部署描述符文件内的元素次序&#8221;将详细介绍这种必需的次序。<br />
例如，程序清单5-1给出了一个名为TestServlet的简单servlet，它驻留在moreservlets程序包中。因为此servlet是扎根在一个名为deployDemo的目录中的Web应用的组成部分，所以TestServlet.class放在deployDemo/WEB-INF/classes/moreservlets中。程序清单5-2给出将放置在deployDemo/WEB-INF/内的web.xml文件的一部分。此web.xml文件使用servlet-name和servlet-class元素将名称Test与TestServlet.class相关联。图5-1和图5-2分别显示利用缺省URL和注册名调用TestServlet时的结果。</p>
<p>程序清单5-1 TestServlet.java<br />
package moreservlets;</p>
<p>import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;</p>
<p>/** Simple servlet used to illustrate servlet naming<br />
* and custom URLs.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* <a href="http://www.moreservlets.com/">http://www.moreservlets.com/</a>.<br />
* &copy; 2002 Marty Hall; may be freely used or adapted.<br />
*/</p>
<p>public class TestServlet extends HttpServlet {<br />
public void doGet(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
response.setContentType(&#8221;text/html&#8221;);<br />
PrintWriter out = response.getWriter();<br />
String uri = request.getRequestURI();<br />
out.println(ServletUtilities.headWithTitle(&#8221;Test Servlet&#8221;) +<br />
&#8220;&lt;BODY BGCOLOR=\&#8221;#FDF5E6\&#8221;&gt;\n&#8221; +<br />
&#8220;&lt;H2&gt;URI: &#8221; + uri + &#8220;&lt;/H2&gt;\n&#8221; +<br />
&#8220;&lt;/BODY&gt;&lt;/HTML&gt;&#8221;);<br />
}<br />
}</p>
<p>程序清单5-2 web.xml（说明servlet名称的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;!&#8211; … &#8211;&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!&#8211; … &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>3.2 定义定制的URL<br />
大多数服务器具有一个缺省的serlvet URL：<br />
<a href="http://host/webAppPrefix/servlet/packageName.ServletName">http://host/webAppPrefix/servlet/packageName.ServletName</a>。虽然在开发中使用这个URL很方便，但是我们常常会希望另一个URL用于部署。例如，可能会需要一个出现在Web应用顶层的URL（如，<a href="http://host/webAppPrefix/Anyname">http://host/webAppPrefix/Anyname</a>），并且在此URL中没有servlet项。位于顶层的URL简化了相对URL的使用。此外，对许多开发人员来说，顶层URL看上去比更长更麻烦的缺省URL更简短。<br />
事实上，有时需要使用定制的URL。比如，你可能想关闭缺省URL映射，以便更好地强制实施安全限制或防止用户意外地访问无初始化参数的servlet。如果你禁止了缺省的URL，那么你怎样访问servlet呢？这时只有使用定制的URL了。<br />
为了分配一个定制的URL，可使用servlet-mapping元素及其servlet-name和url-pattern子元素。Servlet-name元素提供了一个任意名称，可利用此名称引用相应的servlet；url-pattern描述了相对于Web应用的根目录的URL。url-pattern元素的值必须以斜杠（/）起始。<br />
下面给出一个简单的web.xml摘录，它允许使用URL <a href="http://host/webAppPrefix/UrlTest">http://host/webAppPrefix/UrlTest</a>而不是<a href="http://host/webAppPrefix/servlet/Test">http://host/webAppPrefix/servlet/Test</a>或<br />
<a href="http://host/webAppPrefix/servlet/moreservlets.TestServlet">http://host/webAppPrefix/servlet/moreservlets.TestServlet</a>。请注意，仍然需要XML头、DOCTYPE声明以及web-app封闭元素。此外，可回忆一下，XML元素出现地次序不是随意的。特别是，需要把所有servlet元素放在所有servlet-mapping元素之前。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/UrlTest&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
URL模式还可以包含通配符。例如，下面的小程序指示服务器发送所有以Web应用的URL前缀开始，以..asp结束的请求到名为BashMS的servlet。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;BashMS&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;msUtils.ASPTranslator&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;BashMS&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/*.asp&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
3.3 命名JSP页面<br />
因为JSP页面要转换成sevlet，自然希望就像命名servlet一样命名JSP页面。毕竟，JSP页面可能会从初始化参数、安全设置或定制的URL中受益，正如普通的serlvet那样。虽然JSP页面的后台实际上是servlet这句话是正确的，但存在一个关键的猜疑：即，你不知道JSP页面的实际类名（因为系统自己挑选这个名字）。因此，为了命名JSP页面，可将jsp-file元素替换为servlet-calss元素，如下所示：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/TestPage.jsp&lt;/jsp-file&gt;<br />
&lt;/servlet&gt;<br />
命名JSP页面的原因与命名servlet的原因完全相同：即为了提供一个与定制设置（如，初始化参数和安全设置）一起使用的名称，并且，以便能更改激活JSP页面的URL（比方说，以便多个URL通过相同页面得以处理，或者从URL中去掉.jsp扩展名）。但是，在设置初始化参数时，应该注意，JSP页面是利用jspInit方法，而不是init方法读取初始化参数的。<br />
例如，程序清单5-3给出一个名为TestPage.jsp的简单JSP页面，它的工作只是打印出用来激活它的URL的本地部分。TestPage.jsp放置在deployDemo应用的顶层。程序清单5-4给出了用来分配一个注册名PageName，然后将此注册名与<a href="http://host/webAppPrefix/UrlTest2/anything">http://host/webAppPrefix/UrlTest2/anything</a> 形式的URL相关联的web.xml文件（即，deployDemo/WEB-INF/web.xml）的一部分。</p>
<p>程序清单5-3 TestPage.jsp<br />
&lt;!DOCTYPE HTML PUBLIC &#8220;-//W3C//DTD HTML 4.0 Transitional//EN&#8221;&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;<br />
&lt;TITLE&gt;<br />
JSP Test Page<br />
&lt;/TITLE&gt;<br />
&lt;/HEAD&gt;<br />
&lt;BODY BGCOLOR=&#8221;#FDF5E6&#8243;&gt;<br />
&lt;H2&gt;URI: &lt;%= request.getRequestURI() %&gt;&lt;/H2&gt;<br />
&lt;/BODY&gt;<br />
&lt;/HTML&gt;</p>
<p>程序清单5-4 web.xml（说明JSP页命名的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/TestPage.jsp&lt;/jsp-file&gt;<br />
&lt;/servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; PageName &lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/UrlTest2/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>4 禁止激活器servlet</p>
<p>对servlet或JSP页面建立定制URL的一个原因是，这样做可以注册从init（servlet）或jspInit（JSP页面）方法中读取得初始化参数。但是，初始化参数只在是利用定制URL模式或注册名访问servlet或JSP页面时可以使用，用缺省URL <a href="http://host/webAppPrefix/servlet/ServletName">http://host/webAppPrefix/servlet/ServletName</a> 访问时不能使用。因此，你可能会希望关闭缺省URL，这样就不会有人意外地调用初始化servlet了。这个过程有时称为禁止激活器servlet，因为多数服务器具有一个用缺省的servlet URL注册的标准servlet，并激活缺省的URL应用的实际servlet。<br />
有两种禁止此缺省URL的主要方法：<br />
l 在每个Web应用中重新映射/servlet/模式。<br />
l 全局关闭激活器servlet。<br />
重要的是应该注意到，虽然重新映射每个Web应用中的/servlet/模式比彻底禁止激活servlet所做的工作更多，但重新映射可以用一种完全可移植的方式来完成。相反，全局禁止激活器servlet完全是针对具体机器的，事实上有的服务器（如ServletExec）没有这样的选择。下面的讨论对每个Web应用重新映射/servlet/ URL模式的策略。后面提供在Tomcat中全局禁止激活器servlet的详细内容。<br />
4.1 重新映射/servlet/URL模式<br />
在一个特定的Web应用中禁止以<a href="http://host/webAppPrefix/servlet/">http://host/webAppPrefix/servlet/</a> 开始的URL的处理非常简单。所需做的事情就是建立一个错误消息servlet，并使用前一节讨论的url-pattern元素将所有匹配请求转向该servlet。只要简单地使用：<br />
&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />
作为servlet-mapping元素中的模式即可。<br />
例如，程序清单5-5给出了将SorryServlet servlet（程序清单5-6）与所有以<a href="http://host/webAppPrefix/servlet/">http://host/webAppPrefix/servlet/</a> 开头的URL相关联的部署描述符文件的一部分。</p>
<p>程序清单5-5 web.xml（说明JSP页命名的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Sorry&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.SorryServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; Sorry &lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>程序清单5-6 SorryServlet.java<br />
package moreservlets;</p>
<p>import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;</p>
<p>/** Simple servlet used to give error messages to<br />
* users who try to access default servlet URLs<br />
* (i.e., <a href="http://host/webAppPrefix/servlet/ServletName">http://host/webAppPrefix/servlet/ServletName</a>)<br />
* in Web applications that have disabled this<br />
* behavior.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* <a href="http://www.moreservlets.com/">http://www.moreservlets.com/</a>.<br />
* &copy; 2002 Marty Hall; may be freely used or adapted.<br />
*/</p>
<p>public class SorryServlet extends HttpServlet {<br />
public void doGet(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
response.setContentType(&#8221;text/html&#8221;);<br />
PrintWriter out = response.getWriter();<br />
String title = &#8220;Invoker Servlet Disabled.&#8221;;<br />
out.println(ServletUtilities.headWithTitle(title) +<br />
&#8220;&lt;BODY BGCOLOR=\&#8221;#FDF5E6\&#8221;&gt;\n&#8221; +<br />
&#8220;&lt;H2&gt;&#8221; + title + &#8220;&lt;/H2&gt;\n&#8221; +<br />
&#8220;Sorry, access to servlets by means of\n&#8221; +<br />
&#8220;URLs that begin with\n&#8221; +<br />
&#8220;<a href="http://host/webAppPrefix/servlet//n">http://host/webAppPrefix/servlet/\n</a>&#8221; +<br />
&#8220;has been disabled.\n&#8221; +<br />
&#8220;&lt;/BODY&gt;&lt;/HTML&gt;&#8221;);<br />
}</p>
<p>public void doPost(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
doGet(request, response);<br />
}<br />
}</p>
<p>4.2 全局禁止激活器：Tomcat<br />
Tomcat 4中用来关闭缺省URL的方法与Tomcat 3中所用的很不相同。下面介绍这两种方法：<br />
1．禁止激活器： Tomcat 4<br />
Tomcat 4用与前面相同的方法关闭激活器servlet，即利用web.xml中的url-mapping元素进行关闭。不同之处在于Tomcat使用了放在install_dir/conf中的一个服务器专用的全局web.xml文件，而前面使用的是存放在每个Web应用的WEB-INF目录中的标准web.xml文件。<br />
因此，为了在Tomcat 4中关闭激活器servlet，只需在install_dir/conf/web.xml中简单地注释出/servlet/* URL映射项即可，如下所示：<br />
&lt;!&#8211;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;invoker&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&#8211;&gt;<br />
再次提醒，应该注意这个项是位于存放在install_dir/conf的Tomcat专用的web.xml文件中的，此文件不是存放在每个Web应用的WEB-INF目录中的标准web.xml。<br />
2．禁止激活器：Tomcat3<br />
在Apache Tomcat的版本3中，通过在install_dir/conf/server.xml中注释出InvokerInterceptor项全局禁止缺省servlet URL。例如，下面是禁止使用缺省servlet URL的server.xml文件的一部分。<br />
&lt;!&#8211;<br />
&lt;RequsetInterceptor<br />
className=&#8221;org.apache.tomcat.request.InvokerInterceptor&#8221;<br />
debug=&#8221;0&#8243; prefix=&#8221;/servlet/&#8221; /&gt;<br />
&#8211;&gt;</p>
<p>5 初始化和预装载servlet与JSP页面</p>
<p>这里讨论控制servlet和JSP页面的启动行为的方法。特别是，说明了怎样分配初始化参数以及怎样更改服务器生存期中装载servlet和JSP页面的时刻。<br />
5.1 分配servlet初始化参数<br />
利用init-param元素向servlet提供初始化参数，init-param元素具有param-name和param-value子元素。例如，在下面的例子中，如果initServlet servlet是利用它的注册名（InitTest）访问的，它将能够从其方法中调用getServletConfig().getInitParameter(&#8221;param1&#8243;)获得&#8221;Value 1&#8243;，调用getServletConfig().getInitParameter(&#8221;param2&#8243;)获得&#8221;2&#8243;。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;InitTest&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.InitServlet&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;param1&lt;/param-name&gt;<br />
&lt;param-value&gt;value1&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;param2&lt;/param-name&gt;<br />
&lt;param-value&gt;2&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;/servlet&gt;<br />
在涉及初始化参数时，有几点需要注意：<br />
l 返回值。GetInitParameter的返回值总是一个String。因此，在前一个例子中，可对param2使用Integer.parseInt获得一个int。<br />
l JSP中的初始化。JSP页面使用jspInit而不是init。JSP页面还需要使用jsp-file元素代替servlet-class。<br />
l 缺省URL。初始化参数只在通过它们的注册名或与它们注册名相关的定制URL模式访问Servlet时可以使用。因此，在这个例子中，param1和param2初始化参数将能够在使用URL <a href="http://host/webAppPrefix/servlet/InitTest">http://host/webAppPrefix/servlet/InitTest</a> 时可用，但在使用URL <a href="http://host/webAppPrefix/servlet/myPackage.InitServlet">http://host/webAppPrefix/servlet/myPackage.InitServlet</a> 时不能使用。<br />
例如，程序清单5-7给出一个名为InitServlet的简单servlet，它使用init方法设置firstName和emailAddress字段。程序清单5-8给出分配名称InitTest给servlet的web.xml文件。<br />
程序清单5-7 InitServlet.java<br />
package moreservlets;</p>
<p>import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;</p>
<p>/** Simple servlet used to illustrate servlet<br />
* initialization parameters.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* <a href="http://www.moreservlets.com/">http://www.moreservlets.com/</a>.<br />
* &copy; 2002 Marty Hall; may be freely used or adapted.<br />
*/</p>
<p>public class InitServlet extends HttpServlet {<br />
private String firstName, emailAddress;</p>
<p>public void init() {<br />
ServletConfig config = getServletConfig();<br />
firstName = config.getInitParameter(&#8221;firstName&#8221;);<br />
emailAddress = config.getInitParameter(&#8221;emailAddress&#8221;);<br />
}</p>
<p>public void doGet(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
response.setContentType(&#8221;text/html&#8221;);<br />
PrintWriter out = response.getWriter();<br />
String uri = request.getRequestURI();<br />
out.println(ServletUtilities.headWithTitle(&#8221;Init Servlet&#8221;) +<br />
&#8220;&lt;BODY BGCOLOR=\&#8221;#FDF5E6\&#8221;&gt;\n&#8221; +<br />
&#8220;&lt;H2&gt;Init Parameters:&lt;/H2&gt;\n&#8221; +<br />
&#8220;&lt;UL&gt;\n&#8221; +<br />
&#8220;&lt;LI&gt;First name: &#8221; + firstName + &#8220;\n&#8221; +<br />
&#8220;&lt;LI&gt;Email address: &#8221; + emailAddress + &#8220;\n&#8221; +<br />
&#8220;&lt;/UL&gt;\n&#8221; +<br />
&#8220;&lt;/BODY&gt;&lt;/HTML&gt;&#8221;);<br />
}<br />
}</p>
<p>程序清单5-8 web.xml（说明初始化参数的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;InitTest&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.InitServlet&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;firstName&lt;/param-name&gt;<br />
&lt;param-value&gt;Larry&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;emailAddress&lt;/param-name&gt;<br />
&lt;param-value&gt;Ellison@Microsoft.com&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;/servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>5.2 分配JSP初始化参数<br />
给JSP页面提供初始化参数在三个方面不同于给servlet提供初始化参数。<br />
1）使用jsp-file而不是servlet-class。因此，WEB-INF/web.xml文件的servlet元素如下所示：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/RealPage.jsp&lt;/jsp-file&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;&#8230;&lt;/param-name&gt;<br />
&lt;param-value&gt;&#8230;&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&#8230;<br />
&lt;/servlet&gt;<br />
2)几乎总是分配一个明确的URL模式。对servlet，一般相应地使用以<a href="http://host/webAppPrefix/servlet/">http://host/webAppPrefix/servlet/</a> 开始的缺省URL。只需记住，使用注册名而不是原名称即可。这对于JSP页面在技术上也是合法的。例如，在上面给出的例子中，可用URL <a href="http://host/webAppPrefix/servlet/PageName">http://host/webAppPrefix/servlet/PageName</a> 访问RealPage.jsp的对初始化参数具有访问权的版本。但在用于JSP页面时，许多用户似乎不喜欢应用常规的servlet的URL。此外，如果JSP页面位于服务器为其提供了目录清单的目录中（如，一个既没有index.html也没有index.jsp文件的目录），则用户可能会连接到此JSP页面，单击它，从而意外地激活未初始化的页面。因此，好的办法是使用url-pattern（5.3节）将JSP页面的原URL与注册的servlet名相关联。这样，客户机可使用JSP页面的普通名称，但仍然激活定制的版本。例如，给定来自项目1的servlet定义，可使用下面的servlet-mapping定义：<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/RealPage.jsp&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
3）JSP页使用jspInit而不是init。自动从JSP页面建立的servlet或许已经使用了inti方法。因此，使用JSP声明提供一个init方法是不合法的，必须制定jspInit方法。<br />
为了说明初始化JSP页面的过程，程序清单5-9给出了一个名为InitPage.jsp的JSP页面，它包含一个jspInit方法且放置于deployDemo Web应用层次结构的顶层。一般，<a href="http://host/deployDemo/InitPage.jsp">http://host/deployDemo/InitPage.jsp</a> 形式的URL将激活此页面的不具有初始化参数访问权的版本，从而将对firstName和emailAddress变量显示null。但是，web.xml文件（程序清单5-10）分配了一个注册名，然后将该注册名与URL模式/InitPage.jsp相关联。</p>
<p>程序清单5-9 InitPage.jsp<br />
&lt;!DOCTYPE HTML PUBLIC &#8220;-//W3C//DTD HTML 4.0 Transitional//EN&#8221;&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;&lt;TITLE&gt;JSP Init Test&lt;/TITLE&gt;&lt;/HEAD&gt;<br />
&lt;BODY BGCOLOR=&#8221;#FDF5E6&#8243;&gt;<br />
&lt;H2&gt;Init Parameters:&lt;/H2&gt;<br />
&lt;UL&gt;<br />
&lt;LI&gt;First name: &lt;%= firstName %&gt;<br />
&lt;LI&gt;Email address: &lt;%= emailAddress %&gt;<br />
&lt;/UL&gt;<br />
&lt;/BODY&gt;&lt;/HTML&gt;<br />
&lt;%!<br />
private String firstName, emailAddress;</p>
<p>public void jspInit() {<br />
ServletConfig config = getServletConfig();<br />
firstName = config.getInitParameter(&#8221;firstName&#8221;);<br />
emailAddress = config.getInitParameter(&#8221;emailAddress&#8221;);<br />
}<br />
%&gt;</p>
<p>程序清单5-10 web.xml（说明JSP页面的init参数的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;InitPage&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/InitPage.jsp&lt;/jsp-file&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;firstName&lt;/param-name&gt;<br />
&lt;param-value&gt;Bill&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;emailAddress&lt;/param-name&gt;<br />
&lt;param-value&gt;gates@oracle.com&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;/servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; InitPage&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/InitPage.jsp&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>5.3 提供应用范围内的初始化参数<br />
一般，对单个地servlet或JSP页面分配初始化参数。指定的servlet或JSP页面利用ServletConfig的getInitParameter方法读取这些参数。但是，在某些情形下，希望提供可由任意servlet或JSP页面借助ServletContext的getInitParameter方法读取的系统范围内的初始化参数。<br />
可利用context-param元素声明这些系统范围内的初始化值。context-param元素应该包含param-name、param-value以及可选的description子元素，如下所示：<br />
&lt;context-param&gt;<br />
&lt;param-name&gt;support-email&lt;/param-name&gt;<br />
&lt;param-value&gt;blackhole@mycompany.com&lt;/param-value&gt;<br />
&lt;/context-param&gt;<br />
可回忆一下，为了保证可移植性，web.xml内的元素必须以正确的次序声明。但这里应该注意，context-param元素必须出现任意与文档有关的元素（icon、display-name或description）之后及filter、filter-mapping、listener或servlet元素之前。<br />
5.4 在服务器启动时装载servlet<br />
假如servlet或JSP页面有一个要花很长时间执行的init（servlet）或jspInit（JSP）方法。例如，假如init或jspInit方法从某个数据库或ResourceBundle查找产量。这种情况下，在第一个客户机请求时装载servlet的缺省行为将对第一个客户机产生较长时间的延迟。因此，可利用servlet的load-on-startup元素规定服务器在第一次启动时装载servlet。下面是一个例子。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt; … &lt;/servlet-name&gt;<br />
&lt;servlet-class&gt; … &lt;/servlet-class&gt; &lt;!&#8211; Or jsp-file &#8211;&gt;<br />
&lt;load-on-startup/&gt;<br />
&lt;/servlet&gt;<br />
可以为此元素体提供一个整数而不是使用一个空的load-on-startup。想法是服务器应该在装载较大数目的servlet或JSP页面之前装载较少数目的servlet或JSP页面。例如，下面的servlet项（放置在Web应用的WEB-INF目录下的web.xml文件中的web-app元素内）将指示服务器首先装载和初始化SearchServlet，然后装载和初始化由位于Web应用的result目录中的index.jsp文件产生的servlet。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Search&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;myPackage.SearchServlet&lt;/servlet-class&gt; &lt;!&#8211; Or jsp-file &#8211;&gt;<br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Results&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;/results/index.jsp&lt;/servlet-class&gt; &lt;!&#8211; Or jsp-file &#8211;&gt;<br />
&lt;load-on-startup&gt;2&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;</p>
<p>6 声明过滤器</p>
<p>servlet版本2.3引入了过滤器的概念。虽然所有支持servlet API版本2.3的服务器都支持过滤器，但为了使用与过滤器有关的元素，必须在web.xml中使用版本2.3的DTD。<br />
过滤器可截取和修改进入一个servlet或JSP页面的请求或从一个servlet或JSP页面发出的相应。在执行一个servlet或JSP页面之前，必须执行第一个相关的过滤器的doFilter方法。在该过滤器对其FilterChain对象调用doFilter时，执行链中的下一个过滤器。如果没有其他过滤器，servlet或JSP页面被执行。过滤器具有对到来的ServletRequest对象的全部访问权，因此，它们可以查看客户机名、查找到来的cookie等。为了访问servlet或JSP页面的输出，过滤器可将响应对象包裹在一个替身对象（stand-in object）中，比方说把输出累加到一个缓冲区。在调用FilterChain对象的doFilter方法之后，过滤器可检查缓冲区，如有必要，就对它进行修改，然后传送到客户机。<br />
例如，程序清单5-11帝国难以了一个简单的过滤器，只要访问相关的servlet或JSP页面，它就截取请求并在标准输出上打印一个报告（开发过程中在桌面系统上运行时，大多数服务器都可以使用这个过滤器）。</p>
<p>程序清单5-11 ReportFilter.java<br />
package moreservlets;</p>
<p>import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;<br />
import java.util.*;</p>
<p>/** Simple filter that prints a report on the standard output<br />
* whenever the associated servlet or JSP page is accessed.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* <a href="http://www.moreservlets.com/">http://www.moreservlets.com/</a>.<br />
* &copy; 2002 Marty Hall; may be freely used or adapted.<br />
*/</p>
<p>public class ReportFilter implements Filter {<br />
public void doFilter(ServletRequest request,<br />
ServletResponse response,<br />
FilterChain chain)<br />
throws ServletException, IOException {<br />
HttpServletRequest req = (HttpServletRequest)request;<br />
System.out.println(req.getRemoteHost() +<br />
&#8221; tried to access &#8221; +<br />
req.getRequestURL() +<br />
&#8221; on &#8221; + new Date() + &#8220;.&#8221;);<br />
chain.doFilter(request,response);<br />
}</p>
<p>public void init(FilterConfig config)<br />
throws ServletException {<br />
}</p>
<p>public void destroy() {}<br />
}</p>
<p>一旦建立了一个过滤器，可以在web.xml中利用filter元素以及filter-name（任意名称）、file-class（完全限定的类名）和（可选的）init-params子元素声明它。请注意，元素在web.xml的web-app元素中出现的次序不是任意的；允许服务器（但不是必需的）强制所需的次序，并且实际中有些服务器也是这样做的。但这里要注意，所有filter元素必须出现在任意filter-mapping元素之前，filter-mapping元素又必须出现在所有servlet或servlet-mapping元素之前。<br />
例如，给定上述的ReportFilter类，可在web.xml中作出下面的filter声明。它把名称Reporter与实际的类ReportFilter（位于moreservlets程序包中）相关联。<br />
&lt;filter&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;filter-class&gt;moresevlets.ReportFilter&lt;/filter-class&gt;<br />
&lt;/filter&gt;<br />
一旦命名了一个过滤器，可利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。关于此项工作有两种选择。<br />
首先，可使用filter-name和servlet-name子元素把此过滤器与一个特定的servlet名（此servlet名必须稍后在相同的web.xml文件中使用servlet元素声明）关联。例如，下面的程序片断指示系统只要利用一个定制的URL访问名为SomeServletName的servlet或JSP页面，就运行名为Reporter的过滤器。<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;servlet-name&gt;SomeServletName&lt;/servlet-name&gt;<br />
&lt;/filter-mapping&gt;<br />
其次，可利用filter-name和url-pattern子元素将过滤器与一组servlet、JSP页面或静态内容相关联。例如，相面的程序片段指示系统只要访问Web应用中的任意URL，就运行名为Reporter的过滤器。<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />
&lt;/filter-mapping&gt;<br />
例如，程序清单5-12给出了将ReportFilter过滤器与名为PageName的servlet相关联的web.xml文件的一部分。名字PageName依次又与一个名为TestPage.jsp的JSP页面以及以模式<a href="http://host/webAppPrefix/UrlTest2/">http://host/webAppPrefix/UrlTest2/</a> 开头的URL相关联。TestPage.jsp的源代码已经JSP页面命名的谈论在前面的3节&#8221;分配名称和定制的URL&#8221;中给出。事实上，程序清单5-12中的servlet和servlet-name项从该节原封不动地拿过来的。给定这些web.xml项，可看到下面的标准输出形式的调试报告（换行是为了容易阅读）。<br />
audit.irs.gov tried to access<br />
<a href="http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html">http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html</a><br />
on Tue Dec 25 13:12:29 EDT 2001.</p>
<p>程序清单5-12 Web.xml（说明filter用法的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;filter&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;filter-class&gt;moresevlets.ReportFilter&lt;/filter-class&gt;<br />
&lt;/filter&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;/filter-mapping&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/RealPage.jsp&lt;/jsp-file&gt;<br />
&lt;/servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; PageName &lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/UrlTest2/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>7 指定欢迎页</p>
<p>假如用户提供了一个像<a href="http://host/webAppPrefix/directoryName/">http://host/webAppPrefix/directoryName/</a> 这样的包含一个目录名但没有包含文件名的URL，会发生什么事情呢？用户能得到一个目录表？一个错误？还是标准文件的内容？如果得到标准文件内容，是index.html、index.jsp、default.html、default.htm或别的什么东西呢？<br />
Welcome-file-list元素及其辅助的welcome-file元素解决了这个模糊的问题。例如，下面的web.xml项指出，如果一个URL给出一个目录名但未给出文件名，服务器应该首先试用index.jsp，然后再试用index.html。如果两者都没有找到，则结果有赖于所用的服务器（如一个目录列表）。<br />
&lt;welcome-file-list&gt;<br />
&lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;<br />
&lt;welcome-file&gt;index.html&lt;/welcome-file&gt;<br />
&lt;/welcome-file-list&gt;<br />
虽然许多服务器缺省遵循这种行为，但不一定必须这样。因此，明确地使用welcom-file-list保证可移植性是一种良好的习惯。</p>
<p>8 指定处理错误的页面</p>
<p>现在我了解到，你在开发servlet和JSP页面时从不会犯错误，而且你的所有页面是那样的清晰，一般的程序员都不会被它们的搞糊涂。但是，是人总会犯错误的，用户可能会提供不合规定的参数，使用不正确的URL或者不能提供必需的表单字段值。除此之外，其它开发人员可能不那么细心，他们应该有些工具来克服自己的不足。<br />
error-page元素就是用来克服这些问题的。它有两个可能的子元素，分别是：error-code和exception-type。第一个子元素error-code指出在给定的HTTP错误代码出现时使用的URL。第二个子元素excpetion-type指出在出现某个给定的Java异常但未捕捉到时使用的URL。error-code和exception-type都利用location元素指出相应的URL。此URL必须以/开始。location所指出的位置处的页面可通过查找HttpServletRequest对象的两个专门的属性来访问关于错误的信息，这两个属性分别是：javax.servlet.error.status_code和javax.servlet.error.message。<br />
可回忆一下，在web.xml内以正确的次序声明web-app的子元素很重要。这里只要记住，error-page出现在web.xml文件的末尾附近，servlet、servlet-name和welcome-file-list之后即可。</p>
<p>8.1 error-code元素<br />
为了更好地了解error-code元素的值，可考虑一下如果不正确地输入文件名，大多数站点会作出什么反映。这样做一般会出现一个<font size="-0">404</font>错误信息，它表示不能找到该文件，但几乎没提供更多有用的信息。另一方面，可以试一下在<a href="http://www.microsoft.com/">www.microsoft.com</a>、<a href="http://www.ibm.com/">www.ibm.com</a> 处或者特别是在<a href="http://www.bea.com/">www.bea.com</a> 处输出未知的文件名。这是会得出有用的消息，这些消息提供可选择的位置，以便查找感兴趣的页面。提供这样有用的错误页面对于Web应用来说是很有价值得。事实上，<a href="http://www.plinko.net/404/">http://www.plinko.net/404/</a> 就是把整个站点专门用于<font size="-0">404</font>错误页面这个内容。这个站点包含来自全世界最好、最糟和最搞笑的<font size="-0">404</font>页面。<br />
程序清单5-13给出一个JSP页面，此页面可返回给提供位置程序名的客户机。程序清单5-14给出指定程序清单5-13作为返回<font size="-0">404</font>错误代码时显示的页面的web.xml。请注意，浏览器中显示的URL仍然是客户机所提供的。错误页面是一种后台实现技术。<br />
最后一点，请记住IE5的缺省配置显然不符合HTTP规范，它忽略了服务器生成的错误消息，而是显示自己的标准出错信息。可转到其Tools菜单，选择Internet Options，单击Advanced，取消Show Friendly HTTP Error Message来解决此问题。</p>
<p>程序清单5-13 NotFound.jsp<br />
&lt;!DOCTYPE HTML PUBLIC &#8220;-//W3C//DTD HTML 4.0 Transitional//EN&#8221;&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;&lt;TITLE&gt;<font size="-0">404</font>: Not Found&lt;/TITLE&gt;&lt;/HEAD&gt;<br />
&lt;BODY BGCOLOR=&#8221;#FDF5E6&#8243;&gt;<br />
&lt;H2&gt;Error!&lt;/H2&gt;<br />
I&#8217;m sorry, but I cannot find a page that matches<br />
&lt;%= request.getRequestURI() %&gt; on the system. Maybe you should<br />
try one of the following:<br />
&lt;UL&gt;<br />
&lt;LI&gt;Go to the server&#8217;s &lt;A xhref=&#8221;http://blogger.org.cn/blog//&#8221; mce_href=&#8221;http://blogger.org.cn/blog//&#8221;&gt;home page&lt;/A&gt;.<br />
&lt;LI&gt;Search for relevant pages.&lt;BR&gt;<br />
&lt;FORM ACTION=&#8221;<a href="http://www.google.com/search">http://www.google.com/search</a>&#8220;&gt;<br />
&lt;CENTER&gt;<br />
Keywords: &lt;INPUT TYPE=&#8221;http://blogger.org.cn/blog/TEXT&#8221; NAME=&#8221;q&#8221;&gt;&lt;BR&gt;<br />
&lt;INPUT TYPE=&#8221;SUBMIT&#8221; VALUE=&#8221;Search&#8221;&gt;<br />
&lt;/CENTER&gt;<br />
&lt;/FORM&gt;<br />
&lt;LI&gt;Admire a random multiple of <font size="-0">404</font>:<br />
&lt;%= <font size="-0">404</font>*((int)(1000*Math.random())) %&gt;.<br />
&lt;LI&gt;Try a &lt;A xhref=&#8221;http://blogger.org.cn/blog/<a href="http://www.plinko.net/404/rndindex.asp">http://www.plinko.net/404/rndindex.asp</a>&#8221;<br />
TARGET=&#8221;http://blogger.org.cn/blog/_blank&#8221;&gt;<br />
random <font size="-0">404</font> error message&lt;/A&gt;. From the amazing and<br />
amusing plinko.net &lt;A xhref=&#8221;http://blogger.org.cn/blog/<a href="http://www.plinko.net/404/">http://www.plinko.net/404/</a>&#8220;&gt;<br />
<font size="-0">404</font> archive&lt;/A&gt;.<br />
&lt;/UL&gt;<br />
&lt;/BODY&gt;&lt;/HTML&gt;</p>
<p>程序清单5-14 web.xml（指出HTTP错误代码的错误页面的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;error-page&gt;<br />
&lt;error-code&gt;<font size="-0">404</font>&lt;/error-code&gt;<br />
&lt;location&gt;/NotFound.jsp&lt;/location&gt;<br />
&lt;/error-page&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>8.2 exception-type元素<br />
error-code元素处理某个请求产生一个特定的HTTP状态代码时的情况。然而，对于servlet或JSP页面返回200但产生运行时异常这种同样是常见的情况怎么办呢？这正是exception-type元素要处理的情况。只需提供两样东西即可：即提供如下的一个完全限定的异常类和一个位置：<br />
&lt;error-page&gt;<br />
&lt;exception-type&gt;packageName.className&lt;/exception-type&gt;<br />
&lt;location&gt;/SomeURL&lt;/location&gt;<br />
&lt;/error-page&gt;<br />
这样，如果Web应用中的任何servlet或JSP页面产生一个特定类型的未捕捉到的异常，则使用指定的URL。此异常类型可以是一个标准类型，如javax.ServletException或java.lang.OutOfMemoryError，或者是一个专门针对你的应用的异常。<br />
例如，程序清单5-15给出了一个名为DumbDeveloperException的异常类，可用它来特别标记经验较少的程序员（不是说你的开发组中一定有这种人）所犯的错误。这个类还包含一个名为dangerousComputation的静态方法，它时不时地生成这种类型的异常。程序清单5-16给出对随机整数值调用dangerousCompution的一个JSP页面。在抛出此异常时，如程序清单5-18的web.xml版本中所给出的exception-type所指出的那样，对客户机显示DDE.jsp（程序清单5-17）。图5-16和图5-17分别给出幸运和不幸的结果。</p>
<p>程序清单5-15 DumbDeveloperException.java<br />
package moreservlets;</p>
<p>/** Exception used to flag particularly onerous<br />
programmer blunders. Used to illustrate the<br />
exception-type web.xml element.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* <a href="http://www.moreservlets.com/">http://www.moreservlets.com/</a>.<br />
* &copy; 2002 Marty Hall; may be freely used or adapted.<br />
*/</p>
<p>public class DumbDeveloperException extends Exception {<br />
public DumbDeveloperException() {<br />
super(&#8221;Duh. What was I *thinking*?&#8221;);<br />
}</p>
<p>public static int dangerousComputation(int n)<br />
throws DumbDeveloperException {<br />
if (n &lt; 5) {<br />
return(n + 10);<br />
} else {<br />
throw(new DumbDeveloperException());<br />
}<br />
}<br />
}</p>
<p>程序清单5-16 RiskyPage.jsp<br />
&lt;!DOCTYPE HTML PUBLIC &#8220;-//W3C//DTD HTML 4.0 Transitional//EN&#8221;&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;&lt;TITLE&gt;Risky JSP Page&lt;/TITLE&gt;&lt;/HEAD&gt;<br />
&lt;BODY BGCOLOR=&#8221;#FDF5E6&#8243;&gt;<br />
&lt;H2&gt;Risky Calculations&lt;/H2&gt;<br />
&lt;%@ page import=&#8221;moreservlets.*&#8221; %&gt;<br />
&lt;% int n = ((int)(10 * Math.random())); %&gt;<br />
&lt;UL&gt;<br />
&lt;LI&gt;n: &lt;%= n %&gt;<br />
&lt;LI&gt;dangerousComputation(n):<br />
&lt;%= DumbDeveloperException.dangerousComputation(n) %&gt;<br />
&lt;/UL&gt;<br />
&lt;/BODY&gt;&lt;/HTML&gt;</p>
<p>程序清单5-17 DDE.jsp<br />
&lt;!DOCTYPE HTML PUBLIC &#8220;-//W3C//DTD HTML 4.0 Transitional//EN&#8221;&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;&lt;TITLE&gt;Dumb&lt;/TITLE&gt;&lt;/HEAD&gt;<br />
&lt;BODY BGCOLOR=&#8221;#FDF5E6&#8243;&gt;<br />
&lt;H2&gt;Dumb Developer&lt;/H2&gt;<br />
We&#8217;re brain dead. Consider using our competitors.<br />
&lt;/BODY&gt;&lt;/HTML&gt;</p>
<p>程序清单5-18 web.xml（为异常指定错误页面的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;servlet&gt; … &lt;/servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;error-page&gt;<br />
&lt;exception-type&gt;<br />
moreservlets.DumbDeveloperException<br />
&lt;/exception-type&gt;<br />
&lt;location&gt;/DDE.jsp&lt;/location&gt;<br />
&lt;/error-page&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>9 提供安全性</p>
<p>利用web.xml中的相关元素为服务器的内建功能提供安全性。<br />
9.1 指定验证的方法<br />
使用login-confgi元素规定服务器应该怎样验证试图访问受保护页面的用户。它包含三个可能的子元素，分别是：auth-method、realm-name和form-login-config。login-config元素应该出现在web.xml部署描述符文件的结尾附近，紧跟在security-constraint元素之后。<br />
l auth-method<br />
login-config的这个子元素列出服务器将要使用的特定验证机制。有效值为BASIC、DIGEST、FORM和CLIENT-CERT。服务器只需要支持BASIC和FORM。<br />
BASIC指出应该使用标准的HTTP验证，在此验证中服务器检查Authorization头。如果缺少这个头则返回一个401状态代码和一个WWW-Authenticate头。这导致客户机弹出一个用来填写Authorization头的对话框。此机制很少或不提供对攻击者的防范，这些攻击者在Internet连接上进行窥探（如通过在客户机的子网上执行一个信息包探测装置），因为用户名和口令是用简单的可逆base64编码发送的，他们很容易得手。所有兼容的服务器都需要支持BASIC验证。<br />
DIGEST指出客户机应该利用加密Digest Authentication形式传输用户名和口令。这提供了比BASIC验证更高的防范网络截取得的安全性，但这种加密比SSL（HTTPS）所用的方法更容易破解。不过，此结论有时没有意义，因为当前很少有浏览器支持Digest Authentication，所以servlet容器不需要支持它。<br />
FORM指出服务器应该检查保留的会话cookie并且把不具有它的用户重定向到一个指定的登陆页。此登陆页应该包含一个收集用户名和口令的常规HTML表单。在登陆之后，利用保留会话级的cookie跟踪用户。虽然很复杂，但FORM验证防范网络窥探并不比BASIC验证更安全，如果有必要可以在顶层安排诸如SSL或网络层安全（如IPSEC或VPN）等额外的保护。所有兼容的服务器都需要支持FORM验证。<br />
CLIENT-CERT规定服务器必须使用HTTPS（SSL之上的HTTP）并利用用户的公开密钥证书（Pulic Key Certificat）对用户进行验证。这提供了防范网络截取的很强的安全性，但只有兼容J2EE的服务器需要支持它。<br />
l realm-name<br />
此元素只在auth-method为BASIC时使用。它指出浏览器在相应对话框标题使用的、并作为Authorization头组成部分的安全域的名称。<br />
l form-login-config<br />
此元素只在auth-method为FORM时适用。它指定两个页面，分别是：包含收集用户名及口令的HTML表单的页面（利用form-login-page子元素），用来指示验证失败的页面（利用form-error-page子元素）。由form-login-page给出的HTML表单必须具有一个j_security_check的ACTION属性、一个名为j_username的用户名文本字段以及一个名为j_password的口令字段。<br />
例如，程序清单5-19指示服务器使用基于表单的验证。Web应用的顶层目录中的一个名为login.jsp的页面将收集用户名和口令，并且失败的登陆将由相同目录中名为login-error.jsp的页面报告。</p>
<p>程序清单5-19 web.xml（说明login-config的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;security-constraint&gt; &#8230; &lt;/security-constraint&gt;<br />
&lt;login-config&gt;<br />
&lt;auth-method&gt; FORM &lt;/auth-method&gt;<br />
&lt;form-login-config&gt;<br />
&lt;form-login-page&gt;/login.jsp&lt;/form-login-page&gt;<br />
&lt;form-error-page&gt;/login-error.jsp&lt;/form-error-page&gt;<br />
&lt;/form-login-config&gt;<br />
&lt;/login-config&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>9.2 限制对Web资源的访问<br />
现在，可以指示服务器使用何种验证方法了。&#8221;了不起，&#8221;你说道，&#8221;除非我能指定一个来收到保护的URL，否则没有多大用处。&#8221;没错。指出这些URL并说明他们应该得到何种保护正是security-constriaint元素的用途。此元素在web.xml中应该出现在login-config的紧前面。它包含是个可能的子元素，分别是：web-resource-collection、auth-constraint、user-data-constraint和display-name。下面各小节对它们进行介绍。<br />
l web-resource-collection<br />
此元素确定应该保护的资源。所有security-constraint元素都必须包含至少一个web-resource-collection项。此元素由一个给出任意标识名称的web-resource-name元素、一个确定应该保护的URL的url-pattern元素、一个指出此保护所适用的HTTP命令（GET、POST等，缺省为所有方法）的http-method元素和一个提供资料的可选description元素组成。例如，下面的Web-resource-collection项（在security-constratint元素内）指出Web应用的proprietary目录中所有文档应该受到保护。<br />
&lt;security-constraint&gt;<br />
&lt;web-resource-coolection&gt;<br />
&lt;web-resource-name&gt;Proprietary&lt;/web-resource-name&gt;<br />
&lt;url-pattern&gt;/propritary/*&lt;/url-pattern&gt;<br />
&lt;/web-resource-coolection&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/security-constraint&gt;<br />
重要的是应该注意到，url-pattern仅适用于直接访问这些资源的客户机。特别是，它不适合于通过MVC体系结构利用RequestDispatcher来访问的页面，或者不适合于利用类似jsp:forward的手段来访问的页面。这种不匀称如果利用得当的话很有好处。例如，servlet可利用MVC体系结构查找数据，把它放到bean中，发送请求到从bean中提取数据的JSP页面并显示它。我们希望保证决不直接访问受保护的JSP页面，而只是通过建立该页面将使用的bean的servlet来访问它。url-pattern和auth-contraint元素可通过声明不允许任何用户直接访问JSP页面来提供这种保证。但是，这种不匀称的行为可能让开发人员放松警惕，使他们偶然对应受保护的资源提供不受限制的访问。<br />
l auth-constraint<br />
尽管web-resource-collention元素质出了哪些URL应该受到保护，但是auth-constraint元素却指出哪些用户应该具有受保护资源的访问权。此元素应该包含一个或多个标识具有访问权限的用户类别role-name元素，以及包含（可选）一个描述角色的description元素。例如，下面web.xml中的security-constraint元素部门规定只有指定为Administrator或Big Kahuna（或两者）的用户具有指定资源的访问权。<br />
&lt;security-constraint&gt;<br />
&lt;web-resource-coolection&gt; &#8230; &lt;/web-resource-coolection&gt;<br />
&lt;auth-constraint&gt;<br />
&lt;role-name&gt;administrator&lt;/role-name&gt;<br />
&lt;role-name&gt;kahuna&lt;/role-name&gt;<br />
&lt;/auth-constraint&gt;<br />
&lt;/security-constraint&gt;<br />
重要的是认识到，到此为止，这个过程的可移植部分结束了。服务器怎样确定哪些用户处于任何角色以及它怎样存放用户的口令，完全有赖于具体的系统。<br />
例如，Tomcat使用install_dir/conf/tomcat-users.xml将用户名与角色名和口令相关联，正如下面例子中所示，它指出用户joe（口令bigshot）和jane（口令enaj）属于administrator和kahuna角色。<br />
&lt;tomcat-users&gt;<br />
&lt;user name=&#8221;joe&#8221; password=&#8221;bigshot&#8221; roles=&#8221;administrator,kahuna&#8221; /&gt;<br />
&lt;user name=&#8221;jane&#8221; password=&#8221;enaj&#8221; roles=&#8221;kahuna&#8221; /&gt;<br />
&lt;/tomcat-users&gt;<br />
l user-data-constraint<br />
这个可选的元素指出在访问相关资源时使用任何传输层保护。它必须包含一个transport-guarantee子元素（合法值为NONE、INTEGRAL或CONFIDENTIAL），并且可选地包含一个description元素。transport-guarantee为NONE值将对所用的通讯协议不加限制。INTEGRAL值表示数据必须以一种防止截取它的人阅读它的方式传送。虽然原理上（并且在未来的HTTP版本中），在INTEGRAL和CONFIDENTIAL之间可能会有差别，但在当前实践中，他们都只是简单地要求用SSL。例如，下面指示服务器只允许对相关资源做HTTPS连接：<br />
&lt;security-constraint&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;user-data-constraint&gt;<br />
&lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;<br />
&lt;/user-data-constraint&gt;<br />
&lt;/security-constraint&gt;<br />
l display-name<br />
security-constraint的这个很少使用的子元素给予可能由GUI工具使用的安全约束项一个名称。<br />
9.3 分配角色名<br />
迄今为止，讨论已经集中到完全由容器（服务器）处理的安全问题之上了。但servlet以及JSP页面也能够处理它们自己的安全问题。<br />
例如，容器可能允许用户从bigwig或bigcheese角色访问一个显示主管人员额外紧贴的页面，但只允许bigwig用户修改此页面的参数。完成这种更细致的控制的一种常见方法是调用HttpServletRequset的isUserInRole方法，并据此修改访问。<br />
Servlet的security-role-ref子元素提供出现在服务器专用口令文件中的安全角色名的一个别名。例如，假如编写了一个调用request.isUserInRole（&#8221;boss&#8221;）的servlet，但后来该servlet被用在了一个其口令文件调用角色manager而不是boss的服务器中。下面的程序段使该servlet能够使用这两个名称中的任何一个。<br />
&lt;servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;security-role-ref&gt;<br />
&lt;role-name&gt;boss&lt;/role-name&gt; &lt;!&#8211; New alias &#8211;&gt;<br />
&lt;role-link&gt;manager&lt;/role-link&gt; &lt;!&#8211; Real name &#8211;&gt;<br />
&lt;/security-role-ref&gt;<br />
&lt;/servlet&gt;<br />
也可以在web-app内利用security-role元素提供将出现在role-name元素中的所有安全角色的一个全局列表。分别地生命角色使高级IDE容易处理安全信息。</p>
<p>10 控制会话超时</p>
<p>如果某个会话在一定的时间内未被访问，服务器可把它扔掉以节约内存。可利用HttpSession的setMaxInactiveInterval方法直接设置个别会话对象的超时值。如果不采用这种方法，则缺省的超时值由具体的服务器决定。但可利用session-config和session-timeout元素来给出一个适用于所有服务器的明确的超时值。超时值的单位为分钟，因此，下面的例子设置缺省会话超时值为三个小时（180分钟）。<br />
&lt;session-config&gt;<br />
&lt;session-timeout&gt;180&lt;/session-timeout&gt;<br />
&lt;/session-config&gt;</p>
<p>11 Web应用的文档化</p>
<p>越来越多的开发环境开始提供servlet和JSP的直接支持。例子有Borland Jbuilder Enterprise Edition、Macromedia UltraDev、Allaire JRun Studio（写此文时，已被Macromedia收购）以及IBM VisuaAge for Java等。<br />
大量的web.xml元素不仅是为服务器设计的，而且还是为可视开发环境设计的。它们包括icon、display-name和discription等。<br />
可回忆一下，在web.xml内以适当地次序声明web-app子元素很重要。不过，这里只要记住icon、display-name和description是web.xml的web-app元素内的前三个合法元素即可。<br />
l icon<br />
icon元素指出GUI工具可用来代表Web应用的一个和两个图像文件。可利用small-icon元素指定一幅16 x 16的GIF或JPEG图像，用large-icon元素指定一幅32 x 32的图像。下面举一个例子：<br />
&lt;icon&gt;<br />
&lt;small-icon&gt;/images/small-book.gif&lt;/small-icon&gt;<br />
&lt;large-icon&gt;/images/tome.jpg&lt;/large-icon&gt;<br />
&lt;/icon&gt;<br />
l display-name<br />
display-name元素提供GUI工具可能会用来标记此Web应用的一个名称。下面是个例子。<br />
&lt;display-name&gt;Rare Books&lt;/display-name&gt;<br />
l description<br />
description元素提供解释性文本，如下所示：<br />
&lt;description&gt;<br />
This Web application represents the store developed for<br />
rare-books.com, an online bookstore specializing in rare<br />
and limited-edition books.<br />
&lt;/description&gt;</p>
<p>12 关联文件与MIME类型</p>
<p>服务器一般都具有一种让Web站点管理员将文件扩展名与媒体相关联的方法。例如，将会自动给予名为mom.jpg的文件一个image/jpeg的MIME类型。但是，假如你的Web应用具有几个不寻常的文件，你希望保证它们在发送到客户机时分配为某种MIME类型。mime-mapping元素（具有extension和mime-type子元素）可提供这种保证。例如，下面的代码指示服务器将application/x-fubar的MIME类型分配给所有以.foo结尾的文件。<br />
&lt;mime-mapping&gt;<br />
&lt;extension&gt;foo&lt;/extension&gt;<br />
&lt;mime-type&gt;application/x-fubar&lt;/mime-type&gt;<br />
&lt;/mime-mapping&gt;<br />
或许，你的Web应用希望重载（override）标准的映射。例如，下面的代码将告诉服务器在发送到客户机时指定.ps文件作为纯文本（text/plain）而不是作为PostScript（application/postscript）。<br />
&lt;mime-mapping&gt;<br />
&lt;extension&gt;ps&lt;/extension&gt;<br />
&lt;mime-type&gt;application/postscript&lt;/mime-type&gt;<br />
&lt;/mime-mapping&gt;</p>
<p>13 定位TLD</p>
<p>JSP taglib元素具有一个必要的uri属性，它给出一个TLD（Tag Library Descriptor）文件相对于Web应用的根的位置。TLD文件的实际名称在发布新的标签库版本时可能会改变，但我们希望避免更改所有现有JSP页面。此外，可能还希望使用保持taglib元素的简练性的一个简短的uri。这就是部署描述符文件的taglib元素派用场的所在了。Taglib包含两个子元素：taglib-uri和taglib-location。taglib-uri元素应该与用于JSP taglib元素的uri属性的东西相匹配。Taglib-location元素给出TLD文件的实际位置。例如，假如你将文件chart-tags-1.3beta.tld放在WebApp/WEB-INF/tlds中。现在，假如web.xml在web-app元素内包含下列内容。<br />
&lt;taglib&gt;<br />
&lt;taglib-uri&gt;/charts.tld&lt;/taglib-uri&gt;<br />
&lt;taglib-location&gt;<br />
/WEB-INF/tlds/chart-tags-1.3beta.tld<br />
&lt;/taglib-location&gt;<br />
&lt;/taglib&gt;<br />
给出这个说明后，JSP页面可通过下面的简化形式使用标签库。<br />
&lt;%@ taglib uri=&#8221;/charts.tld&#8221; prefix=&#8221;somePrefix&#8221; %&gt;</p>
<p>14 指定应用事件监听程序</p>
<p>应用事件监听器程序是建立或修改servlet环境或会话对象时通知的类。它们是servlet规范的版本2.3中的新内容。这里只简单地说明用来向Web应用注册一个监听程序的web.xml的用法。<br />
注册一个监听程序涉及在web.xml的web-app元素内放置一个listener元素。在listener元素内，listener-class元素列出监听程序的完整的限定类名，如下所示：<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;package.ListenerClass&lt;/listener-class&gt;<br />
&lt;/listener&gt;<br />
虽然listener元素的结构很简单，但请不要忘记，必须正确地给出web-app元素内的子元素的次序。listener元素位于所有的servlet元素之前以及所有filter-mapping元素之后。此外，因为应用生存期监听程序是serlvet规范的2.3版本中的新内容，所以必须使用web.xml DTD的2.3版本，而不是2.2版本。<br />
例如，程序清单5-20给出一个名为ContextReporter的简单的监听程序，只要Web应用的Servlet-Context建立（如装载Web应用）或消除（如服务器关闭）时，它就在标准输出上显示一条消息。程序清单5-21给出此监听程序注册所需要的web.xml文件的一部分。</p>
<p>程序清单5-20 ContextReporterjava<br />
package moreservlets;</p>
<p>import javax.servlet.*;<br />
import java.util.*;</p>
<p>/** Simple listener that prints a report on the standard output<br />
* when the ServletContext is created or destroyed.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* <a href="http://www.moreservlets.com/">http://www.moreservlets.com/</a>.<br />
* &copy; 2002 Marty Hall; may be freely used or adapted.<br />
*/</p>
<p>public class ContextReporter implements ServletContextListener {<br />
public void contextInitialized(ServletContextEvent event) {<br />
System.out.println(&#8221;Context created on &#8221; +<br />
new Date() + &#8220;.&#8221;);<br />
}</p>
<p>public void contextDestroyed(ServletContextEvent event) {<br />
System.out.println(&#8221;Context destroyed on &#8221; +<br />
new Date() + &#8220;.&#8221;);<br />
}<br />
}</p>
<p>程序清单5-21 web.xml（声明一个监听程序的摘录）<br />
&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;ISO-8859-1&#8243;?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC &#8220;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN&#8221;<br />
&#8220;<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>&#8220;&gt;</p>
<p>&lt;web-app&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;filter-mapping&gt; … &lt;/filter-mapping&gt;<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;package.ListenerClass&lt;/listener-class&gt;<br />
&lt;/listener&gt;<br />
&lt;servlet&gt; &#8230; &lt;/servlet&gt;<br />
&lt;!&#8211; &#8230; &#8211;&gt;<br />
&lt;/web-app&gt;</p>
<p>15 J2EE元素</p>
<p>本节描述用作J2EE环境组成部分的Web应用的web.xml元素。这里将提供一个简明的介绍，详细内容可以参阅<a href="http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf">http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf</a>的Java 2 Plantform Enterprise Edition版本1.3规范的第5章。<br />
l distributable<br />
distributable元素指出，Web应用是以这样的方式编程的：即，支持集群的服务器可安全地在多个服务器上分布Web应用。例如，一个可分布的应用必须只使用Serializable对象作为其HttpSession对象的属性，而且必须避免用实例变量（字段）来实现持续性。distributable元素直接出现在discription元素之后，并且不包含子元素或数据，它只是一个如下的标志。<br />
&lt;distributable /&gt;<br />
l resource-env-ref<br />
resource-env-ref元素声明一个与某个资源有关的管理对象。此元素由一个可选的description元素、一个resource-env-ref-name元素（一个相对于java:comp/env环境的JNDI名）以及一个resource-env-type元素（指定资源类型的完全限定的类），如下所示：<br />
&lt;resource-env-ref&gt;<br />
&lt;resource-env-ref-name&gt;<br />
jms/StockQueue<br />
&lt;/resource-env-ref-name&gt;<br />
&lt;resource-env-ref-type&gt;<br />
javax.jms.Queue<br />
&lt;/resource-env-ref-type&gt;<br />
&lt;/resource-env-ref&gt;<br />
l env-entry<br />
env-entry元素声明Web应用的环境项。它由一个可选的description元素、一个env-entry-name元素（一个相对于java:comp/env环境JNDI名）、一个env-entry-value元素（项值）以及一个env-entry-type元素（java.lang程序包中一个类型的完全限定类名，java.lang.Boolean、java.lang.String等）组成。下面是一个例子：<br />
&lt;env-entry&gt;<br />
&lt;env-entry-name&gt;minAmout&lt;/env-entry-name&gt;<br />
&lt;env-entry-value&gt;100.00&lt;/env-entry-value&gt;<br />
&lt;env-entry-type&gt;minAmout&lt;/env-entry-type&gt;<br />
&lt;/env-entry&gt;<br />
l ejb-ref<br />
ejb-ref元素声明对一个EJB的主目录的应用。它由一个可选的description元素、一个ejb-ref-name元素（相对于java:comp/env的EJB应用）、一个ejb-ref-type元素（bean的类型，Entity或Session）、一个home元素（bean的主目录接口的完全限定名）、一个remote元素（bean的远程接口的完全限定名）以及一个可选的ejb-link元素（当前bean链接的另一个bean的名称）组成。<br />
l ejb-local-ref<br />
ejb-local-ref元素声明一个EJB的本地主目录的引用。除了用local-home代替home外，此元素具有与ejb-ref元素相同的属性并以相同的方式使用。</p>
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2005/03/16/tomcat%e4%b8%ad%e7%94%a8webxml%e6%8e%a7%e5%88%b6web%e5%ba%94%e7%94%a8%e8%af%a6%e8%a7%a3%ef%bc%81/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转]Struts的几个精细之处</title>
		<link>http://niyue.com/2005/03/15/%e8%bd%acstruts%e7%9a%84%e5%87%a0%e4%b8%aa%e7%b2%be%e7%bb%86%e4%b9%8b%e5%a4%84/</link>
		<comments>http://niyue.com/2005/03/15/%e8%bd%acstruts%e7%9a%84%e5%87%a0%e4%b8%aa%e7%b2%be%e7%bb%86%e4%b9%8b%e5%a4%84/#comments</comments>
		<pubDate>Tue, 15 Mar 2005 08:10:05 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=113</guid>
		<description><![CDATA[最近在网上看到一篇N. Alex Rupp写的“Beyond MVC: A New Look at the Servlet Infrastructure”文章，意思大致是说MVC被Struts等框架错误地应用到了Servlet架构中。我想只有对Struts有足够的了解再加上在MVC方面有足够深的功力，才敢发此言论，不是经常听人说：最熟悉自己的人是你的敌人。本人功力尚浅，没有引领风潮的能力，而且生活还得继续，只能先来熟悉熟悉Struts。 
申明： 强烈建议在阅读本文之前先阅读一下N. Alex Rupp老兄的文章，如果你赞同他的看法，可能你会觉得研究Struts就没什么意义了。 
说明：本文所讲的Struts知识基于Struts 1.1版本，除非特别说明，本文中的Struts都特指Struts 1.1这个版本。 
目录： 
精细之处一：“利用Token解决重复提交”背后的前提
精细之处二：页面流转控制中的职责分配 
精细之处一：“利用Token解决重复提交”背后的前提 
我们知道，可以利用同步令牌（Token）机制来解决Web应用中重复提交的问题，Struts也给出了一个参考实现。服务器端在处理到达的请求之前，会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较，看是否匹配。在处理完该请求后，且在答复发送给客户端之前，将会产生一个新的令牌，该令牌除传给客户端以外，也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话，客户端传过来的令牌就和服务器端的令牌不一致，从而有效地防止了重复提交的发生。对应于这段描述，你可能会在你的Action子类中有这么一段代码： 



if (isTokenValid(request, true)) {
// your code here
return mapping.findForward("success");
} else {
saveToken(request);
return mapping.findForward("submitagain");
}



其中isTokenValid()和saveToken()都是org.apache.struts.action.Action类中的方法，而具体的Token处理逻辑都在org.apache.struts.util.TokenProcessor类中。Struts中是根据用户会话ID和当前系统时间来生成一个唯一（对于每个会话）令牌的，具体实现可以参考TokenProcessor类中的generateToken()方法。 
不知道大家有没有注意到这样一个问题，因为Struts是将Token保存在Session的一个属性中，也就是说对于每个会话服务器端只保存而且只能保存一个最新Token值。对于这一点，我的同事就提出了疑问：那如果我在同一个会话中打开两个页面，那么后提交的那个页面肯定不能提交成功了。他还给出了一个实际的例子：比如现在需要把两个客户A和B的地址都改为某个值，那用户就可能同时打开两个页面，修改A，修改B，提交A，提交B，按照Struts中的处理逻辑，B的修改提交就肯定不能成功，但是这个提交操作对于用户来说并不存在操作不正确的地方。 
在这里，可能有人要问：怎么可能在同一个会话中打开两个页面呢？重新打开一个IE浏览器不是重新开始了一个会话吗？不错，这种情况下是两个会话，不存在任何问题。但是，你还可以通过菜单“文件”－“新建”－“窗口”（或者快捷键Ctrl+N）来复制当前窗口，这个时候你会发现该页面与原有页面同处在一个会话当中。其实，能够发现这个问题得归功于我的那位同事对IE习惯性的操作方法。 
这下我的那位同事不满意啦，他于是开始动手修改Struts中的实现方式，让每个页面（至少某类页面）在服务器端都保存有一个唯一的Token值。这样，前面所讲的客户A，B同时修改的限制就不存在了。但是不久，我的那位同事就开始意识到他正在走向一条危险的道路。首先，如果每个页面都在服务器端保存一个Token值，则服务器端保存的数据量将越来越大。而且，如果考虑这种同一个会话中打开多个页面的情况的话，就好像打开了潘多拉魔盒，将会给自己带来无穷无尽的麻烦。比如，首先打开页面P1，然后利用Ctrl+N得到页面P2，P1提交，P2提交，目前为止一切正常。但是如果此时，在P1，P2中点击“后退”按钮，然后再提交P1， P2呢，情况会是怎样？如果在P2中提交完后执行其它操作，而在P1中回退后提交，情况又是怎么样呢？如果有P1，P2，P3，那情况又是如何呢？太复杂啦！我想你也会和我们有同感，你需要考虑许多种可能的组合，而且有的时候结果并不是你想象中的那样简单。 
此路不通，还得回来看看Struts。其实经过以上一番折腾，我们可以发现在Struts中的Token机制背后隐藏着这样一个前提：不允许你（客户端）在同一会话中打开多个页面。注意是同一会话，如果打开两个IE浏览器，那已经是两个会话啦，不受该限制。其实，这个看似不合理的规定却自有其道理：一是它极大地简化了Token的实现，二个这种限定也符合大部分人的使用习惯。 
精细之处二：页面流转控制中的职责分配 
我们知道，Struts的执行过程大致如下：首先，控制器接收到客户端请求，将这些请求映射至相应的Action，并调用Action的execute方法，这中间可能还涉及到ActionForm的创建和填充。Action的execute方法执行完以后，返回一个ActionForward对象，控制器根据该ActionForward对象将请求转发至下一个Action或JSP。最后，产生视图响应客户。在大的层面上，Struts是采用了MVC这种架构，没什么特别之处。但从一些小的地方，我们还是可以看出Craig R. McClanahan老兄的一些考虑。我们看到Action与控制器之间传递的是ActionForward对象，由于Action的execute方法要求返回一个ActionForward对象，所以你会经常在Action子类中看到如下语句： 



return (new ActionForward(mapping.getInput()));



或 



return (mapping.findForward("success"));



其实返回的就是一个ActionForward对象。在Action中我们根据程序执行的不同情况，决定接下来的页面走向（比如返回到输入页面或者转到下一个页面），并将这些信息保存在ActionForward对象中。而接下来控制器就可以直接利用该ActionForward对象来进行页面的流转。下面是org.apache.struts.action.RequestProcessor类的processForwardConfig()方法的摘录，该方法调用发生在Action实例调用后。 



protected void processForwardConfig(HttpServletRequest
request,
HttpServletResponse
response,
ForwardConfig forward)
throws IOException, ServletException {
…

String forwardPath [...]]]></description>
			<content:encoded><![CDATA[<p><font>最近在网上看到一篇N. Alex Rupp写的“Beyond MVC: A New Look at the Servlet Infrastructure”文章，意思大致是说MVC被Struts等框架错误地应用到了Servlet架构中。我想只有对Struts有足够的了解再加上在MVC方面有足够深的功力，才敢发此言论，不是经常听人说：最熟悉自己的人是你的敌人。本人功力尚浅，没有引领风潮的能力，而且生活还得继续，只能先来熟悉熟悉Struts。 </font></p>
<p><font><strong>申明：</strong> 强烈建议在阅读本文之前先阅读一下N. Alex Rupp老兄的文章，如果你赞同他的看法，可能你会觉得研究Struts就没什么意义了。 </font></p>
<p><font><strong>说明：</strong>本文所讲的Struts知识基于Struts 1.1版本，除非特别说明，本文中的Struts都特指Struts 1.1这个版本。 </font></p>
<p><font><strong>目录： </strong></font></p>
<p><font><strong><a href="http://tech.ccidnet.com/pub/article/c1078_a82580_p1.html#1">精细之处一：“利用Token解决重复提交”背后的前提</a><br />
<a href="http://tech.ccidnet.com/pub/article/c1078_a82580_p1.html#2">精细之处二：页面流转控制中的职责分配</a></strong> </font></p>
<p><font><a name="1"></a><strong>精细之处一：“利用Token解决重复提交”背后的前提</strong> </font></p>
<p><font>我们知道，可以利用同步令牌（Token）机制来解决Web应用中重复提交的问题，Struts也给出了一个参考实现。服务器端在处理到达的请求之前，会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较，看是否匹配。在处理完该请求后，且在答复发送给客户端之前，将会产生一个新的令牌，该令牌除传给客户端以外，也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话，客户端传过来的令牌就和服务器端的令牌不一致，从而有效地防止了重复提交的发生。对应于这段描述，你可能会在你的Action子类中有这么一段代码： </font></p>
<table width="400" cellspacing="0" cellpadding="2" border="1" align="center">
<tr>
<td bgcolor="#e6e6e6">
<pre>if (isTokenValid(request, true)) {
// your code here
return mapping.findForward("success");
} else {
saveToken(request);
return mapping.findForward("submitagain");
}</pre>
</td>
</tr>
</table>
<p><font>其中isTokenValid()和saveToken()都是org.apache.struts.action.Action类中的方法，而具体的Token处理逻辑都在org.apache.struts.util.TokenProcessor类中。Struts中是根据用户会话ID和当前系统时间来生成一个唯一（对于每个会话）令牌的，具体实现可以参考TokenProcessor类中的generateToken()方法。 </font></p>
<p><font>不知道大家有没有注意到这样一个问题，因为Struts是将Token保存在Session的一个属性中，也就是说对于每个会话服务器端只保存而且只能保存一个最新Token值。对于这一点，我的同事就提出了疑问：那如果我在同一个会话中打开两个页面，那么后提交的那个页面肯定不能提交成功了。他还给出了一个实际的例子：比如现在需要把两个客户A和B的地址都改为某个值，那用户就可能同时打开两个页面，修改A，修改B，提交A，提交B，按照Struts中的处理逻辑，B的修改提交就肯定不能成功，但是这个提交操作对于用户来说并不存在操作不正确的地方。 </font></p>
<p><font>在这里，可能有人要问：怎么可能在同一个会话中打开两个页面呢？重新打开一个IE浏览器不是重新开始了一个会话吗？不错，这种情况下是两个会话，不存在任何问题。但是，你还可以通过菜单“文件”－“新建”－“窗口”（或者快捷键Ctrl+N）来复制当前窗口，这个时候你会发现该页面与原有页面同处在一个会话当中。其实，能够发现这个问题得归功于我的那位同事对IE习惯性的操作方法。 </font></p>
<p><font>这下我的那位同事不满意啦，他于是开始动手修改Struts中的实现方式，让每个页面（至少某类页面）在服务器端都保存有一个唯一的Token值。这样，前面所讲的客户A，B同时修改的限制就不存在了。但是不久，我的那位同事就开始意识到他正在走向一条危险的道路。首先，如果每个页面都在服务器端保存一个Token值，则服务器端保存的数据量将越来越大。而且，如果考虑这种同一个会话中打开多个页面的情况的话，就好像打开了潘多拉魔盒，将会给自己带来无穷无尽的麻烦。比如，首先打开页面P1，然后利用Ctrl+N得到页面P2，P1提交，P2提交，目前为止一切正常。但是如果此时，在P1，P2中点击“后退”按钮，然后再提交P1， P2呢，情况会是怎样？如果在P2中提交完后执行其它操作，而在P1中回退后提交，情况又是怎么样呢？如果有P1，P2，P3，那情况又是如何呢？太复杂啦！我想你也会和我们有同感，你需要考虑许多种可能的组合，而且有的时候结果并不是你想象中的那样简单。 </font></p>
<p><font>此路不通，还得回来看看Struts。其实经过以上一番折腾，我们可以发现在Struts中的Token机制背后隐藏着这样一个前提：不允许你（客户端）在同一会话中打开多个页面。注意是同一会话，如果打开两个IE浏览器，那已经是两个会话啦，不受该限制。其实，这个看似不合理的规定却自有其道理：一是它极大地简化了Token的实现，二个这种限定也符合大部分人的使用习惯。 </font></p>
<p><font><a name="2"></a><strong>精细之处二：页面流转控制中的职责分配</strong> </font></p>
<p><font>我们知道，Struts的执行过程大致如下：首先，控制器接收到客户端请求，将这些请求映射至相应的Action，并调用Action的execute方法，这中间可能还涉及到ActionForm的创建和填充。Action的execute方法执行完以后，返回一个ActionForward对象，控制器根据该ActionForward对象将请求转发至下一个Action或JSP。最后，产生视图响应客户。在大的层面上，Struts是采用了MVC这种架构，没什么特别之处。但从一些小的地方，我们还是可以看出Craig R. McClanahan老兄的一些考虑。我们看到Action与控制器之间传递的是ActionForward对象，由于Action的execute方法要求返回一个ActionForward对象，所以你会经常在Action子类中看到如下语句： </font></p>
<table width="400" cellspacing="0" cellpadding="2" border="1" align="center">
<tr>
<td bgcolor="#e6e6e6">
<pre>return (new ActionForward(mapping.getInput()));</pre>
</td>
</tr>
</table>
<p><font>或 </font></p>
<table width="400" cellspacing="0" cellpadding="2" border="1" align="center">
<tr>
<td bgcolor="#e6e6e6">
<pre>return (mapping.findForward("success"));</pre>
</td>
</tr>
</table>
<p><font>其实返回的就是一个ActionForward对象。在Action中我们根据程序执行的不同情况，决定接下来的页面走向（比如返回到输入页面或者转到下一个页面），并将这些信息保存在ActionForward对象中。而接下来控制器就可以直接利用该ActionForward对象来进行页面的流转。下面是org.apache.struts.action.RequestProcessor类的processForwardConfig()方法的摘录，该方法调用发生在Action实例调用后。 </font></p>
<table width="400" cellspacing="0" cellpadding="2" border="1" align="center">
<tr>
<td bgcolor="#e6e6e6">
<pre>protected void processForwardConfig(HttpServletRequest
request,
HttpServletResponse
response,
ForwardConfig forward)
throws IOException, ServletException {
…

String forwardPath = forward.getPath();
String uri = null;

// paths not starting with /
should be passed through without any  processing
// (ie. they're absolute)
if (forwardPath.startsWith("/")) {
uri = RequestUtils.forwardURL(request, forward);
// get module relative uri
} else {
uri = forwardPath;
}
if (forward.getRedirect()) {
// only prepend context path for relative uri
if (uri.startsWith("/")) {
uri = request.getContextPath() + uri;
}
response.sendRedirect(response.encodeRedirectURL(uri));
}
else {
doForward(uri, request, response);
}
}</pre>
</td>
</tr>
</table>
<p><font><strong>注意：</strong> ForwardConfig是ActionForward的父类 </font></p>
<p><font>该方法首先调用ForwardConfig的getPath()方法获得下一步流转的路径，在某些条件下还需要进行一些拼装得到正确的URI，最后根据该URI进行页面跳转。可见在processForwardConfig()方法中只是对ActionForward进行了一些“技术上”的处理，没有任何和业务相关的内容，这样就将控制器（ActionServlet）和Action完全分开来，两者互不影响，达到了功能模块之间松散耦合的目的。 </font></p>
<p><font>模块间（系统间）松散耦合一直是OO设计所追求的，但是具体如何去实现这样一种松散耦合却不是那么容易做到的。Struts中的设计给了我们一些启示：模块间相互关联影响因素的传递可以用对象的形式来包装起来。其实，个人觉得Struts中的做法还可以稍微有一点点改进，就是在ActionForward中提供一个getURI()方法来给出最终的URI岂不是更好？ </font></p>
<p><font><strong>参考：</strong> </font></p>
<p><font>1、<a href="http://today.java.net/pub/a/today/2003/12/11/mvc.html">Beyond MVC: A New Look at the Servlet Infrastructure</a> </font></p>
<p><font>2、<a href="http://www.javaworld.com/javaworld/jw-07-1999/jw-07-toolbox_p.html">Allen Holub的Build user interfaces for object-oriented systems系列文章</a>,可以从这篇文章中学到很多面向对象设计方面的知识，虽然作者并不认为MVC是一种面向对象的方法，但是我们这些MVC的实践者仍然可以从中学到面向对象的知识。 </font></p>
<p><font>3、<a href="http://www-900.ibm.com/developerWorks/cn/java/l-struts1-1/">Struts 1.1的介绍性文章：深入Struts 1.1</a> </font></p>
<p><font>4、<a href="http://jakarta.apache.org/struts/">Apache Struts Website</a> </font></p>
<p><font>5、关于重复提交问题的讨论及其解决方案，可以参考《Core J2EE Patterns》一书（中文版《J2EE核心模式》）。 </font></p>
<p><font>Deepak Alur,John Crupi,Dan Malks: Core J2EE Patterns－Best Practices and Design Strategies<br />
</font></p>
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2005/03/15/%e8%bd%acstruts%e7%9a%84%e5%87%a0%e4%b8%aa%e7%b2%be%e7%bb%86%e4%b9%8b%e5%a4%84/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用Struts Tiles构建Portal</title>
		<link>http://niyue.com/2005/03/11/%e4%bd%bf%e7%94%a8struts-tiles%e6%9e%84%e5%bb%baportal/</link>
		<comments>http://niyue.com/2005/03/11/%e4%bd%bf%e7%94%a8struts-tiles%e6%9e%84%e5%bb%baportal/#comments</comments>
		<pubDate>Fri, 11 Mar 2005 00:00:36 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=104</guid>
		<description><![CDATA[相关资料:1. Struts Tiles
Struts Tiles Guide 最基本的资料
2. Tiles Advanced Features by Cedric Dumoulin.
这篇文章列在Struts Tiles Guide的reference中,我感觉是写的比较全面而又有一定深度的文章,尤其是其中的第七部分较详细的写了如何使用Tiles进行动态portal的构建,根据这篇文章再配合Struts里面附带的Tiles-document就可以较完整地了解Tiles的全貌了.
3. 基于Tiles框架Struts框架的UI 设计―几种组织HTML和JSP视图组件
这篇是Struts Tiles Guide的reference中的一篇文章的中文版,写的也很不错,很有条理看起来.
4. Struts 和 Tiles 辅助基于组件的开发
这也是Struts Tiles Guide的reference中的一篇文章的中文版,一般吧,中文的看起来快一点而已.
Section 7 DYNAMIC PORTAL EXAMPLE
What&#8217;s a Tile?
A Tile is an area in a web page. This area is rectangular, and can also be called &#8220;region&#8221; (like in another template mechanism by David [...]]]></description>
			<content:encoded><![CDATA[<p>相关资料:1. <a href="http://struts.apache.org/userGuide/dev_tiles.html">Struts Tiles</a></p>
<p>Struts Tiles Guide 最基本的资料</p>
<p>2. <a href="http://www.lifl.fr/~dumoulin/tiles/tilesAdvancedFeatures.pdf"><strong>Tiles Advanced Features</strong> </a>by Cedric Dumoulin.</p>
<p>这篇文章列在Struts Tiles Guide的reference中,我感觉是写的比较全面而又有一定深度的文章,尤其是其中的第七部分较详细的写了如何使用Tiles进行动态portal的构建,根据这篇文章再配合Struts里面附带的Tiles-document就可以较完整地了解Tiles的全貌了.</p>
<p>3. <a href="http://pluto99.blogdriver.com/pluto99/272116.html">基于Tiles框架Struts框架的UI 设计―几种组织HTML和JSP视图组件</a></p>
<p>这篇是Struts Tiles Guide的reference中的一篇文章的中文版,写的也很不错,很有条理看起来.</p>
<p>4. <a href="http://www-900.ibm.com/developerWorks/cn/java/j-strutstiles/">Struts 和 Tiles 辅助基于组件的开发</a></p>
<p>这也是Struts Tiles Guide的reference中的一篇文章的中文版,一般吧,中文的看起来快一点而已.</p>
<p><em>Section 7 DYNAMIC PORTAL EXAMPLE</em></p>
<p><strong>What&#8217;s a Tile?</strong></p>
<p><em>A Tile is an area in a web page. This area is rectangular, and can also be called &#8220;region&#8221; (like in another template mechanism by David Geary).<br />
Assembling several Tiles can make themselves a new Tile. Tiles in a web page can be build recursively and represented as a tree where nodes represent regions. Root node is usually the page, final nodes or leafs contain page content, and intermediate nodes are usually layouts.</em></p>
<p><strong>There are several ways to associate an Action and a View as a Tile:</strong><br />
<em>• Specify the Action classname or action URL in &lt;insert&gt; or in &lt;definition&gt; (Tiles<br />
V1.1)<br />
• Use a Struts Action in struts-config.xml, let it forward to a definition name. In tilesconfig.<br />
xml specify one definition with the action URL as page, and one definition with<br />
the view as the page. The first definition is used as the complete Tile definition (action +view), the second definition is used as the view definition.<br />
• It is possible to associate more than one view to a controller. Exactly one will be chosen.<br />
This is useful when you have a main view and an error view. Same as before, but with more than one forward and view definition.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2005/03/11/%e4%bd%bf%e7%94%a8struts-tiles%e6%9e%84%e5%bb%baportal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转]Portal实现原理</title>
		<link>http://niyue.com/2005/03/06/%e8%bd%acportal%e5%ae%9e%e7%8e%b0%e5%8e%9f%e7%90%86/</link>
		<comments>http://niyue.com/2005/03/06/%e8%bd%acportal%e5%ae%9e%e7%8e%b0%e5%8e%9f%e7%90%86/#comments</comments>
		<pubDate>Sun, 06 Mar 2005 02:44:30 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=101</guid>
		<description><![CDATA[Portal实现原理 
1．Portal用例
读者可以在下面三个网站上注册自己的用户，体会Portal的功能。
http://my.msn.com
http://my.yahoo.com
http://my.liferay.com
My MSN的功能最灵活强大，用户可以任意拖放操作栏目(column)和内容版块(content)的位置和个数。
My Liferay只能选择固定的栏目(column)布局，但可以在本栏目(column)内移动内容版块(content)的位置。
My Yahoo只能选择固定的栏目(column)布局，而且不能移动内容版块(content)的位置。
Portal的结构分为三层。
(1) Page
(2) Column，或者称为Pane
(3) Content，或者称为Portlet
我们来看看Portal的整个操作流程。
(1) 每个Column的下方都有一个[Add Content]按钮，让用户选择加入自己喜欢的内容。
从这里，我们知道，Portal系统里面有一个公用的Common Portlet Repository，供用户选用。
JSR168 Portlet规范里面定义了Portlet Deployment Discriptor。Common Portlet Repository以这个Portlet Deployment Discriptor的格式存放。
开源项目JetSpeed的XReg文件用来存放Common Portlet Repository的定义。
(2) 加入Content之后，用户的Page和Column里面就多了这个Content。下次用户登陆的时候，就会看到自己订制的Portal版面。
从这里，可以看出，Portal系统会纪录用户的个人Portal配置信息 � User Portal Config。
开源项目JetSpeed的PSML文件用来存放User Portal Config的定义。
&#8212;&#8212;- 综上。
Add Content的整个流程为：
Common Portlet Repository &#8211;&#62; Add Content &#8211;&#62; Personal Portal Config
Display Portal的整个流程为：
从Personal Portal Config读取用户配置的Portlet ID &#8211;&#62; 根据Portlet ID，从Common Portlet Repository查找详细的Portlet定义 &#8211;&#62; 根据这个详细的Portlet定义显示这个Portlet。
2．Portal实现
我们考虑如何用Java来实现Portal。
2.1 Dynamic Include
首先，我们采用最简单的思路，我们用100个JSP文件(1.jsp, 2.jsp, 3.jsp, … [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://forum.javaeye.com/viewtopic.php?t=7005">Portal实现原理 </a></p>
<p>1．Portal用例<br />
读者可以在下面三个网站上注册自己的用户，体会Portal的功能。<br />
<a href="http://my.msn.com/">http://my.msn.com</a><br />
<a href="http://my.yahoo.com/">http://my.yahoo.com</a><br />
<a href="http://my.liferay.com/">http://my.liferay.com</a></p>
<p>My MSN的功能最灵活强大，用户可以任意拖放操作栏目(column)和内容版块(content)的位置和个数。<br />
My Liferay只能选择固定的栏目(column)布局，但可以在本栏目(column)内移动内容版块(content)的位置。<br />
My Yahoo只能选择固定的栏目(column)布局，而且不能移动内容版块(content)的位置。</p>
<p>Portal的结构分为三层。<br />
(1) Page<br />
(2) Column，或者称为Pane<br />
(3) Content，或者称为Portlet</p>
<p>我们来看看Portal的整个操作流程。<br />
(1) 每个Column的下方都有一个[Add Content]按钮，让用户选择加入自己喜欢的内容。<br />
从这里，我们知道，Portal系统里面有一个公用的Common Portlet Repository，供用户选用。</p>
<p>JSR168 Portlet规范里面定义了Portlet Deployment Discriptor。Common Portlet Repository以这个Portlet Deployment Discriptor的格式存放。</p>
<p>开源项目JetSpeed的XReg文件用来存放Common Portlet Repository的定义。</p>
<p>(2) 加入Content之后，用户的Page和Column里面就多了这个Content。下次用户登陆的时候，就会看到自己订制的Portal版面。<br />
从这里，可以看出，Portal系统会纪录用户的个人Portal配置信息 � User Portal Config。</p>
<p>开源项目JetSpeed的PSML文件用来存放User Portal Config的定义。</p>
<p>&#8212;&#8212;- 综上。<br />
Add Content的整个流程为：<br />
Common Portlet Repository &#8211;&gt; Add Content &#8211;&gt; Personal Portal Config</p>
<p>Display Portal的整个流程为：<br />
从Personal Portal Config读取用户配置的Portlet ID &#8211;&gt; 根据Portlet ID，从Common Portlet Repository查找详细的Portlet定义 &#8211;&gt; 根据这个详细的Portlet定义显示这个Portlet。</p>
<p>2．Portal实现<br />
我们考虑如何用Java来实现Portal。</p>
<p>2.1 Dynamic Include<br />
首先，我们采用最简单的思路，我们用100个JSP文件(1.jsp, 2.jsp, 3.jsp, … 100.jsp等)，代表100个Portlet。<br />
用户页面MyPage.jsp包含用户选定的多个Portlet。<br />
现在，假设用户选取的Portlet为1.jsp, 3.jsp, 7.jsp等3个Portlet，那么我们如何在MyPage.jsp中显示这些Portlet？最直观的做法是，用jsp:include。比如：</p>
<div>&lt;table&gt;<br />
&lt;tr&gt;&lt;td&gt;<br />
&lt;jsp:include page=”1.jsp” /&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;tr&gt;&lt;td&gt;<br />
&lt;jsp:include page=”3.jsp” /&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;tr&gt;&lt;td&gt;<br />
&lt;jsp:include page=”7.jsp” /&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;/table&gt;</div>
<p>由于&lt;jsp:include&gt;只能指定固定的jsp文件名，不能动态指定jsp文件名。我们需要把&lt;jsp:include&gt;翻译为Java code � RequestDispatcher.include();<br />
下面我们换成这种写法。</p>
<table width="90%" cellspacing="1" cellpadding="3" border="0" align="center">
<tr>
<td><strong>java代码: </strong></td>
</tr>
<tr>
<td>
<div>
<div>&lt;table&gt;<br />
&lt;tr&gt;&lt;td&gt;<br />
&lt;% request.getRequestDispatcher(”1.jsp”).include(request, response); /&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;tr&gt;&lt;td&gt;<br />
&lt;% request.getRequestDispatcher(”3.jsp”).include(request, response); /&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;tr&gt;&lt;td&gt;<br />
&lt;% request.getRequestDispatcher(”7.jsp”).include(request, response); /&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;/table&gt;</div>
</div>
</td>
</tr>
</table>
<p>进一步改进MyPage.jsp。</p>
<table width="90%" cellspacing="1" cellpadding="3" border="0" align="center">
<tr>
<td><strong>java代码: </strong></td>
</tr>
<tr>
<td>
<div>
<div>&lt;% String[] fileNames = {“1.jsp”, “3.jsp”, “7.jsp”}; %&gt;<br />
&lt;table&gt;<br />
&lt;% for(int i = 0; i &lt; fileNames.length; i++) {<br />
String fileName = fileName s[i]; %&gt;<br />
&lt;tr&gt;&lt;td&gt;<br />
&lt;% request.getRequestDispatcher(fileName).include(request, response); /&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;% } // end for %&gt;<br />
&lt;/table&gt;</div>
</div>
</td>
</tr>
</table>
<p>其中的fileNames的内容可以各种各样，只要RequestDispatcher能够处理。<br />
比如Velocity，fileNames = {“1.vm”, “3.vm”, “7.vm”};<br />
比如URL，fileNames = {“/portlet1.do”, “/portlet3.do”, “/portlet4.do”};<br />
我们可以看到，如果我们从用户配置中读取fileNames的内容，这就是一个简单的Portal实现。</p>
<table width="90%" cellspacing="1" cellpadding="3" border="0" align="center">
<tr>
<td><strong>java代码: </strong></td>
</tr>
<tr>
<td>
<div>
<div>&lt;% String[] fileNames = (String[])session.getAttribute(“portlets.config”); %&gt;<br />
&lt;table&gt;<br />
&lt;% for(int i = 0; i &lt; fileNames.length; i++) {<br />
String fileName = fileNames[i]; %&gt;<br />
&lt;tr&gt;&lt;td&gt;<br />
&lt;% request.getRequestDispatcher(fileName).include(request, response); /&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;% } // end for %&gt;<br />
&lt;/table&gt;</div>
</div>
</td>
</tr>
</table>
<p>2.2 Portlet Interface<br />
下面我们来扩展这个例子。<br />
假设每个Portlet都规定实现一个Portlet接口。</p>
<table width="90%" cellspacing="1" cellpadding="3" border="0" align="center">
<tr>
<td><strong>java代码: </strong></td>
</tr>
<tr>
<td>
<div>
<div>interface Portlet {<br />
void render(request, response);<br />
};</div>
<p>MyPage.jsp如下：</p>
<div>&lt;% String[] portletClassNames = (String[])session.getAttribute(“portlets.config”); %&gt;<br />
&lt;table&gt;<br />
&lt;% for(int i = 0; i &lt; portletClassNames.length; i++) {<br />
String className = portletClassNames[i];<br />
Portlet portlet = (Portlet)Class.forName(className).newInstance(); %&gt;<br />
&lt;tr&gt;&lt;td&gt;<br />
&lt;% portlet. render (request, response); /&gt;<br />
&lt;/td&gt;&lt;/tr&gt;<br />
&lt;% } // end for %&gt;<br />
&lt;/table&gt;</div>
<p>Portlet类的示例代码如下：</p>
<div>public class Portlet7{<br />
public void render(request, response){<br />
request.getRequestDispatcher(“7.jsp”).include(request, response);<br />
}<br />
};</div>
</div>
</td>
</tr>
</table>
<p>上述代码是Portal显示Portlet的核心流程的一个简化版本。<br />
JSR168 Portlet规范里面定义了真正的Portlet接口定义。</p>
<p>2.3 Portlet Action<br />
Portlet的操作包括，最大化/最小化/恢复/关闭/编辑/帮助/上下移动，等等。<br />
这些操作都有对应的Action类。<br />
开源项目JetSpeed的module/actions/controls目录下面包含Maximize, Minimize, Close等Action类。<br />
开源项目Liferay的portal/action目录下面包含Maximize, Minimize, Close等Action类。</p>
<p>Portal的操作不仅包括上述Portlet的操作，而且包括其它更高级别的操作。<br />
比如，Add/Move Page, Add/Move Column, 换Layout, 换Skin，之类。</p>
<p>2.4 Portlet Cache<br />
我们操作Portlet的时候，往往只操作某个特定的Portlet，或者只是变化Portlet的位置。这时候，页面中大多数的Porlet的内容是不变的，只有一小块Portlet变化。<br />
我们需要把Portlet的内容缓存起来。Portlet接口有一个render(request, response)方法，我们可以订制定制response类，截获portlet的输出，保存到Portal系统的内容Cache当中。<br />
比如，前面提到liferay开源项目，其StringServletResponse类把Portlet的输出保存到一个String当中。</p>
<div><strong>相关摘要</strong></div>
<ul>
<li><strong><a name="21603"></a><strong><font color="#000000">(一蓑烟雨任平生)</font></strong>Portal</strong> Server的机制与一般的Web Framework是独立的，<strong>Portal</strong> Server有自己的容器或者引擎来对Portlet进行处理，每个Portlet类似于Servlet。Portlet现在有两种标准，一种是以Jetspeed为主的老版本，IBM的Websphere <strong>Portal</strong> Server原先的核心API也采用Jetspeed的API，另一种是目前JCP组织制订的JSR 168标准，BEA和IBM都在自己的产品里实现了该标准，但还没有成熟。IBM的WSAD开发工具里对<strong>Portal</strong>有两种项目类型，分别支持这两种标准。
<p>可以将<strong>Portal</strong>做为表现层的一种类型集成到你的Web Framework中。</li>
<li><a name="21603"></a><strong>(一蓑烟雨任平生)</strong>Jetspeed是一个门户的应用管理系统，应用程序是构建在Turbine这个Web Framework上面的，可以认为Jetspeed是个用Turbine Framework开发的一个应用程序。</li>
<li><a name="21603"></a><strong>(<a name="26555"></a><strong>whitehorse</strong>)portal</strong> 包括 <strong>portal</strong> server 和 portlet container ;JSR-168定义了portlet 通用api ，portlet container 的提供商需要遵循这个API,这样开发出的portlet 可以在任何一个实现jsr-168规范的portlet container下顺利移植。<br />
<strong>portal</strong> server 是各个开发商自行提供的，用来接受用户用求转发给相应的portlet，调整<strong>portal</strong> page 布局，单点登录等等;<br />
portlet container就是在servlet container上又包装了一层，portlet 类似于servlet;<br />
<strong>portal</strong> server 的实现一般采用 web framework 技术来构建； 比如liferay采用了struts + tiles;exo poral 采用了 jsf 等等。portlet开发在遵循规范的基础上可以采用web framework .</li>
<li><a name="21512"></a><strong>(kingkii)</strong>free <strong>portal</strong> server: Jetspeed, liferay, Jportal, etc</li>
<li><a name="26974"></a><strong>(flyisland)</strong></li>
<li>
<table width="90%" cellspacing="1" cellpadding="3" border="0" align="center">
<tr>
<td><strong><em>baichenhong 写道:</em></strong></td>
</tr>
<tr>
<td><em>我觉的<strong>Portal</strong>的作用就是整合，故名意思 门户 嘛就是把所有的集成起来放到一起，你有oa,erp,crm 但是你觉得分开使用很不方便，那么好我可以把他们整合到一起，只要你登陆一次就可以使用所有的系统，这应该是一个很有用的东西</em></td>
</tr>
</table>
<p>你短短一句话包含的东西可是超级多。</p>
<p>所谓集成分为很多层次的，<strong>Portal</strong>关注的是用户集成，包括访问界面、访问手段等。访问界面的集成并不要求应用程序一定要部署在一起。</p>
<p>至于“只要你登陆一次就可以使用所有的系统”，一般称之为单点登陆“Single Sign-on”。<strong>Portal</strong>服务器基本都提供了认证框架，在此框架下开发的新应用实现SSO是很简单的；但如果对异构的系统进行SSO，这又是一个复杂而庞大的话题了。</li>
<li><a name="33626"></a><strong>(tommy_kin)</strong>拖放布局不是<strong>Portal</strong>的核心技术，只是一个personalize的功能而已，<strong>Portal</strong>功能在于应用的集成。所谓一站式访问。</li>
</ul>
<div><strong>参考资料：</strong></div>
<ul>
<li>javaeye论坛内关于Portal讨论的连接<br />
<a href="http://forum.javaeye.com/viewtopic.php?t=5506&#038;highlight=Portal"><u>http://forum.javaeye.com/viewtopic.php?t=5506&#038;highlight=Portal</u></a><br />
<a href="http://forum.javaeye.com/viewtopic.php?t=4413&#038;highlight=Portal"><u>http://forum.javaeye.com/viewtopic.php?t=4413&#038;highlight=Portal</u></a><br />
<a href="http://forum.javaeye.com/viewtopic.php?t=5159&#038;highlight=Portal"><u>http://forum.javaeye.com/viewtopic.php?t=5159&#038;highlight=Portal</u></a></li>
<li>主流企业门户应用性能评测<br />
<a href="http://www2.ccw.com.cn/04/0430/d/0430d31_1.asp"><u>http://www2.ccw.com.cn/04/0430/d/0430d31_1.asp</u></a>几种Portal技术的比较与评述<br />
<a href="http://www.ccw.com.cn/cio/research/info/htm2004/20040813_13UNG.asp"><u>http://www.ccw.com.cn/cio/research/info/htm2004/20040813_13UNG.asp</u></a></p>
<p>4款EIP软件评测揭晓<br />
<a href="http://www.zdnet.com.cn/bizstrategy/eb/tech/story/0,3800029745,39156*043,00.htm"><u>http://www.zdnet.com.cn/bizstrategy/eb/tech/story/0,3800029745,39156*043,00.htm</u></a></p>
<p>How the portals scored<br />
<a href="http://www.infoworld.com/article/04/04/30/18FEportalbl_1.html"><u>http://www.infoworld.com/article/04/04/30/18FEportalbl_1.html</u></a></p>
<p>Enterprise Portals Suites<br />
Portal Power<br />
<a href="http://www.networkcomputing.com/shared/article/printFullArticle.jhtml?articleID=18900467"><u>http://www.networkcomputing.com/shared/article/printFullArticle.jhtml?articleID=18900467</u></a></li>
<li>远程门户网站 Web 服务（WSRP）<br />
<a href="http://www-900.ibm.com/developerWorks/cn/webservices/ws-wsrp/index.shtml">http://www-900.ibm.com/developerWorks/cn/webservices/ws-wsrp/index.shtml</a></li>
<li>Portlet技术发展的思考<br />
<a href="http://www.blogbus.com/blogbus/blog/diary.php?diaryid=204304"><u>http://www.blogbus.com/blogbus/blog/diary.php?diaryid=204304</u></a><br />
WSRP实践&#038;想法<br />
<a href="http://www.blogbus.com/blogbus/blog/diary.php?diaryid=117666"><u>http://www.blogbus.com/blogbus/blog/diary.php?diaryid=117666</u></a><br />
<font face="http://blogger.org.cn/blog/Trebuchet MS">P<font>o</font><font>r</font><font>t</font><font>a</font><font>l</font></font><font face="黑体"><font>展</font><font>现</font><font>机</font><font>制</font><font>研</font><font>究<br />
<a href="http://www.blogbus.com/blogbus/blog/diary.php?diaryid=357938">http://www.blogbus.com/blogbus/blog/diary.php?diaryid=357938</a></font></font></li>
<li>Enterprise Portals Suites<br />
Portal Power<br />
<a href="http://www.networkcomputing.com/shared/article/printFullArticle.jhtml?articleID=18900467"><u>http://www.networkcomputing.com/shared/article/printFullArticle.jhtml?articleID=18900467</u></a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2005/03/06/%e8%bd%acportal%e5%ae%9e%e7%8e%b0%e5%8e%9f%e7%90%86/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>获取运行中的JVM系统属性</title>
		<link>http://niyue.com/2005/03/04/%e8%8e%b7%e5%8f%96%e8%bf%90%e8%a1%8c%e4%b8%ad%e7%9a%84jvm%e7%b3%bb%e7%bb%9f%e5%b1%9e%e6%80%a7/</link>
		<comments>http://niyue.com/2005/03/04/%e8%8e%b7%e5%8f%96%e8%bf%90%e8%a1%8c%e4%b8%ad%e7%9a%84jvm%e7%b3%bb%e7%bb%9f%e5%b1%9e%e6%80%a7/#comments</comments>
		<pubDate>Thu, 03 Mar 2005 20:24:01 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=98</guid>
		<description><![CDATA[
获取运行中的JVM系统属性
getProperties
public static Properties getProperties()

Determines the current system properties.First, if there is a security manager, its checkPropertiesAccess method is called with no arguments. This may result in a security exception.
The current set of system properties for use by the getProperty(String) method is returned as a Properties object. If there is no current set of system properties, [...]]]></description>
			<content:encoded><![CDATA[<h3></h3>
<h4><a href="http://www.huihoo.com/vm/jvm_system.html">获取运行中的JVM系统属性</a></h4>
<h3><a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_J2SE/api/java/lang/System.html#getProperties()">getProperties</a></h3>
<pre>public static <a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_J2SE/api/java/util/Properties.html">Properties</a> <strong>getProperties</strong>()</pre>
<dl>
<dd>Determines the current system properties.First, if there is a security manager, its <code>checkPropertiesAccess</code> method is called with no arguments. This may result in a security exception.</p>
<p>The current set of system properties for use by the <a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_J2SE/api/java/lang/System.html#getProperty(java.lang.String)"><code>getProperty(String)</code></a> method is returned as a <code>Properties</code> object. If there is no current set of system properties, a set of system properties is first created and initialized. This set of system properties always includes values for the following keys:</p>
<table>
<tr>
<th>Key</th>
<th>Description of Associated Value</th>
</tr>
<tr>
<td scope="row"><code>java.version</code></td>
<td>Java Runtime Environment version</td>
</tr>
<tr>
<td scope="row"><code>java.vendor</code></td>
<td>Java Runtime Environment vendor</td>
</tr>
<tr>
<td><code>java.vendor.url</code></td>
<td>Java vendor URL</td>
</tr>
<tr>
<td scope="row"><code>java.home</code></td>
<td>Java installation directory</td>
</tr>
<tr>
<td scope="row"><code>java.vm.specification.version</code></td>
<td>Java Virtual Machine specification version</td>
</tr>
<tr>
<td scope="row"><code>java.vm.specification.vendor</code></td>
<td>Java Virtual Machine specification vendor</td>
</tr>
<tr>
<td scope="row"><code>java.vm.specification.name</code></td>
<td>Java Virtual Machine specification name</td>
</tr>
<tr>
<td scope="row"><code>java.vm.version</code></td>
<td>Java Virtual Machine implementation version</td>
</tr>
<tr>
<td scope="row"><code>java.vm.vendor</code></td>
<td>Java Virtual Machine implementation vendor</td>
</tr>
<tr>
<td scope="row"><code>java.vm.name</code></td>
<td>Java Virtual Machine implementation name</td>
</tr>
<tr>
<td scope="row"><code>java.specification.version</code></td>
<td>Java Runtime Environment specification version</td>
</tr>
<tr>
<td scope="row"><code>java.specification.vendor</code></td>
<td>Java Runtime Environment specification vendor</td>
</tr>
<tr>
<td scope="row"><code>java.specification.name</code></td>
<td>Java Runtime Environment specification name</td>
</tr>
<tr>
<td scope="row"><code>java.class.version</code></td>
<td>Java class format version number</td>
</tr>
<tr>
<td scope="row"><code>java.class.path</code></td>
<td>Java class path</td>
</tr>
<tr>
<td scope="row"><code>java.library.path</code></td>
<td>List of paths to search when loading libraries</td>
</tr>
<tr>
<td scope="row"><code>java.io.tmpdir</code></td>
<td>Default temp file path</td>
</tr>
<tr>
<td scope="row"><code>java.compiler</code></td>
<td>Name of JIT compiler to use</td>
</tr>
<tr>
<td scope="row"><code>java.ext.dirs</code></td>
<td>Path of extension directory or directories</td>
</tr>
<tr>
<td scope="row"><code>os.name</code></td>
<td>Operating system name</td>
</tr>
<tr>
<td scope="row"><code>os.arch</code></td>
<td>Operating system architecture</td>
</tr>
<tr>
<td scope="row"><code>os.version</code></td>
<td>Operating system version</td>
</tr>
<tr>
<td scope="row"><code>file.separator</code></td>
<td>File separator (&#8221;/&#8221; on UNIX)</td>
</tr>
<tr>
<td scope="row"><code>path.separator</code></td>
<td>Path separator (&#8221;:&#8221; on UNIX)</td>
</tr>
<tr>
<td scope="row"><code>line.separator</code></td>
<td>Line separator (&#8221;\n&#8221; on UNIX)</td>
</tr>
<tr>
<td scope="row"><code>user.name</code></td>
<td>User&#8217;s account name</td>
</tr>
<tr>
<td scope="row"><code>user.home</code></td>
<td>User&#8217;s home directory</td>
</tr>
<tr>
<td scope="row"><code>user.dir</code></td>
<td>User&#8217;s current working directory</td>
</tr>
</table>
<p>Multiple paths in a system property value are separated by the path separator character of the platform.</p>
<p>Note that even if the security manager does not permit the <code>getProperties</code> operation, it may choose to permit the <a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_J2SE/api/java/lang/System.html#getProperty(java.lang.String)"><code>getProperty(String)</code></a> operation.</p>
</dd>
<dd>
<dl>
<dt><strong>Returns:</strong>  </dt>
<dd>the system properties  </dd>
<dt><strong>Throws:</strong>  </dt>
<dd><code><a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_J2SE/api/java/lang/SecurityException.html">SecurityException</a></code> &#8211; if a security manager exists and its <code>checkPropertiesAccess</code> method doesn&#8217;t allow access to the system properties.  </dd>
<dt><strong>See Also:</strong>  </dt>
<dd><a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_J2SE/api/java/lang/System.html#setProperties(java.util.Properties)"><code>setProperties(java.util.Properties)</code></a>, <a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_J2SE/api/java/lang/SecurityException.html"><code>SecurityException</code></a>, <a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_J2SE/api/java/lang/SecurityManager.html#checkPropertiesAccess()"><code>SecurityManager.checkPropertiesAccess()</code></a>, <a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_J2SE/api/java/util/Properties.html"><code>Properties</code></a></dd>
</dl>
</dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2005/03/04/%e8%8e%b7%e5%8f%96%e8%bf%90%e8%a1%8c%e4%b8%ad%e7%9a%84jvm%e7%b3%bb%e7%bb%9f%e5%b1%9e%e6%80%a7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转]XML Tag Library</title>
		<link>http://niyue.com/2005/02/16/%e8%bd%acxml-tag-library/</link>
		<comments>http://niyue.com/2005/02/16/%e8%bd%acxml-tag-library/#comments</comments>
		<pubDate>Tue, 15 Feb 2005 22:59:08 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=91</guid>
		<description><![CDATA[

XML Tag Library 

The JSTL XML tag set is listed in Table 14-5.
Table 14-5 XML Tags

A key aspect of dealing with XML documents is to be able to easily access their content. XPath (see How XPath Works), a W3C recommendation since 1999, provides an easy notation for specifying and selecting parts of an XML document. [...]]]></description>
			<content:encoded><![CDATA[<p align="center">
<blockquote><p><a name="wp63716"></a></p>
<h2><a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html">XML Tag Library </a></h2>
<p><a name="wp90225"></a></p>
<p>The JSTL XML tag set is listed in <a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSTL5.html#wp90179">Table 14-5</a>.</p>
<p align="center">Table 14-5 XML Tags</p>
<p><a name="wp64237"></a></p>
<p>A key aspect of dealing with XML documents is to be able to easily access their content. XPath (see <a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JAXPXSLT3.html#wp72547">How XPath Works</a>), a W3C recommendation since 1999, provides an easy notation for specifying and selecting parts of an XML document. In the JSTL XML tags, XPath expressions specified using the <code>select</code> attribute are used to select portions of XML data streams. Note that XPath is used as a <em>local</em> expression language only for the <code>select</code> attribute. This means that values specified for <code>select</code> attributes are evaluated using the XPath expression language but that values for all other attributes are evaluated using the rules associated with the JSP 2.0 expression language.</p>
<p><a name="wp90269"></a></p>
<p>In addition to the standard XPath syntax, the JSTL XPath engine supports the following scopes to access web application data within an XPath expression:</p>
<div>
<ul><a name="wp81644"></a></p>
<div>
<li><code>$foo</code></li>
</div>
<p><a name="wp76356"></a></p>
<div>
<li><code>$param:</code></li>
</div>
<p><a name="wp76314"></a></p>
<div>
<li><code>$header:</code></li>
</div>
<p><a name="wp76315"></a></p>
<div>
<li><code>$cookie:</code></li>
</div>
<p><a name="wp76316"></a></p>
<div>
<li><code>$initParam:</code></li>
</div>
<p><a name="wp76317"></a></p>
<div>
<li><code>$pageScope:</code></li>
</div>
<p><a name="wp76320"></a></p>
<div>
<li><code>$requestScope:</code></li>
</div>
<p><a name="wp76323"></a></p>
<div>
<li><code>$sessionScope:</code></li>
</div>
<p><a name="wp76326"></a></p>
<div>
<li><code>$applicationScope:</code></li>
</div>
</ul>
</div>
<p><a name="wp76808"></a></p>
<p>These scopes are defined in exactly the same way as their counterparts in the JSP expression language discussed in <a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSPIntro7.html#wp71043">Implicit Objects</a>. <a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSTL5.html#wp76812">Table 14-6</a> shows some examples of using the scopes.</p>
<div align="left">
<table border="1" summary="Example XPath Expressions">
<tr align="center">
<th><a name="wp76816"></a></p>
<div>XPath Expression</div>
</th>
<th><a name="wp76818"></a></p>
<div>Result</div>
</th>
</tr>
</table>
</div>
<p><a name="wp89716"></a></p>
<p>The XML tags are illustrated in another version (<code>bookstore5</code>) of the Duke&#8217;s Bookstore application. This version replaces the database with an XML representation of the bookstore database, which is retrieved from another web application. The directions for building and deploying this version of the application are in <a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSPX2.html#wp116707">The Example JSP Document</a>. A sample <code>bookstore5.war</code> is provided in <code>&lt;</code><code>INSTALL</code><code>&gt;/j2eetutorial14/examples/web/provided-wars/</code>.</p>
<p><a name="wp86905"></a></p>
<h3>Core Tags</h3>
<p><a name="wp64219"></a></p>
<p>The core XML tags provide basic functionality to easily parse and access XML data.</p>
<p><a name="wp65344"></a></p>
<p>The <code>parse</code> tag parses an XML document and saves the resulting object in the EL variable specified by attribute <code>var</code>. In <code>bookstore5</code>, the XML document is parsed and saved to a context attribute in <code><a href="http://java.sun.com/j2ee/1.4/docs/tutorial/examples/web/bookstore5/web/parsebooks.txt">parsebooks.jsp</a></code>, which is included by all JSP pages that need access to the document:</p>
<div>
<pre>&lt;c:if test="${applicationScope:booklist == null}" &gt;
&lt;c:import url="${initParam.booksURL}" var="xml" /&gt;
&lt;x:parse doc="${xml}" var="booklist" scope="application" /&gt;
&lt;/c:if&gt; <a name="wp75555"></a></pre>
</div>
<p><a name="wp75446"></a></p>
<p>The <code>set</code> and <code>out</code> tags parallel the behavior described in <a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSTL4.html#wp63882">Variable Support Tags</a> and <a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSTL4.html#wp85708">Miscellaneous Tags</a> for the XPath local expression language. The <code>set</code> tag evaluates an XPath expression and sets the result into a JSP EL variable specified by attribute <code>var</code>. The <code>out</code> tag evaluates an XPath expression on the current context node and outputs the result of the evaluation to the current <code>JspWriter</code> object.</p>
<p><a name="wp85240"></a></p>
<p>The JSP page <code><a href="http://java.sun.com/j2ee/1.4/docs/tutorial/examples/web/bookstore5/web/bookdetails.txt">bookdetails.jsp</a></code> selects a book element whose <code>id</code> attribute matches the request parameter <code>bookId</code> and sets the <code>abook</code> attribute. The <code>out</code> tag then selects the book&#8217;s <code>title</code> element and outputs the result.</p>
<div>
<pre>&lt;x:set var="abook"
select="$applicationScope.booklist/
books/book[@id=$param:bookId]" /&gt;
&lt;h2&gt;&lt;x:out select="$abook/title"/&gt;&lt;/h2&gt;<a name="wp75686"></a></pre>
</div>
<p><a name="wp75452"></a></p>
<p>As you have just seen, <code>x:set</code> stores an internal XML representation of a <em>node</em> retrieved using an XPath expression; it doesn&#8217;t convert the selected node into a <code>String</code> and store it. Thus, <code>x:set</code> is primarily useful for storing parts of documents for later retrieval.</p>
<p><a name="wp75816"></a></p>
<p>If you want to store a <code>String</code>, you must use <code>x:out</code> within <code>c:set</code>. The <code>x:out</code> tag converts the node to a <code>String</code>, and <code>c:set</code> then stores the <code>String</code> as an EL variable. For example, <code><a href="http://java.sun.com/j2ee/1.4/docs/tutorial/examples/web/bookstore5/web/bookdetails.txt">bookdetails.jsp</a></code> stores an EL variable containing a book price, which is later provided as the value of a <code>fmt</code> tag, as follows:</p>
<div>
<pre>&lt;c:set var="price"&gt;
&lt;x:out select="$abook/price"/&gt;
&lt;/c:set&gt;
&lt;h4&gt;&lt;fmt:message key="ItemPrice"/&gt;:
&lt;fmt:formatNumber value="${price}" type="currency"/&gt;  <a name="wp75833"></a></pre>
</div>
<p><a name="wp75834"></a></p>
<p>The other option, which is more direct but requires that the user have more knowledge of XPath, is to coerce the node to a <code>String</code> manually by using XPath&#8217;s <code>string</code> function.</p>
<div>
<pre>&lt;x:set var="price" select="string($abook/price)"/&gt;<a name="wp75391"></a></pre>
</div>
<p><a name="wp63718"></a></p>
<h3>Flow Control Tags</h3>
<p><a name="wp64573"></a></p>
<p>The XML flow control tags parallel the behavior described in <a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSTL4.html#wp74001">Flow Control Tags</a> for XML data streams.</p>
<p><a name="wp75667"></a></p>
<p>The JSP page<code><a href="http://java.sun.com/j2ee/1.4/docs/tutorial/examples/web/bookstore5/web/bookcatalog.txt"> bookcatalog.jsp</a></code> uses the <code>forEach</code> tag to display all the books contained in <code>booklist</code> as follows:</p>
<div>
<pre>&lt;x:forEach var="book"
select="$applicationScope:booklist/books/*"&gt;
&lt;tr&gt;
&lt;c:set var="bookId"&gt;
&lt;x:out select="$book/@id"/&gt;
&lt;/c:set&gt;=
&lt;td bgcolor="#ffffaa"&gt;
&lt;c:url var="url"
value="/bookdetails" &gt;
&lt;c:param name="bookId" value="${bookId}" /&gt;
&lt;c:param name="Clear" value="0" /&gt;
&lt;/c:url&gt;
&lt;a xhref="http://blogger.org.cn/blog/${url}" mce_href="http://blogger.org.cn/blog/${url}"&gt;
&lt;strong&gt;&lt;x:out select="$book/title"/&gt;&nbsp;
&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td bgcolor="#ffffaa" rowspan=2&gt;
&lt;c:set var="price"&gt;
&lt;x:out select="$book/price"/&gt;
&lt;/c:set&gt;
&lt;fmt:formatNumber value="${price}" type="currency"/&gt;
&nbsp;
&lt;/td&gt;
&lt;td bgcolor="#ffffaa" rowspan=2&gt;
&lt;c:url var="url" value="/catalog" &gt;
&lt;c:param name="Add" value="${bookId}" /&gt;
&lt;/c:url&gt;
&lt;p&gt;&lt;strong&gt;&lt;a xhref="http://blogger.org.cn/blog/${url}" mce_href="http://blogger.org.cn/blog/${url}"&gt;&nbsp;
&lt;fmt:message key="CartAdd"/&gt;&nbsp;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td bgcolor="#ffffff"&gt;
&nbsp;&nbsp;&lt;fmt:message key="By"/&gt; &lt;em&gt;
&lt;x:out select="$book/firstname"/&gt;&nbsp;
&lt;x:out select="$book/surname"/&gt;&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/x:forEach&gt;<a name="wp75661"></a></pre>
</div>
<p><a name="wp75662"></a></p>
<h3>Transformation Tags</h3>
<p><a name="wp64586"></a></p>
<p>The <code>transform</code> tag applies a transformation, specified by an XSLT stylesheet set by the attribute <code>xslt</code>, to an XML document, specified by the attribute <code>doc</code>. If the <code>doc</code> attribute is not specified, the input XML document is read from the tag&#8217;s body content.</p>
<p><a name="wp64605"></a></p>
<p>The <code>param</code> subtag can be used along with <code>transform</code> to set transformation parameters. The attributes <code>name</code> and <code>value</code> are used to specify the parameter. The <code>value</code> attribute is optional. If it is not specified, the value is retrieved from the tag&#8217;s body.</p></blockquote>
<p><img width="550" height="8" align="bottom" alt="Divider" src="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/images/blueline.gif" /></p>
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2005/02/16/%e8%bd%acxml-tag-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转]Web Application Form Design</title>
		<link>http://niyue.com/2005/02/10/%e8%bd%acweb-application-form-design/</link>
		<comments>http://niyue.com/2005/02/10/%e8%bd%acweb-application-form-design/#comments</comments>
		<pubDate>Thu, 10 Feb 2005 06:59:11 +0000</pubDate>
		<dc:creator>niyue</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://niyue.com/?p=89</guid>
		<description><![CDATA[Web Application Form Design
by Luke Wroblewski
“Input elements should be organized in logical groups so that your brain can process the form layout in chunks of related fields.” �HTML: the Definitive Guide
Quite rare is the Web application that doesn’t make extensive use of forms for data input and configuration. But not all Web applications use forms [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Web Application Form Design</strong><br />
by <a href="http://www.lukew.com/about/leadership.html">Luke Wroblewski</a></p>
<p>“Input elements should be organized in logical groups so that your brain can process the form layout in chunks of related fields.” �<a href="http://www.web-developer-india.com/web/html/ch10_05.html">HTML: the Definitive Guide</a></p>
<p>Quite rare is the Web application that doesn’t make extensive use of forms for data input and configuration. But not all Web applications use forms consistently. <a href="http://www.themaninblue.com/experiment/InForm/vertical.htm">Variations</a> in the alignment of input fields, their respective labels, calls to action, and their surrounding visual elements can support or impair different aspects of user behavior.</p>
<p><strong /><strong>Form Layouts</strong><br />
When the time to complete a form needs to be minimized and the data being collected is mostly familiar to users (for instance, entering a name, address, and payment information in a check-out flow), a vertical alignment of labels and input fields is likely to work best. Each label and input field is grouped by vertical proximity and the consistent alignment of both input fields and labels reduces eye movement and processing time. Users only need to move in one direction: down.</p>
<p><img width="533" height="509" alt="vertical labels" src="http://www.lukew.com/resources/articles/img/forms_vertical.gif" /></p>
<p>In this layout, it’s advisable to use bold fonts for input field labels. This increases their <a href="http://www.lukew.com/resources/articles/visible_narratives.html">visual weight</a> and brings them to the foreground of the layout. When they are not bold, labels may compete with input fields for a user’s attention as they have almost equal visual weight.</p>
<p>When the data being collected by a form is unfamiliar or does not fall into easy to process groups (such as the various parts of an address), left-justifying input field labels makes scanning the information required by the form easier. Users can just scan the left column of labels up and down without being interrupted by input fields. However, the distance between the labels and input fields is often elongated by long labels, and as a result, completion times may suffer. Users have to “jump” from column to column in order to find the right association of input field and label before inputting data.</p>
<p><img width="533" height="406" alt="Left-Justified Horizontal Labels" src="http://www.lukew.com/resources/articles/img/forms_left.gif" /></p>
<p>An alternative layout, right aligns the input field labels so the association between input field and label is clear. However, the resulting left rag of the labels reduces the effectives of a quick scan to see what information the form requires. In the Western world, we read from left to right, so our eyes prefer a hard edge along the left side.</p>
<p><img width="533" height="406" alt="Right-Justified Horizontal Labels" src="http://www.lukew.com/resources/articles/img/forms_right.gif" /></p>
<p><strong>Using Visual Elements</strong><br />
Due to the advantages of a “left-justified horizontal label” layout (easy scanning of input labels and reduced vertical screen space), it may be tempting to attempt to rectify its primary shortcoming: the separation of input fields and their respective labels.</p>
<p><a href="http://synapticburn.com/comments.php?id=39_0_1_0">One such approach</a> features the addition of background colors and rules: the different background colors create a vertical unit of labels and a vertical unit of inputs; the horizontal rules form a relationship between each label and input field pair. Though this approach may seem desirable, it actually creates a few problems.</p>
<p>Through gestalt (our innate <a href="http://www.lukew.com/resources/articles/visible_narratives.html">rules of visual perception</a>), an additional 15 visual elements are added to the layout: the centerline, each background box, and each horizontal line. These elements begin to distract our eye and make it more difficult to focus on the most important elements in the layout: the labels and input fields. As <a href="http://www.cpcug.org/user/houser/websiteman/style/chartjunk.html">Edward Tufte points out</a>: “Information consists of differences that make a difference.” In other words, any visual element that is not helping your layout ends up hurting it. This can be seen when you try to scan the left column of labels. Your eye repeatedly pauses to consider each horizontal line and the box created by each combination of line and background color.</p>
<p><img width="533" height="500" alt="Backgrounds &#038; Rules" src="http://www.lukew.com/resources/articles/img/forms_backgrounds.gif" /></p>
<p>Of course this doesn’t mean that background colors and rules should never be used within form layouts. When there is value in pointing out related groupings of information to users, a thin horizontal rule or light background color can visually unite related data. Both of these elements (rules and background colors) can be especially useful for drawing attention to the primary call to action of a form.</p>
<p><img width="533" height="336" alt="Seperating Related Content" src="http://www.lukew.com/resources/articles/img/forms_related.gif" /></p>
<p><strong>Primary &#038; Secondary Actions</strong><br />
The primary action associated with a form (most commonly “submit” or “save”) needs to carry a stronger visual weight (in the example above bright color, bold font, background color, etc.) than the other form elements and should vertically align with the input fields. This illuminates a path for users and guides them to competition of the form.</p>
<p>When a form has multiple actions such as “Continue” and “Go Back” it may be wise to reduce the visual weight of the secondary action. This minimizes the risk for potential errors and further directs users to completion.</p>
<p><img width="533" height="260" alt="Primary &#038; Secondary Actions" src="http://www.lukew.com/resources/articles/img/forms_actions.gif" /></p>
<p>Though these guidelines can help better position a form for your specific purpose, the combination of layout, visual elements, and content that’s right for you should still be verified through user testing or data analysis (completion rates, errors, etc.).</p>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td><img width="51" height="1" src="http://www.lukew.com/img5/dotted2.gif" /></td>
</tr>
<tr>
<td><a href="http://www.lukew.com/about/contact_info.html"><img width="4" vspace="1" height="7" border="0" src="http://www.lukew.com/img5/arrow.gif" /> Contact Info</a><br />
<a href="http://www.lukew.com/resources/articles.asp"><img width="4" vspace="1" height="7" border="0" src="http://www.lukew.com/img5/arrow.gif" /> More Articles &#038; Papers</a></td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://niyue.com/2005/02/10/%e8%bd%acweb-application-form-design/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
