<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Jelver'Sky-文章分类-JSP/PHP</title><link>http://www.blogjava.net/jelver/category/7674.html</link><description>“一直很多人说我是天才，但我却相信这个世界没有天才。如果没有卓越的努力和娴熟的球性，你永远不会踢出精彩的足球。我从来不会低估努力的重要性，而这正是我对自己的要求。”
----------------------------------------------------------------------------罗纳尔迪尼奥(Ronaldinho)--------
“不要叫我神童！我不是神童！我所获得的一切成就，都是我用汗水和刻苦训练换来的！” --------------------------丁俊辉（中国斯诺克公开赛冠军）---
</description><language>zh-cn</language><lastBuildDate>Wed, 09 Apr 2008 08:24:21 GMT</lastBuildDate><pubDate>Wed, 09 Apr 2008 08:24:21 GMT</pubDate><ttl>60</ttl><item><title>说说大型高并发高负载网站的系统架构</title><link>http://www.blogjava.net/jelver/articles/191621.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Wed, 09 Apr 2008 01:01:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/191621.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/191621.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/191621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/191621.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/191621.html</trackback:ping><description><![CDATA[<p>转载请保留出处：俊麟 Michael&#8217;s blog (http://www.toplee.com/blog/?p=71)<br />
Trackback Url : <a href="http://www.toplee.com/blog/wp-trackback.php?p=71">http://www.toplee.com/blog/wp-trackback.php?p=71</a></p>
<p>　　我在CERNET做过拨号接入平台的搭建，而后在Yahoo&amp;3721从事过搜索引擎前端开发，又在MOP处理过大型社区猫扑大杂烩的架构升级等工作，同时自己接触和开发过不少大中型网站的模块，因此在大型网站应对高负载和并发的解决方案上有一些积累和经验，可以和大家一起探讨一下。</p>
<p><br />
　　一个小型的网站，比如个人网站，可以使用最简单的html静态页面就实现了，配合一些图片达到美化效果，所有的页面均存放在一个目录下，这样的网站对系统架构、性能的要求都很简单，随着互联网业务的不断丰富，网站相关的技术经过这些年的发展，已经细分到很细的方方面面，尤其对于大型网站来说，所采用的技术更是涉及面非常广，从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求，已经不是原来简单的html静态网站所能比拟的。</p>
<p>　　大型网站，比如门户网站。在面对大量用户访问、高并发请求方面，基本的解决方案集中在这样几个环节：使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。但是除了这几个方面，还没法根本解决大型网站面临的高负载和高并发问题。</p>
<p>　　上面提供的几个解决思路在一定程度上也意味着更大的投入，并且这样的解决思路具备瓶颈，没有很好的扩展性，下面我从低成本、高性能和高扩张性的角度来说说我的一些经验。</p>
<p><strong>1、HTML静态化</strong><br />
　　其实大家都知道，效率最高、消耗最小的就是纯静态化的html页面，所以我们尽可能使我们的网站上的页面采用静态页面来实现，这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站，我们无法全部手动去挨个实现，于是出现了我们常见的信息发布系统CMS，像我们常访问的各个门户站点的新闻频道，甚至他们的其他频道，都是通过信息发布系统来管理和实现的，信息发布系统可以实现最简单的信息录入自动生成静态页面，还能具备频道管理、权限管理、自动抓取等功能，对于一个大型网站来说，拥有一套高效、可管理的CMS是必不可少的。</p>
<p>　　除了门户和信息发布类型的网站，对于交互性要求很高的社区类型网站来说，尽可能的静态化也是提高性能的必要手段，将社区内的帖子、文章进行实时的静态化，有更新的时候再重新静态化也是大量使用的策略，像Mop的大杂烩就是使用了这样的策略，网易社区等也是如此。目前很多博客也都实现了静态化，我使用的这个Blog程序WordPress还没有静态化，所以如果面对高负载访问，www.toplee.com一定不能承受 <img class="wp-smiley" alt=":)" src="http://www.toplee.com/blog/wp-includes/images/smilies/icon_smile.gif" /> </p>
<p>　　同时，html静态化也是某些缓存策略使用的手段，对于系统中频繁使用数据库查询但是内容更新很小的应用，可以考虑使用html静态化来实现，比如论坛中论坛的公用设置信息，这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中，这些信息其实大量被前台程序调用，但是更新频率很小，可以考虑将这部分内容进行后台更新的时候进行静态化，这样避免了大量的数据库访问请求。</p>
<p>　　在进行html静态化的时候可以使用一种折中的方法，就是前端使用动态实现，在一定的策略下进行定时静态化和定时判断调用，这个能实现很多灵活性的操作，我开发的台球网站故人居(<a href="http://www.8zone.cn/">www.8zone.cn</a>)就是使用了这样的方法，我通过设定一些html静态化的时间间隔来对动态网站内容进行缓存，达到分担大部分的压力到静态页面上，可以应用于中小型网站的架构上。故人居网站的地址：<a href="http://www.8zone.cn/">http://www.8zone.cn</a>，顺便提一下，有喜欢台球的朋友多多支持我这个免费网站:)</p>
<p><strong>2、图片服务器分离</strong><br />
　　大家知道，对于Web服务器来说，不管是Apache、IIS还是其他容器，图片是最消耗资源的，于是我们有必要将图片与页面进行分离，这是基本上大型网站都会采用的策略，他们都有独立的图片服务器，甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力，并且可以保证系统不会因为图片问题而崩溃。</p>
<p>　　在应用服务器和图片服务器上，可以进行不同的配置优化，比如Apache在配置ContentType的时候可以尽量少支持，尽可能少的LoadModule，保证更高的系统消耗和执行效率。</p>
<p>　　我的台球网站故人居<a href="http://www.8zone.cn/">8zone.cn</a>也使用了图片服务器架构上的分离，目前是仅仅是架构上分离，物理上没有分离，由于没有钱买更多的服务器:)，大家可以看到故人居上的图片连接都是类似img.9tmd.com或者img1.9tmd.com的URL。</p>
<p>　　另外，在处理静态页面或者图片、js等访问方面，可以考虑使用<a href="http://www.lighttpd.net/">lighttpd</a>代替Apache，它提供了更轻量级和更高效的处理能力。</p>
<p><strong>3、数据库集群和库表散列</strong><br />
　　大型网站都有复杂的应用，这些应用必须使用数据库，那么在面对大量访问的时候，数据库的瓶颈很快就能显现出来，这时一台数据库将很快无法满足应用，于是我们需要使用数据库集群或者库表散列。</p>
<p>　　在数据库集群方面，很多数据库都有自己的解决方案，Oracle、Sybase等都有很好的方案，常用的MySQL提供的Master/Slave也是类似的方案，您使用了什么样的DB，就参考相应的解决方案来实施即可。</p>
<p>　　上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制，于是我们需要从应用程序的角度来考虑改善系统架构，库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离，不同的模块对应不同的数据库或者表，再按照一定的策略对某个页面或者功能进行更小的数据库散列，比如用户表，按照用户ID进行表散列，这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架构，将论坛的用户、设置、帖子等信息进行数据库分离，然后对帖子、用户按照板块和ID进行散列数据库和表，最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。</p>
<p><strong>4、缓存</strong><br />
　　缓存一词搞技术的都接触过，很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。</p>
<p>　　架构方面的缓存，对Apache比较熟悉的人都能知道Apache提供了自己的mod_proxy缓存模块，也可以使用外加的Squid进行缓存，这两种方式均可以有效的提高Apache的访问响应能力。</p>
<p>　　网站程序开发方面的缓存，Linux上提供的<a href="http://www.danga.com/memcached/">Memcached</a>是常用的缓存方案，不少web编程语言都提供memcache访问接口，<a href="http://cn.php.net/memcached">php</a>、perl、c和java都有，可以在web开发中使用，可以实时或者Cron的把数据、对象等内容进行缓存，策略非常灵活。一些大型社区使用了这样的架构。</p>
<p>　　另外，在使用web语言开发的时候，各种语言基本都有自己的缓存模块和方法，PHP有<a href="http://pear.php.net/">Pear</a>的Cache模块和<a href="http://www.toplee.com/blog/?p=100">eAccelerator</a>加速和Cache模块，还要知名的Apc、XCache（国人开发的，支持！）php缓存模块，Java就更多了，.net不是很熟悉，相信也肯定有。</p>
<p><strong>5、镜像</strong><br />
　　镜像是大型网站常采用的提高性能和数据安全性的方式，镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异，比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点，数据进行定时更新或者实时更新。在镜像的细节技术方面，这里不阐述太深，有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路，比如Linux上的rsync等工具。</p>
<p><strong>6、负载均衡</strong><br />
　　负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。</p>
<p>　　负载均衡技术发展了多年，有很多专业的服务提供商和产品可以选择，我个人接触过一些解决方法，其中有两个架构可以给大家做参考。另外有关初级的负载均衡DNS轮循和较专业的CDN架构就不多说了。</p>
<p><strong>6.1 硬件四层交换</strong><br />
　　第四层交换使用第三层和第四层信息包的报头信息，根据应用区间识别业务流，将整个区间段的业务流分配到合适的应用服务器进行处理。　第四层交换功能就象是虚IP，指向物理服务器。它传输的业务服从的协议多种多样，有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上，需要复杂的载量平衡算法。在IP世界，业务类型由终端TCP或UDP端口地址来决定，在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决定。</p>
<p>　　在硬件四层交换产品领域，有一些知名的产品可以选择，比如Alteon、F5等，这些产品很昂贵，但是物有所值，能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。</p>
<p><strong>6.2 软件四层交换</strong><br />
　　大家知道了硬件四层交换机的原理后，基于OSI模型来实现的软件四层交换也就应运而生，这样的解决方案实现的原理一致，不过性能稍差。但是满足一定量的压力还是游刃有余的，有人说软件实现方式其实更灵活，处理能力完全看你配置的熟悉能力。</p>
<p>　　软件四层交换我们可以使用Linux上常用的LVS来解决，LVS就是Linux Virtual Server，他提供了基于心跳线heartbeat的实时灾难应对解决方案，提高系统的鲁棒性，同时可供了灵活的虚拟VIP配置和管理功能，可以同时满足多种应用需求，这对于分布式的系统来说必不可少。</p>
<p>　　一个典型的使用负载均衡的策略就是，在软件或者硬件四层交换的基础上搭建squid集群，这种思路在很多大型网站包括搜索引擎上被采用，这样的架构低成本、高性能还有很强的扩张性，随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。</p>
<p>总结：<br />
　　对于大型网站来说，前面提到的每个方法可能都会被同时使用到，Michael这里介绍得比较浅显，具体实现过程中很多细节还需要大家慢慢熟悉和体会，有时一个很小的squid参数或者apache参数设置，对于系统性能的影响就会很大，希望大家一起讨论，达到抛砖引玉之效。</p>
<p>　　转载请保留出处：俊麟 Michael&#8217;s blog (http://www.toplee.com/blog/?p=71)<br />
Trackback Url : <a href="http://www.toplee.com/blog/wp-trackback.php?p=71">http://www.toplee.com/blog/wp-trackback.php?p=71</a></p>
<img src ="http://www.blogjava.net/jelver/aggbug/191621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2008-04-09 09:01 <a href="http://www.blogjava.net/jelver/articles/191621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不同Web主机上的Servlet之间数据对象的相互传输(转) </title><link>http://www.blogjava.net/jelver/articles/186066.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Thu, 13 Mar 2008 07:53:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/186066.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/186066.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/186066.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/186066.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/186066.html</trackback:ping><description><![CDATA[<div class="storytext">为什么要这样做<br />
在目前所做的一个项目中，我们使用了两台独立的数据库服务器，出于安全方面的考虑，我们同时使用两台Web服务器分别操作这两个数据库。这就形成了这样的一个结构图：<br />
<br />
<div align="center"><img alt="" src="http://blog.itpub.net/upload/2006/4/19/2/14/11453840699060158.gif" border="0" /></div>
<br />
<br />
由于数据库服务器A和服务库服务器B之间存在着数据的交换，而WEB服务器A并不能直接访问数据库服务器B，同理WEB服务器B也不能直接访问数据库服务器A。这样的交换只能是通过两台Web主机来进行。而在绝大多数时候，我们涉及的是较大规模的数据交换，使用带参数的格式显然不能满足我们的要求，这就涉及了不同Web主机上的Servlet之间数据对象的相互传输的问题。<br />
使用通常的Application域或是Session域的javabean看上去不能满足我们的要求，虽然我们相信会有很多更为完美的方案可以解决这个问题，但是我们今天想看看如何直接通过HTTP连接来完成这样的传输。<br />
首先对于我们的每一个独立的应用来说，两台WEB服务器都会存在一个主次的关系，情况也许是这样的：访问者访问WEB服务器A上的一个servlet A，而这个servlet A产生一个数据对象传输到WEB服务器B上的另一个servlet B，servlet B接收到这个数据对象后对其进行相应的处理，然后它可能还会生成另一个数据对象传输到servlet A中。这样的过程看上去有点象一个远程函数调用的概念。限于篇幅的限制，我们这里讨论一种较为简单的情况，test将passobject传输到test2，test2对passobject进行处理后将其传回到test。<br />
<br />
简单示例的源码<br />
passobject.java<br />
首先，我们需要在两台WEB主机上分别建立对passobject的定义，在两台主机上的定义应该是完全一样，这样的类定义和我们通常使用并没有什么不同。只是这样的类必须实现序列化，也就是要实现Serializable：<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;test;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img id="Codehighlighter1_108_400_Open_Image" onclick="this.style.display='none'; Codehighlighter1_108_400_Open_Text.style.display='none'; Codehighlighter1_108_400_Closed_Image.style.display='inline'; Codehighlighter1_108_400_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_108_400_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_108_400_Closed_Text.style.display='none'; Codehighlighter1_108_400_Open_Image.style.display='inline'; Codehighlighter1_108_400_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;PassObject&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;Serializable&nbsp;</span><span id="Codehighlighter1_108_400_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_108_400_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;PassValue1;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;PassValue2;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setNewPassObject()<br />
<img id="Codehighlighter1_227_293_Open_Image" onclick="this.style.display='none'; Codehighlighter1_227_293_Open_Text.style.display='none'; Codehighlighter1_227_293_Closed_Image.style.display='inline'; Codehighlighter1_227_293_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_227_293_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_227_293_Closed_Text.style.display='none'; Codehighlighter1_227_293_Open_Image.style.display='inline'; Codehighlighter1_227_293_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_227_293_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_227_293_Open_Text"><span style="color: #000000">{PassValue1</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">yzysynew</span><span style="color: #000000">"</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassValue2</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">new</span><span style="color: #000000">"</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setOldPassObject()<br />
<img id="Codehighlighter1_350_386_Open_Image" onclick="this.style.display='none'; Codehighlighter1_350_386_Open_Text.style.display='none'; Codehighlighter1_350_386_Closed_Image.style.display='inline'; Codehighlighter1_350_386_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_350_386_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_350_386_Closed_Text.style.display='none'; Codehighlighter1_350_386_Open_Image.style.display='inline'; Codehighlighter1_350_386_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_350_386_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_350_386_Open_Text"><span style="color: #000000">{PassValue1</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">yzysyold</span><span style="color: #000000">"</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br />
test.java<br />
在其中的一台web主机上建立。除去加注释的那几行，这完全是一个通常意义上的用于显示的servlet，不过那几行的内容看上去也许会有点让你眼花缭乱。这几行将数据对象传输到了另一台主机的test2中，并接收经过test2处理的数据对象。对于这里所涉及的一些不太常用的API，我们将会在最后一并说明。<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;test;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.sql.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.http.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.jsp.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.jsp.tagext.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.net.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img id="Codehighlighter1_364_2083_Open_Image" onclick="this.style.display='none'; Codehighlighter1_364_2083_Open_Text.style.display='none'; Codehighlighter1_364_2083_Closed_Image.style.display='inline'; Codehighlighter1_364_2083_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_364_2083_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_364_2083_Closed_Text.style.display='none'; Codehighlighter1_364_2083_Open_Image.style.display='inline'; Codehighlighter1_364_2083_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Test&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;HttpServlet&nbsp;</span><span id="Codehighlighter1_364_2083_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_364_2083_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;doGet(HttpServletRequest&nbsp;request,<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException,&nbsp;ServletException<br />
<img id="Codehighlighter1_527_1853_Open_Image" onclick="this.style.display='none'; Codehighlighter1_527_1853_Open_Text.style.display='none'; Codehighlighter1_527_1853_Closed_Image.style.display='inline'; Codehighlighter1_527_1853_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_527_1853_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_527_1853_Closed_Text.style.display='none'; Codehighlighter1_527_1853_Open_Image.style.display='inline'; Codehighlighter1_527_1853_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_527_1853_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_527_1853_Open_Text"><span style="color: #000000">{PassObject&nbsp;passobject&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;PassObject();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;passobject.setNewPassObject();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrintWriter&nbsp;out&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;response.getWriter();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.println(passobject.PassValue1);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.println(passobject.PassValue2);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">创建一个新的URL实例url</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;url&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;URL(</span><span style="color: #000000">"</span><span style="color: #000000">http://141.56.16.8/examples/servlet/test.Test2</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">根据url建立连接</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URLConnection&nbsp;con&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;url.openConnection();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">设置该连接可写</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.setDoOutput(</span><span style="color: #0000ff">true</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">禁用cache</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.setUseCaches(</span><span style="color: #0000ff">false</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">取出输出流</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;outs</span><span style="color: #000000">=</span><span style="color: #000000">con.getOutputStream();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">将该输出流转换为对象输出流</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectOutputStream&nbsp;objout&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ObjectOutputStream(outs);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">将要传输的对象写入该对象输出流中</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objout.writeObject(passobject);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">取得返回的输入流</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;con.getInputStream();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">将该输入流定义为对象输入流</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectInputStream&nbsp;objStream;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objStream&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ObjectInputStream(in);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">按指定类的格式读取输入流的内容</span><span style="color: #008000"><br />
<img id="Codehighlighter1_1551_1720_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1551_1720_Open_Text.style.display='none'; Codehighlighter1_1551_1720_Closed_Image.style.display='inline'; Codehighlighter1_1551_1720_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1551_1720_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1551_1720_Closed_Text.style.display='none'; Codehighlighter1_1551_1720_Open_Image.style.display='inline'; Codehighlighter1_1551_1720_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1551_1720_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1551_1720_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;passobject</span><span style="color: #000000">=</span><span style="color: #000000">(PassObject)objStream.readObject();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.println(passobject.PassValue1);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.println(passobject.PassValue2);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(java.lang.ClassNotFoundException&nbsp;ysy&nbsp;)<br />
<img id="Codehighlighter1_1792_1839_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1792_1839_Open_Text.style.display='none'; Codehighlighter1_1792_1839_Closed_Image.style.display='inline'; Codehighlighter1_1792_1839_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1792_1839_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1792_1839_Closed_Text.style.display='none'; Codehighlighter1_1792_1839_Open_Image.style.display='inline'; Codehighlighter1_1792_1839_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_1792_1839_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1792_1839_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.println(</span><span style="color: #000000">"</span><span style="color: #000000">fail</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;doPost(HttpServletRequest&nbsp;request,<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException,&nbsp;ServletException<br />
<img id="Codehighlighter1_2017_2069_Open_Image" onclick="this.style.display='none'; Codehighlighter1_2017_2069_Open_Text.style.display='none'; Codehighlighter1_2017_2069_Closed_Image.style.display='inline'; Codehighlighter1_2017_2069_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_2017_2069_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_2017_2069_Closed_Text.style.display='none'; Codehighlighter1_2017_2069_Open_Image.style.display='inline'; Codehighlighter1_2017_2069_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_2017_2069_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_2017_2069_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doGet(request,&nbsp;response);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br />
test2.java<br />
在其中的另一台web主机上建立，用来接收test发送的数据对象，并对其进行处理后返回到test。<br />
<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;test;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.sql.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.http.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.jsp.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.jsp.tagext.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.net.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
<img id="Codehighlighter1_364_1385_Open_Image" onclick="this.style.display='none'; Codehighlighter1_364_1385_Open_Text.style.display='none'; Codehighlighter1_364_1385_Closed_Image.style.display='inline'; Codehighlighter1_364_1385_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_364_1385_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_364_1385_Closed_Text.style.display='none'; Codehighlighter1_364_1385_Open_Image.style.display='inline'; Codehighlighter1_364_1385_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Test2&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;HttpServlet&nbsp;</span><span id="Codehighlighter1_364_1385_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_364_1385_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;doGet(HttpServletRequest&nbsp;request,<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException,&nbsp;ServletException<br />
<img id="Codehighlighter1_527_1155_Open_Image" onclick="this.style.display='none'; Codehighlighter1_527_1155_Open_Text.style.display='none'; Codehighlighter1_527_1155_Closed_Image.style.display='inline'; Codehighlighter1_527_1155_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_527_1155_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_527_1155_Closed_Text.style.display='none'; Codehighlighter1_527_1155_Open_Image.style.display='inline'; Codehighlighter1_527_1155_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_527_1155_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_527_1155_Open_Text"><span style="color: #000000">{</span><span style="color: #008000">//</span><span style="color: #008000">封装用于返回的对象输出流</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectOutputStream&nbsp;out&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ObjectOutputStream(response.getOutputStream());<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">封装用于接收的对象输入流</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectInputStream&nbsp;in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ObjectInputStream(request.getInputStream());<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassObject&nbsp;passobject</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;PassObject();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">按指定类的格式读取对象输入流中的内容</span><span style="color: #008000"><br />
<img id="Codehighlighter1_844_910_Open_Image" onclick="this.style.display='none'; Codehighlighter1_844_910_Open_Text.style.display='none'; Codehighlighter1_844_910_Closed_Image.style.display='inline'; Codehighlighter1_844_910_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_844_910_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_844_910_Closed_Text.style.display='none'; Codehighlighter1_844_910_Open_Image.style.display='inline'; Codehighlighter1_844_910_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_844_910_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_844_910_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;passobject</span><span style="color: #000000">=</span><span style="color: #000000">(PassObject)in.readObject();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(java.lang.ClassNotFoundException&nbsp;ysy&nbsp;)<br />
<img id="Codehighlighter1_982_996_Open_Image" onclick="this.style.display='none'; Codehighlighter1_982_996_Open_Text.style.display='none'; Codehighlighter1_982_996_Closed_Image.style.display='inline'; Codehighlighter1_982_996_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_982_996_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_982_996_Closed_Text.style.display='none'; Codehighlighter1_982_996_Open_Image.style.display='inline'; Codehighlighter1_982_996_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_982_996_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_982_996_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">对接受到的数据对象进行处理</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;passobject.setOldPassObject();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">将处理后的数据对象返回到对象输出流中</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.writeObject(passobject);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;doPost(HttpServletRequest&nbsp;request,<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException,&nbsp;ServletException<br />
<img id="Codehighlighter1_1319_1371_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1319_1371_Open_Text.style.display='none'; Codehighlighter1_1319_1371_Closed_Image.style.display='inline'; Codehighlighter1_1319_1371_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1319_1371_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1319_1371_Closed_Text.style.display='none'; Codehighlighter1_1319_1371_Open_Image.style.display='inline'; Codehighlighter1_1319_1371_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_1319_1371_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1319_1371_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doGet(request,&nbsp;response);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br />
程序中涉及的部分API的说明<br />
java.net.URL<br />
URL类表示了一个统一资源路径。这样的资源可能是一个文件或目录，也可能是更为复杂的诸如数据库的查询或是搜索引擎。<br />
在我们的程序中使用了URL的一种构造函数： <br />
URL(String spec) <br />
直接使用字符串作为构造函数的参数，这实际上是URL的众多构造函数中最为简单的一种。<br />
此外，我们还用到了URL的openConnection()方法：<br />
public URLConnection openConnection()<br />
throws IOException<br />
该方法返回了一个URLConnection对象。每次调用该方法时会开启一个到指定URL的新的连接。<br />
这里需要注意的是，调用该方法的结果是建立了一个连接，这与通常的页面跳转完全是两回事。在更多的情况下，这里仅仅是建立了一个连接的通路，而并没有实现任何其它的操作。<br />
java.net.URLConnection<br />
这是一个抽象类，是所有反映application和一个URL之前的通信的类的超类。这个类的实例可以用来对一个URL表示的资源进行读写。<br />
在我们的程序中我们使用了这个类的如下方法： <br />
getInputStream<br />
public InputStream getInputStream()<br />
throws IOException<br />
返回从这个连接读取的一个输入流<br />
getOutputStream<br />
public OutputStream getOutputStream()<br />
throws IOException<br />
返回一个用于写入这个连接的输出流<br />
setDoOutput<br />
public void setDoOutput(boolean dooutput)<br />
设置该连接是否可以写入<br />
setUseCaches<br />
public void setUseCaches(boolean usecaches)<br />
设置该连接是否使用cache<br />
java.io.OutputStream<br />
这是一个抽象类，是所有反映一个二进制输出流的类的超类。一个这样的输出流可以对二进制数据进行输出或发送。<br />
java.io.ObjectOutputStream<br />
该类用来向一个OutputStream写入java的对象。这个对象可以使用ObjectInputStream进行读取或再造。<br />
只有实现java.io.Serializable接口的对象可以写入该数据流中。<br />
在我们的程序中还使用了该类的writeObject()方法：<br />
public final void writeObject(Object obj)<br />
throws IOException<br />
将指定的对象写入ObjectOutputStream。<br />
java.io.InputStream<br />
这是一个抽象类，是所有反映一个二进制输入流的类的超类。<br />
java.io.ObjectInputStream<br />
一个ObjectInputStream对一个使用ObjectOutputStream写入的对象进行解析。<br />
在我们的程序中使用了该类的readObject()方法：<br />
public final Object readObject()<br />
throws OptionalDataException,<br />
ClassNotFoundException,<br />
IOException<br />
从一个ObjectInputStream中读取一个对象。<br />
<br />
程序执行的结果<br />
如果一切正常，访问test.Test你应该可以看到这样的结果：<br />
yzysynew<br />
new<br />
yzysyold<br />
new<br />
其中yzysynew，new是对象原来的内容，而yzysyold，new所反映的那个对象已经是传送到test2后经test2处理过的了。<br />
</div>
<img src ="http://www.blogjava.net/jelver/aggbug/186066.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2008-03-13 15:53 <a href="http://www.blogjava.net/jelver/articles/186066.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Servlet 监听器应用（转）</title><link>http://www.blogjava.net/jelver/articles/164916.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Mon, 03 Dec 2007 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/164916.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/164916.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/164916.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/164916.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/164916.html</trackback:ping><description><![CDATA[<h3><font color="#993300" size="2">监听器概述</font><br />
<font color="#993300" size="2">&nbsp;&nbsp;1.Listener是Servlet的监听器&nbsp;<br />
&nbsp;&nbsp;2.可以监听客户端的请求、服务端的操作等。<br />
&nbsp;&nbsp;3.通过监听器，可以自动激发一些操作，如监听在线用户数量,当增加一个HttpSession时，给在线人数加1。<br />
&nbsp;&nbsp;4.编写监听器需要实现相应的接口<br />
&nbsp;&nbsp;5.编写完成后在web.xml文件中配置一下,就可以起作用了<br />
&nbsp;&nbsp;6.可以在不修改现有系统基础上,增加web应用程序生命周期事件的跟踪<br />
<br />
</font></h3>
<h3><font color="#993300" size="2">常用的监听接口</font></h3>
<br />
<font color="#993300" size="2">&nbsp;&nbsp;1.ServletContextAttributeListener<br />
&nbsp;&nbsp;监听对ServletContext属性的操作，比如增加/删除/修改<br />
&nbsp;&nbsp;2.ServletContextListener<br />
&nbsp;&nbsp;监听ServletContext,当创建ServletContext时，激发contextInitialized(ServletContextEvent&nbsp;sce)方法；当销毁ServletContext时，激发contextDestroyed(ServletContextEvent&nbsp;sce)方法。<br />
&nbsp;&nbsp;3.HttpSessionListener<br />
&nbsp;&nbsp;监听HttpSession的操作。当创建一个Session时，激发session&nbsp;Created(SessionEvent&nbsp;se)方法；当销毁一个Session时，激发sessionDestroyed&nbsp;(HttpSessionEvent&nbsp;se)方法。<br />
&nbsp;&nbsp;4.HttpSessionAttributeListener<br />
&nbsp;&nbsp;监听HttpSession中的属性的操作。当在Session增加一个属性时，激发attributeAdded(HttpSessionBindingEvent&nbsp;se)&nbsp;方法；当在Session删除一个属性时，激发attributeRemoved(HttpSessionBindingEvent&nbsp;se)方法；当在Session属性被重新设置时，激发attributeReplaced(HttpSessionBindingEvent&nbsp;se)&nbsp;方法。<br />
<br />
使用范例： </font>
<h3><font color="#993300" size="2">由监听器管理共享数据库连接</font></h3>
<br />
<font color="#993300" size="2">&nbsp;&nbsp;生命周期事件的一个实际应用由context监听器管理共享数据库连接。在web.xml中如下定义监听器：<br />
&lt;listener&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;listener-class&gt;XXX.MyConnectionManager&lt;/listener-class&gt;<br />
&lt;/listener&gt;&nbsp;&#216;server创建监听器的实例,接受事件并自动判断实现监听器接口的类型。要记住的是由于监听器是配置在部署描述符web.xml中，所以不需要改变任何代码就可以添加新的监听器。<br />
<br />
public&nbsp;class&nbsp;MyConnectionManager&nbsp;implements&nbsp;ServletContextListener{&nbsp;&nbsp;<br />
&nbsp;&nbsp;public&nbsp;void&nbsp;contextInitialized(ServletContextEvent&nbsp;e)&nbsp;{&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;=&nbsp;//&nbsp;create&nbsp;connection&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.getServletContext().setAttribute("con",&nbsp;con);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;contextDestroyed(ServletContextEvent&nbsp;e)&nbsp;{&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;=&nbsp;(Connection)&nbsp;e.getServletContext().getAttribute("con");&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.close();&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(SQLException&nbsp;ignored)&nbsp;{&nbsp;}&nbsp;//&nbsp;close&nbsp;connection&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
}&nbsp;&nbsp;<br />
&nbsp;&nbsp;监听器保证每新生成一个servlet&nbsp;context都会有一个可用的数据库连接,并且所有的连接对会在context关闭的时候随之关闭。&nbsp;<br />
<br />
</font>
<h3><font color="#993300" size="2">计算在线用户数量的Linstener</font></h3>
<font color="#993300" size="2">(1)<br />
&nbsp;Package&nbsp;xxx;&nbsp;<br />
<br />
&nbsp;public&nbsp;class&nbsp;OnlineCounter&nbsp;{&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;long&nbsp;online&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;long&nbsp;getOnline(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;online;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;raise(){&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;online++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;reduce(){&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;online--;&nbsp;<br />
&nbsp;&nbsp;&nbsp;}<br />
}&nbsp;<br />
<br />
import&nbsp;javax.servlet.http.HttpSessionEvent;<br />
import&nbsp;javax.servlet.http.HttpSessionListener;<br />
<br />
public&nbsp;class&nbsp;OnlineCounterListener&nbsp;implements&nbsp;HttpSessionListener{<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;sessionCreated(HttpSessionEvent&nbsp;hse)&nbsp;{&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OnlineCounter.raise();&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;sessionDestroyed(HttpSessionEvent&nbsp;hse){&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OnlineCounter.reduce();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br />
&nbsp;}&nbsp;<br />
<br />
在需要显示在线人数的JSP中可是使用<br />
目前在线人数：<br />
&lt;%@&nbsp;page&nbsp;import=&#8220;xxx.OnlineCounter"&nbsp;%&gt;<br />
&lt;%=OnlineCounter.getOnline()%&gt;<br />
<br />
退出会话(可以给用户提供一个注销按钮)：<br />
&lt;form&nbsp;action="exit.jsp"&nbsp;method=post&gt;&nbsp;<br />
&nbsp;&nbsp;&lt;input&nbsp;type=submit&nbsp;value="exit"&gt;&nbsp;<br />
&lt;/form&gt;&nbsp;<br />
<br />
exit.jsp:&nbsp;&lt;%session.invalidate()&nbsp;;%&gt;&nbsp;<br />
<br />
在web.xml中加入:<br />
&lt;listener&gt;&nbsp;<br />
&nbsp;&nbsp;&lt;listener-class&gt;servletlistener111111.SecondListener&lt;/listener-class&gt;&nbsp;&lt;/listener&gt;<br />
<br />
怎么样，就是这么简单，不用对现有代码做任何的修改。&nbsp;</font>&nbsp;<br />
<img src ="http://www.blogjava.net/jelver/aggbug/164916.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2007-12-03 16:51 <a href="http://www.blogjava.net/jelver/articles/164916.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>B/S系统权限控制的一种简单方法 (转)</title><link>http://www.blogjava.net/jelver/articles/141767.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Fri, 31 Aug 2007 08:37:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/141767.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/141767.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/141767.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/141767.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/141767.html</trackback:ping><description><![CDATA[<p>&nbsp;看了网上一些关于权限控制的帖子，越看越迷糊，什么用AOP(Aspect Oriented Programming,面向方面编程)，用容器，RBAC(基于角色的访问控制方法),SSO,Jive的Proxy模式等等等等，且又是role又是group，真是头都大了，先写个简单的实现方法，以后再研究高深的。<br />
&nbsp; 此方法不依赖容器 框架，适用于小系统(主要JSP页面要少于100,因为是硬编码到JSP)，适用于要精确控制页面field的情况较多的系统。<br />
&nbsp; (插句话：要分清权限控制与业务逻辑，业务逻辑就是情况由系统运行时的某些条件决定，如学生管理系统中，某一学生进入系统，只能看自己的记录，因为可看的记录是由学号来决定的，所以这是业务逻辑，而又如学生不能看老师的记录，这是有学生的身份来决定的，所以这是权限控制。)<br />
&nbsp; 好了，进入正题！<br />
&nbsp; 建表：<br />
&nbsp; user(user信息： userID userPassword 等)<br />
&nbsp; role(role描述：roleID roleDesc)<br />
&nbsp; permission(permission描述：permissionID permissionDesc)<br />
&nbsp; user-role(user role对应关系表：userID roleID)<br />
&nbsp; role-permission(role permission对应关系表：roleID permissionID)<br />
&nbsp; user-permission(user permission对应关系表：userID permissionID)<br />
&nbsp; <br />
&nbsp; 重要申明： </p>
<p>&nbsp;<strong>1</strong> 此处role没有继承关系,只是permission的集合<br />
&nbsp;<strong>2</strong> user-permission表只是为了方便，其数据是根据user-role role-permission两表得来，只有在user-role role-permission两表有更新的时候更新此表，并不能单独赋予user某个permission,只能赋予user一个或多个role。<br />
<strong>3</strong> permission的分配，这是一个难点，很多比较复杂的权限控制系统也是因为这个才发展出来，此处把它尽量想简单，不考虑业务逻辑，以页面为视角，分两层，首先是需要控制的jsp页面，然后是需要控制的页面field(包括link,text,textbox,button等等)，field这一层还有privilege之分(R和W，即可读和可写)<br />
&nbsp; 基本思路：进入JSP页面时，检查用户信息，查到用户有此permission就包含此代码，如果没有此permission就不包含此代码，此功能由Tag来完成(不会写Tag？不要紧，抄！)。看代码吧！<br />
&nbsp; <strong>1</strong> 建表(如上)<br />
&nbsp; <strong>2</strong> 建两个class(bean) (UserProfile是用户基本信息&nbsp;&nbsp; UserPermission是permission )<br />
&nbsp;&nbsp;&nbsp; UserProfile.java:<br />
package com.&#215;&#215;.&#215;&#215;.&#215;&#215;;<br />
import java.util.Collection;</p>
<p>public class UserProfile {<br />
&nbsp; private String userId;<br />
&nbsp; private String userType;<br />
&nbsp; private String companyNo;<br />
&nbsp; private String companyName;<br />
&nbsp; private String companyType;<br />
&nbsp; private Collection userPermissions;</p>
<p>&nbsp; public String getUserId() {<br />
&nbsp;&nbsp;&nbsp; return userId;<br />
&nbsp; }<br />
&nbsp; public void setUserId(String userId) {<br />
&nbsp;&nbsp;&nbsp; this.userId = userId;<br />
&nbsp; }<br />
&nbsp; public String getUserType() {<br />
&nbsp;&nbsp;&nbsp; return userType;<br />
&nbsp; }<br />
&nbsp; public void setUserType(String userType) {<br />
&nbsp;&nbsp;&nbsp; this.userType = userType;<br />
&nbsp; }<br />
&nbsp; public String getCompanyNo() {<br />
&nbsp;&nbsp;&nbsp; return companyNo;<br />
&nbsp; }<br />
&nbsp; public void setCompanyNo(String companyNo) {<br />
&nbsp;&nbsp;&nbsp; this.companyNo = companyNo;<br />
&nbsp; }<br />
&nbsp; public String getCompanyName() {<br />
&nbsp;&nbsp;&nbsp; return companyName;<br />
&nbsp; }<br />
&nbsp; public void setCompanyName(String companyName) {<br />
&nbsp;&nbsp;&nbsp; this.companyName = companyName;<br />
&nbsp; }<br />
&nbsp; public String getCompanyType() {<br />
&nbsp;&nbsp;&nbsp; return companyType;<br />
&nbsp; }<br />
&nbsp; public void setCompanyType(String companyType) {<br />
&nbsp;&nbsp;&nbsp; this.companyType = companyType;<br />
&nbsp; }<br />
&nbsp; public Collection getUserPermissions() {<br />
&nbsp;&nbsp;&nbsp; return userPermissions;<br />
&nbsp; }<br />
&nbsp; public void setUserPermissions(Collection userPermissions) {<br />
&nbsp;&nbsp;&nbsp; this.userPermissions = userPermissions;<br />
&nbsp; }<br />
}</p>
<p>&nbsp; UserPermission.java:<br />
package com.&#215;&#215;.&#215;&#215;.&#215;&#215;;</p>
<p>public class UserPermission {<br />
&nbsp; private int permissionId;<br />
&nbsp; private String privilege;<br />
&nbsp; public int getPermissionId() {<br />
&nbsp;&nbsp;&nbsp; return permissionId;<br />
&nbsp; }<br />
&nbsp; public void setPermissionId(int permissionId) {<br />
&nbsp;&nbsp;&nbsp; this.permissionId = permissionId;<br />
&nbsp; }<br />
&nbsp; public String getPrivilege() {<br />
&nbsp;&nbsp;&nbsp; return privilege;<br />
&nbsp; }<br />
&nbsp; public void setPrivilege(String privilege) {<br />
&nbsp;&nbsp;&nbsp; this.privilege = privilege;<br />
&nbsp; }<br />
}&nbsp; <br />
&nbsp; <br />
&nbsp; <br />
&nbsp; <strong>3</strong> 加两个Tag(Page与Field)：<br />
&nbsp; SecurityTagForPage.java：<br />
package com.**.**.taglib;<br />
import java.util.*;</p>
<p>public class SecurityTagForPage extends TagSupport<br />
{<br />
&nbsp;<br />
&nbsp; private int permissionID;<br />
&nbsp; <br />
&nbsp; public int doEndTag() throws JspException<br />
&nbsp; {<br />
&nbsp; HttpSession session = pageContext.getSession();<br />
&nbsp; //登陆时把该user的userProfile放到session里 <br />
&nbsp; UserProfile userProfile = (UserProfile)session.getAttribute("userProfile");<br />
&nbsp; Collection collection= userProfile.getUserPermissions();<br />
&nbsp; Iterator it = collection.iterator() ;<br />
&nbsp; while(it.hasNext())<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UserPermission userPermission = (UserPermission)it.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((permissionID == userPermission.getPermissionId()))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return EVAL_PAGE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return SKIP_PAGE;<br />
&nbsp; }</p>
<p>&nbsp; public int getPermissionID()<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; return permissionID;<br />
&nbsp; }<br />
&nbsp; public void setPermissionID(int permissionID)<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; this.permissionID = permissionID;<br />
&nbsp; }<br />
}</p>
<p>&nbsp; SecurityTagForField：<br />
public class SecurityTagForField extends TagSupport<br />
{<br />
&nbsp; private int permissionID;<br />
&nbsp; private String privilege;</p>
<p>&nbsp; public int doStartTag() throws JspException<br />
&nbsp; {<br />
&nbsp;&nbsp; HttpSession session = pageContext.getSession();<br />
&nbsp;&nbsp; UserProfile userProfile = (UserProfile)session.getAttribute("userProfile");</p>
<p>&nbsp;&nbsp;&nbsp; Collection collection= userProfile.getUserPermissions();<br />
&nbsp;&nbsp;&nbsp; Iterator it = collection.iterator() ;<br />
&nbsp;&nbsp;&nbsp; while(it.hasNext())<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UserPermission userPermission = (UserPermission)it.next();<br />
&nbsp;&nbsp;&nbsp; if (privilege ==null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p><br />
if ( (permissionID == userPermission.getPermissionId()))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return EVAL_BODY_INCLUDE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((permissionID == userPermission.getPermissionId())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp;(privilege.equals(userPermission.getPrivilege())))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return EVAL_BODY_INCLUDE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return SKIP_BODY;<br />
&nbsp; } </p>
<p>&nbsp;</p>
<p><br />
&nbsp; public int getPermissionID()<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; return permissionID;<br />
&nbsp; }<br />
&nbsp; public void setPermissionID(int permissionID)<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; this.permissionID = permissionID;<br />
&nbsp; }<br />
&nbsp; public String getPrivilege()<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; return privilege;<br />
&nbsp; }<br />
&nbsp; public void setPrivilege(String privilege)<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; this.privilege = privilege;<br />
&nbsp; }<br />
}<br />
&nbsp; <strong>4</strong> 在web-inf目录下建个securityTag.tld文件，内容如下：(改一下class的目录)<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"<br />
&nbsp;"<a href="http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd</a>"&gt;<br />
&lt;!-- a tag library descriptor --&gt;<br />
&lt;taglib&gt;<br />
&nbsp;&lt;tlibversion&gt;1.0&lt;/tlibversion&gt;<br />
&nbsp;&lt;jspversion&gt;1.1&lt;/jspversion&gt;<br />
&nbsp;&lt;shortname&gt;security&lt;/shortname&gt;<br />
&nbsp;&lt;uri/&gt;<br />
&nbsp;&lt;info&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;access control!<br />
&nbsp; &nbsp;&lt;/info&gt;<br />
&nbsp;&lt;tag&gt;<br />
&nbsp;&nbsp;&lt;name&gt;securityForField&lt;/name&gt;<br />
&nbsp;&nbsp;&lt;tagclass&gt;com.companyname.prjname.taglib.SecurityTagForField&lt;/tagclass&gt;<br />
&nbsp;&nbsp;&lt;attribute&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;permissionID&lt;/name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;required&gt;true&lt;/required&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/attribute&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;attribute&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;privilege&lt;/name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/attribute&gt;</p>
<p>&nbsp;&lt;/tag&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tag&gt;<br />
&nbsp;&nbsp;&lt;name&gt;securityForPage&lt;/name&gt;<br />
&nbsp;&nbsp;&lt;tagclass&gt;com.companyname.prjname.taglib.SecurityTagForPage&lt;/tagclass&gt;<br />
&nbsp;&nbsp;&lt;attribute&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;permissionID&lt;/name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;required&gt;true&lt;/required&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/attribute&gt;</p>
<p>&nbsp;&lt;/tag&gt;<br />
&lt;/taglib&gt;</p>
<p>&nbsp; <strong>5</strong> 修改需要控制的jsp<br />
&nbsp; 在jsp页面这样写：<br />
&lt;%@ taglib uri="/WEB-INF/securityTag.tld" prefix="security" %&gt;<br />
&lt;%@ page import="com.hp.elog2.util.Util" %&gt;<br />
&lt;security:securityForPage permissionID="36" /&gt;<br />
.......<br />
&lt;security:securityForField permissionID="46" privilege="R"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt;&lt;html:text name="formBean" property="property1" readonly="true" /&gt;&lt;/td&gt;<br />
&lt;/security:securityForField&gt;<br />
&lt;security:securityForField permissionID="46" privilege="W"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt;&lt;html:text name="formBean" property="property1" /&gt;&lt;/td&gt;<br />
&lt;/security:securityForField&gt;<br />
......<br />
&nbsp; 这样就大功告成了，建议在所有jsp页面完成后再做权限控制这一块(添加Tag)，主要都是些Copy＋C和Copy＋V的工作。<br />
&nbsp; 此方法最大的问题就是hardcode太多，但结构简单，思路清晰，适用范围广。<br />
&nbsp; 复杂的方法希望同道之士于我联系<a href="mailto:leon_sandy@tom.com">leon_sandy@tom.com</a>，共同研究！</p>
<img src ="http://www.blogjava.net/jelver/aggbug/141767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2007-08-31 16:37 <a href="http://www.blogjava.net/jelver/articles/141767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat5.0-5.5连接池配置指南 （转）</title><link>http://www.blogjava.net/jelver/articles/88127.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Sat, 16 Dec 2006 03:08:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/88127.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/88127.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/88127.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/88127.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/88127.html</trackback:ping><description><![CDATA[本文以目前最流行的MySQL为例，讲解通过Tomcat连接池连接MySQL数据库的基本步骤，如果你了解MySQL可跳过第一步。<br /><br />　　在进行Tomcat连接池配置前，先解压缩mysql-connector-java-xxx.zip，将其中的mysql-connector-java-3.x.x-xxx.jar取出，置于&lt;%TOMCAT_HOME%&gt;\common\lib中。<br /><br />　　接下来，让我们一起进入精彩的Tomcat配置之旅。<br /><br />一.新建用户及数据库<br /><br />操作步骤如下：<br /><br />C:\Documents and Settings\Administrator&gt;d:<br /><br />D:\&gt;cd mysql\bin<br /><br />D:\MySQL\bin&gt;mysql -u root -p<br />Enter password: *******<br />Welcome to the MySQL monitor.  Commands end with ; or \g.<br />Your MySQL connection id is 51 to server version: 4.1.12a-nt<br /><br />Type 'help;' or '\h' for help. Type '\c' to clear the buffer.<br /><br />mysql&gt; GRANT ALL PRIVILEGES ON jcc.* TO jcc@localhost IDENTIFIED BY 'jsp.com.cn'<br />WITH GRANT OPTION;<br />Query OK, 0 rows affected (0.01 sec)<br /><br />mysql&gt; USE mysql;<br />Database changed<br />mysql&gt; SELECT Host,User,Password FROM user;<br />+-----------+------+-------------------------------------------+<br />| Host      | User | Password                                  |<br />+-----------+------+-------------------------------------------+<br />| localhost | root | *60D5B730382EC2170CA366DE181767E4C5343DE8 |<br />| %         | jsp  | *C22AB0FD8A289C7D337C9998B63B8EA8335E5F35 |<br />| localhost | jcc  | *C22AB0FD8A289C7D337C9998B63B8EA8335E5F35 |<br />+-----------+------+-------------------------------------------+<br />3 rows in set (0.01 sec)<br /><br />mysql&gt; exit<br />Bye<br /><br />D:\MySQL\bin&gt;mysql -u jcc -p<br />Enter password: **********<br />Welcome to the MySQL monitor.  Commands end with ; or \g.<br />Your MySQL connection id is 57 to server version: 4.1.12a-nt<br /><br />Type 'help;' or '\h' for help. Type '\c' to clear the buffer.<br /><br />mysql&gt; CREATE DATABASE jcc;<br />Query OK, 1 row affected (0.02 sec)<br /><br />mysql&gt; USE jcc;<br />Database changed<br />mysql&gt; CREATE TABLE user(<br />    -&gt;   id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,<br />    -&gt;   name VARCHAR(8) NOT NULL<br />    -&gt; );<br />Query OK, 0 rows affected (0.08 sec)<br /><br />mysql&gt; INSERT INTO user (name) VALUES ('Corebit');<br />Query OK, 1 row affected (0.03 sec)<br /><br />mysql&gt; INSERT INTO user (name) VALUES ('Ivan');<br />Query OK, 1 row affected (0.03 sec)<br /><br />mysql&gt; SELECT * FROM user;<br />+----+---------+<br />| id | name    |<br />+----+---------+<br />|  1 | Corebit |<br />|  2 | Ivan    |<br />+----+---------+<br />2 rows in set (0.00 sec)<br /><br />mysql&gt;<br /><br />二.配置Tomcat连接池<br /><br />Tomcat5.0进行如下配置：<br /><br />在&lt;%TOMCAT_HOME%&gt;\conf\server.xml的&lt;Host&gt;...&lt;/Host&gt;之间加入以下代码：<br /><br />&lt;Context path="" docBase="D:/jcc"<br />        debug="5" reloadable="true" crossContext="true"&gt;<br /><br />  &lt;Logger className="org.apache.catalina.logger.FileLogger"<br />             prefix="localhost_DBTest_log." suffix=".txt"<br />             timestamp="true"/&gt;<br /><br />  &lt;Resource name="jdbc/JCC"<br />               auth="Container"<br />               type="javax.sql.DataSource"/&gt;<br /><br />  &lt;ResourceParams name="jdbc/JCC"&gt;<br />    &lt;parameter&gt;<br />      &lt;name&gt;factory&lt;/name&gt;<br />      &lt;value&gt;org.apache.commons.dbcp.BasicDataSourceFactory&lt;/value&gt;<br />    &lt;/parameter&gt;<br /><br />    &lt;parameter&gt;<br />      &lt;name&gt;maxActive&lt;/name&gt;<br />      &lt;value&gt;100&lt;/value&gt;<br />    &lt;/parameter&gt;<br /><br />    &lt;parameter&gt;<br />      &lt;name&gt;maxIdle&lt;/name&gt;<br />      &lt;value&gt;30&lt;/value&gt;<br />    &lt;/parameter&gt;<br /><br />    &lt;parameter&gt;<br />      &lt;name&gt;maxWait&lt;/name&gt;<br />      &lt;value&gt;10000&lt;/value&gt;<br />    &lt;/parameter&gt;<br /><br />    &lt;parameter&gt;<br />     &lt;name&gt;username&lt;/name&gt;<br />     &lt;value&gt;jcc&lt;/value&gt;<br />    &lt;/parameter&gt;<br />    &lt;parameter&gt;<br />     &lt;name&gt;password&lt;/name&gt;<br />     &lt;value&gt;jsp.com.cn&lt;/value&gt;<br />    &lt;/parameter&gt;<br /><br />    &lt;parameter&gt;<br />       &lt;name&gt;driverClassName&lt;/name&gt;<br />       &lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;<br />    &lt;/parameter&gt;<br /><br />    &lt;parameter&gt;<br />      &lt;name&gt;url&lt;/name&gt;<br />      &lt;value&gt;jdbc:mysql://localhost/jcc&lt;/value&gt;<br />    &lt;/parameter&gt;<br />  &lt;/ResourceParams&gt;<br />&lt;/Context&gt;<br /><br />Tomcat5.5进行如下配置：<br /><br />在&lt;%TOMCAT_HOME%&gt;\conf\server.xml的&lt;Host&gt;...&lt;/Host&gt;之间加入以下代码：<br /><br />&lt;Context path="" docBase="D:/jcc"<br />        debug="5" reloadable="true" crossContext="true"&gt;<br /><br />  &lt;Resource name="jdbc/JCC" auth="Container" type="javax.sql.DataSource"<br />               maxActive="100" maxIdle="30" maxWait="10000"<br />               username="jcc" password="jsp.com.cn" driverClassName="com.mysql.jdbc.Driver"<br />               url="jdbc:mysql://localhost/jcc"/&gt;<br /><br />&lt;/Context&gt;<br /><br />三.在&lt;%wwwroot%&gt;/下，新建MySQL数据库连接文件Select.jsp<br /><br />　　Select.jsp源码如下：<br /><br />&lt;%@page contentType="text/html;charset=gb2312"%&gt;<br />&lt;%@page import="java.sql.*"%&gt;<br />&lt;%@page import="javax.sql.DataSource"%&gt;<br />&lt;%@page import="javax.naming.*"%&gt;<br />&lt;html&gt;<br />&lt;body&gt;<br />&lt;%<br />try{<br />  Context initCtx=new InitialContext();<br />  DataSource db = (DataSource)initCtx.lookup("java:comp/env/jdbc/JCC");<br />  Connection conn = db.getConnection();<br />  Statement stmt = conn.createStatement();<br />  ResultSet rs = stmt.executeQuery("SELECT * FROM user");<br />  out.println("User-list"+"&lt;br&gt;");<br />  while(rs.next()){<br />    out.print(rs.getString(1)+" ");<br />    out.print(rs.getString(2)+"&lt;br&gt;");<br />  }<br />  rs.close();<br />  stmt.close();<br />  conn.close();<br />}<br />catch(Exception e){<br />  out.print(e);<br />}<br />%&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;<br /><br />四.运行http://localhost/Select.jsp，显示结果如下：<br /><br />User-list<br />1 Corebit<br />2 Ivan<br /><br />　　则表示数据库连接成功！恭喜！恭喜！<br /><br />　　否则请检查数据库连接器版本，出错可能性比较高！<br /><br />　　＊注：<br /><br />　　Tomcat连接池中，部分参数说明如下：<br /><br />　　maxActive="100"　　&lt;!--最大活跃连接数，这里取值为100，表示同时最多有100个数据库连接。设为0表示无限制。--&gt;<br /><br />　　maxIdle="30"       &lt;!--最大的空闲连接数，这里取值为30，表示即使没有数据库连接时依然可以保持30个空闲的连接，而不被清除，随时处于待命状态。设为0表示无限制。--&gt;<br /><br />　　maxWait="10000"    &lt;!--最大建立连接等待时间。如果超过此时间将接到异常。这里设置为10000，表示10秒后超时。设为-1表示无限制，直到超时为止。--&gt;<br /><br />    jdbc:mysql://localhost/jcc    &lt;!--数据库连接字符串,同jdbc:mysql://localhost:3306/jcc?autoReconnect=true--&gt;<br /><br />    PS：如果最大数据库活跃连接数过大，可想而知，内存占用量是非常惊人的！如果空闲连接数过大，则资源利用率低，连接池长期未释放，可导致连接池结点异常。所以选好maxActive和maxIdle是连接池性能的关键因素，当然这取决于服务器环境。<br /><br />　　＊附：<br /><br />　　连接池运作原理：<br /><br />　　在实际应用开发中，特别是在WEB应用系统中，如果JSP、Servlet或EJB使用JDBC直接访问数据库中的数据，每一次数据访问请求都必须经历建立数据库连接、打开数据库、存取数据和关闭数据库连接等步骤，而连接并打开数据库是一件既消耗资源又费时的工作，如果频繁发生这种数据库操作，系统的性能必然会急剧下降，甚至会导致系统崩溃。数据库连接池技术是解决这个问题最常用的方法，在许多应用程序服务器（例如：Weblogic,WebSphere,JBoss）中，基本都提供了这项技术，无需自己编程，但是，深入了解这项技术是非常必要的。<br /><br />　　数据库连接池技术的思想非常简单，将数据库连接作为对象存储在一个Vector对象中，一旦数据库连接建立后，不同的数据库访问请求就可以共享这些连接，这样，通过复用这些已经建立的数据库连接，可以克服上述缺点，极大地节省系统资源和时间。<br /><br />　　数据库连接池的主要操作如下：<br /><br />　　（1）建立数据库连接池对象（服务器启动）。<br /><br />　　（2）按照事先指定的参数创建初始数量的数据库连接（即：空闲连接数）。<br /><br />　　（3）对于一个数据库访问请求，直接从连接池中得到一个连接。如果数据库连接池对象中没有空闲的连接，且连接数没有达到最大（即：最大活跃连接数），创建一个新的数据库连接。<br /><br />　　（4）存取数据库。<br /><br />　　（5）关闭数据库，释放所有数据库连接（此时的关闭数据库连接，并非真正关闭，而是将其放入空闲队列中。如实际空闲连接数大于初始空闲连接数则释放连接）。<br /><br />　　（6）释放数据库连接池对象（服务器停止、维护期间，释放数据库连接池对象，并释放所有连接）。<br /><br />　　希望本文能对你使用Tomcat连接池连接MySQL数据库有所帮助！<br /><br />参考文献：<br />http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-datasource-examples-howto.html<br />http://jakarta.apache.org/tomcat/tomcat-5.5-doc/jndi-datasource-examples-howto.html<br /><br /><img src ="http://www.blogjava.net/jelver/aggbug/88127.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-12-16 11:08 <a href="http://www.blogjava.net/jelver/articles/88127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一篇介绍标签库很详细的文章，可以做为参考手册 (zhuan)</title><link>http://www.blogjava.net/jelver/articles/73954.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Mon, 09 Oct 2006 01:13:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/73954.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/73954.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/73954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/73954.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/73954.html</trackback:ping><description><![CDATA[
		<p>摘要：</p>
		<p>标准的JSP 标记可以调用JavaBeans组件或者执行客户的请求，这大大降低了JSP开发的复杂度和维护量。JSP技术也允许你自定义taglib，其实换句话说，taglib可以看成是对JSP标记的一种扩展，正如xml是对html的一种扩展一样。taglib通常定义在tag标签库中，这种标签库存放着你自己定义的tag标签。简而言之，如果使用taglib，那么你可以设计自己的JSP标记！</p>
		<p>一般来说，自定义tag标签主要用于操作隐藏对象、处理html提交表单、访问数据库或其它企业级的服务，诸如邮件和目录操作等等。自定义tag标签的使用者一般都是那些对java编程语言非常精通，而且对数据访问和企业级服务访问都非常熟悉的程序员，对于HTML设计者来说，使得他可以不去关注那些较复杂的商业逻辑，而将精力放在网页设计上。同时，它也将库开发者和库使用者进行合理分工，自定义tag标签将那些重复工作进行封装，从而大大提高了生产力，而且可以使得tag库可用于不同的项目中，完美地体现了软件复用的思想。</p>
		<p>在这篇文章中，我们主要讨论：</p>
		<p>· 什么是自定义tag标签？</p>
		<p>· 怎么使用tag标签？</p>
		<p>o 声明要使用的tag库</p>
		<p>o 找到与之对应的tag处理类</p>
		<p>o tag标签的类型</p>
		<p>· 自定义tag标签</p>
		<p>o tag处理类</p>
		<p>o tag库描述</p>
		<p>o tag标签示例</p>
		<p>o 带属性的tag</p>
		<p>o 带body的tag</p>
		<p>o 定义了脚本变量的tag</p>
		<p>o 具有协作关系的tag</p>
		<p>· 自定义tag标签</p>
		<p>o 一个迭代tag的例子</p>
		<p>o 一个模板tag库</p>
		<p>o tag处理类到底是怎样被调用的？</p>
		<p>
				<br />什么是自定义的tag?</p>
		<p>一个自定义的tag标签是用户定义的一种JSP标记。当一个含有自定义的tag标签的JSP页面被jsp引擎编译成servlet时，tag标签被转化成了对一个称为tag处理类的对象进行的操作。于是当JSP页面被jsp引擎转化为servlet后，实际上tag标签被转化成为了对tag处理类的操作。</p>
		<p>自定义tag标签有很多特色，诸如：</p>
		<p>· 可以在JSP页面中自定义tag标签的属性</p>
		<p>· 访问JSP页面中的所有对象</p>
		<p>· 可以动态地修改页面输出</p>
		<p>· 彼此这间可以相互通信。你可以先创建一个JavaBeans组件，然后在一个tag中调用此JavaBeans组件，同时可以在另一个tag中调用它。</p>
		<p>· tag允许相互嵌套，可以在一个JSP页面中完成一些复杂的交互。</p>
		<p>
				<br />使用tag标签</p>
		<p>
				<br />本节主要描述怎样在JSP页面中使用tag标签，以及tag标签的不同类型。</p>
		<p>要使用tag标签，JSP程序员必须做2件事：</p>
		<p>· 声明此tag标签的tag库</p>
		<p>· 实现此tag标签</p>
		<p>声明tag标签所在的tag库</p>
		<p>如果要使用tag标签，则应用JSP的taglib指示符来指定其tag库（注意：taglib要在在使用此tag标签之前声明）</p>
		<p>&lt;%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %&gt;</p>
		<p>uri属性定义了唯一的标签库描述(以下简称TLD)，它可以是直接是tld文件名或一个独一无二的名字。prefix是用来区别其它TLD中和本TLD中有重名的tag的一种手段。</p>
		<p>TLD必须以.tld作为扩展名，并且存放在当前应用的WEB-INF目录或其子目录下。你可以通过它的文件名直接引用它，也可以通过别的方式间接地引用它。</p>
		<p>以下taglib指示符直接引用一个TLD：</p>
		<p>&lt;%@ taglib uri=”/WEB-INF/tutorial-template.tld” prefix=”tt” %&gt;</p>
		<p>以下的taglib指示符通过一个逻辑名称间接地引用一个TLD：</p>
		<p>&lt;%@ taglib uri=”/tutorial-template” prefix=”tt” %&gt;</p>
		<p>如果是间接引用TLD的话，那你必须还要在web.xml中定义此逻辑名称与tld文件之间的映射，具体做法是在web.xml中加入一个名为taglib的元素：</p>
		<p>&lt;taglib&gt;</p>
		<p>&lt;taglib-uri&gt;/tutorial-template&lt;/taglib-uri&gt;</p>
		<p>&lt;taglib-location&gt;</p>
		<p>/WEB-INF/tutorial-template.tld</p>
		<p>&lt;/taglib-location&gt;</p>
		<p>&lt;/taglib&gt;</p>
		<p>
				<br />实现此tag标签</p>
		<p>
				<br />为了实现tag标签，你有2种方法来存放tag处理类。一、让tag处理类以.class的方式存放于当前应用的WEB-INF/class子目录下，二、如果tag处理类是以JAR包的形式存在的话，那可以放在当前应用的WEB-INF/lib目录下，如果tag处理类要在多个应用中共享，那么它就应放在jsp服务器上的common/lib目录下，对于tomcat来说，就是tomcat/common/lib目录下。</p>
		<p>
				<br />tag标签类型</p>
		<p>
				<br />自定义的tag标签遵循XML语法。它有一个开始标记和一个结束标记，有的还有body（即文本节点）：</p>
		<p>&lt;tt:tag&gt;</p>
		<p>body</p>
		<p>&lt;/tt:tag&gt;</p>
		<p>
				<br />一个不带body的tag标签如下：</p>
		<p>&lt;tt:tag /&gt;</p>
		<p>
				<br />简单的tag标签</p>
		<p>一个没有body和属性的tag标签如下：</p>
		<p>&lt;tt:simple /&gt;</p>
		<p>
				<br />带属性的tag标签</p>
		<p>
				<br />自定义标签可以有自己的属性。属性一般在开始标记中定义，语法为 attr=”value”。属性的作用相当于自定义标签的一个参数，它影响着tag处理类的行为。你可以在TLD中详细定义它。</p>
		<p>你可以用一个String常量给一个属性赋值，也可以通过表达式给它赋值，如&lt;%= ...%&gt;。以struts为例，它的logic:present标签就是用的String常量来给属性赋值：</p>
		<p>&lt;loglic:present parameter = “Clear”&gt;</p>
		<p>而另一个标签logic:iterate是用表达式来给属性赋值：</p>
		<p>&lt;logci:iterate collection=”&lt;%= bookDB.getBooks() %&gt;”</p>
		<p>id=”book” type=”database.BookDetails”&gt;</p>
		<p>
				<br />带body的tag标签</p>
		<p>一个自定义标签可以包含其它自定义标签、脚本变量、HTML标记或其它内容。</p>
		<p>在下述例子中，此JSP页面使用了struts的logic:present标签，如果些标签定义了parameter=”Clear”的属性，则将清除购物车的内容，然后打印出一条信息：</p>
		<p>&lt;logic:present parameter=”Clear”&gt;</p>
		<p>&lt;% cart.clear(); %&gt;</p>
		<p>&lt;font color=”#ff0000” size=”+2”&gt;&lt;strong&gt;</p>
		<p>你选择了清除购物车！</p>
		<p>&lt;/strong&gt;&lt;/font&gt;</p>
		<p>&lt;/logic:present&gt;</p>
		<p>
				<br />到底是用属性还是用body来传递信息？</p>
		<p>如上所述，我们既可以通过属性，也可以通过body来传递信息。但一般来说，比较简单的类型，如字符串或简单表达式最好采用属性来传递信息。</p>
		<p>
				<br />定义脚本变量的tag标签</p>
		<p>所谓脚本变量，是指JSP中可以调用的变量或对象。它可由tag标签产生。以下示例阐述了一个tag标签定义了一个名为tx的由JNDI所定义的事务处理对象。脚本变量可以是ejb对象、事务、数据库连接等等：</p>
		<p>&lt;tt:lookup id=”tx” type=”UserTransaction” name=”java:comp/UserTransaction” /&gt;</p>
		<p>&lt;% tx.begin(); %&gt;</p>
		<p>...</p>
		<p>
				<br />具有协作关系的tag标签</p>
		<p>自定义tag标签之间可以通过共享对象来实现协作。在下述例子中，标签tag1创建了一个名为obj1的对象，在标签tag2仍可以重复使用obj。</p>
		<p>&lt;tt:tag1 attr1=”obj1” value1=”value” /&gt;</p>
		<p>&lt;tt:tag2 attr1=”obj1” /&gt;</p>
		<p>在以下这个例子当中，如果外层的tag标签创建了一个对象，那么其内层的所有tag标签都可以使用这个对象。由于这样产生的对象没有一个指定的名字，那么就可以将少重名的冲突。这个例子阐述了一系列协作的嵌套对象。</p>
		<p>&lt;tt:outerTag&gt;</p>
		<p>&lt;tt:innerTag /&gt;</p>
		<p>&lt;/tt:outerTag&gt;</p>
		<p>
		</p>
		<p>Tag处理类</p>
		<p>
				<br />Tag处理类必须实现Tag接口或BodyTag接口，不过现在一般都流行从TagSupport或BodyTagSupport类中继承，这些类或接口都可以在javax.servlet.jsp.tagext包中找到。</p>
		<p>当JSP引擎看到自己的JSP页面中包含有tag标签时，它会调用doStartTag方法来处理tag标签的开头，调用doEndTag方法来处理tag标签的结束。</p>
		<p>下表说明不同类型的tag所需要不同的处理过程：</p>
		<p>Tag处理类的方法 </p>
		<p>Tag标签类型<br />所调用的方法</p>
		<p>基本标签<br />doStartTag, doEndTag, release</p>
		<p>带属性的标签<br />doStartTag, doEndTag, set/getAttribute1...N, release</p>
		<p>带内容的标签<br />doStartTag, doEndTag, release</p>
		<p>带内容的标签，且内容重复循环<br />doStartTag, doAfterBody, doEndTag, release</p>
		<p>带内容的标签，且内容与JSP交互<br />doStartTag, doEndTag, release, doInitBody, doAfterBody, release</p>
		<p>一个tag处理类可以通过javax.servlet.jsp.PageContext来与JSP交互，通过javax.servlet.jsp.PageContext类，tag处理类可以访问JSP中的request、session和application对像。</p>
		<p>如果tag标签是互相嵌套的，那内层的tag处理类可以通过它的parent属性来访问上层的tag处理类。</p>
		<p>一般情况都将所有的tag处理类打成了JAR的包，以便于发布。</p>
		<p>
				<br />Tag库描述(简称TLD)</p>
		<p>
				<br />Tag库是用xml语言描述的，TLD包括了tag库中所有tag标签的描述，它一般用来被jsp服务器用来校验tag的语法正确性，或者被jsp开发者用来开发新的标签。</p>
		<p>TLD的文件扩展名必须为.tld，而且必须放在当前WEB应用的WEB-INF目录或其子目录中。</p>
		<p>一个TLD的内容的开头必须遵守标准的XML开头，用于描述DTD和xml的版本，例如：</p>
		<p>&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;</p>
		<p>&lt;!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "<a href="http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd</a>"&gt;<br />TLD必须以&lt;taglib&gt;来作为它的根元素，&lt;taglib&gt;的子元素如下表：</p>
		<p>
				<br />&lt;taglib&gt;的子元素 </p>
		<p>Element<br />Description</p>
		<p>tlib-version<br />Tag库的版本</p>
		<p>jsp-version<br />Tag库所需要的jsp的版本</p>
		<p>short-name<br />助记符，tag的一个别名（可选）</p>
		<p>uri<br />用于确定一个唯一的tag库</p>
		<p>display-name<br />被可视化工具（诸如Jbuilder）用来显示的名称（可选）</p>
		<p>small-icon<br />被可视化工具（诸如Jbuilder）用来显示的小图标（可选）</p>
		<p>large-icon<br />被可视化工具（诸如Jbuilder）用来显示的大图标（可选）</p>
		<p>description<br />对tag库的描述（可选）</p>
		<p>listener<br />参见下面listener元素</p>
		<p>tag<br />参见下面tag 元素</p>
		<p>Listener元素</p>
		<p>一个tag库可能定义一些类做为它的事件侦听类，这些类在TLD中被称为listener 元素，jsp服务器将会实例化这些侦听类，并且注册它们。Listener元素中有一个叫listener-class的子元素，这个元素的值必须是该侦听类的完整类名。</p>
		<p>Tag元素</p>
		<p>每个tag元素在tag库中都要指出它的名字、类名、脚本变量、tag的属性。其中脚本变量的值可以直接在TLD中定义或通过tag附加信息的类来取得。每个属性描述了这个属性是否可以省略，它的值是否可以通过&lt;%= …%&gt;这样的JSP语法来获得，以及属性的类型。</p>
		<p>每一个tag在TLD中对应一个tag元素，下表是tag元素的子元素：</p>
		<p>Tag元素的子元素</p>
		<p>元素名称<br />描述</p>
		<p>name<br />独一无二的元素名</p>
		<p>tag-class<br />Tag标签对应的tag处理类</p>
		<p>tei-class<br />javax.servlet.jsp.tagext.TagExtraInfo的子类，用于表达脚本变量（可选）</p>
		<p>body-content<br />Tag标签body的类型</p>
		<p>display-name<br />被可视化工具（诸如Jbuilder）用来显示的名称（可选）</p>
		<p>small-icon<br />被可视化工具（诸如Jbuilder）用来显示的小图标（可选）</p>
		<p>large-icon<br />被可视化工具（诸如Jbuilder）用来显示的大图标（可选）</p>
		<p>description<br />此tag标签的描述</p>
		<p>variable<br />提供脚本变量的信息（同tei-class）(可选)</p>
		<p>attribute<br />Tag标签的属性名</p>
		<p>以下章节介绍对于不同类型的tag，如何具体地实现它们。</p>
		<p>
				<br />简单的tag</p>
		<p>
				<br />tag处理类</p>
		<p>简单的tag处理类必须实现Tag接口的doStartTag和doEndTag方法。当jsp引擎碰到tag标签的开头时，doStartTag被调用，因为简单的tag没有body，所以此方法将返回 SKIP_BODY。当jsp引擎碰到tag标签的结尾时，doEndTag被调用，如果余下的页面还要被计算，那它将返回EVAL_PAGE,否则将会返回SKIP_PAGE。</p>
		<p>以下是例子：对于标签 &lt;tt:simple /&gt; ，它的tag处理类实现如下：</p>
		<p>
				<br />public SimpleTag extends TagSupport </p>
		<p>{ </p>
		<p>public int doStartTag() throws JspException </p>
		<p>{ </p>
		<p>try{ </p>
		<p>pageContext.getOut().print(“Hello.”); </p>
		<p>}catch(Exception e){ </p>
		<p>throw new JspTagException(“SimpleTag: “ + e.getMessage()); </p>
		<p>} </p>
		<p>return SKIP_BODY; </p>
		<p>} </p>
		<p>public int doEndTag() </p>
		<p>{ </p>
		<p>return EVAL_PAGE; </p>
		<p>} </p>
		<p>} </p>
		<p>
				<br />注意：如果tag标签没有内容的话，那必须定义body-content元素为空，例如</p>
		<p>&lt;body-content&gt;empty&lt;/body-content&gt;</p>
		<p>
				<br />带属性的tag标签</p>
		<p>
				<br />tag处理类</p>
		<p>对于tag标签的每个属性，你必须依照JavaBeans规范来定义其属性，以及get和set方法。以struts的logic:present 标签为例，</p>
		<p>&lt;logic:present parameter=”Clear”&gt;</p>
		<p>与此相应，此tag处理类应有如下方法和定义：</p>
		<p>
				<br />protected String parameter = null; </p>
		<p>public String getParameter() </p>
		<p>{ </p>
		<p>return this.parameter; </p>
		<p>} </p>
		<p>public void setParameter(String parameter) </p>
		<p>{ </p>
		<p>this.parameter = parameter; </p>
		<p>} </p>
		<p>
				<br />注意：如果你的属性名为id，而且你的tag处理类是从TagSupport类继承的，那你就不需要定义它的属性和set和get方法,因为他们早已在TagSupport被定义过了。</p>
		<p>Attribute元素</p>
		<p>对于tag标签的每个属性，你必须定义它是否必须的，它的值是否可以用诸如&lt;%= …%&gt;的表达式来获得，以及它的类型（可选），如果不指定它的类型，那就默认为是java.lang.String类型。如果rtexprvalue元素被定义为true或yes，那么在type元素中就定义了attribute的返回类型。</p>
		<p>&lt;attribute&gt;</p>
		<p>&lt;name&gt;attr1&lt;/name&gt;</p>
		<p>&lt;required&gt;true|false|yes|no&lt;/required&gt;</p>
		<p>&lt;rtexprvalue&gt;true|false|yes|no&lt;/rtexprvalue&gt;</p>
		<p>&lt;type&gt;attribute的返回类型（只用当rtexprvalue为真是才有效）&lt;/type&gt;</p>
		<p>&lt;/attribute&gt;</p>
		<p>如果tag的某个属性不是必须的，那tag处理类会自动提供一个缺省值。</p>
		<p>例如，在logic:present这个tag标签中定义了一个属性叫parameter，但它不是必须的，而且它可以被诸如&lt;%= …%&gt;的表达式来赋值。</p>
		<p>&lt;tag&gt;</p>
		<p>&lt;name&gt;present&lt;/name&gt;</p>
		<p>&lt;tag-class&gt;org.apache.struts.taglib.logic.PresentTag&lt;/tag-class&gt;</p>
		<p>&lt;body-content&gt;JSP&lt;/body-content&gt;</p>
		<p>…</p>
		<p>&lt;attribute&gt;</p>
		<p>&lt;name&gt;parameter&lt;/name&gt;</p>
		<p>&lt;required&gt;false&lt;/required&gt;</p>
		<p>&lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;</p>
		<p>&lt;/attribute&gt;</p>
		<p>…</p>
		<p>&lt;/tag&gt;</p>
		<p>
				<br />属性元素的校验</p>
		<p>
				<br />有关于tag标签的有效值可以从tag库的说明文档中获得，当JSP页面被编译时，jsp引擎会强制性地参照TLD中定义的规则进行检查。</p>
		<p>还有一个方法也可以进行属性元素的校验，就是先继承类TagExtraInfo，然后调用它的isValid方法。这个类同时也起到提供tag中定义的脚本变量信息的作用。</p>
		<p>IsValid方法通过TagData对象来传递属性信息，它包括着tag的所有的属性名－值的信息。由于校验发生在运行时刻，因此这个属性的值将被赋值为TagData.REQUEST_TIME_VALUE。</p>
		<p>例如tag标签&lt;tt:twa attr1=”value1” /&gt;在TLD中定义如下：</p>
		<p>&lt;attribute&gt;</p>
		<p>&lt;name&gt;attr1&lt;/name&gt;</p>
		<p>&lt;required&gt;true&lt;/required&gt;</p>
		<p>&lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;</p>
		<p>&lt;/attribute&gt;</p>
		<p>
				<br />这个定义说明了attr1能在运行期间被赋值。</p>
		<p>以下的isValid方法检查attr1属性的值是否属于Boolean类型。注意由于attr1能在运行刻被赋值，那么isValid方法必须检查tag用户是否对此tag进行了运行时刻赋值。</p>
		<p>
				<br />Public class TwaTEI extends TagExtraInfo </p>
		<p>{ </p>
		<p>public boolean isValid(Tagdata data) </p>
		<p>{ </p>
		<p>Object o = data.getAttribute(“attr1”); </p>
		<p>If(o != null &amp;&amp; o != TagData.REQUEST_TIME_VALUE) </p>
		<p>{ </p>
		<p>if( ( (String)o).toLowerCase().equals(“true”) ||  </p>
		<p>((String)o).toLowerCase().equals(“false”) ) </p>
		<p>return true; </p>
		<p>else </p>
		<p>return false; </p>
		<p>} </p>
		<p>else </p>
		<p>return true; </p>
		<p>} </p>
		<p>} </p>
		<p>
		</p>
		<p>带body的tag</p>
		<p>
		</p>
		<p>tag处理类</p>
		<p>
				<br />如果tag标签含有内容，那处理方式会略微有些不同，而且还要视tag处理类是否要与body交互的情况而定。如果要与body交互，那我们认为tag处理类要可能要对body进行操作。</p>
		<p>Tag处理类不与body交互</p>
		<p>如果tag处理类不与body交互，tag处理类应该实现Tag接口或从TagSupport中派生，如果body要被计算，那么doStartTag方法应返回 EVAL_BODY_INCLUDE，否则应返回SKIP_BODY。</p>
		<p>如果tag处理类要对body反复运算，则它应该实现IterationTag或从TagSupport中派生。如果tag处理类认为body还未计算完的话，那它的doStartTag方法和doAfterBody方法必须返回EVAL_BODY_AGAIN。</p>
		<p>Tag处理类与body交互</p>
		<p>如果tag处理类与body交互，那tag处理类应实现BodyTag接口或从BodyTagSupport中派生。这种tag处理类一般要实现doInitBody和doAfterBody方法。</p>
		<p>Body允许一些方法来读写它的内容。Tag处理类可以调用body内容的getString或getReader方法来从body中提取信息，也可用 writeOut(out) 方法来将body的内容写入到out对象中。其中out对象通过tag处理类的getPreviousOut方法来获得。</p>
		<p>如果body的内容需要被计算，那么doStartTag方法必须返回EVAL_BODY_BUFFERED，否则，它将返回 SKIP_BODY。</p>
		<p>doInitBody 方法</p>
		<p>此方法在body内容已经设好，但未被计算之前被调用。你可以根据不同的body内容来制定初始化策略。</p>
		<p>doAfterBody方法</p>
		<p>此方法在body内容已被计算后进行调用。</p>
		<p>和doStartTag方法一样，doAfterBody方法返回一个指示符指示是否要继续计算body，如果要继续计算，则doAfterBody应返回EVAL_BODY_BUFFERED，否则，它应返回SKIP_BODY。</p>
		<p>release 方法</p>
		<p>tag处理类调用此方法将它的状态重置为初始状态，并释放所有的私有资源。</p>
		<p>
				<br />以下的例子读取body的内容（其中含有一条sql语句），然后将它传递给一个对象，让它进行查询。由于此处body不须重新计算，所以doAfterBody会返回SKIP_BODY。</p>
		<p>
				<br />Public class QueryTag extends BodyTagSupport </p>
		<p>{ </p>
		<p>public int doAfterBody() throws JspTagException </p>
		<p>{ </p>
		<p>BodyContent bc = getBodyContent(); </p>
		<p>//将body的内容以字符串的格式提取出来 </p>
		<p>String query = bc.getString(); </p>
		<p>//清除body </p>
		<p>bc.clearBody(); </p>
		<p>try{ </p>
		<p>Statement stmt = connection.createStatement(); </p>
		<p>Result result = stmt.executeQuery(query); </p>
		<p>}catch(SQLException e){ </p>
		<p>throw new JspTagException(“queryTag: “ + e.getMessage() ); </p>
		<p>return SKIP_BODY; </p>
		<p>} </p>
		<p>} </p>
		<p>
				<br />body-content元素</p>
		<p>
				<br />由于tag可能会有body，你必须用body-content元素来指定body内容的类型：</p>
		<p>&lt;body-content&gt;JSP|tagdependent&lt;/body-content&gt;</p>
		<p>
				<br />如果body的内容是定制的或内部的tag、脚本元素、或HTML广本，则归类为JSP类型。其他的类型，比如上面代码所述的?D?D将sql statement类传给 query tag的这种类型应该标为tagdependent。</p>
		<p>注意：实际上body-content的值并不影响tag处理类对body内容的处理，它仅仅是被tag编辑工具用来描述此body的内容。</p>
		<p>
				<br />用tags定义脚本变量</p>
		<p>
		</p>
		<p>tag处理类</p>
		<p>
				<br />tag处理类负责创建或设置页面中定义的脚本变量，用pageContext.setAttribute(name,value,scope)或pageContext.setAttribute(name,value)方法来实现。一般来说，tag处理类通过脚本变量的名称来获取它，脚本变量的名称一般可用get方法来获得。</p>
		<p>如果脚本变量的值依赖于tag处理类中的上下文中某一对象，那它可用pageContext.getAttribute(name,scope)方法来找到那个对象。一般的处理过程是tag处理类先找到脚本变量，再对其进行处理，然后用pageContext.setAttribute(name,object)的方法来设置它的新值。</p>
		<p>对象的生存周期(scope)如下表：</p>
		<p>对象的生存周期表</p>
		<p>名字<br />可访问范围<br />生存周期</p>
		<p>page<br />当前页面<br />一直有效，除非页面向客户提交响应或重定向到一个新页面</p>
		<p>request<br />当前页面或当前页面重定向到的页面<br />一直有效，除非页面向客户提交响应</p>
		<p>session<br />当前页面或在同一浏览器窗口中的页面<br />一直有效,除非关闭当前浏览器、超时、网络故障</p>
		<p>application<br />整个web应用程序的所有请求<br />一直有效，除非发生网络故障、服务器故障</p>
		<p>提供关于脚本变量的信息</p>
		<p>以下示例定义了一个名为“book”的脚本变量，用来访问程序中关于书的信息：</p>
		<p>&lt;bean:define id=”book” name=”bookDB” property=”bookDetails” type=”database.BookDetails” /&gt;</p>
		<p>&lt;font color=”red” size=”+2” &gt;</p>
		<p>&lt;%= messages.getString(“CartRemoved”) %&gt;</p>
		<p>&lt;strong&gt;&lt;jsp:getProperty name=”book” property=”title” /&gt;&lt;/strong&gt;</p>
		<p>&lt;/font&gt;</p>
		<p>当包含此tag的JSP页面被编译时，jsp引擎会自动生成关于此book的同步的代码（同步可以避免几个客户同时访问此book时造成的冲突），要生成同步代码，jsp引擎需要知道此脚本变量的如下信息：</p>
		<p>· 脚本变量名称 </p>
		<p>· 脚本变量所属的类</p>
		<p>· 此脚本变量是否引用了一个新的或已存在的对象 </p>
		<p>· 此脚本变量的有效性</p>
		<p>有两种办法可以向jsp引擎提供关于脚本变量的信息：在TLD中定义variable子元素，或用tei-class子元素定义一个额外tag信息类。用variable最简单，但可能降低了一些灵活性。</p>
		<p>Variable元素</p>
		<p>Variable元素有如下子元素：</p>
		<p>· name-given ?D?D 给出的名字，是一个常量</p>
		<p>· name-from-attribute?D?D 属性名，在编译时给出的属性名 </p>
		<p>name-given或name-from-attribute两者必须选一，但以下子元素是可选的：</p>
		<p>· variable-class?D?D变量的类型，缺省为java.lang.String。 </p>
		<p>· declare?D?D此脚本变量是否引用了一个新对象，缺省为True。</p>
		<p>· scope?D?D脚本变量的范围，缺省为NESTED。下表描述了scope的几种类型：</p>
		<p>脚本变量的有效范围 </p>
		<p>值<br />有效性<br />方法 </p>
		<p>NESTED<br />在tag标签的开始和结束之间<br />如果tag处理类实现BodyTag接口，则在doInitBody和doAfterBody中调用，否则在doStartTag中调用</p>
		<p>AT_BEGIN<br />从tag标签的开始一直到页面结束<br />如果tag处理类实现BodyTag接口，则在doInitBody、doAfterBody和doEndTag中调用，否则在doStartTag和doEndTag中调用</p>
		<p>AT_END<br />从tag标签的结束一直到页面结束<br />在doEndTag中调用</p>
		<p>以struts为例，它的bean:define标签的实现遵循JSP1.1规范，此规范要求使用额外tag信息类来定义脚本变量。Variable元素是JSP1.2规范中加入的。以bean:define标签为例，你可以定义如下variable元素：</p>
		<p>&lt;tag&gt;</p>
		<p>&lt;variable&gt;</p>
		<p>&lt;name-from-attribute&gt;id&lt;/name-from-attribute&gt;</p>
		<p>&lt;variable-class&gt;database.BookDetails&lt;/variable-class&gt;</p>
		<p>&lt;declare&gt;true&lt;/declare&gt;</p>
		<p>&lt;scope&gt;AT_BEGIN&lt;/scope&gt;</p>
		<p>&lt;/variable&gt;</p>
		<p>&lt;/tag&gt;</p>
		<p>额外tag信息类</p>
		<p>如果要定义一个额外tag信息类，你要继承javax.servlet.jsp.TagExtraInfo类。一个TagExtraInfo类必须实现getVariableInfo方法，此方法返回一个叫VariableInfo的数组类，它包括如下信息：</p>
		<p>· 变量名</p>
		<p>· 变量所属类名 </p>
		<p>· 此变量是否引用了一个新对象</p>
		<p>· 此变量的有效范围</p>
		<p>jsp引擎将一个名为data的参数传给getVariableInfo方法，data中包括tag标签中的所有“属性名?D?D属性值”对。它可以用来向VariableInfo对象提供脚本变量的名字和类名。</p>
		<p>以struts为例，它在bean:define标签中定义了一个名为DefineTei的额外tag信息类，用来向脚本变量提供信息。由于脚本变量的名称（book）和类名（database.BookDetails）是通过tag标签的属性来传递的，它们一般定义在VariableInfo的构建代码中，并且可用data.getAttributeString方法来得到这些信息。如果要允许book脚本变量能在从tag开始直到整个JSP页面结束的范围内都可用的话，那它的范围应设为AT_BEGIN。如下所示：</p>
		<p>
				<br />public class DefineTei extends TagExtraInfo </p>
		<p>{ </p>
		<p>public VariableInfo[] getVariableInfo(TagData data) </p>
		<p>{ </p>
		<p>String type = data.getAttributeString(“type”); </p>
		<p>If( type == null) </p>
		<p>type = “java.lang.Object”; </p>
		<p>return new VariableInfo[] { </p>
		<p>new VariableInfo(data.getAttributeString(“id”),  </p>
		<p>type, </p>
		<p>true, </p>
		<p>VariableInfo.AT_BEGIN) </p>
		<p>}; </p>
		<p>} </p>
		<p>} </p>
		<p>
				<br />注意：关于额外tag信息类的类名必须要在TLD中的tag标签下的tei-class子元素中定义。因此，DefineTei的tei-class中的定义看起来如下：<br />&lt;tei-class&gt;<br />org.apache.struts.taglib.bean.DefineTagTei<br />&lt;/tei-class&gt;</p>
		<p>
				<br />具有协作关系的tag</p>
		<p>
				<br />tag通过共享对象来进行协作，JSP技术支持2种方式的对象共享。</p>
		<p>第一种方法是使用pageContext对象进行对象的共享（可支持JSP页面和tag处理类之间的共享），如果在一个tag处理类中要调用由另一个tag处理类创建的对象，可调用pageContext.getAttribute(name, scope)方法。</p>
		<p>第二各方式的共享是对于tag之间有嵌套关系而言的，外层的tag所创建的对象对于内层的tag来说是可以共用的。这种形式的共享的好处是减少了可能存在的重名冲突。</p>
		<p>要访问一个嵌套tag创建的对象，tag处理类必须先找到此嵌套tag对象，可用TagSupport的静态方法 TagSupport.findAncestorWithClass(from, class)或TagSupport.getParent方法。