﻿<?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-灵魂-放水-随笔分类-J2EE</title><link>http://www.blogjava.net/zqli/category/8355.html</link><description>为学日益，为道日损。</description><language>zh-cn</language><lastBuildDate>Wed, 17 Mar 2010 22:11:53 GMT</lastBuildDate><pubDate>Wed, 17 Mar 2010 22:11:53 GMT</pubDate><ttl>60</ttl><item><title>SpringSide3.2.2开发web初探及MySQL5.1.* UTF-8乱码、自带命令行无法插入中文问题解决。</title><link>http://www.blogjava.net/zqli/archive/2010/03/17/315672.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Wed, 17 Mar 2010 06:44:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2010/03/17/315672.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/315672.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2010/03/17/315672.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/315672.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/315672.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 近期想使用SpringSide开发Web应用，我用的是最新版3.2.2。应该说，入手SS3，是看了<a href="http://www.blogjava.net/youxia">海边沫沫</a>所写的一系列文章，尤其以SS3系列为主。去<a href="http://www.springside.org.cn/">官网</a>下载SS3.2.2，完成一系列变量的配置，并解压安装SS后。开始创建项目，发现使用BIN\new-project.bat创建出来的project文件夹下，并没有lib文件夹，此时，通过点击所创建工程目录下的BIN\init-jar.bat，可以初始化项目所需要的jar文件。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一切就绪，用Eclipse import工程，发现有红叉，add jars之后，红叉消失。由于本身不喜欢使用SS3自带示例的数据库，按海边沫沫的方法将数据库迁移至MySQL，当然，因为SS3.2.2更新过，建表及插入数据语句也因此而不同。在未处理MySQL字符编码的及SS3已统一项目编码UTF-8的前提下，数据库迁移成功。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行project，发现登录之后，熟悉的中文乱码映入眼帘。此时，新建数据插入数据库之后，JSP浏览中文正常显示，说明需要配置MYSQL端。baidu了一阵之后，发现一般的解决方法是统一几处编码，于是打开MySQL安装目录下的my.ini，将client和mysqld下面改为default-character-set=utf8。重启MySQL之后，通过命令行建表成功，但在插入数据时却无法插入中文，百般无奈之下，再次baidu，发现有一种折中处理办法，也即注释掉MYSQL引入的新限制&#8220;sql-mode&#8221;，注释掉之后，发现命令行能插入中文数据，不提示错误，然而select却发现刚刚插入的中文数据为空。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不得不开始了第三组baidu，发现可以将：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [mysql]default-character-set=gbk<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #这个设置的是MySQL自带的命令行显示和输入的<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [mysqld]default-character-set=utf8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #这个设置决定MySQL的工作环境字符集，数据库继承MySQL设置的字符集，而表则继承数据库的字符集，字段则继承表的字符集。至于web端的统一UTF-8就不多说了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 解注释刚才的sql-mode，重启MySQL，打开MySQL自带的命令行，插入中文数据成功，select无乱码和为空白的情况，启动project，到此，乱码问题解决。<br />
<br />
<br />
<br />
<br />
</p>
<img src ="http://www.blogjava.net/zqli/aggbug/315672.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2010-03-17 14:44 <a href="http://www.blogjava.net/zqli/archive/2010/03/17/315672.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]大型互联网网站架构心得之一：分</title><link>http://www.blogjava.net/zqli/archive/2008/06/19/209138.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Thu, 19 Jun 2008 05:25:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2008/06/19/209138.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/209138.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2008/06/19/209138.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/209138.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/209138.html</trackback:ping><description><![CDATA[我们知道，对于一个大型网站来说，可伸缩性是非常重要的，怎么样在纵向和横向有良好的可伸缩性，就需要在做架构设计的时候考虑到一个分的原则，我想在多个方面说一下怎么分：
<p><font face="Verdana"><strong>首先是横向的分：<br />
</strong>1.&nbsp;大的网站化解为多个小网站：当我们一个网站有多个功能的时候，可以考虑把这个网站拆分成几个小模块，每一个模块可以是一个网站，这样的话我们到时候就可以很灵活地去把这些网站部署到不同的服务器上。<br />
2.&nbsp;静态动态分离：静态文件和动态文件最好分离开成2个网站，我们知道静态网站和动态网站对服务器来说压力的侧重不同，前者可能重IO后者重CPU，那么我们在选择硬件的时候也可以有侧重，而且静态和动态内容的缓存策略也不一样。典型的应用，我们一般会有独立的文件或图片服务器。<br />
3.&nbsp;按照功能来分：比如有一个模块是负责上传的，上传操作很消耗时间，如果和其它应用混在一起的话很可能，一点点访问就会使服务器瘫痪，这种特殊的模块应该分开。安全的不安全的也要分开，还需要考虑到以后SSL的购买。<br />
</font><font face="Verdana">4.&nbsp;我们不一定要全部用自己的服务器，搜索、报表可以依靠别人的服务，比如google的搜索和报表服务，自己做的不一定比得过别人，服务器带宽都省了。<br />
<br />
<br />
<strong>其次是纵向的分：<br />
</strong>1.&nbsp;文件也相当于数据库，IO的流量可能比数据库还大，这也算是纵向级别的访问，上传的文件图片一定要和WEB服务器分开。当然，数据库和网站都放在一个服务器上的很少了，这是最基本的。<br />
2.&nbsp;对于涉及到数据库访问的动态程序来说，我们可以使用一个中间层（所谓的应用层或逻辑层）来访问数据库（部署在独立的服务器上），最大的好处就是缓存和灵活性。缓存的内存占用比较大，我们要把它和网站进程分开，而且这样做我们可以很方便的去改变一些数据访问的策略，即使到时候数据库有分布的话在这里可以做一个调配工作，这样灵活性就很大了。还有好处是中间层可以做电线网通桥梁，可能网通访问双线再访问电信会比网通直接访问电信服务器快。<br />
<br />
<br />
有人说我不分，我可以做负载均衡，对，是可以的，但是如果分的话，同样的10台机器肯定比不分10台机器可以承受更多的访问量，而且对硬件的需求可能不会很高，因为知道需要哪个硬件特别好。争取让每一个服务期都不空闲，又都不是太忙，合理进行组合调整和扩充，这样的系统伸缩性就高了，能根据访问量来调整的前提就是之前有考虑到分，分的好处是灵活性、伸缩性、隔离性以及安全性。</font></p>
<p><font face="Verdana"><strong>对服务器来说，我们有几点是要长期观察的，任何一点都可能是瓶颈：</strong><br />
1.&nbsp;CPU：动态文件的解析需要比较多的CPU，CPU出现瓶颈就要看是不是哪个功能过长时间占用线程，如果是就分出去。或者就是每一个请求处理时间不长，但是访问量很高，那么就加服务器。CPU是好东西，不能让他干等，不做事情。<br />
2.&nbsp;内存：缓存从IIS进程独立出去，一般对WEB服务器来说内存不够的情况不是很多。内存比磁盘快，要合理利用。<br />
3.&nbsp;磁盘IO：用性能监视器找到哪些文件IO特别大，找到了就分到独立的一组文件服务器上去，或者直接做CDN。磁盘慢，大规模读取数据的应用靠缓存，大规模写入数据的应用可以靠队列来降低突发的并发。<br />
4.&nbsp;网络：我们知道，网络的通讯是比较慢的，比磁盘还慢，如果是做分布式缓存，分布式计算的话，要考虑到物理服务器之间网络通讯的时间，当然，在流量大了以后，这可以提高系统的接纳能力一个等级。静态内容可以借助CSD分担一部分，在做服务器假设的时候还要考虑中国特色的电信网通情况以及防火墙。<br />
<br />
</font><font face="Verdana"><strong>对SQL SERVER数据库服务器来说[UPDATE]：<br />
</strong>其实还是水平分割和纵向分割，一个二维表，水平分割就是横过来切一刀，纵向分割就是竖直切一刀：<br />
1、纵向分割就是，我们不同的应用可以分到不同的DB中，不同的实例中，或者说把某个拥有很多字段的表拆分成小表。<br />
2、横向分割就是，某些应用可能不负载，比如用户注册，但是用户表会非常大，可以把大表分开。可以采用表分区，数据存储在不同文件上，然后再部署到独立物理服务器增加IO吞吐以改善读写性能，土一点的做法就是自己定期把老的数据存档。表分区的另外一个优势可以增加数据查询速度，因为我们的页索引可以有多层了，就像一个文件夹中的文件不要太多，多分几层文件夹一样。<br />
3、还可以通过数据库镜像、复制订阅、事物日志，把读写分开到不同的镜像物理数据库上，一般来说够用，如果还不行可以用硬件来实现数据库的负载均衡。当然，对于BI，我们可能还会有数据仓库。<br />
<br />
架构上考虑到了这些之后，流量大了，就可以在这个的基础上再去调整或者做WEB服务器或者应用服务器的负载均衡。很多时候我们都是在重复发现问题-》找到瓶颈-》解决这个过程。<br />
<br />
</font><font face="Verdana"><strong>典型的架构如下：</strong><br />
<img alt="" src="http://www.cnblogs.com/images/cnblogs_com/lovecherry/asdh9awsdj.jpg" border="0" /><br />
<br />
动态WEB服务器配好点的CPU，静态WEB服务器和文件服务器磁盘好点<br />
应用服务器内存大点，缓存服务器也是，数据库服务器当然内存和CPU都要好<br />
<br />
<br />
请大家讨论。。。。<br />
<br />
转自http://blog.csdn.net/LoveCherry/archive/2008/06/19/2564096.aspx</font></p>
<img src ="http://www.blogjava.net/zqli/aggbug/209138.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2008-06-19 13:25 <a href="http://www.blogjava.net/zqli/archive/2008/06/19/209138.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]简单创建jar可执行文件.(入门)</title><link>http://www.blogjava.net/zqli/archive/2008/03/14/186330.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 14 Mar 2008 08:59:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2008/03/14/186330.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/186330.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2008/03/14/186330.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/186330.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/186330.html</trackback:ping><description><![CDATA[<p>
author:leo 发表于：2004年11月22日， 3:12:58
</p>
<p>
Email:ltdreamboy@yahoo.com.cn
</p>
<dl><dt>
<a href="http://wwwhomes.uni-bielefeld.de/tliu1/oldpages/wiki/JarUse.html#sec1">前言</a>
</dt><dt>
<a href="http://wwwhomes.uni-bielefeld.de/tliu1/oldpages/wiki/JarUse.html#sec2">jar文件的用法.</a>
</dt><dt>
<a href="http://wwwhomes.uni-bielefeld.de/tliu1/oldpages/wiki/JarUse.html#sec3">具体的打包例子</a>
</dt><dt>
<a href="http://wwwhomes.uni-bielefeld.de/tliu1/oldpages/wiki/JarUse.html#sec4">加入第三方类库</a>
</dt><dt>
<a href="http://wwwhomes.uni-bielefeld.de/tliu1/oldpages/wiki/JarUse.html#sec5">其它信息</a>
</dt></dl>
<h2>前言</h2>
曾经看过一篇关于创建jar可执行文件的文章,但是个人认为讲的过于复杂,尤其是其内涉及了package的概念,这样对于新手而言就有点难懂了,
本文主要是给新手指点迷津.错误之处还望高手指出.
<h2>jar文件的用法.</h2>
jar
<p>
用法：jar {ctxu}[vfm0Mi] [jar-文件] [manifest-文件] [-C 目录] 文件名 ...
</p>
<p>
选项：
</p>
<ul>
    <li>-c  创建新的存档
    </li>
    <li>-t  列出存档内容的列表
    </li>
    <li>-x  展开存档中的命名的（或所有的〕文件
    </li>
    <li>-u  更新已存在的存档
    </li>
    <li>-v  生成详细输出到标准输出上
    </li>
    <li>-f  指定存档文件名
    </li>
    <li>-m  包含来自标明文件的标明信息
    </li>
    <li>-0  只存储方式；未用ZIP压缩格式
    </li>
    <li>-M  不产生所有项的清单（manifest〕文件
    </li>
    <li>-i  为指定的jar文件产生索引信息
    </li>
    <li>-C  改变到指定的目录，并且包含下列文件：
    </li>
</ul>
<p>
如果一个文件名是一个目录，它将被递归处理。
</p>
<p>
清单（manifest〕文件名和存档文件名都需要被指定，按'm' 和 'f'标志指定的相同顺序。
</p>
<p>
示例1：将两个class文件存档到一个名为 'classes.jar' 的存档文件中：
</p>
<pre>       jar cvf classes.jar Foo.class Bar.class<br />
</pre>
示例2：用一个存在的清单（manifest）文件 'mymanifest' 将 foo/ 目录下的所有文件存档到一个名为 'classes.jar' 的存档文件中：
<pre>       jar cvfm classes.jar mymanifest -C foo/ .<br />
</pre>
<hr />
<h2>具体的打包例子</h2>
下面我们来看一个简单的归档例子:
<pre>2004-11-21  20:34    &lt;DIR&gt;          images<br />
2004-11-22  02:19             2,519 CellandMaskDialog.class<br />
2004-11-22  02:19               449 CellEx$1.class<br />
2004-11-22  02:19            13,523 CellEx.class<br />
2004-11-22  02:19             4,636 CellExAction.class<br />
2004-11-22  02:19             2,008 CellImagePanel.class<br />
2004-11-22  02:19             1,919 CellMask.class<br />
2004-11-22  02:19             2,009 CellMaskPanel.class<br />
2004-11-22  02:19             2,139 OptionDialog.class<br />
2004-11-22  02:19               592 PngFilter.class<br />
9 File(s)         29,794 bytes<br />
1 Dir(s)   1,102,630,912 bytes free<br />
</pre>
上面是某个目录中的class文件以及一个images子目录.
<pre>&gt;jar -cvf output.jar *.class images<br />
</pre>
<p>
<code>output.jar</code> 为归档后新生成的 <code>.jar</code> 文件， <code>*.class images</code> 为放入归档中的文件。
即是说， 将*.class以及images目录放入一个名为output.jar的文件当中(即归档文件)。如果你有多个目录则:
</p>
<pre>&gt;jar -cvf output.jar *.class images folder1 folder2 foldern<br />
</pre>
上面描述的是非可执行jar文件,如果你用的是Microsoft windows系统,想在Microsoft windows系统中通过双击执行,
那么请看下面:
我们需要写一个文件名为MANIFEST.MF文件:
一个MANIFEST.MF文件的例子:
<pre>Manifest-Version: 1.0<br />
Created-By: 1.4.2_05 (Sun Microsystems Inc.)<br />
Main-Class: CellEx<br />
</pre>
请将注意力放在第3行, <code>CellEx</code> 为你的主执行类,即有包含main函数的类,例如你的主执行类是 <code>MyClass</code> ,则上例中替换 <code>CellEx</code> 为 <code>MyClass</code>.
<p>
好了,所有条件都具备了,现在我们来看看如何创建你的可执行jar文件,为了显得更加清晰,现在我们的目录结构如下:
</p>
<pre>2004-11-22  02:15                91 MANIFEST.MF<br />
2004-11-21  20:34    &lt;DIR&gt;          images<br />
2004-11-22  02:19             2,519 CellandMaskDialog.class<br />
2004-11-22  02:19               449 CellEx$1.class<br />
2004-11-22  02:19            13,523 CellEx.class<br />
2004-11-22  02:19             4,636 CellExAction.class<br />
2004-11-22  02:19             2,008 CellImagePanel.class<br />
2004-11-22  02:19             1,919 CellMask.class<br />
2004-11-22  02:19             2,009 CellMaskPanel.class<br />
2004-11-22  02:19             2,139 OptionDialog.class<br />
2004-11-22  02:19               592 PngFilter.class<br />
10 File(s)         29,794 bytes<br />
1 Dir(s)   1,102,630,912 bytes free<br />
</pre>
注意多了一个我们自己创建的 <strong><em>MANIFEST.MF</em></strong> 文件.
<p>
开始创建可执行jar文件(注意在此我们加了 <code>m</code> 参数,以及 <code>MANIFEST.MF</code> 文件,请注意 <code>MANIFEST.MF</code> 文件的位置,在 <code>output.jar</code> 文件后):
</p>
<pre>&gt;jar -cvfm output.jar MANIFEST.MF *.class images<br />
</pre>
好了现在试试双击你的jar文件,怎么样,可以运行了吧,是不是很令人兴奋呢?:-)
<p>
如果在linux等其它系统,你需要通过命令行:
&gt;java -jar output.jar
来执行.
</p>
<h2>加入第三方类库</h2>
有时候我们的程序用到了第三方的类库，即不是JDK内的类，这是我们该如何把它加入到jar文件中呢？
<p>
下例中我们加入了一个第三方类库
</p>
<pre>Class-Path: lib/jfig2.jar<br />
Main-Class: CellEx<br />
</pre>
即告诉你的程序到 <code>lib</code> 目录下去找被用到的第三方类库。
<h2>其它信息</h2>
<a href="http://java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html">http://java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html</a> JAR File Specification
<a href="http://java.sun.com/j2se/1.4.2/docs/guide/jar/jarGuide.html">http://java.sun.com/j2se/1.4.2/docs/guide/jar/jarGuide.html</a> JAR File Overview
<a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/jar.html">http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/jar.html</a> Jar tool reference page for Windows
<img src ="http://www.blogjava.net/zqli/aggbug/186330.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2008-03-14 16:59 <a href="http://www.blogjava.net/zqli/archive/2008/03/14/186330.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Java RPC通信机制之RMI</title><link>http://www.blogjava.net/zqli/archive/2008/03/11/185421.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Tue, 11 Mar 2008 08:13:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2008/03/11/185421.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/185421.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2008/03/11/185421.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/185421.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/185421.html</trackback:ping><description><![CDATA[<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 宋体">大卫注</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">1</span><span style="font-size: 10pt; color: green; font-family: 宋体">：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 宋体">写完</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">CORBA</span><span style="font-size: 10pt; color: green; font-family: 宋体">系列后，本想接着写写其它几种典型的远程通信协议：</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">RMI</span><span style="font-size: 10pt; color: green; font-family: 宋体">、</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">XML-RPC</span><span style="font-size: 10pt; color: green; font-family: 宋体">、</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">SOAP</span><span style="font-size: 10pt; color: green; font-family: 宋体">，但由于工作的原因，加之房子装修等麻烦事，一直没有心情动笔。今天接到装修公司老板电话说开工证要晚几天办下来，要停工</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">4-5</span><span style="font-size: 10pt; color: green; font-family: 宋体">天，狂怒后突然有了静下心来完成原本想写的东西的想法，既来之，则安之（</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">i.e.</span><span style="font-size: 10pt; color: green; font-family: 宋体">郁闷啊，郁闷啊，就习惯了</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">...</span><span style="font-size: 10pt; color: green; font-family: 宋体">）</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 宋体">大卫注</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">2</span><span style="font-size: 10pt; color: green; font-family: 宋体">：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 宋体">这个系列基本上是一份笔记，没有加入太多我自己的东西，仅仅记录了自己在使用过程中遇到的问题，及其解决办法。</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-family: 'Courier New'"><font size="3">&nbsp;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">在传统的</span><span style="font-size: 11pt; font-family: 'Courier New'">RPC</span><span style="font-size: 11pt; font-family: 宋体">编程接口逐渐淡出人们视线的同时，新的、更便于使用且附加了更多特性的</span><span style="font-size: 11pt; font-family: 'Courier New'">RPC</span><span style="font-size: 11pt; font-family: 宋体">编程接口也不断涌现，</span><span style="font-size: 11pt; font-family: 'Courier New'">CORBA</span><span style="font-size: 11pt; font-family: 宋体">作为分布式对象计算技术的典范，在很长一段时间内极大地吸引了大家的注意，但是由于</span><span style="font-size: 11pt; font-family: 'Courier New'">CORBA</span><span style="font-size: 11pt; font-family: 宋体">规范试图覆盖过多的内容，使得</span><span style="font-size: 11pt; font-family: 'Courier New'">CORBA</span><span style="font-size: 11pt; font-family: 宋体">显得过于复杂，也极大地限制了</span><span style="font-size: 11pt; font-family: 'Courier New'">CORBA</span><span style="font-size: 11pt; font-family: 宋体">的应用范围，本系列将向大家介绍几种轻量级的，更适于在</span><span style="font-size: 11pt; font-family: 'Courier New'">Java</span><span style="font-size: 11pt; font-family: 宋体">开发中使用的</span><span style="font-size: 11pt; font-family: 'Courier New'">RPC</span><span style="font-size: 11pt; font-family: 宋体">编程接口：</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">、</span><span style="font-size: 11pt; font-family: 'Courier New'">XML-RPC</span><span style="font-size: 11pt; font-family: 宋体">、</span><span style="font-size: 11pt; font-family: 'Courier New'">SOAP</span><span style="font-size: 11pt; font-family: 宋体">。</span></p>
<h2 style="margin: 12pt 0in 3pt"><em>RMI<span style="font-family: 宋体">（</span>Remote Method Invocation<span style="font-family: 宋体">）</span></em></h2>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">与本系列将介绍的其它两种</span><span style="font-size: 11pt; font-family: 'Courier New'">RPC</span><span style="font-size: 11pt; font-family: 宋体">编程接口不同，</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">（</span><span style="font-size: 11pt; font-family: 'Courier New'">Remote Method Invocation</span><span style="font-size: 11pt; font-family: 宋体">）显得有些老旧，它是在</span><span style="font-size: 11pt; font-family: 'Courier New'">Java-IDL</span><span style="font-size: 11pt; font-family: 宋体">加入</span><span style="font-size: 11pt; font-family: 'Courier New'">J2SE</span><span style="font-size: 11pt; font-family: 宋体">之前被引入的。</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">开发流程与</span><span style="font-size: 11pt; font-family: 'Courier New'">CORBA</span><span style="font-size: 11pt; font-family: 宋体">如出一辙（从出现的时间上无法确定</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">是否是按照</span><span style="font-size: 11pt; font-family: 'Courier New'">CORBA</span><span style="font-size: 11pt; font-family: 宋体">规范定制的），因此，其开发过程相对比较烦琐，但是由于</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">是</span><span style="font-size: 11pt; font-family: 'Courier New'">EJB</span><span style="font-size: 11pt; font-family: 宋体">的基础，因此，它在</span><span style="font-size: 11pt; font-family: 'Courier New'">Java</span><span style="font-size: 11pt; font-family: 宋体">开发中具有十分重要的地位。</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">以下是创建远程方法调用的</span><span style="font-size: 11pt; font-family: 'Courier New'">5</span><span style="font-size: 11pt; font-family: 宋体">个步骤：</span></p>
<p style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><span style="font-size: 11pt; font-family: 'Courier New'">1.<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp; </span></span><span style="font-size: 11pt; font-family: 宋体">定义一个扩展了</span><span style="font-size: 11pt; font-family: 'Courier New'">Remote</span><span style="font-size: 11pt; font-family: 宋体">接口的接口，该接口中的每一个方法必须声明它将产生一个</span><span style="font-size: 11pt; font-family: 'Courier New'">RemoteException</span><span style="font-size: 11pt; font-family: 宋体">异常；</span></p>
<p style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><span style="font-size: 11pt; font-family: 'Courier New'">2.<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp; </span></span><span style="font-size: 11pt; font-family: 宋体">定义一个实现该接口的类；</span></p>
<p style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><span style="font-size: 11pt; font-family: 'Courier New'">3.<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp; </span></span><span style="font-size: 11pt; font-family: 宋体">使用</span><span style="font-size: 11pt; font-family: 'Courier New'">rmic</span><span style="font-size: 11pt; font-family: 宋体">程序生成远程实现所需的存根和框架；</span></p>
<p style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><span style="font-size: 11pt; font-family: 'Courier New'">4.<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp; </span></span><span style="font-size: 11pt; font-family: 宋体">创建一个客户程序和服务器进行</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">调用；</span></p>
<p style="margin: 0in 0in 0pt 0.25in; text-indent: -0.25in"><span style="font-size: 11pt; font-family: 'Courier New'">5.<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp; </span></span><span style="font-size: 11pt; font-family: 宋体">启动</span><span style="font-size: 11pt; font-family: 'Courier New'">rmiregistry</span><span style="font-size: 11pt; font-family: 宋体">并运行自己的服务程序和客户程序。</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">下面举一个简单、而且被无数次引用的例子：</span><span style="font-size: 11pt; font-family: 'Courier New'">Echo</span><span style="font-size: 11pt; font-family: 宋体">。</span></p>
<h3 style="margin: 12pt 0in 3pt">1<span style="font-family: 宋体">、定义</span>Echo<span style="font-family: 宋体">接口</span></h3>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 'Courier New'">//Echo.java</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 'Courier New'">//The Echo remote interface</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">package demo.rmi;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">import java.rmi.*;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">public</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">interface</span> Echo extends Remote {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String echo(String msg) throws RemoteException;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<h3 style="margin: 12pt 0in 3pt">2<span style="font-family: 宋体">、实现</span>Echo<span style="font-family: 宋体">接口</span></h3>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 'Courier New'">//EchoServer.java</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 'Courier New'">//The implementation of the Echo remote object</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">package demo.rmi;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">import java.net.*;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">import java.rmi.*;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">import java.rmi.registry.*;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">import java.rmi.server.*;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">public</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">class</span> EchoServer</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; extends UnicastRemoteObject</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; implements Echo {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: green">//默认构件器，也要&#8220;掷&#8221;出</span></span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">RemoteException</span><span style="font-size: 10pt; color: green; font-family: 宋体">违例</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">public</span> EchoServer() throws RemoteException {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super();</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">public</span> String echo(String msg) throws RemoteException {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">return</span> <span style="color: maroon">"Echo: "</span> + msg;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">public</span> <span style="color: blue">static</span> <span style="color: blue">void</span> main(String [] args) {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">/*</span><span style="font-size: 10pt; color: green; font-family: 宋体">创建和安装一个安全管理器，令其支持</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">RMI</span><span style="font-size: 10pt; color: green; font-family: 宋体">。</span><span style="font-size: 10pt; color: green; font-family: 宋体">作为</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">Java</span><span style="font-size: 10pt; color: green; font-family: 宋体">开发包的一部分，适用于</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">RMI</span><span style="font-size: 10pt; color: green; font-family: 宋体">唯一一个是</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">RMISecurityManager.*/</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.setSecurityManager(<span style="color: blue">new</span> RMISecurityManager());</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">try</span> {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: green">/*创建远程对象的一个或多个实例，下面是</span></span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">EchoServer</span><span style="font-size: 10pt; color: green; font-family: 宋体">对象*/</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EchoServer es = <span style="color: blue">new</span> EchoServer();</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: green; font-family: 宋体">/*向</span><span style="font-size: 10pt; color: green; font-family: 'Courier New'">RMI</span><span style="font-size: 10pt; color: green; font-family: 宋体">远程对象注册表注册至少一个远程对象。一个远程对象拥有的方法即可生成指向其他远程对象的句柄，这样，客户到注册表里访问一次，得到第一个远程对象即可.*/</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; font-family: 'Courier New'">Naming.rebind(<span style="color: maroon">"EchoServer"</span>, es);</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(<span style="color: maroon">"Ready to provide echo service..."</span>);</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <span style="color: blue">catch</span> (Exception e) {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">这个实现类使用了</span><span style="font-size: 11pt; font-family: 'Courier New'">UnicastRemoteObject</span><span style="font-size: 11pt; font-family: 宋体">去连接</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">系统。在我们的例子中，我们是直接的从</span><span style="font-size: 11pt; font-family: 'Courier New'">UnicastRemoteObject</span><span style="font-size: 11pt; font-family: 宋体">这个类上继承的，事实上并不一定要这样做，如果一个类不是从</span><span style="font-size: 11pt; font-family: 'Courier New'">UnicastRmeoteObject</span><span style="font-size: 11pt; font-family: 宋体">上继承，那必须使用它的</span><span style="font-size: 11pt; font-family: 'Courier New'">exportObject()</span><span style="font-size: 11pt; font-family: 宋体">方法去连接到</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">。（否则，运行时将被告知无法序列化。）</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">如果一个类继承自</span><span style="font-size: 11pt; font-family: 'Courier New'">UnicastRemoteObject</span><span style="font-size: 11pt; font-family: 宋体">，那么它必须提供一个构造函数并且声明抛出一个</span><span style="font-size: 11pt; font-family: 'Courier New'">RemoteException</span><span style="font-size: 11pt; font-family: 宋体">对象（否则，会遇到编译错误）。当这个构造函数调用了</span><span style="font-size: 11pt; font-family: 'Courier New'">super()</span><span style="font-size: 11pt; font-family: 宋体">，它就激活</span><span style="font-size: 11pt; font-family: 'Courier New'">UnicastRemoteObject</span><span style="font-size: 11pt; font-family: 宋体">中的代码完成</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">的连接和远程对象的初始化。</span></p>
<h3 style="margin: 12pt 0in 3pt">3<span style="font-family: 宋体">、运行</span>rmic<span style="font-family: 宋体">编译实现类，产生</span>_Stub<span style="font-family: 宋体">类</span></h3>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">在</span><span style="font-size: 11pt; font-family: 'Courier New'">demo.rmi.EchoServer.java</span><span style="font-size: 11pt; font-family: 宋体">上级目录下运行如下命令：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">rmic demo.rmi.EchoServer</span></p>
<h3 style="margin: 12pt 0in 3pt">4<span style="font-family: 宋体">、编写客户程序</span></h3>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 'Courier New'">//EchoClient.java</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: green; font-family: 'Courier New'">//Uses remote object EchoServer</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">package demo.rmi;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">import java.rmi.*;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">import java.rmi.registry.*;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">public</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">class</span> EchoClient {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">public</span> <span style="color: blue">static</span> <span style="color: blue">void</span> main(String [] args) {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.setSecurityManager(<span style="color: blue">new</span> RMISecurityManager());</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">try</span> {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Echo t = (Echo)Naming.lookup(<span style="color: maroon">"EchoServer"</span>);</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">for</span> (<span style="color: blue">int</span> i = 0; i &lt; 10; i++) {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(t.echo(String.valueOf(i)));</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <span style="color: blue">catch</span> (Exception e) {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<h3 style="margin: 12pt 0in 3pt">5<span style="font-family: 宋体">、运行</span></h3>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">编码的工作就只有这些，现在可以依次启动</span><span style="font-size: 11pt; font-family: 'Courier New'">rmiregistry</span><span style="font-size: 11pt; font-family: 宋体">（启动</span><span style="font-size: 11pt; font-family: 'Courier New'">rmiregistry</span><span style="font-size: 11pt; font-family: 宋体">时可以附加一个端口，一般使用默认的端口</span><span style="font-size: 11pt; font-family: 'Courier New'">1099</span><span style="font-size: 11pt; font-family: 宋体">即可，这是默认的</span><span style="font-size: 11pt; font-family: 'Courier New'">Naming Service</span><span style="font-size: 11pt; font-family: 宋体">运行端口）、</span><span style="font-size: 11pt; font-family: 'Courier New'">EchoServer</span><span style="font-size: 11pt; font-family: 宋体">、</span><span style="font-size: 11pt; font-family: 'Courier New'">EchoClient</span><span style="font-size: 11pt; font-family: 宋体">了。但是，虽然有些</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">的资料没有提到，但你运行时不可避免会遇到如下两个错误：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 'Courier New'">1</span><span style="font-size: 11pt; font-family: 宋体">）</span><span style="font-size: 11pt; font-family: 'Courier New'">java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:1099 connect,resolve)</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">原因很简单，</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI Server/Client</span><span style="font-size: 11pt; font-family: 宋体">程序试图通过</span><span style="font-size: 11pt; font-family: 'Courier New'">Socket</span><span style="font-size: 11pt; font-family: 宋体">连接访问本机的</span><span style="font-size: 11pt; font-family: 'Courier New'">rmiregistry</span><span style="font-size: 11pt; font-family: 宋体">服务（即</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">的</span><span style="font-size: 11pt; font-family: 'Courier New'">Naming Service</span><span style="font-size: 11pt; font-family: 宋体">，其运行的默认端口是</span><span style="font-size: 11pt; font-family: 'Courier New'">1099</span><span style="font-size: 11pt; font-family: 宋体">）。要解决这个问题，可以在运行</span><span style="font-size: 11pt; font-family: 'Courier New'">Server/Client</span><span style="font-size: 11pt; font-family: 宋体">时指定一个</span><span style="font-size: 11pt; font-family: 'Courier New'">Policy</span><span style="font-size: 11pt; font-family: 宋体">文件（关于</span><span style="font-size: 11pt; font-family: 'Courier New'">Policy</span><span style="font-size: 11pt; font-family: 宋体">的更多信息，见参考</span><span style="font-size: 11pt; font-family: 'Courier New'">2</span><span style="font-size: 11pt; font-family: 宋体">），如下：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">java -Djava.security.policy=demo/rmi/policyfile.txt demo.rmi.EchoServer</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 'Courier New'">Policy</span><span style="font-size: 11pt; font-family: 宋体">文件的内容为：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">grant{</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; permission java.net.SocketPermission <span style="color: maroon">"localhost:1099"</span>, <span style="color: maroon">"connect, resolve"</span>;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">};</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">即允许访问本机的</span><span style="font-size: 11pt; font-family: 'Courier New'">1099</span><span style="font-size: 11pt; font-family: 宋体">端口。</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">或者干脆来个彻底开放：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">grant {</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; permission java.security.AllPermission <span style="color: maroon">""</span>, <span style="color: maroon">""</span>;</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">};</span></p>
<p style="margin: 0in 0in 0pt"><font size="3"><span style="font-family: 'Courier New'">2</span><span style="font-family: 宋体">）</span></font><span style="font-size: 10pt; font-family: 'Courier New'">java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.lang.ClassNotFoundException: demo.rmi.EchoServer_Stub</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">如果你凑巧用启动</span><span style="font-size: 11pt; font-family: 'Courier New'">rmiregistry</span><span style="font-size: 11pt; font-family: 宋体">的终端窗口启动了</span><span style="font-size: 11pt; font-family: 'Courier New'">EchoServer</span><span style="font-size: 11pt; font-family: 宋体">，那么你很走运，你看不到上面的错误，但如果你不是在看完这篇文章后就再也用不到</span><span style="font-size: 11pt; font-family: 'Courier New'">RMI</span><span style="font-size: 11pt; font-family: 宋体">，那么，这个错误在那里等着你，</span><span style="font-size: 11pt; font-family: 'Courier New'">:)</span><span style="font-size: 11pt; font-family: 宋体">。</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">错误很明显，</span><span style="font-size: 11pt; font-family: 'Courier New'">rmiregistry</span><span style="font-size: 11pt; font-family: 宋体">找不到与</span><span style="font-size: 11pt; font-family: 'Courier New'">EchoServer</span><span style="font-size: 11pt; font-family: 宋体">放在同一目录下的</span><span style="font-size: 11pt; font-family: 'Courier New'">EchoServer_Stub</span><span style="font-size: 11pt; font-family: 宋体">，因为</span><span style="font-size: 11pt; font-family: 'Courier New'">package</span><span style="font-size: 11pt; font-family: 宋体">所在</span><span style="font-size: 11pt; font-family: 'Courier New'">demo.rmi</span><span style="font-size: 11pt; font-family: 宋体">目录的上级目录不在</span><span style="font-size: 11pt; font-family: 'Courier New'">rmiregistry</span><span style="font-size: 11pt; font-family: 宋体">的</span><span style="font-size: 11pt; font-family: 'Courier New'">classpath</span><span style="font-size: 11pt; font-family: 宋体">中，这个问题有两种解决方案：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 'Courier New'">a</span><span style="font-size: 11pt; font-family: 宋体">）在启动</span><span style="font-size: 11pt; font-family: 'Courier New'">rmiregistry</span><span style="font-size: 11pt; font-family: 宋体">前先调整一下</span><span style="font-size: 11pt; font-family: 'Courier New'">CLASSPATH</span><span style="font-size: 11pt; font-family: 宋体">环境变量，以目录</span><span style="font-size: 11pt; font-family: 'Courier New'">E:"</span><span style="font-size: 11pt; font-family: 宋体">为例，执行：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">set CLASSPATH=%CLASSPATH%;E:"</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 'Courier New'">b</span><span style="font-size: 11pt; font-family: 宋体">）修改</span><span style="font-size: 11pt; font-family: 'Courier New'">code</span><span style="font-size: 11pt; font-family: 宋体">，在</span><span style="font-size: 11pt; font-family: 'Courier New'">EchoServer</span><span style="font-size: 11pt; font-family: 宋体">中通过如下代码：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">Registry r = LocateRegistry.createRegistry(8111);</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">r.rebind(<span style="color: maroon">"EchoServer"</span>, es);</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">在程序内部创建一个</span><span style="font-size: 11pt; font-family: 'Courier New'">LocateRegistry</span><span style="font-size: 11pt; font-family: 宋体">，并将自身注册到该</span><span style="font-size: 11pt; font-family: 'Courier New'">LocateRegistry</span><span style="font-size: 11pt; font-family: 宋体">，其中的数值</span><span style="font-size: 11pt; font-family: 'Courier New'">8111</span><span style="font-size: 11pt; font-family: 宋体">表示</span><span style="font-size: 11pt; font-family: 'Courier New'">LocateRegistry</span><span style="font-size: 11pt; font-family: 宋体">运行的端口。</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">同样，对于客户程序，也需要作相应的调整：</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">Registry r = LocateRegistry.getRegistry(<span style="color: maroon">"localhost"</span>, 8111);</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 10pt; font-family: 'Courier New'">Echo e = (Echo)r.lookup(<span style="color: maroon">"EchoServer"</span>);</span></p>
<p style="margin: 0in 0in 0pt"><span style="font-size: 11pt; font-family: 宋体">而不是像上面例子中一样访问</span><span style="font-size: 11pt; font-family: 'Courier New'">Naming</span><span style="font-size: 11pt; font-family: 宋体">类的</span><span style="font-size: 11pt; font-family: 'Courier New'">static</span><span style="font-size: 11pt; font-family: 宋体">方法来访问默认的</span><span style="font-size: 11pt; font-family: 'Courier New'">rmiregistry</span><span style="font-size: 11pt; font-family: 宋体">服务。</span></p>
<h2 style="margin: 12pt 0in 3pt"><span style="font-family: 宋体"><em>参考：</em></span></h2>
<p style="margin: 0in 0in 0pt 21.75pt; text-indent: -21.75pt"><span style="font-size: 11pt; font-family: 'Courier New'">1.<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 11pt; font-family: 'Courier New'">Java RMI Tutorial, <a href="http://www.ccs.neu.edu/home/kenb/com3337/rmi_tut.html">http://www.ccs.neu.edu/home/kenb/com3337/rmi_tut.html</a></span></p>
<p style="margin: 0in 0in 0pt 21.75pt; text-indent: -21.75pt"><span style="font-size: 11pt; font-family: 'Courier New'">2.<span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 11pt; font-family: 'Courier New'">Policy Tool - Policy File Creation and Management Tool. <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/policytool.html">http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/policytool.html</a></span></p>
<span style="font-family: 'Courier New'"><font size="3">3.</font><span style="font: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 11pt; font-family: 'Courier New'">Java RMI</span><span style="font-size: 11pt; font-family: 宋体">入门实战，</span><span style="font-size: 11pt; font-family: 'Courier New'"><a href="http://www.huihoo.com/java/rmi/index.html">http://www.huihoo.com/java/rmi/index.html</a></span><br />
</font>
<img src ="http://www.blogjava.net/zqli/aggbug/185421.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2008-03-11 16:13 <a href="http://www.blogjava.net/zqli/archive/2008/03/11/185421.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]在TOMCAT中使用RMI服务的常见问题 </title><link>http://www.blogjava.net/zqli/archive/2008/03/11/185411.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Tue, 11 Mar 2008 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2008/03/11/185411.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/185411.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2008/03/11/185411.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/185411.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/185411.html</trackback:ping><description><![CDATA[<div class="postbody">近日因项目临近尾声，开始启动工程化的工作。但是才刚刚开始就遇到个不小的问题。我们的发布是将项目连同TOMCAT一起打包，而我们的项目中使用了RMI的通信，在启动项目时会建立一个RMI的server，这样问题就来了。当我们将项目安装在带有空格的目录中（如C:\Program Files\...）时，在启动TOMCAT时即会报错，报错的信息大致如下(其中隐去了部分公司相关代码)：<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,0)">java.io.IOException:&nbsp;Cannot&nbsp;bind&nbsp;to&nbsp;URL&nbsp;[jmx]:&nbsp;javax.naming.CommunicationException:&nbsp;Failed&nbsp;to&nbsp;retrieve&nbsp;stub&nbsp;from&nbsp;server&nbsp;</span><span style="color: rgb(0,0,0)">127.0</span><span style="color: rgb(0,0,0)">.</span><span style="color: rgb(0,0,0)">0.1</span><span style="color: rgb(0,0,0)">:</span><span style="color: rgb(0,0,0)">1099</span><span style="color: rgb(0,0,0)">&nbsp;[Root&nbsp;exception&nbsp;is&nbsp;java.net.MalformedURLException:&nbsp;no&nbsp;protocol:&nbsp;Files\<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />]<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;javax.management.remote.rmi.RMIConnectorServer.newIOException(RMIConnectorServer.java:</span><span style="color: rgb(0,0,0)">814</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;javax.management.remote.rmi.RMIConnectorServer.start(RMIConnectorServer.java:</span><span style="color: rgb(0,0,0)">431</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
javax.servlet.GenericServlet.init(GenericServlet.java:</span><span style="color: rgb(0,0,0)">211</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:</span><span style="color: rgb(0,0,0)">1029</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:</span><span style="color: rgb(0,0,0)">862</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:</span><span style="color: rgb(0,0,0)">4013</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardContext.start(StandardContext.java:</span><span style="color: rgb(0,0,0)">4357</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:</span><span style="color: rgb(0,0,0)">823</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:</span><span style="color: rgb(0,0,0)">807</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardHost.addChild(StandardHost.java:</span><span style="color: rgb(0,0,0)">595</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardHostDeployer.addChild(StandardHostDeployer.java:</span><span style="color: rgb(0,0,0)">903</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.reflect.NativeMethodAccessorImpl.invoke0(Native&nbsp;Method)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:</span><span style="color: rgb(0,0,0)">39</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:</span><span style="color: rgb(0,0,0)">25</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.reflect.Method.invoke(Method.java:</span><span style="color: rgb(0,0,0)">585</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.commons.beanutils.MethodUtils.invokeMethod(MethodUtils.java:</span><span style="color: rgb(0,0,0)">216</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.commons.digester.SetNextRule.end(SetNextRule.java:</span><span style="color: rgb(0,0,0)">256</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.commons.digester.Rule.end(Rule.java:</span><span style="color: rgb(0,0,0)">276</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.commons.digester.Digester.endElement(Digester.java:</span><span style="color: rgb(0,0,0)">1058</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.util.CatalinaDigester.endElement(CatalinaDigester.java:</span><span style="color: rgb(0,0,0)">76</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.xerces.parsers.XML11Configuration.parse(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.xerces.parsers.XML11Configuration.parse(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.xerces.parsers.XMLParser.parse(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.commons.digester.Digester.parse(Digester.java:</span><span style="color: rgb(0,0,0)">1567</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardHostDeployer.install(StandardHostDeployer.java:</span><span style="color: rgb(0,0,0)">488</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardHost.install(StandardHost.java:</span><span style="color: rgb(0,0,0)">863</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:</span><span style="color: rgb(0,0,0)">483</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:</span><span style="color: rgb(0,0,0)">427</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.startup.HostConfig.start(HostConfig.java:</span><span style="color: rgb(0,0,0)">983</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:</span><span style="color: rgb(0,0,0)">349</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:</span><span style="color: rgb(0,0,0)">119</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ContainerBase.start(ContainerBase.java:</span><span style="color: rgb(0,0,0)">1091</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardHost.start(StandardHost.java:</span><span style="color: rgb(0,0,0)">789</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ContainerBase.start(ContainerBase.java:</span><span style="color: rgb(0,0,0)">1083</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardEngine.start(StandardEngine.java:</span><span style="color: rgb(0,0,0)">478</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardService.start(StandardService.java:</span><span style="color: rgb(0,0,0)">480</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardServer.start(StandardServer.java:</span><span style="color: rgb(0,0,0)">2313</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.startup.Catalina.start(Catalina.java:</span><span style="color: rgb(0,0,0)">556</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.reflect.NativeMethodAccessorImpl.invoke0(Native&nbsp;Method)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:</span><span style="color: rgb(0,0,0)">39</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:</span><span style="color: rgb(0,0,0)">25</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.reflect.Method.invoke(Method.java:</span><span style="color: rgb(0,0,0)">585</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:</span><span style="color: rgb(0,0,0)">287</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:</span><span style="color: rgb(0,0,0)">425</span><span style="color: rgb(0,0,0)">)<br />
Caused&nbsp;by:&nbsp;javax.naming.CommunicationException:&nbsp;Failed&nbsp;to&nbsp;retrieve&nbsp;stub&nbsp;from&nbsp;server&nbsp;</span><span style="color: rgb(0,0,0)">127.0</span><span style="color: rgb(0,0,0)">.</span><span style="color: rgb(0,0,0)">0.1</span><span style="color: rgb(0,0,0)">:</span><span style="color: rgb(0,0,0)">1099</span><span style="color: rgb(0,0,0)">&nbsp;[Root&nbsp;exception&nbsp;is&nbsp;java.net.MalformedURLException:&nbsp;no&nbsp;protocol:&nbsp;Files\<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />]<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.jnp.interfaces.NamingContext.getServer(NamingContext.java:</span><span style="color: rgb(0,0,0)">161</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.jnp.interfaces.NamingContext.checkRef(NamingContext.java:</span><span style="color: rgb(0,0,0)">871</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.jnp.interfaces.NamingContext.bind(NamingContext.java:</span><span style="color: rgb(0,0,0)">377</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.jnp.interfaces.NamingContext.bind(NamingContext.java:</span><span style="color: rgb(0,0,0)">370</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;javax.naming.InitialContext.bind(InitialContext.java:</span><span style="color: rgb(0,0,0)">359</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;javax.management.remote.rmi.RMIConnectorServer.bind(RMIConnectorServer.java:</span><span style="color: rgb(0,0,0)">635</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;javax.management.remote.rmi.RMIConnectorServer.start(RMIConnectorServer.java:</span><span style="color: rgb(0,0,0)">427</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />&nbsp;</span><span style="color: rgb(0,0,0)">51</span><span style="color: rgb(0,0,0)">&nbsp;more<br />
Caused&nbsp;by:&nbsp;java.net.MalformedURLException:&nbsp;no&nbsp;protocol:&nbsp;Files\<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URL.</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">init</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">(URL.java:</span><span style="color: rgb(0,0,0)">567</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URL.</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">init</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">(URL.java:</span><span style="color: rgb(0,0,0)">464</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.net.URL.</span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,0)">init</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)">(URL.java:</span><span style="color: rgb(0,0,0)">413</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.rmi.server.LoaderHandler.pathToURLs(LoaderHandler.java:</span><span style="color: rgb(0,0,0)">747</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:</span><span style="color: rgb(0,0,0)">147</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.rmi.server.RMIClassLoader$</span><span style="color: rgb(0,0,0)">2</span><span style="color: rgb(0,0,0)">.loadClass(RMIClassLoader.java:</span><span style="color: rgb(0,0,0)">620</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:</span><span style="color: rgb(0,0,0)">247</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:</span><span style="color: rgb(0,0,0)">197</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:</span><span style="color: rgb(0,0,0)">1538</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:</span><span style="color: rgb(0,0,0)">1460</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:</span><span style="color: rgb(0,0,0)">1693</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.io.ObjectInputStream.readObject0(ObjectInputStream.java:</span><span style="color: rgb(0,0,0)">1299</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.io.ObjectInputStream.readObject(ObjectInputStream.java:</span><span style="color: rgb(0,0,0)">339</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.rmi.MarshalledObject.get(MarshalledObject.java:</span><span style="color: rgb(0,0,0)">135</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.jnp.interfaces.NamingContext.getServer(NamingContext.java:</span><span style="color: rgb(0,0,0)">151</span><span style="color: rgb(0,0,0)">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />&nbsp;</span><span style="color: rgb(0,0,0)">57</span><span style="color: rgb(0,0,0)">&nbsp;more</span></div>
可以看到路径被从空格处截断了，致使RMI的server无法找到启动所需要的classpath。<br />
通过查找相关的文档和资料，发现很多人都遇到过类似的问题，其中最有意义的信息是<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,0,0)">There&nbsp;is&nbsp;a&nbsp;bug&nbsp;in&nbsp;the&nbsp;JDK&nbsp;which&nbsp;makes&nbsp;RMI&nbsp;fail&nbsp;if&nbsp;Tomcat&nbsp;is&nbsp;installed&nbsp;in&nbsp;directory&nbsp;containing&nbsp;spaces&nbsp;(e.g.&nbsp;C:\Program&nbsp;Files\Apache&nbsp;Group\Jakarta&nbsp;Tomcat&nbsp;5.0).&nbsp;This&nbsp;bug&nbsp;won't&nbsp;be&nbsp;fixed,&nbsp;so&nbsp;you&nbsp;can&nbsp;only&nbsp;workaround&nbsp;it.<br />
<br />
The&nbsp;installation&nbsp;should&nbsp;have&nbsp;checked&nbsp;the&nbsp;folder&nbsp;name&nbsp;for&nbsp;you&nbsp;and&nbsp;promted&nbsp;you&nbsp;to&nbsp;reinstall&nbsp;Tomcat.&nbsp;If&nbsp;you&nbsp;missed&nbsp;that&nbsp;or&nbsp;renamed&nbsp;the&nbsp;folder&nbsp;after&nbsp;you&nbsp;installed&nbsp;KIM,&nbsp;follow&nbsp;the&nbsp;seme&nbsp;advice&nbsp;now:&nbsp;reinstall&nbsp;Tomcat&nbsp;in&nbsp;a&nbsp;folder&nbsp;(using&nbsp;underscores&nbsp;instead&nbsp;of&nbsp;spaces&nbsp;for&nbsp;example)&nbsp;or&nbsp;just&nbsp;rename&nbsp;folders&nbsp;needed&nbsp;so&nbsp;that&nbsp;the&nbsp;full&nbsp;path&nbsp;contains&nbsp;no&nbsp;spaces.&nbsp;Then&nbsp;reinstall&nbsp;KIM&nbsp;too&nbsp;and&nbsp;point&nbsp;it&nbsp;to&nbsp;the&nbsp;new&nbsp;loacation&nbsp;when&nbsp;asked&nbsp;for&nbsp;Tomcat&nbsp;server,&nbsp;or&nbsp;to&nbsp;skip&nbsp;the&nbsp;new&nbsp;install&nbsp;just&nbsp;manually&nbsp;edit&nbsp;your&nbsp;start/stop&nbsp;Tomcat&nbsp;bat/sh&nbsp;files&nbsp;in&nbsp;%KIM_Platform_Home%/bin&nbsp;directory&nbsp;where&nbsp;this&nbsp;path&nbsp;is&nbsp;used.<br />
<br />
For&nbsp;more&nbsp;details&nbsp;refer&nbsp;to:<br />
<br />
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=4543<br />
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4496398<br />
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4273532</span></div>
按照上文的意思，这是一个由JDK引起的bug，而且今后也不会被修复。<br />
<br />
但是我们的项目有两个版本，我所做的是WEB版的，而另外一个是独立运行版本。问题就在这儿，那个独立运行的版本安装在带有空格的目录中时依然可以正常工作，但是一旦放到TOMCAT中就不行了。通过反复查看上述报错信息中的各个类文件的报错位置，也未能找到确切的原因。但是因为这些类中有多处使用了ClassLoader，所以怀疑是因为放到TOMCAT中后缺省的ClassLoader和独立运行时不同，造成了在使用RMI相关的操作时出现了一些差别。<br />
</div>
<img src ="http://www.blogjava.net/zqli/aggbug/185411.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2008-03-11 15:50 <a href="http://www.blogjava.net/zqli/archive/2008/03/11/185411.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Java加密和licence控制的设计</title><link>http://www.blogjava.net/zqli/archive/2007/06/28/126744.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Thu, 28 Jun 2007 02:37:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2007/06/28/126744.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/126744.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2007/06/28/126744.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/126744.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/126744.html</trackback:ping><description><![CDATA[<h1>1.版权声明</h1>
<div>&nbsp;&nbsp;&nbsp; 本文是关于如何通过序列号来加载加密的class文件的阐述。</div>
<div>&nbsp;&nbsp; 本文所提及的Resin hessian是Caucho公司的注册产品名称， 其版权规caucho所有。</div>
<div>本文可以转载， 但是必须注明作者的Blog地址：</div>
<div>http://blog.csdn.net/oldjavaman</div>
<h1>2.&nbsp;本文的适用对象</h1>
<div>&nbsp;&nbsp;&nbsp; 作为技术人员，本文的技术细节涉及到Java语言的基础知识， 您在阅读前应该了解Java动态装载Class的机制，以及常规的Java加密的相关知识， 同时本文假定您已经具有开发web的基本能力， 了解jsp和servlet的运作过程。</div>
<h1>3.怎样阅读</h1>
<div>你可以在下面地址下载到本文所用到的Jar文件和加密工具</div>
<div>http://www.collegesoft.com.cn/download/licenceClient_1.0.3.jar</div>
<div>加密工具的下载：</div>
<div>http://www.collegesoft.com.cn/download/encryption.exe</div>
<div>关于序列号的生成部分， 鉴于保护公司产品的考虑就不再公开发布了， 有兴趣的同仁可以用mail和我交流。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h1>4.&nbsp;概述</h1>
<h2>4.1.&nbsp;加密Java源码的原因</h2>
<div>　　Java源代码经过编译以后在JVM中执行。由于JVM界面是完全透明的，Java类文件能够很容易通过反编译器重新转换成源代码。因此，所有的算法、类文件等都可以以源代码的形式被公开，使得软件不能受到保护，为了保护产权，一般可以有以下几种方法：</div>
<div>&nbsp;</div>
<div>　　（1）"模糊"类文件，把文件的名称和方法换成000OOoo的方式,当然只要你有足够的耐心, 将这些编码转换成自己可以看懂的代码, 并非难事。</div>
<div>&nbsp;</div>
<div>　　（2）流行的加密工具对源文件进行加密，比如PGP（Pretty Good Privacy）或GPG（GNU Privacy Guard）。这时，最终用户在运行应用之前必须先进行解密。但解密之后，最终用户就有了一份不加密的类文件，这和事先不进行加密没有什么差别。</div>
<div>&nbsp;</div>
<div>　　（3）加密类文件，在运行中JVM用定制的类装载器（Class Loader）解密类文件。Java运行时装入字节码的机制隐含地意味着可以对字节码进行修改。JVM每次装入类文件时都需要一个称为ClassLoader的对象，这个对象负责把新的类装入正在运行的JVM。JVM给ClassLoader一个包含了待装入类（例如java.lang.Object）名字的字符串，然后由ClassLoader负责找到类文件，装入原始数据，并把它转换成一个Class对象。</div>
<div>&nbsp;</div>
<div>　　用户下载的是加密过的类文件，在加密类文件装入之时进行解密，因此可以看成是一种即时解密器。由于解密后的字节码文件永远不会保存到文件系统，所以窃密者很难得到解密后的代码。 </div>
<div>&nbsp;</div>
<div>　　由于把原始字节码转换成Class对象的过程完全由系统负责，所以创建定制ClassLoader对象其实并不困难，只需先获得原始数据，接着就可以进行包含解密在内的任何转换。</div>
<div>&nbsp;</div>
<h2>4.2.&nbsp;Java密码体系和Java密码扩展</h2>
<div>&nbsp;</div>
<div>　　Java密码体系(JCA)和Java密码扩展(JCE)的设计目的是为Java提供与实现无关的加密函数API。它们都用factory方法来创建类的例程，然后把实际的加密函数委托给提供者指定的底层引擎,引擎中为类提供了服务提供者接口在Java中实现数据的加密/解密，是使用其内置的JCE(Java加密扩展)来实现的。Java密码体系结构支持供应商的互操作,同时支持硬件和软件实现。</div>
<h2>4.3.&nbsp;本文采用的方式</h2>
<div>我们采用的是第三种方式, 将class文件加密作为产品的发行版本,但是为了让这个加密的方式可以在不同的项目里面使用, 又将这个解密的处理做成webservice的方式来进行.</div>
<h1>5.&nbsp;基本设计思想</h1>
<p>&nbsp;</p>
<p>这个过程可以划分成5个部分:</p>
<div>1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将加密的class文件传递到webService里面.</div>
<div>2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由webService来查看Licence是里面, 是否有合法的信息, 譬如产品名称, 版本, 授权用户,已经过期时间等, 有此决定是否继续执行第3个步骤</div>
<div>3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果一切验证通过, 将由webService返回一个解密的文件</div>
<div>4)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由本地的webService来装载这个class对象, </div>
<div>5)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 构造成一个class的instance</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h1>6.那个文件应该被加密</h1>
<div>&nbsp;&nbsp; 在以前, 尝试将自己的API进行加密, 但是作为API本身在公司内部发行, 这就要求我们每个programmer在编写代码的时候必须人手一个Licence才可以进行正常的工作, 为API的升级和维护也带来极大的不便, 为什么? 因为API不能作为一个Jar发布, 只能以class的方式来发布.</div>
<div>&nbsp;&nbsp; 那么. 我们应该加密的是什么呢? 在我们设计web程序的时候, 一般的流程是, login 然后在session或cookie里面记录他的身份信息, 譬如她是一个什么样的用户, 是学生或者教师还是管理员, 同时, 我们要记录他具有什么权限, 每个权限的操作范围又是什么? 那么这个过程我们一般在用户登陆, 和数据库连接之后来进行的, 这是一个复杂的逻辑操作过程,, 加密这个方法是一个好的想法, 这样恶意的用户, 即使把所有的其他class文件用jad来还原, 也无济于事, 除非他可以猜出你在login的时候到底做了什么。</div>
<div>&nbsp;</div>
<h1>7.&nbsp;怎样加密自己的java文件</h1>
<h2>7.2.&nbsp;&nbsp;文件的加密</h2>
<div>&nbsp;&nbsp; 加密我们的文件， 我们采用的是JCE的算法来进行的， 具体的加密实现， 我再次不再叙述， 在google里面， 你可以获取n多的文章在描述这个JCE的用法， 对于我们的文件， 已经提供了一个windows的exe程序来之行,这个文件叫做encryption.exe</div>
<div>你可以用如下命令来加密自己的文件</div>
<p>
<table cellSpacing=0 cellPadding=0 bgColor=#c0c0c0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <div>c:&gt; encryption &#8211;encrypto myClass.class </div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<div>&nbsp;</div>
<div>这样就可以把你的文件做成Jad等工具无法反编译的文件了。</div>
<div>&nbsp;</div>
<h2></h2>
<h1>8. 从LicenceCenter获取的产品信息</h1>
<div>无论再添加课程还是， 建立新的用户的时候， 您都可能会有一个需求， 我怎么知道自己的产品授权给这个用户什么样的信息呢， 是否允许他再建立一个课程或者添加一个客户？</div>
<div>&nbsp;</div>
<div>我们提供的jar里面可以解决你的困惑：</div>
<div>代码如下</div>
<div>&nbsp;</div>
<p>
<table cellSpacing=0 cellPadding=0 bgColor=#d9d9d9 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <div>LicenceFactory licenceFactory=new LicenceFactory();</div>
            <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; licenceFactory.getLicence("urProductName");</div>
            <div>&nbsp;</div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<div>如果这个产品在验证中心没有注册序列号， 将返回null;</div>
<div>&nbsp;</div>
<h1>9.程序需要增加什么配置</h1>
<div>在licenceClient里面， 系统需要读取licenceCenter的地址， 在您的web应用发布的时候， 必须将webService的地址编写成环境变量， 在web.xml里面增加一段代码：</div>
<p>
<table cellSpacing=0 cellPadding=0 bgColor=#d9d9d9 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <div>&lt;env-entry&gt;</div>
            <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;env-entry-name&gt;licence_service_url&lt;/env-entry-name&gt;</div>
            <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;env-entry-value&gt;http://192.168.2.212:8080/licenceCenter/LicenceService&lt;/env-entry-value&gt;</div>
            <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;env-entry-type&gt;java.lang.String&lt;/env-entry-type&gt;</div>
            <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/env-entry&gt;</div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<div>&nbsp;</div>
<div>你可以将红色的部分放在你的web server上访问， 假设看到如下界面， 表示验证中心已经安装成功</div>
<div></div>
<h1>10.关于验证中心的安装</h1>
<div>验证中心的安装文件为 licenceService1.0.1.zip</div>
<div>在你的操作系统里面解压在一个目录中。</div>
<div>在你的Java web server里面配置一个应用， 譬如叫做：licenceCenter</div>
<div>以Resin为例子：在httpd.conf里面加上一下代码：</div>
<p>
<table cellSpacing=0 cellPadding=0 bgColor=#d9d9d9 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <div>&lt;web-app id="demo" app-dir="E:/licencescenter/webapp"&gt;</div>
            <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-mapping url-pattern='*.jsp'</div>
            <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; servlet-name='com.caucho.jsp.JspServlet'/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
            <div>&nbsp;</div>
            <div>&lt;/web-app&gt;</div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<div>&nbsp;</div>
<div>其中在你的这个应用中的web.xml文件必须包含</div>
<p>
<table cellSpacing=0 cellPadding=0 bgColor=#d9d9d9 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <div align=left>&lt;servlet servlet-name="LicenceService"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; servlet-class="com.caucho.hessian.server.HessianServlet"&gt;</div>
            <div align=left>&nbsp;&nbsp;&nbsp; &lt;init-param service-class="com.collegesoft.licence.LicenceService"/&gt;</div>
            <div align=left>&nbsp;&nbsp;&nbsp; &lt;init-param api-class="com.collegesoft.licence.LicenceServiceStub"/&gt;</div>
            <div align=left>&nbsp; &lt;/servlet&gt;</div>
            <div align=left>&nbsp; &lt;servlet-mapping url-pattern="/LicenceService" servlet-name="LicenceService"/&gt;</div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<div></div>
<div>&nbsp;</div>
<h1>11. 常见问题</h1>
<div><strong>Q:</strong> 为什么不直接在webService里面加载好一个Class， 而是要在客户端来用classLoader来装载？</div>
<div><strong>A: </strong>很多的程序员问过我这个问题，其实很简单， 你如果知道classloader的机制， 就知道假设你扩展login的实例用到你的另外一个对象， 譬如OnlineUser， 那么要在webService里面来装载你的类， 我就必须拥有你这个类， 但是webservice里面是不知道你未来是要用到什么类的。</div>
<div>Q：为什么在redhat9上，访问验证中心会出现中文乱码问题？</div>
<div>A：是由于redhat9的默认字符集不为GBK的缘故。一般采用将命令export LANG=zh_CN.GBK加在resin服务启动文件中。</div>
<div>&nbsp;</div>
<h1>13.关于作者</h1>
<div>OldJavaMan， 是一个Java的狂热分子， 喜欢OpenSouce的东西， 无奈自己还要靠这个东西养家， 无法实现开源的做法， 期望有一天可以衣食无忧地编写自己喜欢地程序， 并从中获取自己的人生乐趣。</div>
<img src ="http://www.blogjava.net/zqli/aggbug/126744.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2007-06-28 10:37 <a href="http://www.blogjava.net/zqli/archive/2007/06/28/126744.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Request.setAtrribute()&amp;&amp;Request.getParameter()&amp;&amp;Request.getAttribute()</title><link>http://www.blogjava.net/zqli/archive/2007/06/27/126638.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Wed, 27 Jun 2007 09:34:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2007/06/27/126638.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/126638.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2007/06/27/126638.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/126638.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/126638.html</trackback:ping><description><![CDATA[HttpServletRequest类既有getAttribute()方法，也由getParameter()方法，这两个方法有以下区别： &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; （1）HttpServletRequest类有setAttribute()方法，而没有setParameter()方法 &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; （2）当两个Web组件之间为链接关系时，被链接的组件通过getParameter()方法来获得请求参数，例如假定welcome.jsp和authenticate.jsp之间为链接关系，welcome.jsp中有以下代码： &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; &lt;a &nbsp; href="authenticate.jsp?username=weiqin"&gt;authenticate.jsp &nbsp; &lt;/a&gt; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 或者： &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; &lt;form &nbsp; name="form1" &nbsp; method="post" &nbsp; action="authenticate.jsp"&gt; &nbsp; <br>&nbsp; &nbsp; &nbsp; 请输入用户姓名：&lt;input &nbsp; type="text" &nbsp; name="username"&gt; &nbsp; <br>&nbsp; &nbsp; &nbsp; &lt;input &nbsp; type="submit" &nbsp; name="Submit" &nbsp; value="提交"&gt; &nbsp; <br>&nbsp; &lt;/form&gt; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 在authenticate.jsp中通过request.getParameter("username")方法来获得请求参数username: &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; &lt;% &nbsp; String &nbsp; username=request.getParameter("username"); &nbsp; %&gt; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; （3）当两个Web组件之间为转发关系时，转发目标组件通过getAttribute()方法来和转发源组件共享request范围内的数据。假定 &nbsp; authenticate.jsp和hello.jsp之间为转发关系。authenticate.jsp希望向hello.jsp传递当前的用户名字，如何传递这一数据呢？先在authenticate.jsp中调用setAttribute()方法： &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; &lt;% &nbsp; <br>&nbsp; String &nbsp; username=request.getParameter("username"); &nbsp; <br>&nbsp; request.setAttribute("username"，username); &nbsp; <br>&nbsp; %&gt; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; &lt;jsp:forward &nbsp; page="hello.jsp" &nbsp; /&gt; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 在hello.jsp中通过getAttribute()方法获得用户名字: &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; &lt;% &nbsp; String &nbsp; username=(String)request.getAttribute("username"); &nbsp; %&gt; &nbsp; <br>&nbsp; Hello: &nbsp; &lt;%=username &nbsp; %&gt; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; ＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝ &nbsp; <br>&nbsp; 从更深的层次考虑，request.getParameter()方法传递的数据，会从Web客户端传到Web服务器端，代表HTTP请求数据。request.getParameter()方法返回String类型的数据。 &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; request.setAttribute()和getAttribute()方法传递的数据只会存在于Web容器内部，在具有转发关系的Web组件之间共享。这两个方法能够设置Object类型的共享数据。
<img src ="http://www.blogjava.net/zqli/aggbug/126638.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2007-06-27 17:34 <a href="http://www.blogjava.net/zqli/archive/2007/06/27/126638.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]从URL获取文件保存到本地的JAVA代码</title><link>http://www.blogjava.net/zqli/archive/2007/04/12/110215.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Thu, 12 Apr 2007 08:58:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2007/04/12/110215.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/110215.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2007/04/12/110215.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/110215.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/110215.html</trackback:ping><description><![CDATA[<p>&lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#112;&#97;&#103;&#101;">%@page</a> import="java.net.*,java.io.*"%&gt;<br>&lt;%!<br>&nbsp; public boolean saveUrlAs(String photoUrl, String fileName) {<br>//此方法只能用户HTTP协议<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL url = new URL(photoUrl);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpURLConnection connection = (HttpURLConnection) url.openConnection();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataInputStream in = new DataInputStream(connection.getInputStream());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataOutputStream out = new DataOutputStream(new FileOutputStream(fileName));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buffer = new byte[4096];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int count = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ((count = in.read(buffer)) &gt; 0) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.write(buffer, 0, count);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (Exception e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp;<br>public String getDocumentAt(String urlString) {<br>//此方法兼容HTTP和FTP协议<br>&nbsp;&nbsp;&nbsp; StringBuffer document = new StringBuffer();<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL url = new URL(urlString);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URLConnection conn = url.openConnection();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufferedReader reader = new BufferedReader(new InputStreamReader(conn.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getInputStream()));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String line = null;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ( (line = reader.readLine()) != null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.append(line + "\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reader.close();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (MalformedURLException e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Unable to connect to URL: " + urlString);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; catch (IOException e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("IOException when connecting to URL: " + urlString);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return document.toString();<br>&nbsp; }<br>%&gt;<br>&lt;%<br>//测试<br>&nbsp; String photoUrl = "<a href="http://ad4.sina.com.cn/200601/12/43932_750450.jpg">http://ad4.sina.com.cn/200601/12/43932_750450.jpg</a>";<br>&nbsp; String fileName = photoUrl.substring(photoUrl.lastIndexOf("/"));<br>&nbsp; String filePath = "d:/ghost/";<br>&nbsp; boolean flag = saveUrlAs(photoUrl, filePath + fileName);<br>&nbsp; out.println("Run ok!\n&lt;BR&gt;Get URL file " + flag);<br>%&gt;</p>
<p><br>转赛迪技术<br></p>
<img src ="http://www.blogjava.net/zqli/aggbug/110215.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2007-04-12 16:58 <a href="http://www.blogjava.net/zqli/archive/2007/04/12/110215.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]每个Java初学者都应该搞懂的六个问题。</title><link>http://www.blogjava.net/zqli/archive/2007/02/03/97792.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Sat, 03 Feb 2007 12:24:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2007/02/03/97792.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/97792.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2007/02/03/97792.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/97792.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/97792.html</trackback:ping><description><![CDATA[对于这个系列里的问题，每个学Java的人都应该搞懂。当然，如果只是学Java玩玩就无所谓了。如果你认为自己已经超越初学者了，却不很懂这些问题，请将你自己重归初学者行列。内容均来自于CSDN的经典老贴。
<p>　　问题一：我声明了什么！</p><!--NEWSZW_HZH_BEGIN--><table cellspacing="0" cellpadding="0" align="left" border="0"><tbody><tr><td><div id="PublicRelation5" name="PublicRelation"> </div></td></tr></tbody></table><!--NEWSZW_HZH_END--><p class="code">String s = "Hello world!";</p><p>　　许多人都做过这样的事情，但是，我们到底声明了什么？回答通常是：一个String，内容是“Hello world!”。这样模糊的回答通常是概念不清的根源。如果要准确的回答，一半的人大概会回答错误。<br />这个语句声明的是一个指向对象的引用，名为“s”，可以指向类型为String的任何对象，目前指向"Hello world!"这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象，我们只是声明了一个只能指向String对象的引用变量。所以，如果在刚才那句语句后面，如果再运行一句：</p><p class="code">String string = s;</p><p>　　我们是声明了另外一个只能指向String对象的引用，名为string，并没有第二个对象产生，string还是指向原来那个对象，也就是，和s指向同一个对象。</p><p>　　问题二："=="和equals方法究竟有什么区别？</p><p>　　==操作符专门用来比较变量的值是否相等。比较好理解的一点是：</p><p class="code">int a=10;<br />int b=10;</p><p>　　则a==b将是true。<br />　　但不好理解的地方是：</p><p class="code">String a=new String("foo");<br />String b=new String("foo");</p><p>　　则a==b将返回false。</p><p>　　根据前一帖说过，对象变量其实是一个引用，它们的值是指向对象所在的内存地址，而不是对象本身。a和b都使用了new操作符，意味着将在内存中产生两个内容为"foo"的字符串，既然是“两个”，它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值，所以使用"=="操作符，结果会是false。诚然，a和b所指的对象，它们的内容都是"foo"，应该是“相等”，但是==操作符并不涉及到对象内容的比较。</p><p>　　对象内容的比较，正是equals方法做的事。</p><p>　　看一下Object对象的equals方法是如何实现的：</p><p class="code">boolean equals(Object o){<br />return this==o;<br />}</p><p>　　Object对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法，那你的类使用equals和使用==会得到同样的结果。同样也可以看出，Object的equals方法没有达到equals方法应该达到的目标：比较两个对象内容是否相等。因为答案应该由类的创建者决定，所以Object把这个任务留给了类的创建者。</p><p>　　看一下一个极端的类：</p><p class="code">Class Monster{<br />private String content;<br />...<br />boolean equals(Object another){ return true;}<br />}</p><p>　　覆盖了equals方法。这个实现会导致无论Monster实例内容如何，它们之间的比较永远返回true。</p><p>　　所以当你是用equals方法判断对象的内容是否相等，请不要想当然。因为可能你认为相等，而这个类的作者不这样认为，而类的equals方法的实现是由他掌握的。如果你需要使用equals方法，或者使用任何基于散列码的集合（HashSet,HashMap,HashTable），请察看一下java doc以确认这个类的equals逻辑是如何实现的。</p><p> </p><p>　　问题三：String到底变了没有？</p><p>　　没有。因为String被设计成不可变(immutable)类，所以它的所有对象都是不可变对象。请看下列代码：</p><p class="code">String s = "Hello";<br />s = s + " world!";</p><p>　　s所指向的对象是否改变了呢？从本系列第一篇的结论很容易导出这个结论。我们来看看发生了什么事情。在这段代码中，s原先指向一个String对象，内容是"Hello"，然后我们对s进行了+操作，那么s所指向的那个对象是否发生了改变呢？答案是没有。这时，s不指向原来那个对象了，而指向了另一个String对象，内容为"Hello world!"，原来那个对象还存在于内存之中，只是s这个引用变量不再指向它了。</p><p>　　通过上面的说明，我们很容易导出另一个结论，如果经常对字符串进行各种各样的修改，或者说，不可预见的修改，那么使用String来代表字符串的话会引起很大的内存开销。因为String对象建立之后不能再改变，所以对于每一个不同的字符串，都需要一个String对象来表示。这时，应该考虑使用StringBuffer类，它允许修改，而不是每个不同的字符串都要生成一个新的对象。并且，这两种类的对象转换十分容易。 </p><p>　　同时，我们还可以知道，如果要使用内容相同的字符串，不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化，把它设置为初始值，应当这样做：</p><p class="code">public class Demo {<br />private String s;<br />...<br />public Demo {<br />s = "Initial Value";<br />}<br />...<br />}</p><p>　　而非</p><p class="code">　　s = new String("Initial Value");</p><p>　　后者每次都会调用构造器，生成新对象，性能低下且内存开销大，并且没有意义，因为String对象不可改变，所以对于内容相同的字符串，只要一个String对象来表示就可以了。也就说，多次调用上面的构造器创建多个对象，他们的String类型属性s都指向同一个对象。</p><p>　　上面的结论还基于这样一个事实：对于字符串常量，如果内容相同，Java认为它们代表同一个String对象。而用关键字new调用构造器，总是会创建一个新的对象，无论内容是否相同。</p><p>　　至于为什么要把String类设计成不可变类，是它的用途决定的。其实不只String，很多Java标准类库中的类都是不可变的。在开发一个系统的时候，我们有时候也需要设计不可变类，来传递一组相关的值，这也是面向对象思想的体现。不可变类有一些优点，比如因为它的对象是只读的，所以多线程并发访问也不会有任何问题。当然也有一些缺点，比如每个不同的状态都要一个对象来代表，可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本，即StringBuffer。</p><p>　　问题四：final关键字到底修饰了什么？</p><p>　　final使得被修饰的变量"不变"，但是由于对象型变量的本质是“引用”，使得“不变”也有了两种含义：引用本身的不变，和引用指向的对象不变。</p><p>　　引用本身的不变：</p><p class="code">final StringBuffer a=new StringBuffer("immutable");<br />final StringBuffer b=new StringBuffer("not immutable");<br />a=b;//编译期错误</p><p>　　引用指向的对象不变：</p><p class="code">final StringBuffer a=new StringBuffer("immutable");<br />a.append(" broken!"); //编译通过</p><p>　　可见，final只对引用的“值”(也即它所指向的那个对象的内存地址)有效，它迫使引用只能指向初始指向的那个对象，改变它的指向会导致编译期错误。至于它所指向的对象的变化，final是不负责的。这很类似==操作符：==操作符只负责引用的“值”相等，至于这个地址所指向的对象内容是否相等，==操作符是不管的。</p><p>　　理解final问题有很重要的含义。许多程序漏洞都基于此----final只能保证引用永远指向固定对象，不能保证那个对象的状态不变。在多线程的操作中,一个对象会被多个线程共享或修改，一个线程对对象无意识的修改可能会导致另一个使用此对象的线程崩溃。一个错误的解决方法就是在此对象新建的时候把它声明为final，意图使得它“永远不变”。其实那是徒劳的。</p><p> </p><p>　　问题五：到底要怎么样初始化！</p><p>　　本问题讨论变量的初始化，所以先来看一下Java中有哪些种类的变量。</p><p>1. 类的属性，或者叫值域<br />2. 方法里的局部变量<br />3. 方法的参数</p><p>　　对于第一种变量，Java虚拟机会自动进行初始化。如果给出了初始值，则初始化为该初始值。如果没有给出，则把它初始化为该类型变量的默认初始值。</p><p>int类型变量默认初始值为0<br />float类型变量默认初始值为0.0f<br />double类型变量默认初始值为0.0<br />boolean类型变量默认初始值为false<br />char类型变量默认初始值为0(ASCII码)<br />long类型变量默认初始值为0</p><p>　　所有对象引用类型变量默认初始值为null，即不指向任何对象。注意数组本身也是对象，所以没有初始化的数组引用在自动初始化后其值也是null。</p><p>　　对于两种不同的类属性，static属性与instance属性，初始化的时机是不同的。instance属性在创建实例的时候初始化，static属性在类加载，也就是第一次用到这个类的时候初始化，对于后来的实例的创建，不再次进行初始化。这个问题会在以后的系列中进行详细讨论。 </p><p>　　对于第二种变量，必须明确地进行初始化。如果再没有初始化之前就试图使用它，编译器会抗议。如果初始化的语句在try块中或if块中，也必须要让它在第一次使用前一定能够得到赋值。也就是说，把初始化语句放在只有if块的条件判断语句中编译器也会抗议，因为执行的时候可能不符合if后面的判断条件，如此一来初始化语句就不会被执行了，这就违反了局部变量使用前必须初始化的规定。但如果在else块中也有初始化语句，就可以通过编译，因为无论如何，总有至少一条初始化语句会被执行，不会发生使用前未被初始化的事情。对于try-catch也是一样，如果只有在try块里才有初始化语句，编译部通过。如果在catch或finally里也有，则可以通过编译。总之，要保证局部变量在使用之前一定被初始化了。所以，一个好的做法是在声明他们的时候就初始化他们，如果不知道要出事化成什么值好，就用上面的默认值吧！</p><p>　　其实第三种变量和第二种本质上是一样的，都是方法中的局部变量。只不过作为参数，肯定是被初始化过的，传入的值就是初始值，所以不需要初始化。</p><p>　　问题六：instanceof是什么东东？</p><p>　　instanceof是Java的一个二元操作符，和==，&gt;，&lt;是同一类东东。由于它是由字母组成的，所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例，返回boolean类型的数据。举个例子：</p><p class="code">String s = "I AM an Object!";<br />boolean isObject = s instanceof Object;</p><p>　　我们声明了一个String对象引用，指向一个String对象，然后用instancof来测试它所指向的对象是否是Object类的一个实例，显然，这是真的，所以返回true，也就是isObject的值为True。</p><p>　　instanceof有一些用处。比如我们写了一个处理账单的系统，其中有这样三个类：</p><p class="code">public class Bill {//省略细节}<br />public class PhoneBill extends Bill {//省略细节}<br />public class GasBill extends Bill {//省略细节}</p><p>　　在处理程序里有一个方法，接受一个Bill类型的对象，计算金额。假设两种账单计算方法不同，而传入的Bill对象可能是两种中的任何一种，所以要用instanceof来判断：</p><p class="code">public double calculate(Bill bill) {<br />if (bill instanceof PhoneBill) {<br />//计算电话账单<br />}<br />if (bill instanceof GasBill) {<br />//计算燃气账单<br />}<br />...<br />}</p><p>　　这样就可以用一个方法处理两种子类。</p><p>　　然而，这种做法通常被认为是没有好好利用面向对象中的多态性。其实上面的功能要求用方法重载完全可以实现，这是面向对象变成应有的做法，避免回到结构化编程模式。只要提供两个名字和返回值都相同，接受参数类型不同的方法就可以了：</p><p class="code">public double calculate(PhoneBill bill) {<br />//计算电话账单<br />}<br /><br />public double calculate(GasBill bill) {<br />//计算燃气账单<br />}</p><p>　　所以，使用instanceof在绝大多数情况下并不是推荐的做法，应当好好利用多态。 </p><img src ="http://www.blogjava.net/zqli/aggbug/97792.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2007-02-03 20:24 <a href="http://www.blogjava.net/zqli/archive/2007/02/03/97792.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]网上比较好的html在线编辑器介绍 </title><link>http://www.blogjava.net/zqli/archive/2007/01/11/93253.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Thu, 11 Jan 2007 12:35:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2007/01/11/93253.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/93253.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2007/01/11/93253.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/93253.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/93253.html</trackback:ping><description><![CDATA[
		<div class="postText">出处:http://www.cnblogs.com/zkxp/archive/2006/01/18/319607.aspx<br /><br />1.FCKeditor 编辑器 <br /><br />FCKeditor is compatible with most internet browsers which include: IE 5.5+ (Windows), Firefox 1.0+, Mozilla 1.3+ and Netscape 7+. <br />最新版本:FCKeditor 2.0 <br />语言环境:多国语言<br />特性功能:所见所得,支持平台众多,支持XHTML 1.0,文本格式设置,常见的编辑,复制,粘贴,撤销,文件上传等功能<br />授权方式:Open Source &amp; Free<br />官方地址:<a href="http://www.fckeditor.net/" target="_blank"><font color="#000080">http://www.fckeditor.net/</font></a><br />下载地址:<a href="http://www.fckeditor.net/download/default.html" target="_blank"><font color="#000080">http://www.fckeditor.net/download/default.html</font></a><br />演示:<a href="http://www.fckeditor.net/demo/default.html" target="_blank"><font color="#000080">http://www.fckeditor.net/demo/default.html</font></a><br />小节:FCKeditor的2.0版比1.6版有了许多的改进。首先是FCKeditor的文件结构更加清晰，<br />可以更方便地将其部署在自己的系统中。另外2.0版开始支持了Firefox浏览器<br /><br />2.WebEditor <br />WebEditor系列文档控件，采用了ESS专业电子签名和电子盖章的技术，除继续支持手写签名，电子印章，痕迹保留外，<br />该版本采用了我们强大的B/S通讯技术，能够自由的将服务器数据库<br /><br />最新版本:WebEditor[V4.3.0.0 OCX版]<br />语言环境:简体中文<br />技术特性<br />采用IE5.0以上版本内置的传输协议，通讯性能稳定，高效。 <br />采用标准HTTP通讯端口80，使用方便，无需特别配置、安全性好、更无需特别设置防火墙。 <br />采用插件技术，可以完全融入IE浏览器中，方便系统维护、方便用户操作。 <br />采用自定义协议包进行数据的组装和分析，系统开放性好，便于二次开发。 <br />采用了Com组件和JavaBean组件技术，很好的实现了跨平台系统，便于开发。 <br />官方地址:<a href="http://www.dragongod.com/" target="_blank"><font color="#000080">http://www.dragongod.com/</font></a><br />演示:<a href="http://www.dragongod.com/WebEditor/Demo.asp" target="_blank"><font color="#000080">http://www.dragongod.com/WebEditor/Demo.asp</font></a><br />下载:<a href="http://www.dragongod.com/download/index.asp" target="_blank"><font color="#000080">http://www.dragongod.com/download/index.asp</font></a>#item1<br />小节:这个编辑器很具有中国特色的,但必须支持安装WebEditor插件，才能正常运行<br />对于很多用户来说,,这个是无法接收的.<br /><br />3.InnovaStudio WYSIWYG Editor在线编辑器WYSIWYG 英文：What You See Is What You Get(所见所得)<br />一款基于web的WYSIWYG（所见即所得）的HTML编辑器，支持ASP, PHP, ASP.NET<br />最新版本:InnovaStudio WYSIWYG Editor version 2.9 <br />功能特性:快速加载,融合所有的HTML标签,全屏编辑模式,所见所得预览,拼写检查.<br />特有的嵌入式WEB编辑.<br />官方:<a href="http://www.innovastudio.com/" target="_blank"><font color="#000080">http://www.innovastudio.com/</font></a><br />演示:<a href="http://www.innovastudio.com/editor_tutorial.asp" target="_blank"><font color="#000080">http://www.innovastudio.com/editor_tutorial.asp</font></a><br />下载:官方好像都是收费的,,自己去网上搜索找找,好像有人已经做过有2.0的汉化版<br /><br /><br />小节:采用DHTML, javascript 构件的WYSIWYG也有很多不足之处，由于代码放在远程服务器，<br />一些控件事先没有下载到客户端，使得一些操作速度变慢，那些加入了ActiveX 控件的更慢，<br />另外它无法在网页里直接调用CSS，所以在操作框里的界面效果和尺寸和实际上的界面有差距。<br />有很多WYSIWYG对各种浏览器还不兼容,而且有的也要在IE的高版本下才能正常运行(此段出自老鬼的blog).<br /><br /><br />4.eWebEditor在线编辑器<br /><br />eWebEditor是基于网页的、所见即所得的在线HTML编辑器。她能够在网页上实现许多桌面编辑软件<br />（如：Word）所具有的强大可视编辑功能；她是一个真正的绿色软件，不需要在计算机上安装<br />任何的客户端软件；她的易用使得WEB开发人员只要一行代码即可完成调用。<br />最新版本:Version 3.6 (ASP版、PHP版、JSP版、ASP.NET版)<br />官方:<a href="http://www.ewebsoft.com/" target="_blank"><font color="#000080">http://www.ewebsoft.com/</font></a><br />演示:<a href="http://ewebeditor.webasp.net/demo.asp" target="_blank"><font color="#000080">http://ewebeditor.webasp.net/demo.asp</font></a><br />下载:<a href="http://ewebeditor.webasp.net/download.asp" target="_blank"><font color="#000080">http://ewebeditor.webasp.net/download.asp</font></a><br />功能特性:<br />纯静态：大大提高了效率，最佳的融入您的产品； <br />多样式支持：您只需要在您的整个网站中使用一个eWebEditor； <br />自动提交：无需在提交按钮中加入脚本进行处理； <br />自动获取远程文件：把别人服务器上的图片等文件自动传到自己的服务器； <br />相对或绝对路径：完全摆脱了站点或系统或目录迁移而带来的路径问题； <br />图形热点链接：始创能够在线编辑实现图形的热点链接功能； <br />多种编辑模式：HTML代码模式、可视设计模式、纯文本模式、预览模式； <br />大小自适应：可以按你调用的宽度和高度自适应编辑器的大小； <br />内附文件上传功能：自带有从客户端直接上传到服务器端的功能； <br />完善的接口：您可以通过接口实时控制或者获取编辑器的内容或者状态；<br /><br /><br />小节:我个人比较推荐这个编辑器,为什么呢?除了他是国产的外,比较符合国人的习惯,另外也可能是众多编辑器,<br />唯一还带后台管理模式,可以直接在后台管理编辑模式,<br />另外接口定制非常容易,具体的自己可以去官方下载回来看看.<br /><br /><br />5.htmlarea<br />htmlarea.com is a directory of browser based wysiwyg editor components for use<br />in CMS (content management software) and other web software. <br />htmlArea是一款非常优秀的所见即所得编辑器,被使用在CMS系统或其他的WEB系统中..<br />语言环境:多国语言版<br />版本:version 3.0<br />官方:<a href="http://www.htmlarea.com/" target="_blank"><font color="#000080">http://www.htmlarea.com/</font></a><br />演示:没找到,<br />下载:官方没找到下载地址,我自己找了个3.0的版本 <a href="http://www.92key.com/mp3/chinahtml@_HTMLArea3.rar" target="_blank"><font color="#000080">http://www.92key.com/mp3/chinahtml@_HTMLArea3.rar</font></a><br />小节:这个编辑器调用也非常方便,<br />已经广泛用在各种CMS和blog系统里,记得bo-blog,phpArticle里整合了这个编辑器.<br /><br /><br />6.XStandard XHTML (Strict or 1.1) WYSIWYG Editor 也是所见所得,比起前几个,,它已经完全支持XHTML 1.1的严格验证,<br />这个非常厉害 @@<br />版本:XStandard Version 1.6.2<br />官方:<a href="http://xstandard.com/" target="_blank"><font color="#000080">http://xstandard.com/</font></a><br />下载:<a href="http://xstandard.com/download.asp" target="_blank"><font color="#000080">http://xstandard.com/download.asp</font></a><br />演示:<a href="http://blog.sina.com.cn/pic/405da78d0200001h" target="_blank"><img title="http://blog.sina.com.cn/pic/405da78d0200001h" alt="http://blog.sina.com.cn/pic/405da78d0200001h" src="http://blog.sina.com.cn/pic/405da78d0200001h" border="1" /></a><br />小节:这个编辑器,我也很少在国内的CMS,blog上见到有人使用,当然一个原因就是它是一个共享软件.<br />XStandard Lite是免费的<br />XStandard Pro是30天的试用期,而且价格还不菲$179<br /><br /><br />7.Cross-Browser Rich Text Editor<br />The cross-browser rich-text editor (RTE) is based on the designMode() functionality introduced in Internet Explorer 5, and implemented in Mozilla 1.3+ using the Mozilla Rich Text Editing API. The cross-browser rich-text editor now includes table support (as of 2/10/2005) as well as an option to generate xhtml-compliant code<br /><br />官方:<a href="http://www.kevinroth.com/" target="_blank"><font color="#000080">http://www.kevinroth.com</font></a><br />演示:<a href="http://www.kevinroth.com/rte/demo.htm" target="_blank"><font color="#000080">http://www.kevinroth.com/rte/demo.htm</font></a><br />下载:<a href="http://www.kevinroth.com/rte/demo.htm" target="_blank"><font color="#000080">http://www.kevinroth.com/rte/demo.htm</font></a> <br /> <br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1478143</p><br /></div>
<img src ="http://www.blogjava.net/zqli/aggbug/93253.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2007-01-11 20:35 <a href="http://www.blogjava.net/zqli/archive/2007/01/11/93253.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat、Jboss数据源配置手记总结</title><link>http://www.blogjava.net/zqli/archive/2006/12/25/89967.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Mon, 25 Dec 2006 11:33:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/12/25/89967.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/89967.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/12/25/89967.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/89967.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/89967.html</trackback:ping><description><![CDATA[
		<p>一、Tomcat5.5.7+SQL Server2000<br />1、把数据库JDBC驱动（msutil.jar、mssqlserver.jar、msbase.jar）拷贝到%TOMCAT_HOME%/common/lib和% TOMCAT_HOME%/webapps/yourweb/WEB-INF/lib下。并把tools.jar（可选）、commons-collections-2.1.jar、commons-dbcp-1.2.1.jar、commons-logging-api-1.0.2.jar、commons-pool-1.3.jar拷到%TOMCAT_HOME%/common/lib目录下。<br />2、修改%TOMCAT_HOME%/conf/server.xml文件,在  &lt;GlobalNamingResources&gt;&lt;/GlobalNamingResources&gt;之间<br />添加以下内容：<br /><br /> &lt;!-- Global JNDI resources --&gt;<br />  &lt;GlobalNamingResources&gt;<br /> &lt;Resource      name="jdbc/MSSQLDS"      type="javax.sql.DataSource"      password="sa"      driverClassName="com.microsoft.jdbc.sqlserver.SQLServerDriver"      maxIdle="30"      maxWait="5000"      username="sa"      url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=SuperDB"      maxActive="30"/&gt;</p>
		<p>    &lt;!-- Test entry for demonstration purposes --&gt;<br />    &lt;Environment name="simpleValue" type="java.lang.Integer" value="30"/&gt;</p>
		<p>    &lt;!-- Editable user database that can also be used by<br />         UserDatabaseRealm to authenticate users --&gt;<br />    &lt;Resource name="UserDatabase" auth="Container"<br />              type="org.apache.catalina.UserDatabase"<br />       description="User database that can be updated and saved"<br />           factory="org.apache.catalina.users.MemoryUserDatabaseFactory"<br />          pathname="conf/tomcat-users.xml" /&gt;</p>
		<p>  &lt;/GlobalNamingResources&gt;<br /><br />注：<font size="2"><font face="Times New Roman"><span style="FONT-SIZE: 12pt">maxActive</span> ：<span style="FONT-SIZE: 12pt">指定数据库连接池中处于活动状态的数据库连接最大数目，</span><span style="FONT-SIZE: 12pt">0</span><span style="FONT-SIZE: 12pt">表示不受限制；<span style="FONT-SIZE: 12pt">maxIdle：<span style="FONT-SIZE: 12pt">指定数据库连接池中</span><font size="2"></font><span style="FONT-SIZE: 12pt">处于</span><font size="2"></font><span style="FONT-SIZE: 12pt">空闲状态的数据库连接的最大数目，</span><font size="2"></font><span style="FONT-SIZE: 12pt">0</span><font size="2"></font><span style="FONT-SIZE: 12pt">表示不受限制；<font size="2"><font face="Times New Roman"><span style="FONT-SIZE: 12pt">maxWait</span> ：<span style="FONT-SIZE: 12pt">指定数据库连接池中的数据库连接处于空闲状态的最长时间（单位为毫秒），超过这一事件，将会抛出异常。</span><span style="FONT-SIZE: 12pt">-1</span><span style="FONT-SIZE: 12pt">表示可以无限期等待；<span style="FONT-SIZE: 12pt">auth：<font size="2"><font face="Times New Roman"><span style="FONT-SIZE: 12pt">指定管理</span><span style="FONT-SIZE: 12pt">Resource</span><span style="FONT-SIZE: 12pt">的</span><span style="FONT-SIZE: 12pt">Manager</span><span style="FONT-SIZE: 12pt">，由两个可选值：</span><span style="FONT-SIZE: 12pt">Container</span><span style="FONT-SIZE: 12pt">和</span><span style="FONT-SIZE: 12pt">Application</span><span style="FONT-SIZE: 12pt">。</span><span style="FONT-SIZE: 12pt">Container</span><span style="FONT-SIZE: 12pt">表示由容器来创建和管理</span><span style="FONT-SIZE: 12pt">Resource</span><span style="FONT-SIZE: 12pt">，</span><span style="FONT-SIZE: 12pt">Application</span><span style="FONT-SIZE: 12pt">表示由</span><span style="FONT-SIZE: 12pt">WEB</span><span style="FONT-SIZE: 12pt">应用来创建和管理</span><span style="FONT-SIZE: 12pt">Resource</span><span style="FONT-SIZE: 12pt">。如果在</span><span style="FONT-SIZE: 12pt">web application deployment descriptor</span><span style="FONT-SIZE: 12pt">中使用</span><span style="FONT-SIZE: 12pt">&lt;resource-ref&gt;</span><span style="FONT-SIZE: 12pt">，这个属性是必需的，如果使用</span><span style="FONT-SIZE: 12pt">&lt;resource-env-ref&gt;</span><span style="FONT-SIZE: 12pt">，这个属性是可选的。</span></font></font></span></span></font></font></span></span></span></font></font></p>
		<p>
				<br />
				<br />3、在%TOMCAT_HOME%/conf/Catalina/localhost下新建一个与你web文件夹同名的xml文件（KuaiBaoWeb.war.xml）<br />这一步非常重要,如果没有这步就会出错,会出现错误：<br /><br />Database init error:org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'<br /><br />在文件中内容如下：<br /><br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;Context&gt;  <br />  &lt;Resource      name="jdbc/MSSQLDS"      type="javax.sql.DataSource"      password="sa"      driverClassName="com.microsoft.jdbc.sqlserver.SQLServerDriver"      maxIdle="30"      maxWait="5000"      username="sa"      url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=SuperDB"      maxActive="30"/&gt;<br />&lt;/Context&gt;<br /><br />可以看出，就是在元素&lt;Content&gt;里加入第2步同样的内容，根据个人情况做相应修改。<br />4、修改%TOMCAT_HOME%/webapps/yourweb/WEB-INF下的web.xml文件,在&lt;web-app&gt;&lt;/web-app&gt;之间添加以下内容：<br />  &lt;resource-ref&gt;<br />    &lt;res-ref-name&gt;jdbc/MSSQLDS&lt;/res-ref-name&gt;<br />    &lt;res-type&gt;javax.sql.DataSource&lt;/res-type&gt;<br />    &lt;res-auth&gt;Container&lt;/res-auth&gt;<br />  &lt;/resource-ref&gt;<br />jdbc/MSSQLDS为前面定义的JNDI名字。<br /><br />相应的获取JNDI的代码：<br />......<br />Context initCtx=new InitialContext();<br />                <br />DataSource ds=(DataSource)initCtx.lookup("java:comp/env/jdbc/MSSQLDS")<br />.......<br /><br />到此为止，数据源配置完成。<br /><br />二、Jboss3.2.8+SQL Server2000</p>
		<p>1、把数据库JDBC驱动（msutil.jar、mssqlserver.jar、msbase.jar）拷贝到jboss-3.2.8.SP1\server ..\lib目录下。<br />2、修改mssql-ds.xml文件,如下:<br /><br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;datasources&gt;<br />  &lt;local-tx-datasource&gt;<br />    &lt;jndi-name&gt;MSSQLDS&lt;/jndi-name&gt;<br />    &lt;connection-url&gt;jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=SuperDB&lt;/connection-url&gt;<br />    &lt;driver-class&gt;com.microsoft.jdbc.sqlserver.SQLServerDriver&lt;/driver-class&gt;<br />    &lt;user-name&gt;sa&lt;/user-name&gt;<br />    &lt;password&gt;sa&lt;/password&gt;<br />    &lt;connection-property name="char.encoding"&gt;UTF-8&lt;/connection-property&gt;<br />    &lt;min-pool-size&gt;30&lt;/min-pool-size&gt;<br />    &lt;max-pool-size&gt;100&lt;/max-pool-size&gt;<br />    &lt;blocking-timeout-millis&gt;5000&lt;/blocking-timeout-millis&gt;<br />    &lt;idle-timeout-minutes&gt;5&lt;/idle-timeout-minutes&gt;<br />  &lt;/local-tx-datasource&gt;<br />&lt;/datasources&gt;<br />获取JNDI代码：<br /><br /> ctx = new InitialContext();<br />    ds = (DataSource) ctx.lookup("java:/MSSQLDS");<br />      conn = ds.getConnection();<br /><br />数据源配置完成。注：JBOSS4.0下，配置多数据源比JBOSS3要容易。<br /></p>
<img src ="http://www.blogjava.net/zqli/aggbug/89967.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-12-25 19:33 <a href="http://www.blogjava.net/zqli/archive/2006/12/25/89967.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] 简单宜用的网站静态化思路及代码分析 </title><link>http://www.blogjava.net/zqli/archive/2006/12/18/88631.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Mon, 18 Dec 2006 12:41:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/12/18/88631.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/88631.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/12/18/88631.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/88631.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/88631.html</trackback:ping><description><![CDATA[
		<p>出处:http://www.net2china.net/blog/user1/sunychen/archives/2006/226.html<br /></p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<div class="post-body">
												<div>
														<font color="#ffffff" size="3">
																<a href="http://www.ewaimao.cn/blog/">finddream的外贸网络营销</a>
														</font>
												</div>
												<div>
														<font size="3">静态化是有很大好处的。最值得称道的应该是加快下载速度,更利于搜索引擎的抓取,这两点对一个企业网站来说应该比较重要吧。</font>
												</div>
												<div> </div>
												<div>
														<font size="3">一般的静态化是通过fso组件读取网站模板的内容，然后替换其中的特定字符，生成静态页面，这是个不错的想法，如果你要自己写一个网站，建议你用这种办法，因为比较稳定。而且如果想以后更换网站界面也相当容易，只需修改模板而无需更改程序。这个办法很多高手已经说得很明白了，推荐一个：</font>
												</div>
												<div>
														<font size="3">http://www.jingzhengli.cn/Blog/zjh/265.html</font>
												</div>
												<div> </div>
												<div>
														<font size="3">然而很不幸，很多公司的网站已经做好，而且每一页都是html中夹杂大量asp代码的形式，没有模板，功能也没有模块化，如果想仍用以上方法进行静态化处理，其复杂程度相当于重做一个网站。</font>
												</div>
												<div> </div>
												<div>
														<font size="3">提出一个简单宜用的解决办法。不用模板、不用修改程序，非常便捷。利用XMLHTTP对象及其方法。他的原理是将已有的asp网页内容一次性读取出来，然后写到静态页中，实现网站的静态化重构。</font>
												</div>
												<div> </div>
												<div>
														<font size="3">现在以生成 <a href="http://www.rocky-glass.com/"><font color="#3f729e">www.rocky-glass.com</font></a>的首页为例，介绍一下这种方法，代码如下：</font>
												</div>
												<div> </div>
												<div>
														<font size="3">Url="http://www.rocky-glass.com/default.asp" ‘<span style="COLOR: red">定义动态首页</span></font>
												</div>
												<div>
														<font size="3">wstr = GetPage(Url) ‘<span style="COLOR: red">把动态首页的内容全部读取出来</span></font>
												</div>
												<div> </div>
												<div>
														<font size="3">Set fs=Server.CreateObject("Scripting.FileSystemObject")</font>
												</div>
												<div> </div>
												<div>
														<font size="3">Set CrFi=fs.CreateTextFile(server.MapPath("../")&amp;"\index.htm") ‘<span style="COLOR: red">创建静态首页</span><span style="COLOR: red">index.htm</span></font>
												</div>
												<div>
														<font size="3">CrFi.Writeline(wstr) ‘<span style="COLOR: red">将读取出的内容写入静态页面</span></font>
												</div>
												<div>
														<font size="3">set CrFi=nothing ‘<span style="COLOR: red">关闭两个对象</span></font>
												</div>
												<div>
														<font size="3">set fs=nothing</font>
												</div>
												<div> </div>
												<div>
														<font size="3">以下两个函数涉及到xmlhttp对象和方法的使用，如果能看懂就看，看不懂直接调用就行。</font>
												</div>
												<div>
														<font size="3">
																<span style="COLOR: red">Function GetPage(url) </span>
																<span style="COLOR: red">‘此过程的功能是实现把</span>
																<span style="COLOR: red">asp</span>
																<span style="COLOR: red">网页的内容一次性读取出来。</span>
														</font>
												</div>
												<div>
														<font size="3">dim Retrieval</font>
												</div>
												<div>
														<font size="3">Set Retrieval = CreateObject("Microsoft.XMLHTTP") </font>
												</div>
												<div>
														<font size="3">With Retrieval </font>
												</div>
												<div>
														<font size="3">.Open "Get", url, False ', "", "" </font>
												</div>
												<div>
														<font size="3">.Send </font>
												</div>
												<div>
														<font size="3">GetPage = BytesToBstr(.ResponseBody)</font>
												</div>
												<div>
														<font size="3">End With </font>
												</div>
												<div>
														<font size="3">Set Retrieval = Nothing </font>
												</div>
												<div>
														<span style="COLOR: red">
																<font size="3">End Function</font>
														</span>
												</div>
												<div> </div>
												<div>
														<font size="3">
																<span style="COLOR: red">Function BytesToBstr(body)</span>
																<span style="COLOR: red">‘字符转换</span>
														</font>
												</div>
												<div>
														<font size="3">dim objstream</font>
												</div>
												<div>
														<font size="3">set objstream = Server.CreateObject("adodb.stream")</font>
												</div>
												<div>
														<font size="3">objstream.Type = 1</font>
												</div>
												<div>
														<font size="3">objstream.Mode =3</font>
												</div>
												<div>
														<font size="3">objstream.Open</font>
												</div>
												<div>
														<font size="3">objstream.Write body</font>
												</div>
												<div>
														<font size="3">objstream.Position = 0</font>
												</div>
												<div>
														<font size="3">objstream.Type = 2</font>
												</div>
												<div>
														<font size="3">objstream.Charset = "utf-8" ‘<span style="COLOR: red">如果是中文页面请用</span><span style="COLOR: red">gb2312.</span><span style="COLOR: red">，英文页面用</span><span style="COLOR: red">utf-8</span></font>
												</div>
												<div>
														<font size="3">BytesToBstr = objstream.ReadText </font>
												</div>
												<div>
														<font size="3">objstream.Close</font>
												</div>
												<div>
														<font size="3">set objstream = nothing</font>
												</div>
												<div>
														<span style="COLOR: red">
																<font size="3">End Function</font>
														</span>
												</div>
												<div> </div>
												<div>
														<font size="3">首页的静态化就完成了，生成为 index.htm 这个静态页，其他的页面也可以按照这个思路进行，利用不同的后缀id值，就可以批量生成所有网页。</font>
												</div>
												<div> </div>
												<div>
														<font size="3">两点注意：1、如果是批量生成页面要保证网速，否则程序的运行很容易超出服务器的允许时间。</font>
												</div>
												<div>
														<font size="3">
																<span>          2</span>、生成英文页面的时候，要保证原页面上没有汉字或其他语言，否则生成出错。</font>
												</div>
												<div> </div>
												<div>
														<font size="3">这种静态化相对比较容易，尤其是那些对那些写的很差劲的网站进行静态化处理。我一直用这种方法给企业静态化处理。</font>
												</div>
												<div>
														<font size="3">有机会我会把这种方法进一步写成类，方便各位网友调用。</font>
												</div>
												<div> </div>
												<div>
														<font size="3">下边说说两种骗人的静态化方案，引起各位注意。</font>
												</div>
												<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt">
														<font size="3">
																<span>1、 </span>框架伪静态,这种是非常简单而且也是非常便于识别的,它的原理比较简单,就是做一个静态的主框架页面,然后把动态的内容链入副框架内,这个单从它的URL就可以看出眉目,如果整个网站的URL都是一样的,那么就一定是框架伪静态的。这种所谓的静态化不仅达不到优化的目的，而且还不如不优化。</font>
												</div>
												<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt">
														<font size="3">
																<span>2、 </span>利用组件把asp的辍显示为htm,它主要是利用一个组件强制性的把asp文件的后辍显示为htm,比较有名的组件是MOD REWRITE，这种东西只是在形式上让你感觉已经静态化了，其实仍然是执行动态网页。识别这个也比较容易，那就是看看有没有生成静态页就是了。如果没有生成静态页，显然是骗人的，因为只有动态页才是虚拟的，从数据库中调用数据进行显示，而静态页面一定是独立的。当然，利用这种方案可以起到seo优化作用，但是对访问速度来说，是一点提高都没有的，而且还有可能降低访问速度。</font>
												</div>
										</div>
								</td>
						</tr>
				</tbody>
		</table> <br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1444169</p><img src ="http://www.blogjava.net/zqli/aggbug/88631.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-12-18 20:41 <a href="http://www.blogjava.net/zqli/archive/2006/12/18/88631.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]漫谈解决Struts分页显示</title><link>http://www.blogjava.net/zqli/archive/2006/12/11/86948.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Mon, 11 Dec 2006 08:37:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/12/11/86948.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/86948.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/12/11/86948.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/86948.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/86948.html</trackback:ping><description><![CDATA[
		<p>漫谈解决Struts分页显示  <br /><br /><font color="#ff0000">方案&lt;一&gt;<br /></font><br />   ChinaITLab 收集整理     2004-9-24   <br />学习Struts已经有2个多月了，前几天群里的朋友问我Struts分页显示的问题，觉得好像与在jsp中的差不多，但还是遇到了这样那样的问题，好不容易花了几天时间把问题都搞清楚，觉得还是写点东西跟大家分享一下的好！<br />至于Struts的语法这里就不多介绍了，不懂的朋友可以先看网上的其他文章。<br />一 开发环境<br />Elicpse+Struts Studio+SqlServer2000+Tomcat。<br />二 开发思路<br />既然讲的是Struts，那自然离不了MVC，分页显示也是如此。<br />1 建立适当的模型组件，对应你要查询数据库中的表。这部分由我们熟悉的javaBean来充当。并在其中建立数据库查询方法，该方法需要一个java.sql.Conntection类型的参数，并返回一个ArrayList。在本例中为 Book.java<br />2 建立分页所需要的模型组件，也是由javaBean来充当，通过由Book中提供的ArrayList来构造。本例中为 PageBean.java.。<br />3建立控制器组件，这部分由Struts 中的Action来实现。主要负责将实例化Book，并利用返回的ArrayList对象，构造PageBean。以及接收由视图传递而来的action参数。从而在PageBean对象中调用不同的方法，该方法返回Book[] 对象。最后将 Book[]和PageBean放入request中。本例中为PageListAction.java。<br />4建立视图组件，这部分由jsp来充当，为了不出现java 代码，我们使用Struts提供的标签库，主要负责从request中取出刚刚放入的对象，通过反复调用PageListAction以及action参数，而实现分页显示。本例中为pagetest.jsp.<br />5 建立并配置struts-config.xml。<br />6 建立数据库。<br />三 实例代码<br />1 Book.java<br />package bean;<br />import java.sql.*;<br />import java.util.ArrayList;<br />/**<br />* Struts分页显示数据Bean，对应数据库中Book表<br />*/<br />public class Book {<br />private String bookname; //书名<br />private String author;　 //作者<br />private String price;　　//价格</p>
		<p>public Book(String name,String author,String price){<br />this.bookname=name;<br />this.author=author;<br />this.price=price;<br />}</p>
		<p>public String getAuthor() {<br />return author;<br />}</p>
		<p>public void setAuthor(String author) {<br />this.author = author;<br />}</p>
		<p>public String getBookname() {<br />return bookname;<br />}</p>
		<p>public void setBookname(String bookname) {<br />this.bookname = bookname;<br />}</p>
		<p>public String getPrice(){<br />return this.price;<br />}</p>
		<p>public void setPrice(String price){<br />this.price=price;<br />}</p>
		<p>public static ArrayList getAllBook(Connection connection){<br />String sql="select * from book";<br />ArrayList arrayList = new ArrayList();<br />try{<br />Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);<br />ResultSet resultSet = statement.executeQuery(sql);<br />System.out.println("BookBean 数据查询已完成！");<br />while(resultSet.next())<br />{<br />String name = resultSet.getString("name");<br />String author = resultSet.getString("author");<br />String price = resultSet.getString("price");<br />System.out.println("开始数据封装：name="+name+"author="+author+"price="+price);<br />Book book = new Book(name,author,price);<br />arrayList.add(book);<br />}<br />connection.close();<br />resultSet.close();<br />}catch(SQLException e)<br />{<br />System.out.println("数据库异常"+e.toString());<br />}</p>
		<p>return arrayList;<br />}<br />}</p>
		<p>2 PageBean.java<br />package page;<br />import bean.Book;<br />import java.util.*;<br />/**<br />* Struts分页显示逻辑Bean<br />*/<br />public class PageBean {</p>
		<p>int currentPage=1;　//当前页<br />public int totalPages=0;　//总页数<br />int pageRecorders=5;//每页5条数据<br />int totalRows=0;　//总数据数<br />int pageStartRow=0;//每页的起始数<br />int pageEndRow=0;　//每页显示数据的终止数<br />boolean hasNextPage=false; //是否有下一页<br />boolean hasPreviousPage=false; //是否有前一页<br />ArrayList arrayList;<br />Iterator it;<br />public PageBean(){}</p>
		<p>public PageBean(ArrayList arrayList){<br />this.arrayList=arrayList;<br />totalRows=arrayList.size();<br />it=arrayList.iterator();<br />hasPreviousPage=false;<br />currentPage=1;<br />if((totalRows%pageRecorders)==0)<br />{<br />totalPages=totalRows/pageRecorders;<br />}<br />else<br />{<br />totalPages=totalRows/pageRecorders+1;<br />}</p>
		<p>if(currentPage&gt;=totalPages)<br />{<br />hasNextPage=false;<br />}<br />else<br />{<br />hasNextPage=true;<br />}</p>
		<p>
				<br />if(totalRows&lt;pageRecorders)<br />{<br />this.pageStartRow=0;<br />this.pageEndRow=totalRows;<br />}<br />else<br />{<br />this.pageStartRow=0;<br />this.pageEndRow=pageRecorders;<br />}</p>
		<p>}</p>
		<p>/**<br />* @return Returns the currentPage.<br />*/<br />public String getCurrentPage() {<br />return this.toString(currentPage);<br />}<br />/**<br />* @param currentPage The currentPage to set.<br />*/<br />public void setCurrentPage(int currentPage) {<br />this.currentPage = currentPage;<br />}<br />/**<br />* @return Returns the pageRecorders.<br />*/<br />public int getPageRecorders() {<br />return pageRecorders;<br />}<br />/**<br />* @param pageRecorders The pageRecorders to set.<br />*/<br />public void setPageRecorders(int pageRecorders) {<br />this.pageRecorders = pageRecorders;<br />}<br />/**<br />* @return Returns the pageEndRow.<br />*/<br />public int getPageEndRow() {<br />return pageEndRow;<br />}<br />/**<br />* @return Returns the pageStartRow.<br />*/<br />public int getPageStartRow() {<br />return pageStartRow;<br />}<br />/**<br />* @return Returns the totalPages.<br />*/<br />public String getTotalPages() {</p>
		<p>return this.toString(totalPages);<br />}<br />/**<br />* @return Returns the totalRows.<br />*/<br />public String getTotalRows() {<br />return this.toString(totalRows);<br />}<br />/**<br />* @return Returns the hasNextPage.<br />*/<br />public boolean isHasNextPage() {<br />return hasNextPage;<br />}<br />/**<br />* @param hasNextPage The hasNextPage to set.<br />*/<br />public void setHasNextPage(boolean hasNextPage) {<br />this.hasNextPage = hasNextPage;<br />}<br />/**<br />* @return Returns the hasPreviousPage.<br />*/<br />public boolean isHasPreviousPage() {<br />return hasPreviousPage;<br />}<br />/**<br />* @param hasPreviousPage The hasPreviousPage to set.<br />*/<br />public void setHasPreviousPage(boolean hasPreviousPage) {<br />this.hasPreviousPage = hasPreviousPage;<br />}<br />public Book[] getNextPage(){</p>
		<p>currentPage=currentPage+1;<br />System.out.println("PageBean.getNextPage()正在执行；");<br />System.out.println("参数currentPage="+currentPage);</p>
		<p>if((currentPage-1)&gt;0)<br />{<br />hasPreviousPage=true;<br />}<br />else<br />{<br />hasPreviousPage=false;<br />}<br />if(currentPage&gt;=totalPages)<br />{<br />hasNextPage=false;<br />}<br />else<br />{<br />hasNextPage=true;<br />}<br />System.out.println("参数hasNextPage="+hasNextPage);<br />System.out.println("准备执行PageBean.getBooks()");<br />Book[] books=getBooks();<br />this.description();<br />return books;<br />}</p>
		<p>public Book[] getPreviouspage(){<br />currentPage=currentPage-1;</p>
		<p>if(currentPage==0){currentPage=1;}</p>
		<p>if(currentPage&gt;=totalPages)<br />{<br />hasNextPage=false;<br />}<br />else<br />{<br />hasNextPage=true;<br />}<br />if((currentPage-1)&gt;0)<br />{<br />hasPreviousPage=true;<br />}<br />else<br />{<br />hasPreviousPage=false;<br />}<br />Book[] books=getBooks();<br />this.description();<br />return books;<br />}</p>
		<p>public Book[] getBooks(){<br />System.out.println("pageBean.getBooks（）开始执行；");<br />if(currentPage*pageRecorders&lt;totalRows){//判断是否为最后一页<br />pageEndRow=currentPage*pageRecorders;<br />pageStartRow=pageEndRow-pageRecorders;<br />}<br />else{<br />pageEndRow=totalRows;<br />pageStartRow=pageRecorders*(totalPages-1);<br />}<br />Book[] books=new Book[pageEndRow-pageStartRow+1];</p>
		<p>System.out.println("pageStartRow="+pageStartRow);<br />System.out.println("pageEndRow="+pageEndRow);<br />int j=0;<br />for(int i=pageStartRow;i&lt;pageEndRow;i++)<br />{<br />Book book=(Book)arrayList.get(i);<br />books[j++]=book;</p>
		<p>}<br />System.out.println("要显示的页面数据已经封装,具体信息如下：");<br />this.description();<br />return books;<br />}</p>
		<p>public String toString(int temp)<br />{<br />String str=Integer.toString(temp);<br />return str;<br />}</p>
		<p>public void description()<br />{<br />String description="共有数据数:"+this.getTotalRows()+"共有页数: "+this.getTotalPages() +"当前页数为:"+this.getCurrentPage()+" 是否有前一页: "+this.isHasPreviousPage() +" 是否有下一页:"+this.isHasNextPage()+" 开始行数:"+this.getPageStartRow()+" 终止行数:"+this.getPageEndRow();<br />System.out.println(description);<br />}<br />}<br />3　PageListAction.java<br />package page;<br />import org.apache.struts.action.*;<br />import javax.servlet.http.*;<br />import comm.Constants;<br />import bean.Book;<br />import java.util.*;<br />import javax.sql.DataSource;<br />/**<br />* Struts分页显示Action<br />*/<br />public class PageListAction extends Action {</p>
		<p>public PageListAction(){}<br />ArrayList arrayList=new ArrayList();<br />PageBean pb;</p>
		<p>public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {<br />String action;<br />action=request.getParameter("action");<br />if(action==null || action.equals("null")){ //第一次读取数据<br />try{<br />DataSource datasource=this.getDataSource(request,Constants.DATASOURCE_KEY);<br />arrayList=Book.getAllBook(datasource.getConnection());<br />System.out.println("第一步，数据已经成功传递到Action，action="+action);<br />}catch(Exception e){<br />e.printStackTrace();<br />System.out.println("数据库连接出现异常");<br />}<br />pb=new PageBean(arrayList);<br />Book[] books=pb.getBooks();<br />pb.description();<br />request.setAttribute("result",books);<br />request.setAttribute("page",pb);<br />}<br />else<br />{<br />if(action=="nextPage" || action.equals("nextPage"))<br />{<br />System.out.println("参数action="+action);<br />System.out.println("函数pb.getNextPage()准备执行");<br />Book[]books=pb.getNextPage();<br />request.setAttribute("page",pb);<br />request.setAttribute("result",books);<br />}<br />if(action=="previousPage" || action.equals("previousPage"))<br />{<br />System.out.println("参数action="+action);<br />System.out.println("函数pb.getPreviouspage()准备执行");<br />Book[] books=pb.getPreviouspage();<br />request.setAttribute("page",pb);<br />request.setAttribute("result",books);<br />}<br />}<br />return (mapping.findForward("success"));<br />}<br />}<br />4 pagetest.jsp<br />&lt;%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %&gt;<br />&lt;%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %&gt;<br />&lt;%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %&gt;<br />&lt;%@ page contentType="text/html; charset=gb2312" language="java"%&gt;<br />&lt;html:html locale="true"&gt;<br />&lt;head&gt;<br />&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<br />&lt;/head&gt;<br />&lt;body&gt;<br />&lt;table border="1"&gt;<br />&lt;tr&gt;&lt;th&gt;书名&lt;/th&gt;&lt;th&gt;作者&lt;/th&gt;&lt;th&gt;价格&lt;/th&gt;&lt;/tr&gt;<br />&lt;logic:present name="result"&gt;<br />&lt;logic:iterate id="book" name="result"　type="bean.Book" &gt;<br />&lt;logic:present name="book"&gt;<br />&lt;tr&gt;<br />&lt;td&gt;&lt;bean:write name="book" property="bookname" /&gt;&lt;/td&gt;<br />&lt;td&gt; &lt;bean:write name="book" property="author" /&gt;&lt;/td&gt;<br />&lt;td&gt;&lt;bean:write name="book" property="price" /&gt;&lt;/td&gt;<br />&lt;/tr&gt;<br />&lt;/logic:present&gt;<br />&lt;/logic:iterate&gt;<br />&lt;/logic:present&gt;<br />&lt;/table&gt;<br />&lt;logic:equal name="page" property="hasNextPage" value="true"&gt;<br />&lt;html:link page="/page.do?action=nextPage"&gt;nextPage&lt;/html:link&gt;<br />&lt;/logic:equal&gt;<br />&lt;logic:equal name="page" property="hasPreviousPage" value="true"&gt;<br />&lt;html:link page="/page.do?action=previousPage"&gt;PreviousPage&lt;/html:link&gt;<br />&lt;/logic:equal&gt;<br />共有数据总数&lt;bean:write name="page" property="totalRows"/&gt;;<br />共分&lt;bean:write name="page" property="totalPages"/&gt;页,当前是第<br />&lt;bean:write name="page" property="currentPage"/&gt;页<br />&lt;/body&gt;<br />&lt;/html:html&gt;<br />5 struts-config.xml<br />&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;</p>
		<p>&lt;!DOCTYPE struts-config PUBLIC<br />"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"<br />"<a href="http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd</a>";&gt;</p>
		<p>&lt;struts-config&gt;<br />&lt;data-sources&gt;<br />&lt;data-source key="dataSource" type="org.apache.commons.dbcp.BasicDataSource"&gt;<br />&lt;set-property property="driverClassName" value="com.microsoft.jdbc.sqlserver.SQLServerDriver"/&gt;<br />&lt;set-property property="url" value="jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=eBookStore;SelectMethod=cursor"/&gt;<br />&lt;set-property property="username" value="limq"/&gt;<br />&lt;set-property property="password" value="1"/&gt;<br />&lt;set-property property="maxActive" value="10"/&gt;<br />&lt;set-property property="maxWait" value="5000"/&gt;<br />&lt;set-property property="defaultAutoCommit" value="true"/&gt;<br />&lt;set-property property="defaultReadOnly" value="false"/&gt;<br />&lt;/data-source&gt;<br />&lt;/data-sources&gt;<br />&lt;form-beans&gt;<br />&lt;/form-beans&gt;<br />&lt;global-forwards&gt;<br />&lt;/global-forwards&gt;<br />&lt;action-mappings&gt;<br />&lt;action path="/page" type="page.PageListAction" scope="request"&gt;<br />&lt;forward name="success" path="/pagetest.jsp"/&gt;<br />&lt;/action&gt;<br />&lt;/action-mappings&gt;<br />&lt;controller&gt;<br />&lt;/controller&gt;<br />&lt;/struts-config&gt;<br />6 建立eBookStore数据库，以及表book（name,author,parce）;其中数据的配置可以根据你的不同情况在struts-config.xml中而定。<br />7 Constants.java<br />package comm;</p>
		<p>/**<br />* this interface provides the constant string for applicator constant<br />*/<br />public class Constants {<br />/**<br />* name of the User Object in HttpSession<br />*/<br />public static String USER_KEY="user";<br />/**<br />* dataSource name<br />*/<br />public static String DATASOURCE_KEY="dataSource";<br />}</p>
		<p>
				<font color="#ff0000">方案&lt;二&gt;</font>
				<br />
		</p>
		<h2 class="diaryTitle">●struts中的分页实例- -</h2>
		<p>                                       </p>
		<p>
		</p>
		<p>
				<font color="#333333">这仅是一个入门实例，简洁实用，从网上整理而来，供参考。这里仅列出部分文件，其它文件、数据库及目录结构请从本站下载。<a href="http://blog.blogchina.com/mcp/error.jsp" target="_blank">下载源文件</a></font>
		</p>
		<p>
				<br />
				<font color="#333333">一、struts-config.xml配置，主要是配数据库,这里用access。 <br />&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt; <br /><br />&lt;!DOCTYPE struts-config PUBLIC <br />          "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" <br />          "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"&gt; <br /><br /><br />&lt;struts-config&gt; <br />&lt;data-sources&gt; <br />   &lt;data-source key="dataSource" type="org.apache.commons.dbcp.BasicDataSource"&gt; <br />            &lt;set-property property="driverClassName" value="sun.jdbc.odbc.JdbcOdbcDriver" /&gt; <br />            &lt;set-property property="url" value="jdbc:odbc:page" /&gt; <br />            &lt;set-property property="username" value="admin" /&gt; <br />            &lt;set-property property="password" value="" /&gt; <br />            &lt;set-property property="maxActive" value="20" /&gt; <br />            &lt;set-property property="maxWait" value="5000" /&gt; <br />            &lt;set-property property="defaultAutoCommit" value="true" /&gt; <br />            &lt;set-property property="defaultReadOnly" value="false" /&gt; <br />            &lt;set-property property="validationQuery" value="SELECT 1" /&gt; <br />            &lt;set-property property="removeAbandoned" value="true" /&gt; <br />            &lt;set-property property="removeAbandonedTimeout" value="120" /&gt;             <br />            &lt;set-property property="encoding" value="false" /&gt;             <br />        &lt;/data-source&gt; <br /><br /> &lt;/data-sources&gt; <br />  &lt;form-beans&gt; <br />  &lt;/form-beans&gt; <br />  &lt;global-forwards&gt; <br />  &lt;/global-forwards&gt; <br /><br />  &lt;action-mappings&gt; <br />  &lt;action path="/page" type="page.DataSourceAction" scope="request"&gt; <br />  &lt;forward name="success" path="/pagetest.jsp"/&gt; <br />  &lt;/action&gt; <br />  &lt;/action-mappings&gt; <br /><br />  &lt;controller&gt; <br />  &lt;/controller&gt; <br />&lt;/struts-config&gt; <br /><br />二、Action类 <br />用 page.do?start=1 来显示第一个页面  <br />参数说明：  <br />  list：信息列表  <br />  start：开始位置  <br />  page：每页显示的信息数目  <br />  pages: 总页数 <br />  previous：上页开始位置  <br />  next：下页开始位置  <br /><br />package page; <br />import org.apache.struts.action.*; <br />import javax.servlet.http.*; <br /><br />import java.util.*; <br />import javax.sql.*; <br />import java.sql.*; <br />import bean.*; <br /><br />public class DataSourceAction extends Action { <br /><br /> public DataSourceAction(){} <br />  <br /> public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {    <br />  try{ <br />      DataSource ds=this.getDataSource(request,"dataSource");    <br />      Connection con = ds.getConnection(); <br />      Statement stmt = con.createStatement(); <br />      ResultSet resultSet = stmt.executeQuery("select count(*) from book" );  <br />      resultSet.next();  <br />      int data_num=resultSet.getInt(1);  <br />      int start=1; <br />      int page = 4; //每页的记录数。 <br />      int pages=data_num/page; <br />      if(data_num%page!=0) <br />         pages++; <br />      if(request.getParameter("start")!=null) <br />          start = Integer.parseInt(request.getParameter("start"));  <br />      if(request.getParameter("go")!=null){ <br />                int go = Integer.parseInt(request.getParameter("go"));  <br />                if(go&lt;=1) <br />                  start=1; <br />                else if(go&gt;pages) <br />                  start=(pages-1)*page+1; <br />                else  <br />                   start=(go-1)*page+1; <br />       }  <br />      <br />      String sql = "SELECT * FROM book where id&gt;="+start+" and id&lt;"+(start+page); <br />      resultSet = stmt.executeQuery(sql);   <br />      ArrayList list = new java.util.ArrayList();  <br />      while(resultSet.next()) <br />      {   <br />        int id=resultSet.getInt("id"); <br />        String name = resultSet.getString("name"); <br />        String author = resultSet.getString("author"); <br />        String price = resultSet.getString("price"); <br />        System.out.println("开始数据封装：name="+name+"author="+author+"price="+price); <br />        Book book= new Book(id,name,author,price);        <br />        list.add(book); <br />      } <br />    con.close(); <br />    request.setAttribute("pages",new Integer(pages)); <br />    request.setAttribute("list",list); <br />    //request.setAttribute("start", new Integer(start));  <br />    request.setAttribute("page", new Integer(page));  <br /><br />        // if there is a previous page, set the previous variable  <br />        int previous = start-page;  <br />        if ( previous&gt;=0 ){  <br />            request.setAttribute("previous", new Integer(previous));  <br />            System.out.println ("previous:" + previous);  <br />        }  <br /><br />        // if there is a next page, set the next variable  <br />        int next = start+page;  <br />        if ( next&lt;=data_num ){  <br />            request.setAttribute("next", new Integer(next));  <br />            System.out.println ("next:" + next);  <br />        }  <br /><br />   }catch(SQLException e){ <br />          e.printStackTrace(); <br />          System.out.println("数据库连接出现异常"); <br />      }  <br />    <br />             return (mapping.findForward("success")); <br />  }  <br />} <br /><br /><br />三、bean类Book.java <br />package bean; <br />import java.sql.*; <br />import java.util.ArrayList; <br />public class Book { <br /> int id; <br /> private String bookname; //书名 <br /> private String author;   //作者 <br /> private String price;    //价格 <br />  <br />public Book(int id,String name,String author,String price){ <br /> this.id=id; <br /> this.bookname=name; <br /> this.author=author; <br /> this.price=price; <br />} <br /><br />public int getId(){  <br />        return id;  <br />    }  <br /><br /> public String getAuthor() { <br />  return author; <br /> } <br /><br /> public void setAuthor(String author) { <br />  this.author = author; <br /> } <br /><br /> public String getBookname() { <br />  return bookname; <br /> } <br /><br /> public void setBookname(String bookname) { <br />  this.bookname = bookname; <br /> } <br />  <br /> public String getPrice(){ <br />     return this.price;  <br /> } <br />  <br /> public void setPrice(String price){ <br />     this.price=price;  <br /> } <br />  <br />} <br />四、分页的jsp页面pagetest.jsp,用了jstl中的c标记。 <br />&lt;%@ page contentType="text/html; charset=gb2312" language="java"%&gt; <br />&lt;%@ page import="java.util.*" %&gt; <br />&lt;%@ page import="bean.*" %&gt; <br />&lt;%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %&gt; <br />&lt;%@ taglib uri="/tags/struts-bean" prefix="bean" %&gt; <br />&lt;%@ taglib uri="/tags/struts-html" prefix="html" %&gt; <br />&lt;%@ taglib uri="/tags/struts-logic" prefix="logic" %&gt; <br /><br />&lt;logic:iterate id="book" name="list" type="bean.Book"&gt;  <br />            &lt;br&gt;&lt;html:link   <br />                    paramId="id" paramName="book" paramProperty="id"  <br />                    page="/messagedetail.do"&gt;  <br />                    &lt;bean:write name="book" property="bookname" /&gt;  <br />                &lt;/html:link&gt;  <br />&lt;/logic:iterate&gt;  <br /><br />&lt;form action="/TestPage/page.do"&gt; <br />   &lt;logic:present name="previous"&gt;  <br />            &lt;html:link   <br />                    paramId="start" paramName="previous"  <br />                    page="/page.do"&gt;  <br />                    上一页  <br />                &lt;/html:link&gt;  <br />   &lt;/logic:present&gt;  <br /><br />   &lt;logic:present name="next"&gt;  <br />              &lt;html:link   <br />                    paramId="start" paramName="next"  <br />                    page="/page.do"&gt;  <br />                    下一页  <br />                &lt;/html:link&gt;  <br />   &lt;/logic:present&gt;  <br /><br />每页&lt;c:out value="${page}"/&gt;条记录,共&lt;c:out value="${pages}"/&gt;页  跳到&lt;input type="text"  name="go" size="3" maxlength="30" &gt; <br />&lt;input type="submit" value="go" &gt; <br />&lt;/form&gt; <br />          <br /><br /><br /><br />OK!!!! <br />五、测试，请下载本实例的目录结构TestPage,放入tomcat的webapps下，在浏览器中输入： <br />    http://127.0.0.1:8080/TestPage/page.do </font>
				<br />
		</p>
<img src ="http://www.blogjava.net/zqli/aggbug/86948.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-12-11 16:37 <a href="http://www.blogjava.net/zqli/archive/2006/12/11/86948.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]乱码问题之终极解决 </title><link>http://www.blogjava.net/zqli/archive/2006/12/08/86380.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 08 Dec 2006 08:07:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/12/08/86380.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/86380.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/12/08/86380.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/86380.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/86380.html</trackback:ping><description><![CDATA[
		<p>多人 特别是新手 做j2ee 项目中<br />总能受困于 这样或那样的编码问题</p>
		<p>这里讨论下 新手学习，高手指教 一起研究下<br />(以 tomcat mysql 做例子 我推荐所有的编码采用utf-8)</p>
		<p>1 工程<br />工程内所有的 .java .jsp .xml .txt 都有默认的编码 默认的是系统环境的编码<br />我们中文系统通常是GBK 推荐都采用utf-8 <br />utf-8 的时候 你编译 生成doc 可能会遇到乱码（特别是采用ant 的时候,生成doc你几乎100%会遇到）</p>
		<p>解决方法 以ant 为例子<br />编译 注意 encoding 参数<br />&lt;target name="build" &gt;<br />       &lt;mkdir dir="${build.dir}" /&gt;<br />       &lt;javac encoding="utf-8" destdir="${build.dir}" target="1.3" debug="true" deprecation="false" optimize="false" failonerror="true"&gt;<br />           &lt;src path="${src.dir}" /&gt;<br />           &lt;classpath refid="master-classpath" /&gt;<br />       &lt;/javac&gt;<br />   &lt;/target&gt;</p>
		<p>生成doc 注意 encoding 和 charset<br />&lt;target name="doc"&gt;<br />&lt;mkdir dir="doc" /&gt;<br />&lt;javadoc charset="utf-8" encoding="utf-8" packagenames="${packages}" sourcepath="src" destdir="doc" author="true" version="true" use="true" splitindex="true" &gt;<br />&lt;classpath refid="master-classpath" /&gt;<br />&lt;/javadoc&gt;<br />&lt;/target&gt;</p>
		<p>这里 的encoding 就是指的你 java 文件的编码格式 javac 和javadoc 都有这个参数<br />charset 指的是 生成 doc 后的编码方式 javadoc 的参数</p>
		<p>2 数据库<br />mysql 的编码最复杂 从4以后 mysql 号称支持多编码 它更灵活了 我们也更麻烦了<br />mysql 有4个级别的编码 <br />系统级<br />库级<br />表级<br />sql语句级<br />请保持采用统一的编码 推荐utf-8<br />其它数据库要简单的多 一般都是一种编码</p>
		<p>3 web server <br />tomcat 为例<br />tomcat server.xml 中一个参数<br />&lt;Connectorport="8080" maxHttpHeaderSize="8192"<br />maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<br />enableLookups="false" redirectPort="8443" acceptCount="100"<br />connectionTimeout="20000" disableUploadTimeout="true" URIncoding="utf-8"/&gt;<br />经测试 这个URIncoding 参数主要是 get 方法中采用编码</p>
		<p>4 jsp 显示层<br />第1条中说明了 jsp 文件本身的格式<br />很多朋友采用eclipse +myeclipse 生成jsp<br />它自动生成一个头&lt;%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%&gt;<br />不要误解 这句话不能保证你在ie里看到的不是乱码<br />pageEncoding它的意思是 这个页面本身采用的是 utf-8 (似乎只在eclipse 里有效果 ，我不确定)<br />为了在ie 里不乱码  你还得加一句 &lt;%@ page contentType="text/html; charset=UTF-8"%&gt;<br />它不能在(myeclispe)自动生成  推荐修改 myeclipse的模板 在下边的目录里<br />MyEclipse\eclipse\plugins\com.genuitec.eclipse.wizards_4.0.1\Templates<br />里边的jsp模版 你加上&lt;%@ page contentType="text/html; charset=${encoding}"%&gt;</p>
		<p>5 filter<br />自从tomcat 4 以后 网上就流传了一个SetCharacterEncodingFilter 过滤器 搜一下有很多<br />很好用 web.xml 中加入<br />&lt;filter&gt;<br />?? &lt;filter-name&gt;Set Character Encoding&lt;/filter-name&gt;<br />?? &lt;filter-class&gt;filters.SetCharacterEncodingFilter&lt;/filter-class&gt;<br />?? &lt;init-param&gt;<br />?? &lt;param-name&gt;encoding&lt;/param-name&gt;<br />?? &lt;param-value&gt;utf-8&lt;/param-value&gt;<br />?? &lt;/init-param&gt;<br />&lt;/filter&gt;<br />?? &lt;filter-mapping&gt;<br />?? &lt;filter-name&gt;Set Character Encoding&lt;/filter-name&gt;<br />?? &lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />?? &lt;/filter-mapping&gt;</p>
		<p>6 资源文件<br />首先保证 文件本身是utf-8<br />然后部署的时候用 native2ascii 转换 <br />这里给出 ant 里的例子<br />&lt;native2ascii encoding="utf-8" dest="${web.dir}/WEB-INF/classes" src="${src.dir}" includes="**/*.properties" /&gt;<br /></p>
<img src ="http://www.blogjava.net/zqli/aggbug/86380.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-12-08 16:07 <a href="http://www.blogjava.net/zqli/archive/2006/12/08/86380.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] log4j配置详解 </title><link>http://www.blogjava.net/zqli/archive/2006/11/27/83887.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Mon, 27 Nov 2006 13:50:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/11/27/83887.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/83887.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/11/27/83887.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/83887.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/83887.html</trackback:ping><description><![CDATA[
		<p>log4j详解<br />        根据网络资料整理        <br /><strong><font color="#0000ff">&gt;&gt;&gt;&gt;1. 概述&lt;&lt;&lt;&lt;<br /></font></strong>　　<strong>1.1. 背景<br /></strong>　　<br />　　在应用程序中添加日志记录总的来说基于三个目的：监视代码中变量的变化情况，周期性的记录到文件中供其他应用进行统计分析工作；跟踪代码运行时轨迹，作为日后审计的依据；担当集成开发环境中的调试器的作用，向文件或控制台打印代码的调试信息。<br />　　<br />　　最普通的做法就是在代码中嵌入许多的打印语句，这些打印语句可以输出到控制台或文件中，比较好的做法就是构造一个日志操作类来封装此类操作，而不是让一系列的打印语句充斥了代码的主体。<br />　　<br />　　<strong>1.2. Log4j简介</strong><br />　　<br />　　在强调可重用组件开发的今天，除了自己从头到尾开发一个可重用的日志操作类外，Apache为我们提供了一个强有力的日志操作包-Log4j。<br />　　<br />　 　Log4j是Apache的一个开放源代码项目，通过使用Log4j，我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务 器、NT的事件记录器、UNIX Syslog守护进程等；我们也可以控制每一条日志的输出格式；通过定义每一条日志信息的级别，我们能够更加细致地控制日志的生成过程。最令人感兴趣的就 是，这些可以通过一个配置文件来灵活地进行配置，而不需要修改应用的代码。<br />　　<br />　　此外，通过Log4j其他语言接口，您可以在C、C+ +、.Net、PL/SQL程序中使用Log4j，其语法和用法与在Java程序中一样，使得多语言分布式系统得到一个统一一致的日志组件模块。而且，通 过使用各种第三方扩展，您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。<br />　　<br />　　本文介绍的Log4j版本是 1.2.3。作者试图通过一个简单的客户/服务器Java程序例子对比使用与不使用Log4j 1.2.3的差别，并详细讲解了在实践中最常使用Log4j的方法和步骤。在强调可重用组件开发的今天，相信Log4j将会给广大的设计开发人员带来方 便。加入到Log4j的队伍来吧！<br />　　<br /><font color="#0000ff"><strong>&gt;&gt;&gt;&gt; 2. 一个简单的例子 &lt;&lt;&lt;&lt;</strong></font></p>
		<p>　　我们先来看一个简单的例子，它是一个用Java实现的客户/服务器网络程序。刚开始我们不使用Log4j，而是使用了一系列的打印语句，然后我们将使用Log4j来实现它的日志功能。这样，大家就可以清楚地比较出前后两个代码的差别。<br />　　<br />　　2.1. 不使用Log4j<br />　　<br />　　2.1.1. 客户程序<br />　　package log4j ;<br />　　<br />　　import java.io.* ;<br />　　import java.net.* ;<br />　　<br />　　/**<br />　　 *<br />　　 * &lt;p&gt; Client Without Log4j &lt;/p&gt;<br />　　 * &lt;p&gt; Description: a sample with log4j&lt;/p&gt;<br />　　 * @version 1.0<br />　　 */<br />　　public class ClientWithoutLog4j {<br />　　<br />　　　　/**<br />　　　　 *<br />　　　　 * @param args<br />　　　　 */<br />　　　　public static void main ( String args [] ) {<br />　　<br />　　　　　　String welcome = null;<br />　　　　　　String response = null;<br />　　　　　　BufferedReader reader = null;<br />　　　　　　PrintWriter writer = null;<br />　　　　　　InputStream in = null;<br />　　　　　　OutputStream out = null;<br />　　　　　　Socket client = null;<br />　　<br />　　　　　　try {<br />　　　　　　　　client = new Socket ( "localhost", 8001 ) ;<br />　　　　　　　　System.out.println ( "info: Client socket: " + client ) ;<br />　　　　　　　　in = client.getInputStream () ;<br />　　　　　　　　out = client.getOutputStream () ;<br />　　　　　　} catch ( IOException e ) {<br />　　　　　　　　System.out.println ( "error: IOException : " + e ) ;<br />　　　　　　　　System.exit ( 0 ) ;<br />　　　　　　}<br />　　<br />　　　　　　try{<br />　　　　　　　　reader = new BufferedReader( new InputStreamReader ( in ) ) ;<br />　　　　　　　　writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;<br />　　<br />　　　　　　　　welcome = reader.readLine () ;<br />　　　　　　　　System.out.println ( "debug: Server says: '" + welcome + "'" ) ;<br />　　<br />　　　　　　　　System.out.println ( "debug: HELLO" ) ;<br />　　　　　　　　writer.println ( "HELLO" ) ;<br />　　　　　　　　response = reader.readLine () ;<br />　　　　　　　　System.out.println ( "debug: Server responds: '" + response + "'") ;<br />　　<br />　　　　　　　　System.out.println ( "debug: HELP" ) ;<br />　　　　　　　　writer.println ( "HELP" ) ;<br />　　　　　　　　response = reader.readLine () ;<br />　　　　　　　　System.out.println ( "debug: Server responds: '" + response + "'" ) ;<br />　　<br />　　　　　　　　System.out.println ( "debug: QUIT" ) ;<br />　　　　　　　　writer.println ( "QUIT" ) ;<br />　　　　　　} catch ( IOException e ) {<br />　　　　　　　　System.out.println ( "warn: IOException in client.in.readln()" ) ;<br />　　　　　　　　System.out.println ( e ) ;<br />　　　　　　}<br />　　　　　　try{<br />　　　　　　　　Thread.sleep ( 2000 ) ;<br />　　　　　　} catch ( Exception ignored ) {}<br />　　　　}<br />　　}<br />　　<br />　　2.1.2. 服务器程序<br />　　package log4j ;<br />　　<br />　　import java.util.* ;<br />　　import java.io.* ;<br />　　import java.net.* ;<br />　　<br />　　/**<br />　　 *<br />　　 * &lt;p&gt; Server Without Log4j &lt;/p&gt;<br />　　 * &lt;p&gt; Description: a sample with log4j&lt;/p&gt;<br />　　 * @version 1.0<br />　　 */<br />　　public class ServerWithoutLog4j {<br />　　<br />　　　　final static int SERVER_PORT = 8001 ; // this server's port<br />　　<br />　　　　/**<br />　　　　 *<br />　　　　 * @param args<br />　　　　 */<br />　　　　public static void main ( String args [] ) {<br />　　　　　　String clientRequest = null;<br />　　　　　　BufferedReader reader = null;<br />　　　　　　PrintWriter writer = null;<br />　　　　　　ServerSocket server = null;<br />　　　　　　Socket socket = null;<br />　　　　　　InputStream in = null;<br />　　　　　　OutputStream out = null;<br />　　<br />　　　　　　try {<br />　　　　　　　　server = new ServerSocket ( SERVER_PORT ) ;<br />　　　　　　　　System.out.println ( "info: ServerSocket before accept: " + server ) ;<br />　　　　　　　　System.out.println ( "info: Java server without log4j, on-line!" ) ;<br />　　<br />　　　　　　　　// wait for client's connection<br />　　　　　　　　socket = server.accept () ;<br />　　　　　　　　System.out.println ( "info: ServerSocket after accept: " + server )　;<br />　　<br />　　　　　　　　in = socket.getInputStream () ;<br />　　　　　　　　out = socket.getOutputStream () ;<br />　　<br />　　　　　　} catch ( IOException e ) {<br />　　　　　　　　System.out.println( "error: Server constructor IOException: " + e ) ;<br />　　　　　　　　System.exit ( 0 ) ;<br />　　　　　　}<br />　　　　　　reader = new BufferedReader ( new InputStreamReader ( in ) ) ;<br />　　　　　　writer = new PrintWriter ( new OutputStreamWriter ( out ) , true ) ;<br />　　<br />　　　　　　// send welcome string to client<br />　　　　　　writer.println ( "Java server without log4j, " + new Date () ) ;<br />　　<br />　　　　　　while ( true ) {<br />　　　　　　　　try {<br />　　　　　　　　　　// read from client<br />　　　　　　　　　　clientRequest = reader.readLine () ;<br />　　　　　　　　　　System.out.println ( "debug: Client says: " + clientRequest ) ;<br />　　　　　　　　　　if ( clientRequest.startsWith ( "HELP" ) ) {<br />　　　　　　　　　　　　System.out.println ( "debug: OK!" ) ;<br />　　　　　　　　　　　　writer.println ( "Vocabulary: HELP QUIT" ) ;<br />　　　　　　　　　　}<br />　　　　　　　　　　else {<br />　　　　　　　　　　　　if ( clientRequest.startsWith ( "QUIT" ) ) {<br />　　　　　　　　　　　　　　System.out.println ( "debug: OK!" ) ;<br />　　　　　　　　　　　　　　System.exit ( 0 ) ;<br />　　　　　　　　　　　　}<br />　　　　　　　　　　　　else{<br />　　　　　　　　　　　　　　System.out.println ( "warn: Command '" + <br />　　 clientRequest + "' not understood." ) ;<br />　　　　　　　　　　　　　　writer.println ( "Command '" + clientRequest <br />　　 + "' not understood." ) ;<br />　　　　　　　　　　　　}<br />　　　　　　　　　　}<br />　　　　　　　　} catch ( IOException e ) {<br />　　　　　　　　　　System.out.println ( "error: IOException in Server " + e ) ;<br />　　　　　　　　　　System.exit ( 0 ) ;<br />　　　　　　　　}<br />　　　　　　}<br />　　　　}<br />　　}<br />　　<br />　　2.2. 迁移到Log4j<br />　　<br />　　2.2.1. 客户程序<br />　　<br />　　package log4j ;<br />　　<br />　　import java.io.* ;<br />　　import java.net.* ;<br />　　<br />　　// add for log4j: import some package<br />　　import org.apache.log4j.PropertyConfigurator ;<br />　　import org.apache.log4j.Logger ;<br />　　import org.apache.log4j.Level ;<br />　　<br />　　/**<br />　　 *<br />　　 * &lt;p&gt; Client With Log4j &lt;/p&gt;<br />　　 * &lt;p&gt; Description: a sample with log4j&lt;/p&gt;<br />　　 * @version 1.0<br />　　 */<br />　　public class ClientWithLog4j {<br />　　<br />　　　　/*<br />　　　　add for log4j: class Logger is the central class in the log4j package.<br />　　　　we can do most logging operations by Logger except configuration.<br />　　　　getLogger(...): retrieve a logger by name, if not then create for it.<br />　　　　*/<br />　　　　static Logger logger = Logger.getLogger <br />　　 ( ClientWithLog4j.class.getName () ) ;<br />　　<br />　　　　/**<br />　　　　 *<br />　　　　 * @param args : configuration file name<br />　　　　 */<br />　　　　public static void main ( String args [] ) {<br />　　<br />　　　　　　String welcome = null ;<br />　　　　　　String response = null ;<br />　　　　　　BufferedReader reader = null ;<br />　　　　　　PrintWriter writer = null ;<br />　　　　　　InputStream in = null ;<br />　　　　　　OutputStream out = null ;<br />　　　　　　Socket client = null ;<br />　　<br />　　　　　　/*<br />　　　　　　add for log4j: class BasicConfigurator can quickly configure the package.<br />　　　　　　print the information to console.<br />　　　　　　*/<br />　　　　　　PropertyConfigurator.configure ( "ClientWithLog4j.properties" ) ;<br />　　<br />　　　　　　// add for log4j: set the level<br />　　//　　　　logger.setLevel ( ( Level ) Level.DEBUG ) ;<br />　　<br />　　　　　　try{<br />　　　　　　　　client = new Socket( "localhost" , 8001 ) ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the info level<br />　　　　　　　　logger.info ( "Client socket: " + client ) ;<br />　　<br />　　　　　　　　in = client.getInputStream () ;<br />　　　　　　　　out = client.getOutputStream () ;<br />　　　　　　} catch ( IOException e ) {<br />　　<br />　　　　　　　　// add for log4j: log a message with the error level<br />　　　　　　　　logger.error ( "IOException : " + e ) ;<br />　　<br />　　　　　　　　System.exit ( 0 ) ;<br />　　　　　　}<br />　　<br />　　　　　　try{<br />　　　　　　　　reader = new BufferedReader ( new InputStreamReader ( in ) ) ;<br />　　　　　　　　writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;<br />　　<br />　　　　　　　　welcome = reader.readLine () ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the debug level<br />　　　　　　　　logger.debug ( "Server says: '" + welcome + "'" ) ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the debug level<br />　　　　　　　　logger.debug ( "HELLO" ) ;<br />　　<br />　　　　　　　　writer.println ( "HELLO" ) ;<br />　　　　　　　　response = reader.readLine () ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the debug level<br />　　　　　　　　logger.debug ( "Server responds: '" + response + "'" ) ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the debug level<br />　　　　　　　　logger.debug ( "HELP" ) ;<br />　　<br />　　　　　　　　writer.println ( "HELP" ) ;<br />　　　　　　　　response = reader.readLine () ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the debug level<br />　　　　　　　　logger.debug ( "Server responds: '" + response + "'") ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the debug level<br />　　　　　　　　logger.debug ( "QUIT" ) ;<br />　　<br />　　　　　　　　writer.println ( "QUIT" ) ;<br />　　　　　　} catch ( IOException e ) {<br />　　<br />　　　　　　　　// add for log4j: log a message with the warn level<br />　　　　　　　　logger.warn ( "IOException in client.in.readln()" ) ;<br />　　<br />　　　　　　　　System.out.println ( e ) ;<br />　　　　　　}<br />　　　　　　try {<br />　　　　　　　　Thread.sleep ( 2000 ) ;<br />　　　　　　} catch ( Exception ignored ) {}<br />　　　　}<br />　　}<br />　　<br />　　2.2.2. 服务器程序<br />　　<br />　　package log4j;<br />　　<br />　　import java.util.* ;<br />　　import java.io.* ;<br />　　import java.net.* ;<br />　　<br />　　// add for log4j: import some package<br />　　import org.apache.log4j.PropertyConfigurator ;<br />　　import org.apache.log4j.Logger ;<br />　　import org.apache.log4j.Level ;<br />　　<br />　　/**<br />　　 *<br />　　 * &lt;p&gt; Server With Log4j &lt;/p&gt;<br />　　 * &lt;p&gt; Description: a sample with log4j&lt;/p&gt;<br />　　 * @version 1.0<br />　　 */<br />　　public class ServerWithLog4j {<br />　　<br />　　　　final static int SERVER_PORT = 8001 ; // this server's port<br />　　<br />　　　　/*<br />　　　　add for log4j: class Logger is the central class in the log4j package.<br />　　　　we can do most logging operations by Logger except configuration.<br />　　　　getLogger(...): retrieve a logger by name, if not then create for it.<br />　　　　*/<br />　　　　static Logger logger = Logger.getLogger <br />　　 ( ServerWithLog4j.class.getName () ) ;<br />　　<br />　　　　/**<br />　　　　 *<br />　　　　 * @param args<br />　　　　 */<br />　　　　public static void main ( String args[]) {<br />　　　　　　String clientRequest = null ;<br />　　　　　　BufferedReader reader = null ;<br />　　　　　　PrintWriter writer = null ;<br />　　　　　　ServerSocket server = null ;<br />　　　　　　Socket socket = null ;<br />　　<br />　　　　　　InputStream in = null ;<br />　　　　　　OutputStream out = null ;<br />　　<br />　　　　　　/*<br />　　　　　　add for log4j: class BasicConfigurator can quickly configure the package.<br />　　　　　　print the information to console.<br />　　　　　　*/<br />　　　　　　PropertyConfigurator.configure ( "ServerWithLog4j.properties" ) ;<br />　　<br />　　　　　　// add for log4j: set the level<br />　　//　　　　logger.setLevel ( ( Level ) Level.DEBUG ) ;<br />　　<br />　　　　　　try{<br />　　　　　　　　server = new ServerSocket ( SERVER_PORT ) ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the info level<br />　　　　　　　　logger.info ( "ServerSocket before accept: " + server ) ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the info level<br />　　　　　　　　logger.info ( "Java server with log4j, on-line!" ) ;<br />　　<br />　　　　　　　　// wait for client's connection<br />　　　　　　　　socket = server.accept() ;<br />　　<br />　　　　　　　　// add for log4j: log a message with the info level<br />　　　　　　　　logger.info ( "ServerSocket after accept: " + server ) ;<br />　　<br />　　　　　　　　in = socket.getInputStream() ;<br />　　　　　　　　out = socket.getOutputStream() ;<br />　　<br />　　　　　　} catch ( IOException e ) {<br />　　<br />　　　　　　　　// add for log4j: log a message with the error level<br />　　　　　　　　logger.error ( "Server constructor IOException: " + e ) ;<br />　　　　　　　　System.exit ( 0 ) ;<br />　　　　　　}<br />　　　　　　reader = new BufferedReader ( new InputStreamReader ( in ) ) ;<br />　　　　　　writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;<br />　　<br />　　　　　　// send welcome string to client<br />　　　　　　writer.println ( "Java server with log4j, " + new Date () ) ;<br />　　<br />　　　　　　while ( true ) {<br />　　　　　　　　try {<br />　　　　　　　　　　// read from client<br />　　　　　　　　　　clientRequest = reader.readLine () ;<br />　　<br />　　　　　　　　　　// add for log4j: log a message with the debug level<br />　　　　　　　　　　logger.debug ( "Client says: " + clientRequest ) ;<br />　　<br />　　　　　　　　　　if ( clientRequest.startsWith ( "HELP" ) ) {<br />　　<br />　　　　　　　　　　　　// add for log4j: log a message with the debug level<br />　　　　　　　　　　　　logger.debug ( "OK!" ) ;<br />　　<br />　　　　　　　　　　　　writer.println ( "Vocabulary: HELP QUIT" ) ;<br />　　　　　　　　　　}<br />　　　　　　　　　　else {<br />　　　　　　　　　　　　if ( clientRequest.startsWith ( "QUIT" ) ) {<br />　　<br />　　　　　　　　　　　　　　// add for log4j: log a message with the debug level<br />　　　　　　　　　　　　　　logger.debug ( "OK!" ) ;<br />　　<br />　　　　　　　　　　　　　　System.exit ( 0 ) ;<br />　　　　　　　　　　　　}<br />　　　　　　　　　　　　else {<br />　　<br />　　　　　　　　　　　　　　// add for log4j: log a message with the warn level<br />　　　　　　　　　　　　　　logger.warn ( "Command '" <br />　　 + clientRequest + "' not understood." ) ;<br />　　<br />　　　　　　　　　　　　　　writer.println ( "Command '"<br />　　 + clientRequest + "' not understood." ) ;<br />　　　　　　　　　　　　}<br />　　　　　　　　　　}<br />　　　　　　　　} catch ( IOException e ) {<br />　　<br />　　　　　　　　　　// add for log4j: log a message with the error level<br />　　　　　　　　　　logger.error( "IOException in Server " + e ) ;<br />　　<br />　　　　　　　　　　System.exit ( 0 ) ;<br />　　　　　　　　}<br />　　　　　　}<br />　　　　}<br />　　}<br />　　<br />　　2.2.3. 配置文件<br />　　<br />　　2.2.3.1. 客户程序配置文件<br />　　<br />　　log4j.rootLogger=INFO, A1<br />　　<br />　　log4j.appender.A1=org.apache.log4j.ConsoleAppender<br />　　<br />　　log4j.appender.A1.layout=org.apache.log4j.PatternLayout<br />　　<br />　　log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n<br />　　<br />　　2.2.3.2. 服务器程序配置文件<br />　　<br />　　log4j.rootLogger=INFO, A1<br />　　<br />　　log4j.appender.A1=org.apache.log4j.ConsoleAppender<br />　　<br />　　log4j.appender.A1.layout=org.apache.log4j.PatternLayout<br />　　<br />　　log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n<br />　　<br />　　2.3. 比较<br />　　<br />　 　比较这两个应用可以看出，采用Log4j进行日志操作的整个过程相当简单明了，与直接使用System.out.println语句进行日志信息输出的 方式相比，基本上没有增加代码量，同时能够清楚地理解每一条日志信息的重要程度。通过控制配置文件，我们还可以灵活地修改日志信息的格式，输出目的地等等 方面，而单纯依靠System.out.println语句，显然需要做更多的工作。<br /><br /><font color="#0000ff"><strong>&gt;&gt;&gt;&gt; 3 . Log4j日志管理系统简单使用说明 &lt;&lt;&lt;&lt;<br /></strong></font><br />    通常，我们都提供一个名为 log4j.properties的文件，在第一次调用到Log4J时，Log4J会在类路径（../web-inf/class/当然也可以放到其它任何目录，只要该目录被包含到类路径中即可）中定位这个文件，并读入这个文件完成的配置。这个配置文件告 诉Log4J以什么样的格式、把什么样的信息、输出到什么地方。<br />　　Log4j有三个主要的组件：Loggers(记录器)，Appenders(输出源)和Layouts(布局)，这里可简单理解为日志类别，日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松的记录信息的类型和级别，并可以在运行时控制日志输出的样式和位置。下面对三个组件分别进行说明：<br />　　<br />　　<strong>1、 Loggers<br /></strong>　 　Loggers组件在此系统中被分为五个级别：DEBUG、INFO、WARN、ERROR和FATAL。这五个级别是有顺序的，DEBUG &lt; INFO &lt; WARN &lt; ERROR &lt; FATAL，分别用来指定这条日志信息的重要程度,明白这一点很重要，这里Log4j有一个规则：假设Loggers级别为P，如果在Loggers中发生了一个级别Q比P高，则可以启动，否则屏蔽掉。<br />假设你定义的级别是info，那么error和warn的日志可以显示而比他低的debug信息就不显示了。<br /> 　<br />　　Java程序举例来说：<br />　　<br />　　//建立Logger的一个实例，命名为“com.foo”<br />　　　Logger　logger = Logger.getLogger("com.foo"); //"com.foo"是实例进行命名，也可以任意<br />　　//设置logger的级别。通常不在程序中设置logger的级别。一般在配置文件中设置。<br />　　logger.setLevel(Level.INFO);<br />　　Logger barlogger = Logger.getLogger("com.foo.Bar");<br />　　//下面这个请求可用，因为WARN &gt;= INFO<br />　　logger.warn("Low fuel level.");<br />　　//下面这个请求不可用，因为DEBUG &lt; INFO<br />　　logger.debug("Starting search for nearest gas station.");<br />　　//命名为“com.foo.bar”的实例barlogger会继承实例“com.foo”的级别。因此，下面这个请求可用，因为INFO &gt;= INFO<br />　　barlogger.info("Located nearest gas station.");<br />　　//下面这个请求不可用，因为DEBUG &lt; INFO<br />　　barlogger.debug("Exiting gas station search");<br />　　这里“是否可用”的意思是能否输出Logger信息。<br />　　　　在对Logger实例进行命名时，没有限制，可以取任意自己感兴趣的名字。一般情况下建议以类的所在位置来命名Logger实例，这是目前来讲比较有效的Logger命名方式。这样可以使得每个类建立自己的日志信息，便于管理。比如：<br />　　<br />　　static Logger logger = Logger.getLogger(ClientWithLog4j.class.getName());<br />　　<br />　<strong>　2、Appenders<br /></strong>　　禁用与使用日志请求只是Log4j其中的一个小小的地方，Log4j日志系统允许把日志输出到不同的地方，如控制台（Console）、文件（Files）、根据天数或者文件大小产生新的文件、以流的形式发送到其它地方等等。<br />　　<br />　　其语法表示为：<br />　　<br />　　org.apache.log4j.ConsoleAppender（控制台）<br />　　org.apache.log4j.FileAppender（文件）<br />　　org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件）<br />    org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件）<br />　　org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br />　　<br />　　配置时使用方式为：<br />　　log4j.appender.appenderName = fully.qualified.name.of.appender.class<br />　　log4j.appender.appenderName.option1 = value1<br />　　…<br />    log4j.appender.appenderName.option = valueN<br />　　这样就为日志的输出提供了相当大的便利。<br />　　<br /><strong>　　3、Layouts</strong><br />　 　有时用户希望根据自己的喜好格式化自己的日志输出。Log4j可以在Appenders的后面附加Layouts来完成这个功能。Layouts提供了 四种日志输出样式，如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式等等。<br />　　<br />　　其语法表示为：<br />　　<br />　　org.apache.log4j.HTMLLayout（以HTML表格形式布局），<br />　　org.apache.log4j.PatternLayout（可以灵活地指定布局模式），<br />　　org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串），<br />　　org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br />　　<br />　　配置时使用方式为：<br />　　<br />　　log4j.appender.appenderName.layout =fully.qualified.name.of.layout.class<br />　　log4j.appender.appenderName.layout.option1 = value1<br />　　…<br />　　log4j.appender.appenderName.layout.option = valueN</p>
		<p>
				<strong>
						<font color="#0000ff">&gt;&gt;&gt;&gt;  4 . Log4j的配置 &lt;&lt;&lt;&lt;　</font>
				</strong>　<br />　　<br />　　以上是从原理方面说明Log4j的使用方法，在具体Java编程使用Log4j可以参照以下示例：<br />　　<br />　　<strong>1、 建立Logger实例</strong>：<br />　　语法表示：public static Logger getLogger( String name)<br />　　实际使用：static Logger logger = Logger.getLogger(ServerWithLog4j.class.getName ()) ;<br />　　<br />　　<strong>2、 读取配置文件</strong>：<br />　　获得了Logger的实例之后，接下来将配置Log4j使用环境：<br />　　语法表示：<br />　　BasicConfigurator.configure()：自动快速地使用缺省Log4j环境。<br />　　PropertyConfigurator.configure(String configFilename)：读取使用Java的特性文件编写的配置文件。<br />　　DOMConfigurator.configure(String filename)：读取XML形式的配置文件。<br />　　实际使用：<br />    PropertyConfigurator.configure("ServerWithLog4j.properties");<br />　　<br />　　<strong>3、 插入日志信息</strong><br />　　完成了以上连个步骤以后，下面就可以按日志的不同级别插入到你要记录日志的任何地方了。<br />　　语法表示：<br />　　Logger.debug(Object message);//调试信息<br />　　Logger.info(Object message);//一般信息<br />　　Logger.warn(Object message);//警告信息<br />　　Logger.error(Object message);//错误信息<br />　　Logger.fatal(Object message);//致命错误信息</p>
		<p>　　实际使用：logger.info("ServerSocket before accept: " + server);<br />　　<br />　<strong><font color="#0000ff">&gt;&gt;&gt;&gt; 5. 配置过程 &lt;&lt;&lt;&lt;<br /><br /></font></strong>　在实际编程时，要使Log4j真正在系统中运行事先还要对配置文件进行定义。定义步骤就是对Logger、Appender及Layout的分别使用。<br />    Log4j支持两种配置文件格式，一种是XML格式的文件，一种是java properties（key=value）【Java特性文件（键=值）】。下面我们介绍使用Java特性文件做为配置文件的方法<br />   具体如下：<br />　　<br />　　<strong>1、配置根Logger，</strong>其语法为：<br />　　log4j.rootLogger = [ level ] , appenderName1, appenderName2, …<br />         level : 是日志记录的优先级，分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别，优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定 义了INFO级别，则应用程序中所有DEBUG级别的日志信息将不被打印出来。<br />　　     appenderName:就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。<br />   例如：log4j.rootLogger＝info,A1,B2,C3<br />　　<br />　　<strong>2、配置日志信息输出目的地</strong>，其语法为：<br />　　log4j.appender.appenderName = fully.qualified.name.of.appender.class  //<br />　　  "fully.qualified.name.of.appender.class" 可以指定下面五个目的地中的一个：<br />          1.org.apache.log4j.ConsoleAppender（控制台）<br />          2.org.apache.log4j.FileAppender（文件）<br />          3.org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件）<br />          4.org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件）<br />          5.org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br />             <strong>1.ConsoleAppender选项<br /></strong>                    Threshold=WARN:指定日志消息的输出最低层次。<br />                    ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。<br />                    Target=System.err：默认情况下是：System.out,指定输出控制台<br />              <strong>2.FileAppender</strong> 选项<br />                    Threshold=WARN:指定日志消息的输出最低层次。<br />                    ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。<br />                    File=mylog.txt:指定消息输出到mylog.txt文件。<br />                    Append=false:默认值是true,即将消息增加到指定文件中，false指将消息覆盖指定的文件内容。<br />            3.<strong>DailyRollingFileAppender</strong> 选项<br />                    Threshold=WARN:指定日志消息的输出最低层次。<br />                    ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。<br />                    File=mylog.txt:指定消息输出到mylog.txt文件。<br />                    Append=false:默认值是true,即将消息增加到指定文件中，false指将消息覆盖指定的文件内容。<br />                    DatePattern='.'yyyy-ww:每周滚动一次文件，即每周产生一个新的文件。当然也可以指定按月、周、天、时和分。即对应的格式如下：<br />                    1)'.'yyyy-MM: 每月<br />                    2)'.'yyyy-ww: 每周 <br />                    3)'.'yyyy-MM-dd: 每天<br />                    4)'.'yyyy-MM-dd-a: 每天两次<br />                    5)'.'yyyy-MM-dd-HH: 每小时<br />                    6)'.'yyyy-MM-dd-HH-mm: 每分钟<br />            4.<strong>RollingFileAppender</strong> 选项<br />                    Threshold=WARN:指定日志消息的输出最低层次。<br />                    ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。<br />                    File=mylog.txt:指定消息输出到mylog.txt文件。<br />                    Append=false:默认值是true,即将消息增加到指定文件中，false指将消息覆盖指定的文件内容。<br />                    MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时，将会自动滚动，即将原来的内容移到mylog.log.1文件。<br />                    MaxBackupIndex=2:指定可以产生的滚动文件的最大数。</p>
		<p>实际应用：<br />　　log4j.appender.A1=org.apache.log4j.ConsoleAppender //这里指定了日志输出的第一个位置A1是控制台ConsoleAppender<br />　　<br />　　<strong>3、配置日志信息的格式</strong>，其语法为：<br />　　<strong>A.</strong><strong>log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class<br /></strong>              "fully.qualified.name.of.layout.class" 可以指定下面4个格式中的一个：<br />               1.org.apache.log4j.HTMLLayout（以HTML表格形式布局），<br />　　       2.org.apache.log4j.PatternLayout（可以灵活地指定布局模式），<br />　　       3.org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串），<br />　　       4.org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br />                   1.HTMLLayout 选项<br />                      LocationInfo=true:默认值是false,输出java文件名称和行号<br />                      Title=my app file: 默认值是 Log4J Log Messages.<br />                   2.PatternLayout 选项<br />                      ConversionPattern=%m%n :指定怎样格式化指定的消息。<br />                   3.XMLLayout  选项<br />                      LocationInfo=true:默认值是false,输出java文件和行号<br />   实际应用：<br />   　　log4j.appender.A1.layout=org.apache.log4j.PatternLayout</p>
		<p>       <strong>B</strong>.<strong> log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n<br /></strong>           这里需要说明的就是日志信息格式中几个符号所代表的含义：<br />　　         －X号: X信息输出时左对齐；<br />                   %p: 输出日志信息优先级，即DEBUG，INFO，WARN，ERROR，FATAL,<br />                   %d: 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921<br />                   %r: 输出自应用启动到输出该log信息耗费的毫秒数<br />                   %c: 输出日志信息所属的类目，通常就是所在类的全名<br />                   %t: 输出产生该日志事件的线程名<br />                   %l: 输出日志事件的发生位置，相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程，以及在代码中的行数。举例：Testlog4.main(TestLog4.java:10)<br />                   %x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。<br />                   %%: 输出一个"%"字符<br />                   %F: 输出日志消息产生时所在的文件名称<br />                   %L: 输出代码中的行号<br />                   %m: 输出代码中指定的消息,产生的日志具体信息<br />                   %n: 输出一个回车换行符，Windows平台为"\r\n"，Unix平台为"\n"输出日志信息换行<br />            可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如：<br />                     1)%20c：指定输出category的名称，最小的宽度是20，如果category的名称小于20的话，默认的情况下右对齐。<br />                     2)%-20c:指定输出category的名称，最小的宽度是20，如果category的名称小于20的话，"-"号指定左对齐。<br />                     3)%.30c:指定输出category的名称，最大的宽度是30，如果category的名称大于30的话，就会将左边多出的字符截掉，但小于30的话也不会有空格。<br />                     4)%20.30c:如果category的名称小于20就补空格，并且右对齐，如果其名称长于30字符，就从左边交远销出的字符截掉。</p>
		<p>　　这里上面三个步骤是对前面Log4j组件说明的一个简化；下面给出一个具体配置例子，在程序中可以参照执行：<br />　　log4j.rootLogger=INFO,A1，B2<br />　　log4j.appender.A1=org.apache.log4j.ConsoleAppender<br />　　log4j.appender.A1.layout=org.apache.log4j.PatternLayout<br />　　log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n<br /> 　　根据上面的日志格式，某一个程序的输出结果如下：<br />　　0　　INFO　2003-06-13 13:23:46968 ClientWithLog4j Client socket: Socket[addr=localhost/127.0.0.1,port=8002,localport=2014]<br />         16　 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j Server says: 'Java server with log4j, Fri Jun 13 13:23:46 CST 2003'<br />　　16　 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j GOOD<br />　　16　 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j Server responds: 'Command 'HELLO' not understood.'<br />　　16　 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j HELP<br />　　16　 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j Server responds: 'Vocabulary: HELP QUIT'<br />　　16　 DEBUG 2003-06-13 13:23:46984 ClientWithLog4j QUIT<br /> <br />     <strong> 4. # 当输出信息于回滚文件时</strong></p>
		<p>          log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender   //指定以文件的方式输出日志<br />           log4j.appender.ROLLING_FILE.Threshold=ERROR <br />           log4j.appender.ROLLING_FILE.File=rolling.log  //文件位置,也可以用变量${java.home}、rolling.log<br />           log4j.appender.ROLLING_FILE.Append=true <br />           log4j.appender.ROLLING_FILE.MaxFileSize=10KB  //文件最大尺寸<br />           log4j.appender.ROLLING_FILE.MaxBackupIndex=1  //备份数<br />           log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout <br />           log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n  　　</p>
		<p>××××××××××××××××××××××××××××××××××××××××××××××××<br /><strong><font color="#0000ff"> <br /></font></strong><strong><font color="#0000ff">&gt;&gt;&gt;&gt; 6. Log4j比较全面的配置 &lt;&lt;&lt;&lt;</font></strong></p>
		<p> LOG4J的配置之简单使它遍及于越来越多的应用中了：Log4J配置文件实现了输出到控制台、文件、回滚文件、发送日志邮件、输出到数据库日志表、自定义标签等全套功能。择其一二使用就够用了， </p>
		<p> log4j.rootLogger=DEBUG,CONSOLE,A1,im <br /> log4j.addivity.org.apache=true </p>
		<p> # 应用于控制台 </p>
		<p> log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender <br /> log4j.appender.Threshold=DEBUG <br /> log4j.appender.CONSOLE.Target=System.out <br /> log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout <br /> log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n <br /> #log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n </p>
		<p> #应用于文件 </p>
		<p> log4j.appender.FILE=org.apache.log4j.FileAppender <br /> log4j.appender.FILE.File=file.log <br /> log4j.appender.FILE.Append=false <br /> log4j.appender.FILE.layout=org.apache.log4j.PatternLayout <br /> log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n <br /> # Use this layout for LogFactor 5 analysis </p>
		<p> # 应用于文件回滚 </p>
		<p> log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender <br /> log4j.appender.ROLLING_FILE.Threshold=ERROR <br /> log4j.appender.ROLLING_FILE.File=rolling.log  //文件位置,也可以用变量${java.home}、rolling.log<br /> log4j.appender.ROLLING_FILE.Append=true       //true:添加  false:覆盖<br /> log4j.appender.ROLLING_FILE.MaxFileSize=10KB   //文件最大尺寸<br /> log4j.appender.ROLLING_FILE.MaxBackupIndex=1  //备份数<br /> log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout <br /> log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n </p>
		<p>
				<br /> #应用于socket <br /> log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender <br /> log4j.appender.SOCKET.RemoteHost=localhost <br /> log4j.appender.SOCKET.Port=5001 <br /> log4j.appender.SOCKET.LocationInfo=true <br /> # Set up for Log Facter 5 <br /> log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout <br /> log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n </p>
		<p>
				<br /> # Log Factor 5 Appender <br /> log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender <br /> log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000 </p>
		<p> # 发送日志给邮件 </p>
		<p> log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender <br /> log4j.appender.MAIL.Threshold=FATAL <br /> log4j.appender.MAIL.BufferSize=10 <br /> <a href="mailto:log4j.appender.MAIL.From=web@www.wuset.com">log4j.appender.MAIL.From=web@www.wuset.com</a><br /> log4j.appender.MAIL.SMTPHost=www.wusetu.com <br /> log4j.appender.MAIL.Subject=Log4J Message <br /> <a href="mailto:log4j.appender.MAIL.To=web@www.wusetu.com">log4j.appender.MAIL.To=web@www.wusetu.com</a><br /> log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout <br /> log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n </p>
		<p> # 用于数据库 <br /> log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender <br /> log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test <br /> log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver <br /> log4j.appender.DATABASE.user=root <br /> log4j.appender.DATABASE.password= <br /> log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n') <br /> log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout <br /> log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n </p>
		<p>
				<br /> log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender <br /> log4j.appender.A1.File=SampleMessages.log4j <br /> log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j' <br /> log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout </p>
		<p> #自定义Appender </p>
		<p> log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender </p>
		<p> log4j.appender.im.host = mail.cybercorlin.net <br /> log4j.appender.im.username = username <br /> log4j.appender.im.password = password <br /> log4j.appender.im.recipient = <a href="mailto:corlin@cybercorlin.net">corlin@cybercorlin.net</a></p>
		<p> log4j.appender.im.layout=org.apache.log4j.PatternLayout <br /> log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n</p>
		<p>
		</p>
		<br />
		<br />
		<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=488099</p>
<img src ="http://www.blogjava.net/zqli/aggbug/83887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-11-27 21:50 <a href="http://www.blogjava.net/zqli/archive/2006/11/27/83887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]EE系统标准（JAVA EE5） </title><link>http://www.blogjava.net/zqli/archive/2006/11/24/83256.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 24 Nov 2006 06:58:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/11/24/83256.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/83256.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/11/24/83256.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/83256.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/83256.html</trackback:ping><description><![CDATA[最近，SUN的伙伴们(the folks at SUN)将J2EE 1.5改名为java EE 5，当然以前J2EE版本还是称为J2EE，之所以改名，目的还是让大家清楚J2EE只是Java企业应用，用我的话来说，J2EE就是Java在数据库服务器端的应用（见<a href="http://www.jdon.com/idea/j2eebasic.htm" target="_blank">初学者如何开发出一个高质量的J2EE系统</a>）。 
<p>　　看来，现在大多数人倾向于更加突出Java了，J2EE容易让初学者误解是独立于一套Java的技术方案。</p><p>　　从更深层次来看，Java诞生十年来，很多近十年前的业务组件至今还可以使用，软件应用不再由于语言的更迭革命带来毁灭的打击了。</p><p>　　但是，随着WEB和EJB容器概念诞生，使得软件应用业开始担心SUN的伙伴们是否还在Java平台上不断推出翻新的标准框架，致使软件应用业的业务核心组件架构无所适从，从一直以来是否需要EJB的讨论声中说明了这种彷徨。</p><p>　　笔者曾经在2004年底中国软件技术大会Ioc微容器(也就是<a href="http://www.jdon.com/jdonframework/" target="_blank">Jdon框架</a>的实现原理)演讲中指出：我们需要一个跨J2SE/WEB/EJB的微容器，保护我们的业务核心组件（中间件），以延续它的生命力，而不是依赖J2SE/J2EE版本，如下图：</p><p><img height="239" alt="" src="http://www.jdon.com/artichect/images/javaEE.jpg" width="300" /></p><p>　　此次J2EE改名为Java EE，实际也反映出业界这种共同心声。</p><p>　　让我们看看Java EE 5有哪些新的功能或规定，我们可以从SUN网站<a href="http://jcp.org/en/jsr/detail?id=244" target="_blank">下载Java EE 5规范</a>。其架构图如下：</p><p><img height="479" alt="" src="http://www.jdon.com/artichect/images/javaEEArchitecture.jpg" width="546" /></p><p>　　图中灰色加黑部分是Java EE 5新的功能，我们看到，在WEB层主要加入了JSF这个新的表现层框架，和我们日常开发关系密切的是，引入了新的Java Persistence标准，这个标准正在由EJB 3.0专家组制定。</p><p>　　值得指出的是，这个Java持久化标准也可以嵌入在WEB层调用，所以，它肯定不会从属于EJB标准，这样，当前所有的Java持久层标准如：JDBC/JDO/Hibernate/Entity Bean将可能统一，减少用户的架构选择 痛苦。</p><p>　　从架构图可以看出，无论Web结构或EJB结构，提供实现的功能相差不多，这样，我们的业务核心组件就可以根据需要部署在Web或EJB中运行，而不依赖具体的Java EE容器了。前面一章图的目标在Java EE 5中可以实现了。 </p><p>　　当然，Java EE 5重要改变还是：Java EE不再象以前那样只注重大型商业系统的开发，而是更关注小到中型系统的开发，简化这部分系统开发步骤。</p><p>　　落实这一简化行动的最大特征是在Java 5.0(Java 1.5)中加入Annotations，通过Annotations引入，降低Java EE开发时，既要写code，又要写XML配置文件之苦，来回照顾，疲于奔命，Annotations既是得益于C++语言，也是从开源项目xDoclet实践中获得经验。</p><p>　　但是Annotations是一把双刃剑，初学者用得不好，将会使得原本在XML中的Hard code（硬编码） 写进入代码Annotations，破坏代码的简洁和灵活性，<a href="http://www.jdon.com/jive/thread.jsp?forum=91&amp;thread=22356" target="_blank">Annotations讨论按这里</a>。</p><p>　　当然，Annotations的引入不只是解决XML配置，从大的概念说，是解决一个资源注射问题(XML属于其中一个资源)，在原理J2EE中，容器管理的资源都是由JNDI向应用程序提供的，现在通过Annotations可以方便实现注射。</p><p>　　资源注射（Resource injection）设计概念其实是来自Ioc模式(<a href="http://www.jdon.com/AOPdesign/Ioc.htm" target="_blank">Dependency Injection</a> )，笔者设计开发的Jdon框架其实已经将Annotations这一宗旨的目的实现，在<a href="http://www.jdon.com/jdonframework/SimpleJdonFrameworkTest.rar" target="_blank">Jdon框架应用演示源码</a><a href="http://www.jdon.com/artichect/SimpleJdonFrameworkTest.rar"><strong>SimpleJdonFrameworkTest</strong></a>中，在jdonframework.xml中有一段如下配置：</p><p>&lt;pojoService class="com.jdon.framework.test.dao.JdbcDAO" name="jdbcDAO"&gt;<br />　　&lt;constructor value="java:/TestDS"/&gt;<br />&lt;/pojoService&gt; </p><p>　　这段配置是将数据库的JNDI名java:/TestDS注射到JdbcDAO中。Jdon Framework下一个版本将是基于Java 5.0，这行配置 将可通过 Annotations写在jdbcDAO代码中，方便程序员开发。</p><p>　　从这里，大家也可以知道EJB 3.0和EJB 2.0的区别了，有的人疑惑，是学习EJB 3.0还是学习EJB 2.0，其实EJB 3.0并没有在原理机制上对EJB有多大改动，只是做了编程方面的简化，另外EJB CMP参考了Hibernate新特点，EJB 3.0最大简化变动是CMP编程方法上。所以，无论学习EJb 3.0/2.0，EJB原理和运行机制都是一样，这部分才是学习EJB最大的困难处，而不是因为到了EJB 3.0，理解EJB就会容易。</p><p>　　初学者可从Eclipse+Xdoclet开发EJB 2.0开始学习， EJB 3.0 = EJB 2.0 + xDoclet，<a href="http://www.jdon.com/idea/eclipse-jbossIDE.htm" target="_blank">这里有一篇Eclipse开发EJB教程</a>，使用JBossIDE非常简单，无需Lomboz等插件。</p><p>　　Security安全是Java EE的一个重要特点，也就是基于容器的安全访问，无需自己手工编码，具体实现可参考<a href="http://www.jdon.com/jdonframework/news.htm" target="_blank">Jdon框架应用演示源码JdonNews</a>。这虽然是基于J2EE 1.3编写，但是和Java EE 5区别不是很大。</p><p>　　事务管理Transaction Management也是Java EE 5的一个重要部分，该标准文档 从几个方面阐述了事务管理的要点，标准中规定了在WEB层中使用事务和线程的处理关系，标准中规定：Web服务器如Tomcat无需在Web层提供事务支持，因为Web组件根本不支持事务繁衍/传递。</p><p>　　因为目前一些架构如Struts+Spring+Hibernate/Struts+Hibernate是标准中的Web结构，因此Java EE 5在J2EE 4.2.2规定了 Web组件事务的生命周期，如果Web组件直接调用JTA，事务就不可以跨一个客户端的多个请求，事务只能在一个请求(Servlet/Jsp)中完成，这个标准规定了我们在Web架构中（如上述架构）无法使用长事务(如<a href="http://www.uidesign.net/Articles/Papers/WebMVC-BrowsersTransactio.html" target="_blank">工作流/状态图中跨页面请求事务</a>)，针对一个客户端跨请求的事务目前只有唯一解决方案：只有使用EJB的有态Session。<a href="http://www.jguru.com/faq/view.jsp?EID=121370" target="_blank">参考文章：I manage long duration transactions?</a></p><p>　　以上是Java EE 5主要部分，Java EE包含更多其他技术部分如Jdbc JMS JCA JNDI 等等，需要用户在实践中摸索。</p><br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=821836</p><img src ="http://www.blogjava.net/zqli/aggbug/83256.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-11-24 14:58 <a href="http://www.blogjava.net/zqli/archive/2006/11/24/83256.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是SOAP</title><link>http://www.blogjava.net/zqli/archive/2006/11/24/83254.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 24 Nov 2006 06:56:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/11/24/83254.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/83254.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/11/24/83254.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/83254.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/83254.html</trackback:ping><description><![CDATA[SOAP：简单对象访问协议 <br />（SOAP：Simple Object Access Protocol） <br /><br />　　简单对象访问协议（SOAP）是一种轻量的、简单的、基于 XML 的协议，它被设计成在 WEB 上交换结构化的和固化的信息。 SOAP 可以和现存的许多因特网协议和格式结合使用，包括超文本传输协议（ HTTP），简单邮件传输协议（SMTP），多用途网际邮件扩充协议（MIME）。它还支持从消息系统到远程过程调用（RPC）等大量的应用程序。<br /><br />SOAP 包括三个部分： <br />SOAP 封装：它定义了一个框架 , 该框架描述了消息中的内容是什么，谁应当处理它以及它是可选的还是必须的。 <br />SOAP 编码规则：它定义了一种序列化的机制，用于交换应用程序所定义的数据类型的实例。 <br />SOAP RPC 表示：它定义了用于表示远程过程调用和应答的协定。 <br /><br />　　SOAP 消息基本上是从发送端到接收端的单向传输，但它们常常结合起来执行类似于请求 / 应答的模式。所有的 SOAP 消息都使用 XML 编码。一条 SOAP 消息就是一个包含有一个必需的 SOAP 的封装包，一个可选的 SOAP 标头和一个必需的 SOAP 体块的 XML 文档。<br /><br />　　把 SOAP 绑定到 HTTP 提供了同时利用 SOAP 的样式和分散的灵活性的特点以及 HTTP 的丰富的特征库的优点。在 HTTP 上传送 SOAP 并不是说 SOAP 会覆盖现有的 HTTP 语义，而是 HTTP 上的 SOAP 语义会自然的映射到 HTTP 语义。在使用 HTTP 作为协议绑定的场合中， RPC 请求映射到 HTTP 请求上，而 RPC 应答映射到 HTTP 应答。然而，在 RPC 上使用 SOAP 并不仅限于 HTTP 协议绑定。 <br /><br />协议结构 <br /><br />　　SOAP 消息格式：<br /><br />　　SOAP 标头<br /><br />　　&lt;SOAP-ENV: Envelope <br /><br />　　Attributes&gt;<br /><br />　　&lt;SOAP-ENV:Body<br /><br />　　Attributes <br /><br />　　&lt;/SOAP-ENV:Body&gt; <br /><br />　　&lt;/SOAP-ENV:Envelope&gt; <br /><br />　　示例 1 ： 内嵌在 HTTP 请求中的 SOAP 消息 <br /><br />POST /StockQuote HTTP/1.1<br />Host: www.stockquoteserver.com<br />Content-Type: text/xml; charset="utf-8"<br />Content-Length: nnnn<br />SOAPAction: "Some-URI"<br /><br />&lt;SOAP-ENV:Envelope<br />xmlns:SOAP-ENV="<a title="http://schemas.xmlsoap.org/soap/envelope/" href="http://schemas.xmlsoap.org/soap/envelope/" target="_blank">http://schemas.xmlsoap.org/soap/envelope/</a>"<br />SOAP-ENV:encodingStyle="<a title="http://schemas.xmlsoap.org/soap/encoding/" href="http://schemas.xmlsoap.org/soap/encoding/" target="_blank">http://schemas.xmlsoap.org/soap/encoding/</a>"&gt;<br />&lt;SOAP-ENV:Body&gt;<br />&lt;m:GetLastTradePrice xmlns:m="Some-URI"&gt;<br />&lt;symbol&gt;DIS&lt;/symbol&gt;<br />&lt;/m:GetLastTradePrice&gt;<br />&lt;/SOAP-ENV:Body&gt;<br />&lt;/SOAP-ENV:Envelope&gt;<br /><br />　　下面是一个包含将 SOAP 消息作为负载的 HTTP 应答消息。<br /><br />　　示例 2 ： 内嵌在 HTTP 应答中的 SOAP 消息 <br /><br />HTTP/1.1 200 OK<br />Content-Type: text/xml; charset="utf-8"<br />Content-Length: nnnn<br /><br />&lt;SOAP-ENV:Envelope<br />xmlns:SOAP-ENV="<a title="http://schemas.xmlsoap.org/soap/envelope/" href="http://schemas.xmlsoap.org/soap/envelope/" target="_blank">http://schemas.xmlsoap.org/soap/envelope/</a>"<br />SOAP-ENV:encodingStyle="<a title="http://schemas.xmlsoap.org/soap/encoding/" href="http://schemas.xmlsoap.org/soap/encoding/" target="_blank">http://schemas.xmlsoap.org/soap/encoding/</a>"/&gt;<br />&lt;SOAP-ENV:Body&gt;<br />&lt;m:GetLastTradePriceResponse xmlns:m="Some-URI"&gt;<br />&lt;Price&gt;34.5&lt;/Price&gt;<br />&lt;/m:GetLastTradePriceResponse&gt;<br />&lt;/SOAP-ENV:Body&gt;<br />&lt;/SOAP-ENV:Envelope&gt; <img src ="http://www.blogjava.net/zqli/aggbug/83254.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-11-24 14:56 <a href="http://www.blogjava.net/zqli/archive/2006/11/24/83254.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] 招聘中经常伴随Java出现的20项技术 </title><link>http://www.blogjava.net/zqli/archive/2006/11/23/83110.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Thu, 23 Nov 2006 12:03:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/11/23/83110.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/83110.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/11/23/83110.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/83110.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/83110.html</trackback:ping><description><![CDATA[
		<p>下图显示了英国最近六个月内招聘工作的岗位中和Java同时出线的一些关键词，按照流行度排序的。</p>
		<p>
				<a href="http://www.itjobswatch.co.uk/jobs/uk/java.do">
						<img alt="" src="http://www.javalobby.org/images/postings/java_it_skills.gif" border="0" />
				</a> </p>
		<p>下表是Java和Java应用经常出现的关键词,其中绝大多数都是和J2EE相关的。</p>
		<p>1 31498 (38.50 %) J2EE <br />2 21368 (26.12 %) XML <br />3 13380 (16.35 %) .NET <br />4 11514 (14.07 %) JSP <br />5 9895 (12.09 %) HTML <br />6 8217 (10.04 %) WebSphere <br />7 6583 (8.05 %) Struts <br />8 6295 (7.69 %) EJB <br />9 6068 (7.42 %) Servlets <br />10 5182 (6.33 %) WebServices <br />11 4998 (6.11 %) Hibernate <br />12 4447 (5.44 %) JDBC </p>
		<br />
		<br />
		<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1406718</p>
<img src ="http://www.blogjava.net/zqli/aggbug/83110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-11-23 20:03 <a href="http://www.blogjava.net/zqli/archive/2006/11/23/83110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] F3: Sun的新Java脚本语言</title><link>http://www.blogjava.net/zqli/archive/2006/11/14/81108.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Tue, 14 Nov 2006 13:59:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/11/14/81108.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/81108.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/11/14/81108.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/81108.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/81108.html</trackback:ping><description><![CDATA[
		<p>F3是Form follows function的简称。Sun即将对这个项目开放源代码</p>
		<p>F3 是一个声明式的Java脚本语言，它使用静态类型以获得更好的IDE支持和编译时错误（这和Javascript不同），还支持类型引用，申明式语法和自动数据绑定，完全支持2D图像接口和标准的Swing组件，以及声明式的动画。你还可以在里面引用java类，创建新的java对象，调用它们的方法和实现Java接口。</p>
		<p>该项目还同时设计了Netbeans和Eclipse的插件来支持代码即使检查，代码自动完成，语法高亮，和超链接导航。</p>
		<p>F3 向我们展示了，我们尚未完全挖掘Java平台在GUI开发方面的能力，有了工具支持的F3，使Java平台在GUI开发上比Macromedia Flash/Flex/Open Laszlo, Adobe Apollo, Microsoft WPF/XAML, Mozilla XUL, AJAX/DHMTL.更具有竞争力。</p>
		<p>
				<strong>Example</strong>
		</p>
		<p>
				<br />
				<span style="COLOR: #a1a100">import f3.ui.*;</span>
				<br />
				<span style="COLOR: #a1a100">import f3.ui.canvas.*;</span>
				<br />
				<span style="COLOR: #a1a100">import f3.ui.filter.*;</span>
				<br /> <br /><a href="http://www.google.com/search?q=allinurl%3ACanvas+java.sun.com&amp;bntl=1"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Canvas</span></a><span style="FONT-WEIGHT: bold; COLOR: #006600">{</span><br />    content: Text <span style="FONT-WEIGHT: bold; COLOR: #006600">{</span><br />        x: <span style="COLOR: #800000">20</span><br />        y: <span style="COLOR: #800000">20</span><br />        content: <span style="COLOR: #ff0000">"Welcome to F3"</span><br />        font: <a href="http://www.google.com/search?q=allinurl%3AFont+java.sun.com&amp;bntl=1"><span style="FONT-WEIGHT: bold; COLOR: #aaaadd">Font</span></a><span style="FONT-WEIGHT: bold; COLOR: #006600">{</span> face: VERDANA, style: <span style="FONT-WEIGHT: bold; COLOR: #006600">[</span>ITALIC, BOLD<span style="FONT-WEIGHT: bold; COLOR: #006600">]</span>, size: <span style="COLOR: #800000">80</span><span style="FONT-WEIGHT: bold; COLOR: #006600">}</span><br />        fill: LinearGradient <span style="FONT-WEIGHT: bold; COLOR: #006600">{</span><br />            x1: <span style="COLOR: #800000">0</span>, y1: <span style="COLOR: #800000">0</span>, x2: <span style="COLOR: #800000">0</span>, y2: <span style="COLOR: #800000">1</span><br />            stops: <br />            <span style="FONT-WEIGHT: bold; COLOR: #006600">[</span>Stop <span style="FONT-WEIGHT: bold; COLOR: #006600">{</span><br />                offset: <span style="COLOR: #800000">0</span><br />                color: blue<br />            <span style="FONT-WEIGHT: bold; COLOR: #006600">}</span>,<br />            Stop <span style="FONT-WEIGHT: bold; COLOR: #006600">{</span><br />                offset: <span style="COLOR: #800000">0</span>.<span style="COLOR: #800000">5</span><br />                color: dodgerblue<br />            <span style="FONT-WEIGHT: bold; COLOR: #006600">}</span>,<br />            Stop <span style="FONT-WEIGHT: bold; COLOR: #006600">{</span><br />                offset: <span style="COLOR: #800000">1</span><br />                color: blue<br />            <span style="FONT-WEIGHT: bold; COLOR: #006600">}</span><span style="FONT-WEIGHT: bold; COLOR: #006600">]</span><br />        <span style="FONT-WEIGHT: bold; COLOR: #006600">}</span><br />        filter: <span style="FONT-WEIGHT: bold; COLOR: #006600">[</span>Glow <span style="FONT-WEIGHT: bold; COLOR: #006600">{</span>amount: <span style="COLOR: #800000">0</span>.<span style="COLOR: #800000">1</span><span style="FONT-WEIGHT: bold; COLOR: #006600">}</span>, Noise <span style="FONT-WEIGHT: bold; COLOR: #006600">{</span>monochrome: <span style="FONT-WEIGHT: bold; COLOR: #000000">true</span>, distribution: <span style="COLOR: #800000">0</span><span style="FONT-WEIGHT: bold; COLOR: #006600">}</span><span style="FONT-WEIGHT: bold; COLOR: #006600">]</span><br />    <span style="FONT-WEIGHT: bold; COLOR: #006600">}</span><br /><span style="FONT-WEIGHT: bold; COLOR: #006600">}</span><br /></p>
		<p>would produce:</p>
		<p>
				<img alt="" src="http://blogs.sun.com/chrisoliver/resource/welcome.PNG" />
		</p>
		<p> </p>
		<br />
		<br />
		<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1378821</p>
<img src ="http://www.blogjava.net/zqli/aggbug/81108.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-11-14 21:59 <a href="http://www.blogjava.net/zqli/archive/2006/11/14/81108.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]在网页中插入flash</title><link>http://www.blogjava.net/zqli/archive/2006/11/03/78996.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 03 Nov 2006 14:15:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/11/03/78996.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/78996.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/11/03/78996.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/78996.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/78996.html</trackback:ping><description><![CDATA[
		<p>常用参数设置<br /> <br /> <br />作者：佚名</p>
		<p>    文章来源：互联网    </p>
		<p>点击数： <br /> <br /> <br />我们现在大部分人做网页，都是直接用DW插入flash，</p>
		<p>而且DW也是所见即所得，直接生成了相应的flash显示代码。</p>
		<p>可是我们又有多少人了解这些直接由DW生成的代码呢？</p>
		<p>其实我接触flash player标签，是在刚学习html的时候，</p>
		<p>那时书中插入flash只有最简单的&lt;embed src="" width=""</p>
		<p> height=""&gt;&lt;/embed&gt;一句,而且在很长一段时间里，</p>
		<p>只要网页中插入flash我也都是这样写的，</p>
		<p>当时认为，这样写即简单好记，又节省代码，反倒对DW起疑问，</p>
		<p>为什么这么简单的代码，它要搞得这么复杂呢。但仔细想想，</p>
		<p>DW生成的代码必有他的道理。而在后来的应用中，</p>
		<p>也应证了我的判断（呵呵，也许想法本来就菜）。 <br />    这几个星期，一直在做flash与JS及.NET交互相关的应用，</p>
		<p>所以对OBJECT、EMBED标签有了更深的了解。就这两天，</p>
		<p>在做flash实现网页拖块布局功能（类似QQ空间的JS布局），</p>
		<p>由于要根据不同用户，载入及输出不同的用户配置文件，</p>
		<p>所以我想到了由.NET生成的相应用户的配置文件名，</p>
		<p>而用&lt;param name="FlashVars"</p>
		<p>value="import=userimport1.txt&amp;output=useroutput1.txt"&gt;</p>
		<p>来传递相关的文件变量给flash。但在实际应用中，</p>
		<p>发现Firefox及opera等浏览器并不能识变这样的变量传递，</p>
		<p>更确切地说，它们并不支持&lt;param&gt;标签。所以今天抽空，</p>
		<p>上MM网收集整合了一下相关的内容。 </p>
		<p>    一、介绍： <br />    我们要在网页中正常显示flash内容，</p>
		<p>那么页面中必须要有指定flash路径的标签。也就是OBJECT</p>
		<p>和EMBED标签。OBJECT标签是用于windows平台的IE浏览器的，</p>
		<p>而EMBED是用于windows和Macintosh平台下的Netscape Navigator浏览</p>
		<p>器以及Macintosh平</p>
		<p>台下的IE浏览器。windows平台的IE利用Activex控件来播放</p>
		<p>flash而其它的浏览器则使用Netscape插件技术来播放flash。 </p>
		<p>    下面是简单的网页中插入flash的代码示例：</p>
		<p>
				<br />    Code:</p>
		<p>
				<br />&lt;OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"<br />codebase="<a href="http://download.macromedia.com/pub/sho">http://download.macromedia.com/pub/sho</a><br />ckwave/cabs/flash/swflash.cab#version=6,0,40,0"<br />WIDTH="550" HEIGHT="400" id="myMovieName"&gt;<br />&lt;PARAM NAME=movie VALUE="myFlashMovie.swf"&gt;<br />&lt;PARAM NAME=quality VALUE=high&gt;<br />&lt;PARAM NAME=bgcolor VALUE=#FFFFFF&gt;<br />&lt;EMBED src="/support/flash/ts/docum<br />ents/myFlashMovie.swf" quality=high bgcolor=#FFFFFF WIDTH="550"<br /> HEIGHT="400"<br />NAME="myMovieName" ALIGN="" TYPE="application/x-shockwave-flash"<br />PLUGINSPAGE="<a href="http://www.macromedia.com/go/getflashplayer">http://www.macromedia.com/go/getflashplayer</a>"&gt;<br />&lt;/EMBED&gt;<br />&lt;/OBJECT&gt;</p>
		<p>    二、为什么要使用以上全部的标签？能省略某些标签不？ <br />    OBJECT标签是用于windows IE3.0及以后浏览器或者其</p>
		<p>它支持Activex控件的浏览器。“classid”和“codebase”</p>
		<p>属性必须要精确地按上例所示的写法写，它们告诉浏览器自动下</p>
		<p>载flash player的地址。如果你没有安装过flash player</p>
		<p>那么IE3.0以后的浏览器会跳出一个提示框访问是否要自动安装</p>
		<p>flash player。当然，如果你不想让那些没有安装flash</p>
		<p>player的用户自动下载播放器，或许你可以省略掉这些代码。<br /> <br />    EMBED标签是用于Netscape Navigator2.0及以后的浏</p>
		<p>览器或其它支持Netscape插件的浏览器。“pluginspage”</p>
		<p>属性告诉浏览器下载flash player的地址，如果还没有安装</p>
		<p>flash player的话，用户安装完后需要重启浏览器才能正常</p>
		<p>使用。<br />  为了确保大多数浏览器能正常显示flash，你需要把EMBED</p>
		<p>标签嵌套放在OBJECT标签内，就如上面代码例子一样。</p>
		<p>支持Activex控件的浏览器将会忽略OBJECT标签内的EMBED标签。</p>
		<p>Netscape和使用插件的IE浏览器将只</p>
		<p>读取EMBED标签而不会识别OBJECT标签。也就是说，如果你省</p>
		<p>略了EMBED标签，那firefox就不能识别你的flash了</p>
		<p>（不过纳闷的是，省略了object只写embed，IE也能正常显示</p>
		<p>flash，呵呵，具体的再仔细看看了）。<br />本文列出了用于发布影片的OBJECT和EMBED标签的必要以及可选属性。 </p>
		<p>    一、必需属性：<br />  ·CLASSID-设置浏览器的Activex控件，仅用于OBJECT标</p>
		<p>签。<br />  ·CODEBASE-设置flash Activex控件的位置，因而如果</p>
		<p>浏览器如果没有安装的话，可以自动下载安装。仅用于OBJECT</p>
		<p>标签。<br />  ·WIDTH-以百分比或象素指定flash影片的宽度。<br />  ·HEIGHT-以百分比或象素指定flash影片的高度。<br />  ·SRC-指定影片的下载地址。仅用于EMBED标签。<br />  ·PLUGINSPAGE-设置flash 插件的位置，因而如果浏览器</p>
		<p>如果没有安装的话，可以自动下载安装。仅用于EMBED标签。<br />  ·MOVIE-指定影片的下载地址。仅用于OBJECT标签。</p>
		<p>二、可选属性及可用的值：<br />  ·ID-设定变量名，用于脚本代码的引用。仅用于OBJECT。<br />  ·NAME -设定变量名，用于脚本代码（如javascript）的</p>
		<p>引用。仅用于EMBED。<br />  ·SWLIVECONNECT - （true或false）指定当flash</p>
		<p>player第一次下载时，是否启用java。如果些属性省略，</p>
		<p>默认值为false。你果你在相同页同使用javascript和flash，</p>
		<p>java必须使用FSCommand来工作。<br />  ·PLAY -（true或false）指定flash影片是否在下载完成</p>
		<p>后就自动播放，如果省略此属性，则默认为true。<br />  ·LOOP - （true或false）指定影片播放完最后一帧后是</p>
		<p>停止还是继续循环播放，如果省略此属性，则默认为true。<br />  ·MENU - （true或false）<br />    ·True 显示全部的菜单，允许用户放大，缩小等控制影</p>
		<p>片播放等操作。<br />    ·False 显示只包含设置选项和关于flash的菜单。<br />  ·QUALITY - (low, high, autolow, autohigh, best )<br />     ·Low 速度优于美观，而且不应用反锯齿。<br />   ·Autolow 刚开始着重于速度，但当需要时随时提升美观。<br />   ·Autohigh 同时着重播放速度和美观，但需要时则牺牲美</p>
		<p>观来保证播放速度。<br />   ·Medium 应用一些反锯齿而不平滑位图。它质量高于low</p>
		<p>设置而低于high设置。<br />   ·High 美观优于播放速度，而且一直应用反锯齿。</p>
		<p>如果影片不包含动画，位图会被平滑化;而如果影片包含动画，</p>
		<p>位图将不变平滑。<br />   ·Best 提供最好的显示质量而不考虑播放速度。</p>
		<p>所有输出都应用反锯齿及所有位图都被平滑化。<br />  ·SCALE - (showall, noborder, exactfit)<br />     ·Default(Show all)影片在指定的区域内显示，</p>
		<p>但保持原始的比例。影片两侧将会出现边框。<br />   ·No Boder 收缩影片以适合指定的区域，保持影片不失真，</p>
		<p>但部分影片将可能将裁切。然而保持影片的原始比例。<br />   ·Exact Fit 使整个影片在指定的区域内显示，影片有可</p>
		<p>能变形失真，而且不保持原始的比例。<br />  ·ALIGN - (l, t, r, b)<br />   ·默认为居中，当浏览器窗口小于影片时，边缘会被裁切。<br />   ·Left,Right,Top,Bottom按照相应的设置沿浏览器的边</p>
		<p>缘对齐。如果需要，另外三边将被裁切。<br />  ·SALIGN - (l, t, r, b, tl, tr, bl, br)<br />   ·L,R,T,B<br />   ·TL,TR<br />   ·BL,BR<br />  ·WMODE- (window, opaque, transparent)</p>
		<p>设置flash影片的window mode属性，指定flash在浏览器中</p>
		<p>的透明，层叠及位置。<br />   ·Window 影片在浏览器中自己的矩形窗口内播放。<br />   ·Opaque 影片隐藏了所有在它后面的内容。<br />   ·Transparent 使flash影片透明，显示透明影片后</p>
		<p>面的网页内容。这将会降低动画的性能。而且这个属性不是在所</p>
		<p>有浏览器中都可用的。<br />  ·BGCOLOR - （#RRGGBB, 十六进制RGB值。）指定影片的</p>
		<p>背景颜色。使用这个属性覆盖flash中设定的背景颜色。<br />  ·BASE - 设定基准目录或URL，用来解决所以flash中的相</p>
		<p>对路径。类似网页中的&lt;base&gt;标签。<br />  ·FLASHVARS 传递变量到flash player，需要flash</p>
		<p>player6及以后的版本。<br />   ·传递root级变量到影片。字符串的格式是用“&amp;”分</p>
		<p>隔的name=value集。<br />   ·浏览器支持64kB大小的字符串长度。<br />   ·更多关于FlashVars的信息，请查看相关文档。<br /> <br /></p>
<img src ="http://www.blogjava.net/zqli/aggbug/78996.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-11-03 22:15 <a href="http://www.blogjava.net/zqli/archive/2006/11/03/78996.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]JBOSS服务</title><link>http://www.blogjava.net/zqli/archive/2006/10/31/78373.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Tue, 31 Oct 2006 14:27:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/10/31/78373.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/78373.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/10/31/78373.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/78373.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/78373.html</trackback:ping><description><![CDATA[
		<div class="username">作者: ELFer</div>
		<div class="dateline">2006-09-27 10:11</div>
		<div class="posttext">    JBoss中包含了几种不同的服务器类型，以适应不同的需求。下面就以JBoss-4.0.0为例简要说明这几种服务器的区别以及根据需要配置自己的服务器的方法。<br />    <strong>一、服务器的类型</strong><br />    在JBoss的server目录中包含了四个文件夹：all、default、standard和minimal，它们分别代表了JBoss自带的四种类服务器。从字面就可以看出四种服务器的区别。具体如下：<br />    minimal：这是JBoss最小化配置服务器，它包含了启动JBoss所需要的最小化的服务。它启动一个日志服务、一个JNDI服务器和一个用来发现新的发布内容的URL发布扫描器。如果你想使用JMX/JBoss启动你自己的服务，而不是用任何J2EE的技术，那么这个就是最佳选择。它没有web容器，不支持EJB或者JMX。<br />    default：这是JBoss服务器的默认配置，它包含大多数J2EE应用程序所需要的标准服务。它不包括JAXR服务、IIOP服务和任何关于集群的服务。<br />    all：这是JBoss服务器的完整配置，它包含了所有可用的服务，像RMI/IIOP和集群服务这些在default配置中不支持的服务。<br />    standard：这是JBoss服务器的标准配置。<br />    当然，我们还可以配置属于自己的服务器。<br />    <strong>二、服务器的启动<br /></strong>    在%JBOSS_HOME%/bin下有一个run.bat，双击这个文件就可以启动JBoss服务器，同时会发现在bin中还有一个run.sh和shutdown.sh，这是用来在UNIX和Linux中启动和关闭服务器。除了这种方法以外，如果配置了环境变量，还可以在命令行直接输入run来启动服务器。以上的方式启动的只是JBoss中default配置的服务器，如果要启动别的服务器，可以使用：run -c all，这样就会启动all服务器。    <br />    <strong>三、配置自己的服务器</strong><br />     在开发过程中，我们可以直接把自己的应用程序放在需要的服务器中，但是为了保持原来的服务器，也为了使用的方便，通常的做法是将需要的服务器复制一份,命名为自己服务器的名字，例如myserver。像前面的启动all服务器一样，在命令行输入：run -c myserver，就可以启动myserver服务器。<br />    在%JBOSS_HOME%/bin中可以通过run.bat启动default服务器，那么我们也可以在其中建立启动自己服务器的bat文件。首先，复制run.bat，命名为myserver.bat（为了明白期间，一般将bat文件命名为和要启动的服务器同样的名字）。然后，打开myserver.bat，找到如下：<br />        "%JAVA%" %JAVA_OPTS% -Djava.endorsed.dirs=%JBOSS_ENDORSED_DIRS% -classpath "%JBOSS_CLASSPATH%" org.jboss.Main %* <br />在后面添加 -c myservser，如下所示：<br />        "%JAVA%" %JAVA_OPTS% -Djava.endorsed.dirs=%JBOSS_ENDORSED_DIRS% -classpath "%JBOSS_CLASSPATH%" org.jboss.Main %* -c myserver最后，保存退出，双击这个文件，就会启动myserver服务器。 <br />    <strong>四、端口号的修改</strong><br />    JBoss服务器在启动过程会为每一个服务器指定一个端口号，例如HTTP是8080，但是有时可能一些端口已经被占用，这时就会导致服务器启动失败。常见的一种情况，如果先后在同一台机器上安装了Oracle和JBoss，这时HTTP服务的8080端口就会被占用，启动服务器时就会报错。此时就要修改JBoss的默认端口了。<br />    在当前的服务器文件夹中，找到deploy\jbossweb-tomcat50.sar文件夹，例如：%JBOSS_HOME%\server\myserver\deploy\jbossweb-tomcat50.sar，这个文件夹下有一个server.xml，打开，会看到如下内容：<br />        <!-- A HTTP/1.1 Connector on port 8080 --><br />          <connector address="${jboss.bind.address}" port="8080"></connector>            maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<br />            enableLookups="false" redirectPort="8443" acceptCount="100"<br />            connectionTimeout="20000" disableUploadTimeout="true"/&gt;<br />这就指定了HTTP的端口为8080，将8080修改为其他没有使用的端口，例如8000，保存。再启动时就会发现端口号已经更改。<br />    关于端口的占用问题，有时先启动BT下载，再启动JBoss时就有可能报端口被占用的错误，这时先退出BT，待JBoss完全启动后再打开BT就可以了。</div>
<img src ="http://www.blogjava.net/zqli/aggbug/78373.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-10-31 22:27 <a href="http://www.blogjava.net/zqli/archive/2006/10/31/78373.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]关于J2EE Tranaction的几个基本概念 </title><link>http://www.blogjava.net/zqli/archive/2006/10/30/78077.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Mon, 30 Oct 2006 08:23:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/10/30/78077.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/78077.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/10/30/78077.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/78077.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/78077.html</trackback:ping><description><![CDATA[
		<font face="Arial"> Transaction不管在J2EE还是.NET领域中都是相当重要的一个组成部分。尽管很多与Transaction相关的概念在两个不同的平台中都是相通的，但是它们在Transaction的实现方面却有着很多的不同。想对.NET下的Transaction有更深入了解的朋友，可以参考</font>
		<a href="http://www.cnblogs.com/idior">
				<font face="Arial">idior</font>
		</a>
		<font face="Arial">兄写<font color="#000000">的</font><font color="#000000"><a href="http://www.cnblogs.com/idior/archive/2005/08/15/214300.html">Transaction in ADO.net 2.0</a></font>。在以下的篇幅里面，我就J2EE中与Transaction相关的几个概念做些讲述。<br />        1.什么是Transaction？所谓Transaction是指一系列不可分割的改动数据库的操作。在这个解释中，有三个关键词：<font color="#000080"><strong>一系列</strong></font>，<strong><font color="#000080">不可</font></strong><strong><font color="#000080">分割</font></strong>以及<font color="#000080"><strong>改动</strong></font>。仅仅是一个改动数据库的操作是没有Transaction可言，只有“一系列”操作(一组SQL语句)才可能组成Transaction；“不可分割”就意味着一致性和完整性，要么这一系列操作全部commit，要么就全部rollback；如果一系列的操作只包含enquiry操作，那么这些操作也不是Transaction。 <br />        2.在J2EE中，Transaction主要有几大类，具体有几种？在J2EE中，Transaction主要有Bean-Managed Transaction和Container-Managed Transaction两大类。其中在Bean-Managed Transaction中还会分为JDBC Transaction和JTA Transaction两种。<br />        3.什么是JDBC Transaction？它有怎样的特点？JDBC Transaction是指由Database本身去管理的事务。其最大的特点就是通过显示调用Connection接口的commit和rollback方法来完成事务的提交和回滚。事务结束的边界是commit或者rollback方法的调用，而开始的边界则不是那么明显了，它会开始于组成当前事务的所有statement中的第一个被执行的时候。具体代码如下：</font>
		<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
				<div>
						<font face="Courier New">
								<img id="Codehighlighter1_41_691_Open_Image" onclick="this.style.display='none'; Codehighlighter1_41_691_Open_Text.style.display='none'; Codehighlighter1_41_691_Closed_Image.style.display='inline'; Codehighlighter1_41_691_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
								<img id="Codehighlighter1_41_691_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_41_691_Closed_Text.style.display='none'; Codehighlighter1_41_691_Open_Image.style.display='inline'; Codehighlighter1_41_691_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" />
								<span style="COLOR: #0000ff">class</span>
								<span style="COLOR: #000000"> CreditDAoImpl implements CreditDAO </span>
								<span id="Codehighlighter1_41_691_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.cnblogs.com/Images/dot.gif" />
								</span>
						</font>
						<span id="Codehighlighter1_41_691_Open_Text">
								<font face="Courier New">
										<span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />    Connection conn </span>
										<span style="COLOR: #000000">=</span>
								</font>
								<font face="Courier New">
										<span style="COLOR: #000000"> getConnection();<br /><img id="Codehighlighter1_187_689_Open_Image" onclick="this.style.display='none'; Codehighlighter1_187_689_Open_Text.style.display='none'; Codehighlighter1_187_689_Closed_Image.style.display='inline'; Codehighlighter1_187_689_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_187_689_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_187_689_Closed_Text.style.display='none'; Codehighlighter1_187_689_Open_Image.style.display='inline'; Codehighlighter1_187_689_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">public</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">void</span>
										<span style="COLOR: #000000"> transfer(Currency amount, Account fromAccount, Account toAccount) throws CreditException </span>
										<span id="Codehighlighter1_187_689_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.cnblogs.com/Images/dot.gif" />
										</span>
								</font>
								<span id="Codehighlighter1_187_689_Open_Text">
										<font face="Courier New">
												<span style="COLOR: #000000">{<br /><img id="Codehighlighter1_201_401_Open_Image" onclick="this.style.display='none'; Codehighlighter1_201_401_Open_Text.style.display='none'; Codehighlighter1_201_401_Closed_Image.style.display='inline'; Codehighlighter1_201_401_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_201_401_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_201_401_Closed_Text.style.display='none'; Codehighlighter1_201_401_Open_Image.style.display='inline'; Codehighlighter1_201_401_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        </span>
												<span style="COLOR: #0000ff">try</span>
												<span style="COLOR: #000000"> </span>
												<span id="Codehighlighter1_201_401_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.cnblogs.com/Images/dot.gif" />
												</span>
										</font>
										<span id="Codehighlighter1_201_401_Open_Text">
												<font face="Courier New">
														<span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />             conn.setAutoCommit(</span>
														<span style="COLOR: #0000ff">false</span>
												</font>
												<span style="COLOR: #000000">
														<font face="Courier New">);<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />             depositToAccount(conn, toAccount, amount);<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />             withdrawFromAccount(conn, fromAccount, amount);     <br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />             conn.commit();<br /><img id="Codehighlighter1_423_682_Open_Image" onclick="this.style.display='none'; Codehighlighter1_423_682_Open_Text.style.display='none'; Codehighlighter1_423_682_Closed_Image.style.display='inline'; Codehighlighter1_423_682_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_423_682_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_423_682_Closed_Text.style.display='none'; Codehighlighter1_423_682_Open_Image.style.display='inline'; Codehighlighter1_423_682_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        }</font>
												</span>
										</span>
										<font face="Courier New">
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">catch</span>
												<span style="COLOR: #000000"> (Exception e) </span>
												<span id="Codehighlighter1_423_682_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.cnblogs.com/Images/dot.gif" />
												</span>
										</font>
										<span id="Codehighlighter1_423_682_Open_Text">
												<font face="Courier New">
														<span style="COLOR: #000000">{<br /><img id="Codehighlighter1_441_549_Open_Image" onclick="this.style.display='none'; Codehighlighter1_441_549_Open_Text.style.display='none'; Codehighlighter1_441_549_Closed_Image.style.display='inline'; Codehighlighter1_441_549_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_441_549_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_441_549_Closed_Text.style.display='none'; Codehighlighter1_441_549_Open_Image.style.display='inline'; Codehighlighter1_441_549_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />            </span>
														<span style="COLOR: #0000ff">try</span>
														<span style="COLOR: #000000"> </span>
														<span id="Codehighlighter1_441_549_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.cnblogs.com/Images/dot.gif" />
														</span>
												</font>
												<span id="Codehighlighter1_441_549_Open_Text">
														<font face="Courier New">
																<span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />                 conn.rollback();<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />                 </span>
																<span style="COLOR: #0000ff">throw</span>
																<span style="COLOR: #000000"> </span>
																<span style="COLOR: #0000ff">new</span>
														</font>
														<span style="COLOR: #000000">
																<font face="Courier New"> CreditException(e.getMessage());<br /><img id="Codehighlighter1_575_649_Open_Image" onclick="this.style.display='none'; Codehighlighter1_575_649_Open_Text.style.display='none'; Codehighlighter1_575_649_Closed_Image.style.display='inline'; Codehighlighter1_575_649_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_575_649_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_575_649_Closed_Text.style.display='none'; Codehighlighter1_575_649_Open_Image.style.display='inline'; Codehighlighter1_575_649_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />            }</font>
														</span>
												</span>
												<font face="Courier New">
														<span style="COLOR: #000000"> </span>
														<span style="COLOR: #0000ff">catch</span>
														<span style="COLOR: #000000"> (SQLException e1) </span>
														<span id="Codehighlighter1_575_649_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.cnblogs.com/Images/dot.gif" />
														</span>
												</font>
												<span id="Codehighlighter1_575_649_Open_Text">
														<font face="Courier New">
																<span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />                 </span>
																<span style="COLOR: #0000ff">throw</span>
																<span style="COLOR: #000000"> </span>
																<span style="COLOR: #0000ff">new</span>
														</font>
														<span style="COLOR: #000000">
																<font face="Courier New"> CreditException(e.getMessage());<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />            }</font>
														</span>
												</span>
												<span style="COLOR: #000000">
														<font face="Courier New">                       <br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</font>
												</span>
										</span>
										<span style="COLOR: #000000">
												<font face="Courier New"> <br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</font>
										</span>
								</span>
								<span style="COLOR: #000000">
										<br />
										<font face="Courier New">
												<img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</font>
								</span>
						</span>
				</div>
		</div>
		<p>
				<font face="Arial">        4.什么是JTA Transaction？它有怎样的特点呢？JTA Transaction是指由J2EE Transaction manager去管理的事务。其最大的特点是调用UserTransaction接口的begin，commit和rollback方法来完成事务范围的界定，事务的提交和回滚。JTA Transaction可以实现同一事务对应不同的数据库，但是它仍然无法实现事务的嵌套。具体的代码如下<sup>[1]</sup>：</font>
		</p>
		<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
				<div>
						<font face="Courier New">
								<img id="Codehighlighter1_40_538_Open_Image" onclick="this.style.display='none'; Codehighlighter1_40_538_Open_Text.style.display='none'; Codehighlighter1_40_538_Closed_Image.style.display='inline'; Codehighlighter1_40_538_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
								<img id="Codehighlighter1_40_538_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_40_538_Closed_Text.style.display='none'; Codehighlighter1_40_538_Open_Image.style.display='inline'; Codehighlighter1_40_538_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" />
								<span style="COLOR: #0000ff">public</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">void</span>
								<span style="COLOR: #000000"> withdrawCash(</span>
								<span style="COLOR: #0000ff">double</span>
								<span style="COLOR: #000000"> amount) </span>
								<span id="Codehighlighter1_40_538_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.cnblogs.com/Images/dot.gif" />
								</span>
						</font>
						<span id="Codehighlighter1_40_538_Open_Text">
								<font face="Courier New">
										<span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />   UserTransaction ut </span>
										<span style="COLOR: #000000">=</span>
								</font>
								<font face="Courier New">
										<span style="COLOR: #000000"> context.getUserTransaction();<br /><img id="Codehighlighter1_103_244_Open_Image" onclick="this.style.display='none'; Codehighlighter1_103_244_Open_Text.style.display='none'; Codehighlighter1_103_244_Closed_Image.style.display='inline'; Codehighlighter1_103_244_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_103_244_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_103_244_Closed_Text.style.display='none'; Codehighlighter1_103_244_Open_Image.style.display='inline'; Codehighlighter1_103_244_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />   </span>
										<span style="COLOR: #0000ff">try</span>
										<span style="COLOR: #000000"> </span>
										<span id="Codehighlighter1_103_244_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.cnblogs.com/Images/dot.gif" />
										</span>
								</font>
								<span id="Codehighlighter1_103_244_Open_Text">
										<font face="Courier New">
												<span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />      ut.begin();<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />      updateChecking(amount);<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />      machineBalance </span>
												<span style="COLOR: #000000">-=</span>
										</font>
										<span style="COLOR: #000000">
												<font face="Courier New"> amount;<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />      insertMachine(machineBalance);<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />      ut.commit();<br /><img id="Codehighlighter1_267_536_Open_Image" onclick="this.style.display='none'; Codehighlighter1_267_536_Open_Text.style.display='none'; Codehighlighter1_267_536_Closed_Image.style.display='inline'; Codehighlighter1_267_536_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_267_536_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_267_536_Closed_Text.style.display='none'; Codehighlighter1_267_536_Open_Image.style.display='inline'; Codehighlighter1_267_536_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />   }</font>
										</span>
								</span>
								<font face="Courier New">
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">catch</span>
										<span style="COLOR: #000000"> (Exception ex) </span>
										<span id="Codehighlighter1_267_536_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.cnblogs.com/Images/dot.gif" />
										</span>
								</font>
								<span id="Codehighlighter1_267_536_Open_Text">
										<font face="Courier New">
												<span style="COLOR: #000000">{<br /><img id="Codehighlighter1_280_314_Open_Image" onclick="this.style.display='none'; Codehighlighter1_280_314_Open_Text.style.display='none'; Codehighlighter1_280_314_Closed_Image.style.display='inline'; Codehighlighter1_280_314_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_280_314_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_280_314_Closed_Text.style.display='none'; Codehighlighter1_280_314_Open_Image.style.display='inline'; Codehighlighter1_280_314_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />       </span>
												<span style="COLOR: #0000ff">try</span>
												<span style="COLOR: #000000"> </span>
												<span id="Codehighlighter1_280_314_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.cnblogs.com/Images/dot.gif" />
												</span>
										</font>
										<font face="Courier New">
												<span id="Codehighlighter1_280_314_Open_Text">
														<span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />          ut.rollback();<br /><img id="Codehighlighter1_345_445_Open_Image" onclick="this.style.display='none'; Codehighlighter1_345_445_Open_Text.style.display='none'; Codehighlighter1_345_445_Closed_Image.style.display='inline'; Codehighlighter1_345_445_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_345_445_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_345_445_Closed_Text.style.display='none'; Codehighlighter1_345_445_Open_Image.style.display='inline'; Codehighlighter1_345_445_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />       }</span>
												</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">catch</span>
												<span style="COLOR: #000000"> (SystemException syex) </span>
												<span id="Codehighlighter1_345_445_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.cnblogs.com/Images/dot.gif" />
												</span>
										</font>
										<span id="Codehighlighter1_345_445_Open_Text">
												<font face="Courier New">
														<span style="COLOR: #000000">{<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />           </span>
														<span style="COLOR: #0000ff">throw</span>
														<span style="COLOR: #000000"> </span>
														<span style="COLOR: #0000ff">new</span>
												</font>
												<font face="Courier New">
														<span style="COLOR: #000000"> EJBException<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />              (</span>
														<span style="COLOR: #000000">"</span>
														<span style="COLOR: #000000">Rollback failed: </span>
														<span style="COLOR: #000000">"</span>
														<span style="COLOR: #000000"> </span>
														<span style="COLOR: #000000">+</span>
												</font>
												<span style="COLOR: #000000">
														<font face="Courier New"> syex.getMessage());<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />       }</font>
												</span>
										</span>
										<span style="COLOR: #000000">
												<br />
												<font face="Courier New">
														<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />       </font>
										</span>
										<font face="Courier New">
												<span style="COLOR: #0000ff">throw</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">new</span>
										</font>
										<font face="Courier New">
												<span style="COLOR: #000000"> EJBException <br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />          (</span>
												<span style="COLOR: #000000">"</span>
												<span style="COLOR: #000000">Transaction failed: </span>
												<span style="COLOR: #000000">"</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #000000">+</span>
										</font>
										<span style="COLOR: #000000">
												<font face="Courier New"> ex.getMessage());<br /><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</font>
										</span>
								</span>
								<span style="COLOR: #000000">
										<br />
										<font face="Courier New">
												<img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</font>
								</span>
						</span>
				</div>
		</div>
		<p>        5.什么是Container-Managed Transaction？它又有怎样的特点呢？Container-Managed Transaction，顾名思义，就是由Container负责管理的Transaction，当然这样Transaction是出现在EJB的范畴中。Container-Managed Transaction最大的特点是不需要显式界定事务的边界，也不需要显式的提交或者回滚事务，这一切都由Container来替我们完成。我们需要做的就是设定在一个Bean中，哪些方法是跟事务相关的，同时设定它们的Transaction Attribute既可。<br />        Transaction的Scope是相当重要的，特别是在一个Bean的方法中调用另外一个Bean的方法。为了便于说明问题，我们把这两个方法分别称为methodA和methodB。当methodA调用methodB的时候，methodB在事务的层面上对调用者methodA有怎样的限制(methodB中是否存在事务)以及methodA如何在事务的层面上实现对methodB的调用(是否需要重新创建一个新的事务来处理methodB的调用)都需要通过Transaction Attribute来设定的。具体的Transaction Attribute有以下六种：Required，RequiresNew，Mandatory，NotSupported，Supports和Never。<font face="Arial">有关Transaction Attribute的介绍，可以参阅J2EE Tutorial中<a href="http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html">关于Container-Managed Transaction的介绍</a>。<br /><br />        [1] 代码来自SUN的J2EE Tutorial中关于<a href="http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction4.html">Bean-Managed Transaction</a>的介绍</font></p>
<img src ="http://www.blogjava.net/zqli/aggbug/78077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-10-30 16:23 <a href="http://www.blogjava.net/zqli/archive/2006/10/30/78077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]JavaBean与EJB有何不同</title><link>http://www.blogjava.net/zqli/archive/2006/10/25/77281.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Wed, 25 Oct 2006 12:54:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/10/25/77281.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/77281.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/10/25/77281.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/77281.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/77281.html</trackback:ping><description><![CDATA[
		<table style="WORD-BREAK: break-all" cellspacing="0" cellpadding="0" width="700" align="center" border="0">
				<tbody>
						<tr>
								<td align="middle" height="25">
										<font face="黑体" size="4">JavaBean与EJB有何不同</font>
								</td>
						</tr>
						<tr bgcolor="#f9f9f9">
								<td id="fontzoom" style="LINE-HEIGHT: 200%">
										<p align="center">作者：佚名    来自：未知</p>
										<p>
										</p>
										<p>您现在可能已在使用 JavaBean，但还不了解它。如果有支持 Java 的浏览器，那么，在桌面上使用 JavaBean 就没有限制。使用的 Web 页面可以将 bean 作为小应用程序的一部分。您很快就会和作为浏览器可视部分的 JavaBean 交互，然后，那些 JavaBean 将与服务器上的 EJB 接口。这种能力也可以扩展到因特网和内部网。</p>
										<p>　　JavaBean 和 Server Bean（通常称为 Enterprise JavaBean (EJB)）有一些基本相同之处。它们都是用一组特性创建，以执行其特定任务的对象或组件。它们还有从当前所驻留服务器上的容器获得其它特性的能力。这使得 bean 的行为根据特定任务和所在环境的不同而有所不同。</p>
										<p>　　这开辟了巨大商机。因为 JavaBean 是与平台无关的，所以对于将来的解决方案，供应商可以轻易向不同用户推出其客户机方的 JavaBean，而不必创建或维护不同的版本。这些 JavaBean 可以与执行商业功能（例如订购、信用卡处理、电子汇款、存货分配、运输等）的 EJB 配合使用。这里有巨大潜力，而这正是组件代理（WebSphere Application Server 企业版）设计提供的那种潜力。</p>
										<p>　　JavaBean 是一种组件，它在内部有接口或有与其相关的属性，以便不同人在不同时间开发的 bean 可以询问和集成。可以构建一个 bean，而在以后构造时将其与其它 bean 绑定。这种过程提供了先构建，然后重复使用的方法，这就是组件的概念。可以将这种单一应用程序部署成独立程序、ActiveX 组件或在浏览器中。</p>
										<p>　　JavaBean 因其外部接口（即属性接口）而与纯对象不同。这种接口允许工具读取组件要执行的功能，将其与其它 bean 挂钩，以及将其插入其它环境。JavaBean 设计成对单一进程而言是本地的，它们在运行时通常可视。这种可视组件可能是按钮、列表框、图形或图表 - 但这不是必需的。</p>
										<p>　　可执行组件</p>
										<p>　　Server Bean 或 EJB 是部署在服务器上的可执行组件或商业对象。有一个协议允许对其进行远程访问或在特定服务器上安装或部署它们。有一系列机制允许它们将服务安全性、事务行为、并发性（由多个客户机同时访问的能力）和持久性（其状态可以保存多久）的主要方面授权给 EJB 服务器上其所在的容器。当安装在容器中时，它们获得各自的行为，该行为提供不同质量的服务，因此，选择正确的 EJB 服务器至关重要。这正是 IBM WebSphere 企业版的优势所在。</p>
										<p>　　EJB 是设计成运行在服务器上，并由客户机调用的非可视远程对象。可通过多个非可视 JavaBean 构建 EJB。它们有一个部署描述符，其目的与 JavaBean 属性相同：它是以后可由工具读取的 bean 的描述。EJB 还独立于平台，一旦编写好，还可以在任何支持 Java 的平台（包括客户机和服务器）上使用。</p>
										<p>　　因为 EJB 由诸如 IBM VisualAge for Java 这样的工具集生成，所以，它是基于服务器的对象，并用于远程调用。它们安装在 EJB 服务器上，并象调用其它 CORBA 远程对象那样获得进行调用的远程接口。</p>
										<p>　　ActiveX 对象</p>
										<p>　　可以将 JavaBean 部署成 ActiveX 对象，虽然 EJB 的代理也可以这样做，但是，因为 ActiveX 运行在桌面上，所以，EJB 本身不能成为 ActiveX 对象。要在与平台相关的、仅 Windows 平台上做到这一点，开发人员可以将 JavaBean 变换成 ActiveX 组件。</p>
										<p>　　好处</p>
										<p>　　EJB 的主要好处在于：构建 bean 时，bean 开发人员可以规定需要什么类型的行为，而不必规定如何去做。开发分为两部分：程序员开发 bean，然后验证：它可与构建工具一起工作，并包括标识所需服务质量行为种类的部署描述符。下一步，另一个程序员可以采用这个 bean，并使用读取 EJB 部署描述符的部署工具，然后将该 bean 安装到 Enterprise Java Server 上的容器中。在第二步中，部署工具采取一些操作 - 这可能意味着生成如状态保存代码，放入事务挂钩，或执行安全性检查这样的代码。所有这些操作由部署工具生成，bean 开发人员和部署人员可以是不同的人。</p>
										<p>　　可以通过使用部署工具，将任何独立于平台的 JavaBean 改写成具有可靠服务质量、特定于平台的 EJB，以满足现有商业系统和应用程序的特定需求。这就是 EJB 服务器对集成系统、网络和体系结构如此重要的原因所在。</p>
										<p>　　EJB 与 IBM WebSphere 企业版</p>
										<p>　　在 IBM WebSphere 企业版中使用时，可以将 EJB 配置成被管理的商业对象。接受它们授权服务的容器是其安装到的容器。将 EJB 的持久性部分映射在数据或状态对象中。EJB 服务器为 EJB 提供不同的服务质量，选择正确的 EJB 服务器可能对满足完整的商业需求至关重要。“组件代理”功能极其健壮，该功能提供如负载均衡和支持服务器组中多台机器的高级功能。它还有大大超出 Enterprise Java Server (EJS) 规范所倡导的系统管理功能。因此，按照基本标准编写的 JavaBean 或 EJB 可以运行在使用“组件代理”功能的 WebSphere 企业版上，并获得那些所有的附加功能。</p>
										<p>　　EJB 服务器还提供独特的特性和服务质量，而且不完全相同。IBM“组件代理”有一些强大特性 - 例如，可伸缩性，它允许开发人员将 EJB 部署到从小型系统到大型网络的不同类型服务器。开发人员可以从小处入手，例如，在一个部门中，首先在 LAN 的 Java 服务器上部署，一旦准备好，就知道可以将在那里创建的 JavaBean 和 EJB 部署到全球网络。然后，开发人员可以测试并熟悉这些 bean，试运行，制作样本等等。满意之后，开发人员可以通过将其移至高性能服务器，来大幅度扩大其规模。JavaBean 和 EJB 不受任何计算机体系结构边界的限制。它们用 Java 编写，可以运行在任何具有 Java 虚拟机的系统上，并可以使用任何 Enterprise Java Server (EJS) 来部署对象。因此，开发人员现在可以在方便的系统上构建，以后在方便的系统上部署，而不必是同一台或同样类型的机器。</p>
										<p>　　IBM WebSphere 企业版支持将商业对象部署到多台服务器。EJB 作为商业对象集成到“组件代理”功能，并作为任何其它商业对象处理。因此，EJB 可以连接到所选的后端系统，并执行任何所需操作，以满足其商业需求。这就成为“组件代理”为 EJB 提供的基础设施。通过将“组件代理”用作 EJB 服务器，开发人员将能够继续使用当前旧有系统，并将其与电子商务接口一起提供。</p>
										<p>　　为使 EJB 能在 WebSphere“组件代理”环境中工作，可以使用“组件代理”部署工具将其安装在一台或多台服务器上，然后将其添加到命名服务器，以便可以全局查找到它。任何可以访问公共命名服务器的人都可以找到它，找到其宿主，并可以在宿主上执行方法，同时创建 EJB。这就是“代理组件”要做的事。</p>
										<p>　　示例</p>
										<p>　　让我们举一个在 Web 购物站点上可以看到的电子购物车的例子。用户的购物车是一个 JavaBean。用户将货架上的商品放入购物车，这些商品本身是 JavaBean。它们全部可视，并且面向用户。结帐时，将用户购物车中的商品发送到服务器上的 EJB，该 EJB 执行一些必要的操作，如检查信用卡授权和可用额度，生成封条，或生成给发货部门的有关提什么货和发货地点的特殊指示 - 这就是商业程序已在进行的活动。</p>
										<p>　　结束语</p>
										<p>　　Bean 的全部意义不只是其现有能力，更在于其可以为商业提供的有竞争力的潜在能力。IT 设计师和应用开发人员现在可以将精力完全集中在商业逻辑，而将如事务、持久性和安全性的底层工作留给服务器。WebSphere 的“组件代理”功能将提供所有这些（还有后端访问）和对象事务管理器。</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/zqli/aggbug/77281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-10-25 20:54 <a href="http://www.blogjava.net/zqli/archive/2006/10/25/77281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]POJO应用框架：Spring与EJB3.0的比较</title><link>http://www.blogjava.net/zqli/archive/2006/10/24/77046.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Tue, 24 Oct 2006 10:27:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/10/24/77046.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/77046.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/10/24/77046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/77046.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/77046.html</trackback:ping><description><![CDATA[
		<h4>摘要:</h4>Spring框架虽然很流行但并不是一个标准的开源框架。EJB3.0是由Java Community Process (JCP)制订的标准框架.这两个框架结构都有一个共同核心设计理念：将中间件服务传递给耦合松散的POJOS (Plain Old Java Objects, 简单洁净Java对象)。 本文将对Srping和EJB3.0框架背后的关键不同处进行考察，并讨论其优缺点。本文的观点也适用于其它更少为人知的框架，因为他们都是对“耦合松散的POJO”的设计 <br /><br /><center><b><span style="FONT-SIZE: 20px">POJO应用框架：Spring与EJB3.0的比较</span></b></center><br /><center>作者：Michael Juntao Yuan</center><br /><center>06/29/2005</center><br /><center>翻译：<a href="http://www.matrix.org.cn/user.shtml?username=loryliu" target="_new"><font color="#002c99">loryliu</font></a></center><br /><br /><span style="COLOR: purple">版权声明</span>：可以任意转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明<br />英文原文地址:<br /><a href="http://www.onjava.com/pub/a/onjava/2005/06/29/spring-ejb3.html" target="_new"><font color="#002c99">http://www.onjava.com/pub/a/onjava/2005/06/29/spring-ejb3.html</font></a><br />中文地址:<br /><a href="http://www.matrix.org.cn/resource/article/43/43718_Spring_EJB.html" target="_new"><font color="#002c99">http://www.matrix.org.cn/resource/article/43/43718_Spring_EJB.html</font></a><br />关键词： Spring EJB<br /><br /><br /><br />艾伯特.爱因斯坦曾经说过：“一切都应该尽可能地简单，但是不能更简单。”确实如此，简化一门理论的基本假设，使我们可以专注于真正关键的地方，这正是一直以来对科学真理的追求。企业软件开发同样如此。<br /><br />提供一个将复杂的事物（例如，事务、安全或持久性）对开发者进行隐藏的应用框架是简化企业软件开发的关键。一个设计良好的框架可以提高代码重用率、开发者的生产力及软件的质量。然而，现有J2EE1.4的EJB2.1框架被普遍认为设计差，且过于复杂。不满于EJB2.1的框架结构，Java开发者尝试了各种各样的中间件服务传递方法。最引人注目的是，以下两个框架引起了开发者极大兴趣并得到了大量正面的反馈。他们以未来企业Java应用所选框架的姿态展现。<br /><br />        Spring框架虽然很流行但并不是一个标准的开源框架。它主要由Interface21 Inc开发和控制。Spring框架结构是基于依赖注入(Dependency Injection (DI))的设计模式。它可以独立或在现有的应用服务器上运行，而且大量地使用了xml配置文件<br /><br />        EJB3.0是由Java Community Process (JCP)制订的标准框架，为所有主要的J2EE厂商支持。JBoss已经提供了试用版EJB3.0标准的开源或商业性质实现。EJB3.0充分利用了Java的注释<br /><br />这两个框架结构都有一个共同核心设计理念：将中间件服务传递给耦合松散的POJOS (Plain Old Java Objects, 简单洁净Java对象)。 这样的框架利用截取执行上下文或在运行时将服务对象注入POJO来把应用服务“缠绕”到POJO。POJO本身并不关心这种“缠绕”，对这种框架结构也没有什么依赖。因此，开发者可专注于业务逻辑和脱离框架的POJO单元测试。除此之外， 由于POJO并不须要继承框架的类或实现其接口，开发者能够极其灵活地搭建继承结构和建造应用。<br /><br />然而，在拥有同一理念的同时，两个框架结构使用不同的方式来传递POJO服务。许多书籍或文章都将Spring 或EJB3.0和EJB2.1做了比较，但是对Spring 和EJB3.0的比较并没有仔细研究过。在本文中，我将对Srping和EJB3.0框架背后的关键不同处进行考察，并讨论其优缺点。本文的观点也适用于其它更少为人知的框架，因为他们都是对“耦合松散的POJO”的设计。希望这篇文章可以帮助你选择适合你需求的最好框架。<br /><br /><b><span style="FONT-SIZE: 16px">厂商无关性</span></b><br />开发者选择Java平台其中最引人注目的理由之一：厂商无关性。EJB3.0正是一套设计为厂商无关的开放性标准。EJB3.0标准为所有企业Java社团里开源或商业性质厂商所开发和支持。它将开发者与应用服务器实现完全隔离。例如，JBoss的 EJB3.0实现基于Hibernate，Oracle的基于TopLink，但是开发者并不须要学习Hibernate- 或TopLink的具体API来使应用可在Jboss或Oracle上运行。厂商无关性使EJB3.0与现今其它POJO中间件框架区别开来。<br /><br />但是，正如许多EJB3.0评论家迅速所指出的，在本文撰写时EJB3.0标准还没有到达一个最终版本。大概还有一到两年的时间EJB3.0才能广泛地为所有主要J2EE厂商所支持。即使你的应用服务器本身不支持EJB3.0，你仍然可以通过下载安装”内嵌的”EJB3.0产品来运行EJB3.0的应用。例如，JBoss的内嵌EjB3.0是开源产品且可以在任何J2SE5.0兼容的环境运行(例如, 在任何Java服务器上)，此产品正处于软件测试阶段。其它厂商不久也将发布自己的内嵌EJB3.0产品，特别是针对标准中关于数据持久性的部分。<br /><br />另一方面，Spring一直以来都是非标准的技术，在未来可预知的一段时间内这种情况将持续下去。虽然你可以在任何应用服务器上使用Spring框架，Spring应用会被锁入在Spring本身和你选择整合进Spring的具体服务中。<br /><br />        Spring框架是一个开源项目，但同时它有一个XML格式的配置文件和编程接口。当然任何一个非标准的产品都会有这种“锁入”(lock-in)的情况，并不是Spring特有的。但Spring应用的长期生存能力仍然还得托Spring这个项目的福（或者是Interface21公司，它雇佣了大部分Spring核心开发人员）。除此之外，假如你用到任何一个具体的Spring服务，例如，Spring事务管理器或则Spring MVC，你也会被锁入到这些API里。<br />        Spring的应用对终端用户是不可知的。例如，对数据持久服务，Spring框架兼容不同的DAO和JDBC的模版帮助类，如Hibernate, iBatis, 和 JDO。所以假如你需要为spring应用切换在数据持久化服务（例如从JBDC到Hibernate），你需要修改你的代码以适合新的模版帮助类。<br /><br /><b><span style="FONT-SIZE: 16px">服务整合</span></b><br />从一个很高的角度上看，Spring框架处于应用服务器和服务库的上方。服务整合的代码（如，数据访问模板和帮助类）属于框架，并暴露于应用开发者。相反，EJB3.0框架与应用服务器高度整合，服务整合代码也包装在一个标准接口后面。<br /><br />因此，实现EJB3.0的厂商可以大大地优化整体性能和提升开发者的体验。例如，在JBoss EJB3.0的实现中，当你在用EntityManager持久化一个Entity Bean时，后台的Hibernate会话事务已经自动地帮定到调用方法的JTA 的事务上，在JTA 事务提交的同时Hibernate会话事务也提交了。你甚至可以使用一个简单的 @PersistenceContext 注释（稍候例子演示）将EntityManager和它后台的Hibernate事务绑定到一个stateful session bean的应用事务中。在一个会话中应用事务横跨多个线程，这在事务性网页应用很有用，例如，多页面的购物车。<br />由于高度整合的EJB3.0的框架，使简单、集成的编程接口成为可能。Oracle EJB3.0框架和其后台的Toplink持久化服务也同样程度地整合。<br /><br />另一个EJB3.0整合服务的绝好例子就是集群支持。假如你在一个服务器集群上部署了一个EJB3.0的应用，所有容错(fail-over)、负载均衡、分布式缓冲和状态复制都已经自动为应用所获得可用。后台的集群支持被隐藏在EJB3.0的框架后面，对EJB3.0开发者来说这些都是完全透明不可见的。<br /><br />在Spring里，很难优化框架和服务之间的通讯。例如，为了使用Spring里的声明事务服务来管理Hibernate事务，你必须显示地在XML文件中配置Spring TransactionManager和Hibernate SessionFactory对象。Spring必须电显示地管理横跨多个HTTP请求的事务。除此之外，没有别的方法均衡Spring应用里的集群。<br /><br /><b><span style="FONT-SIZE: 16px">服务组合的弹性</span></b><br />由于Spring的服务整合代码作为编程接口的一部份暴露在外，应用开发者有按自己需求装配服务的弹性。这个特点使你能够组合自己的轻量级应用服务器。Spring的一个普遍用法就是将Tomcat和Hibernate组合在一起支持数据库驱动的web应用。在这种情况，Spring本身提供事务服务，Hibernat提供持久化服务——这种设置创建了一个袖珍型的应用服务器。<br /><br />EJB3.0应用服务器典型地不提供这种根据需求任你挑捡服务的弹性空间。大多数时间，你得到的只是一系列包装好的特性，其中一些你可能根本就不需要。但是如果应用服务器像JBoss一样提供一个模块性的内部设计，那么你可以只取其中一部分，而把不必要的部分剥去。在任何情况，去自定义一个功能强大的应用服务器是没有什么价值的。<br /><br />当然，假如应用已经超过单个点，那么你应该加入常用服务器上的服务，例如，资源池（resource pooling），消息队列（message queuing）和集群（clustering）。就总体的资源消耗而言，Spring解决方法和其他EJB3.0解决方法一样是重量级的。<br /><br />在Spring框架里，具有弹性的服务装配使得将虚拟对象而不是真正的业务对象绑定到应用中做脱离容器的单元测试更简单。在EJB3.0应用中，大多数组件都是简单POJO，他们可以很容易地在容器外被测试。但是对于与容器服务相关的对象（例如持久化实实体管理器EntityManager）建议用容器内测试。因为这样会比虚拟对象测试方法更简单，强壮及准确。<br /><br /><b><span style="FONT-SIZE: 16px">XML Vs.注解</span></b><br />从应用开发者的观点上来看，Spring的编程开发接口主要基于XML配置文件而EJB3.0广泛地应用Java注解。XML可以表达复杂的关系，但是它也冗长且不够健壮；注解简单明了，但是很难在注解里表达复杂或继承性的关系。<br /><br />Spring选择XML或EJB3.0选择注解都是有他们两者框架后的体系结构决定的。因为注解只能容纳很少的配置信息，只有整合前的框架（重头戏都在框架里）才可以把广泛地使用注解作为配置选择。正如我们所讨论过的，EJB3.0刚好符合这个要求，而Spring作为一个普通的DI框架并不符合。 <br /><br />当然，EJB3.0和Spring都相互取长补短，在某种程度上他们都支持XML和注解。例如，在EJB3.0中，XML配置文件作为一个可选的重载机制来改变注解的默认行为。注解也可以配置一些Spring服务。<br /><br />通过例子是学习XML和注解方式之间差异的最好方法。在下面几个环节里，让我们来看看Spring和EJB3.0是怎样提供关键服务给应用的。<br /><br /><b><span style="FONT-SIZE: 16px">声明性服务</span></b><br />Spring和EJB3.0都将运行时服务（例如，事务、安全、日志和配置服务）绑定到应用。因为这些服务于应用的业务逻辑是没有直接联系，他们只是由应用本身管理。换句话说，这些服务在运行时由容器透明地应用到应用中。开发者或是管理者配置容器，准确地告诉它什么时候怎样应用这些服务。<br /><br />EJB3.0运用Java注解来配置声明性服务，而Sring使用XML配置文件。在大多数情况下，EJB3.0注解方式对于这种服务更简单明了。这里有一个在EJB3.0中将事务服务运用到POJO的例子。<br /><br /><pre class="overflow">public class Foo {<br />    <br />    @TransactionAttribute(TransactionAttributeType.REQUIRED)<br />    public bar () {<br />      // do something ...<br />    }    <br />}</pre><br /><br />你也可以为一个代码段声明多个属性，应用多个服务。这是一个在EJB3.0里同时应用事务和安全服务到POJO的例子。<br /><br /><pre class="overflow">@SecurityDomain("other")<br />public class Foo {<br />    <br />    @RolesAllowed({"managers"})<br />    @TransactionAttribute(TransactionAttributeType.REQUIRED)<br />    public bar () {<br />      // do something ...<br />    }   <br />}</pre><br /><br />使用XML说明代码属性和配置声明性服务会导致冗长和不稳定的配置文件。下面是一个在Spring应用中的XML片段，其应用一个非常简单的Hibernate事务到方法Foo.bar()中。<br /><br /><pre class="overflow">&lt;!-- Setup the transaction interceptor --&gt;<br />&lt;bean id="foo" <br />  class="org.springframework.transaction<br />        .interceptor.TransactionProxyFactoryBean"&gt;<br />    <br />    &lt;property name="target"&gt;<br />        &lt;bean class="Foo"/&gt;<br />    &lt;/property&gt;<br />    <br />    &lt;property name="transactionManager"&gt;<br />        &lt;ref bean="transactionManager"/&gt;<br />    &lt;/property&gt;<br />    <br />    &lt;property name="transactionAttributeSource"&gt;<br />        &lt;ref bean="attributeSource"/&gt;<br />    &lt;/property&gt;<br />&lt;/bean&gt;<br /><br />&lt;!-- Setup the transaction manager for Hibernate --&gt;<br />&lt;bean id="transactionManager" <br />  class="org.springframework.orm<br />         .hibernate.HibernateTransactionManager"&gt;<br />    <br />    &lt;property name="sessionFactory"&gt;<br />        &lt;!-- you need to setup the sessionFactory bean in <br />             yet another XML element -- omitted here --&gt;<br />        &lt;ref bean="sessionFactory"/&gt;<br />    &lt;/property&gt;<br />&lt;/bean&gt;<br /><br />&lt;!-- Specify which methods to apply transaction --&gt;<br />&lt;bean id="transactionAttributeSource"<br />  class="org.springframework.transaction<br />         .interceptor.NameMatchTransactionAttributeSource"&gt;<br />  <br />    &lt;property name="properties"&gt;<br />        &lt;props&gt;<br />            &lt;prop key="bar"&gt;<br />        &lt;/props&gt;<br />    &lt;/property&gt;<br />&lt;/bean&gt;</pre><br /><br />XML的复杂度会以几何级数增长，如果你向同一个POJO添加更多的拦截器(interceptors)（例如安全拦截器）。意识到只有XML配置文件的局限，Spring使用Apache Commons 元数据在Java源码中来说明事务属性。最新版本的Spring1.2也支持JDK-1.5风格注解。要使用事务元数据，你须要将上面的transactionAttributeSourc bean变成一个AttributesTransactionAttributeSource实例。并为元数据拦截器添加额外邦定。<br /><br /><pre class="overflow">    class="org.springframework.aop.framework.autoproxy<br />           .DefaultAdvisorAutoProxyCreator"/&gt;<br />&lt;bean id="transactionAttributeSource"<br />    class="org.springframework.transaction.interceptor<br />           .AttributesTransactionAttributeSource"<br />    autowire="constructor"/&gt;<br />&lt;bean id="transactionInterceptor"<br />    class="org.springframework.transaction.interceptor<br />           .TransactionInterceptor"<br />    autowire="byType"/&gt;<br />&lt;bean id="transactionAdvisor"<br />    class="org.springframework.transaction.interceptor<br />           .TransactionAttributeSourceAdvisor"<br />    autowire="constructor"/&gt;<br />&lt;bean id="attributes"<br />    class="org.springframework.metadata.commons<br />           .CommonsAttributes"/&gt;</pre><br /><br />当你有很多事务性方法时，Spring元数据可以简化transactionAttributeSource。但是这并没有解决XML配置文件的根本问题。冗长而又繁琐的事务拦截器, transactionManager,和transactionAttributeSource仍然需要。<br /><br /><b><span style="FONT-SIZE: 16px">依赖注入(Dependency Injection, DI)</span></b><br /><br />中间件容器的一个关键好处之一就是它可以让开发者建造一个关系耦合松散的应用。服务端客户只需要知道服务的接口。容器依据具体的实现实例化服务对象，使他们为客户端所用。在不改变接口和客户端代码的情况下，这使得容器可以在多种服务实现之间切换。<br /><br />依赖注入的模式是实现耦合松散应用的最好方法之一。它更易用，比其他方法也明了多了，比如通过JNDI依赖性查询或容器回调。使用DI，框架就像一个对象工厂，它创建服务对象然后按照运行时配置将这些服务对象注入到应用的POJO里。站在应用开发者的角度，客户端POJO在被使用时可自动获得正确的服务对象。<br /><br />Spring和EJB3.0都提供广泛的DI模式支持。但是他们之间仍存在很大的不同之处。Spring支持一般意义上且复杂的DI API，其基于XML配置文件。EJB3.0支持大多数普通服务对象（如EJB及context对象）的注入和任何简单注解的JDNI。 <br /><br />EJB63.0注解非常简单易用。@Resource 标记表示注入大多数普通服务对象和JDNI对象。以下例子展示了怎样把服务的JDNI的默认DataSource 对象注入到POJO的一个属性变量中。DefaultDS是DataSource.的JDNI名字。MyDb变量在第一次被使用时被赋上了正确的值。<br /><br /><pre class="overflow">public class FooDao {<br /><br />    @Resource (name="DefaultDS")<br />    DataSource myDb;<br />    <br />    // Use myDb to get JDBC connection to the database<br />}</pre><br /><br />除了直接属性变量注入，Ejb3.0的@Resource注解也可以用来在setter方法里面注入对象。例如，下面的例子就是注入session context对象。应用从不会显示地调用setter方法，其在其他方法被调用前由容器来触发。<br /><br /><pre class="overflow">@Resource <br />public void setSessionContext (SessionContext ctx) { <br />    sessionCtx = ctx; <br />} </pre><br /><br />针对更复杂的服务对象，定义了专用的注入注解。例如，@EJB注释用来注入EJB的Stub，@PersistenceContext注解用来注入处理EJB3.0实体bean访问数据库的EntityManager对象。下面是一个怎样将EntityManager对象注入有状态的 session bean的例子。@PersistenceContext的type属性具体说明了被注入的EntityManager有一个扩展的事务transaction context。transaction context并不会同JTA transaction manager一起自动提交。因此它可以用在在一个会话横跨多个线程的应用事务中。<br /><br /><pre class="overflow">@Stateful<br />public class FooBean implements Foo, Serializable {<br /><br />    @PersistenceContext(<br />      type=PersistenceContextType.EXTENDED<br />    )<br />    protected EntityManager em;<br />    <br />    public Foo getFoo (Integer id) {<br />        return (Foo) em.find(Foo.class, id);<br />    }<br />}</pre><br /><br />EJB3.0标准通过注解可以被注入的服务器资源。但是它并支持将用户定义的应用POJO之间的相互注入。<br /><br />在Spring中，首先你必须为POJO中的服务对象定义一个setter方法。下面的例子说明POJO需要一个Hibernate session 的引用<br /><br /><pre class="overflow">public class FooDao {<br />    <br />    HibernateTemplate hibernateTemplate;<br />    <br />    public void setHibernateTemplate (HibernateTemplate ht) {<br />        hibernateTemplate = ht;<br />    }<br />    <br />    // Use hibernateTemplate to access data via Hibernate<br />    public Foo getFoo (Integer id) {<br />        return (Foo) hibernateTemplate.load (Foo.class, id);<br />    }<br />}</pre><br /><br />然后，以XML里的元素作为桥梁具体描述容器怎样在运行时得到服务对象并将其注入到POJO里。以下是一个XML例子，具体描述了将一个数据源绑定到一个Hibernate session factory，然后从Hibernate session factory到Hibernate template object，最后从template object到应用的POJO。Spring代码如此复杂的部分原因是因为我们须手手动注入后台Hibernate plumbing objects。而EJB3.0 EntityManager是自动被服务器管理和配置。这又将我们带回到Spring并不像EJB3.0那样高度与服务整合的论点上。<br /><br /><pre class="overflow">&lt;bean id="dataSource" <br />  class="org.springframework<br />         .jndi.JndiObjectFactoryBean"&gt;<br />    &lt;property name="jndiname"&gt;<br />        &lt;value&gt;java:comp/env/jdbc/MyDataSource&lt;/value&gt;<br />    &lt;/property&gt;<br />&lt;/bean&gt;<br /><br />&lt;bean id="sessionFactory" <br />  class="org.springframework.orm<br />         .hibernate.LocalSessionFactoryBean"&gt;<br />    &lt;property name="dataSource"&gt;<br />        &lt;ref bean="dataSource"/&gt;<br />    &lt;/property&gt;<br />&lt;/bean&gt;<br /><br />&lt;bean id="hibernateTemplate" <br />  class="org.springframework.orm<br />         .hibernate.HibernateTemplate"&gt;<br />    &lt;property name="sessionFactory"&gt;<br />        &lt;ref bean="sessionFactory"/&gt;<br />    &lt;/property&gt;    <br />&lt;/bean&gt;<br /><br />&lt;bean id="fooDao" class="FooDao"&gt;<br />    &lt;property name="hibernateTemplate"&gt;<br />        &lt;ref bean="hibernateTemplate"/&gt;<br />    &lt;/property&gt;<br />&lt;/bean&gt;<br /><br />&lt;!-- The hibernateTemplate can be injected<br />        into more DAO objects --&gt;</pre><br /><br />虽然，Spring里基于XML的依赖注入语法复杂，但却功能强大。你可以将任何POJO注入到另一个POJO，包括你自己在应用定义的那些POJO。假如你想在EJB3.0应用中用Spring的DI功能 ，你可以通过JNDI把一个Spring bean factory注入到EJB。在一些EJB3.0的应用服务器里，厂商可能会额外定义非标准的POJO注入API。一个很好的例子就是JBoss MicroContainer。它比Spring更一般化，因为它处理Aspect-Oriented Programming（AOP）的依赖。<br /><br /><b><span style="FONT-SIZE: 16px">结论</span></b><br /><br />Spring和Ejb3.0虽然都是为了向企业服务提供耦合松散的POJO，但是使用了不同方法来达到这个目的。两者都大量地使用了依赖注入。<br /><br />对于EJB3.0，基于标准的方案、注解的广泛使用、与应用服务器的高度整合都使得EJB3.0拥有更好的厂商无关性，更高的开发效率。依赖注入和集中的XML配置文件协调一致的使用使开发者能够构建更有弹性的应用，并且可以同时和几个应用服务提供者一起协作。<br /><br /><b>鸣谢</b><br />作者感谢tephen Chambers,、ill Burke、Andy Oliver的珍贵意见。<br /><br /><b>资源</b><br />Spring框架(参见CodeZoo: Spring) <br />EJB 3.0 <br />JBoss EJB 3.0 <br />Oracle Application Server EJB 3.0 Preview <br /><br />Michael Juntao Yuan 善长于提供end-to-end的企业解决方案， 也是一个移动方面的专家，是avid这个开源项目的支持者。<br /><img src ="http://www.blogjava.net/zqli/aggbug/77046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-10-24 18:27 <a href="http://www.blogjava.net/zqli/archive/2006/10/24/77046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Hadoop笔记--不需要分布式编程经验地分布式编程</title><link>http://www.blogjava.net/zqli/archive/2006/09/15/69833.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 15 Sep 2006 03:05:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/09/15/69833.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/69833.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/09/15/69833.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/69833.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/69833.html</trackback:ping><description><![CDATA[作者：<a href="/calvin/">江南白衣</a><p>    <a href="http://lucene.apache.org/hadoop">Hadoop</a> 是 Google labs 的<a href="http://labs.google.com/papers/mapreduce.html">MapReduce</a>的一个实现，<a href="http://lucene.apache.org/nutch">Nutch项目</a>的全部数据处理都构建在其之上。MapReduce是一种简化的分布式编程模式，让程序可以自动在普通机器组成的集群中以并行方式分布执行。</p><p>    就如同java程序员可以不考虑内存泄露一样，MapReduce程序员也不许要关心海量数据如何被分配到多台机器上，不需要考虑机器失效的处理，不需要考虑这些机器间如何协作共同完成工作，程序员不需要什么并发处理或者分布式系统的经验，就可以进行分布式的编程。</p><p>   MapReduce来源于函数式编程的Map,Reduce概念，Map是映射，Reduce是规约。说了非常简单，就真的是非常简单的，先看Hadoop自带的sample-WordCount ，再看Nutch里的Indexer,Fetcher两个实战的例子，最后阅读<a href="http://wiki.apache.org/lucene-hadoop/HadoopMapReduce">Hadoop wiki 上的HadoopMapReduce</a>，很快就可以上手：<br />  <br /><strong>   MapReduce过程简记: <br /></strong>    1.根据输入路径，先用<a href="http://lucene.apache.org/hadoop/docs/api/org/apache/hadoop/mapred/FileSplit.html">FileSplit</a>把输入的文件剁碎，根据<a href="http://lucene.apache.org/hadoop/docs/api/org/apache/hadoop/mapred/InputFormat.html">InputFormat</a>(读入资料的格式)内含的<a href="http://lucene.apache.org/hadoop/docs/api/org/apache/hadoop/mapred/RecordReader.html">RecordReader</a>把资料读入成一组(key,value)对，然后按mapper count平均分给不同的Mapper处理。(这段因为没看过源码，还有点模糊)<br />    2.Mapper进行Map操作 :: (InitialKey, IntialValue) -&gt; [(InterKey, InterValue)] 从Inupt key,value 产生<a href="http://lucene.apache.org/hadoop/docs/api/org/apache/hadoop/mapred/OutputCollector.html#collect(org.apache.hadoop.io.WritableComparable,%20org.apache.hadoop.io.Writable)">中间数据集</a>。<br />    3.Reducer进行Reduce操作:: (Interkey, InterValuesIterator) -&gt; [(InterKey, InterValue)]，Reducer遍历所有节点取得需要的中间数据集，再对其进行去重、过滤等后期处理，得到结果。<br />    4.最后由OutputFormat类（输出资料的格式）内含的RecordWriter，将最终结果输出。结果输出可以是文件，也可以是其他形式，比如Nutch的Indexer，output时并不是去写文件，而是调用Lucene的IndexWriter将作为中间数据集的Lucene Document存盘。</p><p>  <strong>一段典型的Hadoop代码:</strong></p><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"><div><span style="COLOR: #000000">  </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> main(String[] args) main()<br />   { <br />    JobConf conf </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> JobConf(WordCount.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br />    conf.setJobName(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">wordcount</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);   <br /><br />    jobConf.setInputFormat(MyInputFormat.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br />    jobConf.setOutputFormat(MyOutputFormat.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br />   <br />    jobConf.setInputKeyClass(BytesWritable.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br />    jobConf.setInputValueClass(BytesWritable.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br />    jobConf.setOutputKeyClass(BytesWritable.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br />    jobConf.setOutputValueClass(BytesWritable.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br />    <br />    jobConf.setMapperClass(MyMapper.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);        <br />    jobConf.setReducerClass(MyReducer.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">);<br /><br />    jobConf.setNumMapTasks(num_maps);<br />    jobConf.setNumReduceTasks(num_reduces);<br />    <br />    JobClient.runJob(jobConf);<br />   <br />   }<br /><br /></span></div></div><p>     这就是一段hadoop式程序的主代码，用户自行实现四个内部类，MyInputFormat，MyOutputFormat，MyMapper和MyReducer，然后一一在jobConf里配置，最后执行runJob()即可。对比一下Nutch的源码就知道，只要把原来一段顺序执行的代码，拆分到上面四个类里面去，再在jobConf里进行指定，就可以拥有分布式执行的能力，无须要处理分布式编程的代码。配置一下服务器列表，在每台服务器上执行nutch/bin/start-all.sh，你的代码就分布式地执行了。</p><p>   最后看一下<a href="http://wiki.apache.org/lucene-hadoop/HadoopOverview">Hadoop的结构</a>，除了MapReduce的分发外，还有两个很重要的部分：</p><p>   Hadoop的快速接口反射式RPC系统：<a href="http://wiki.apache.org/lucene-hadoop/ipc">IPC</a>。</p><p>   Hadoop的分布式文件系统NDFS：见 <a href="http://blog.csdn.net/CSharpProgrammer/archive/2006/07/05/881906.aspx">CSharpProgrammer blog上的文章</a>。</p><p>   注1：笔记中部分句子直接从网上文章摘录，不一一声明。</p><p>   注2：Hadoop 目前版本为0.5，还不够成熟，看过源码的Donald对其源码评价一般，值得继续等待。</p><br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1063315</p><img src ="http://www.blogjava.net/zqli/aggbug/69833.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-09-15 11:05 <a href="http://www.blogjava.net/zqli/archive/2006/09/15/69833.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]在Eclipse3.0中配置SQLExplorer访问数据库</title><link>http://www.blogjava.net/zqli/archive/2006/09/15/69825.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 15 Sep 2006 02:44:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/09/15/69825.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/69825.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/09/15/69825.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/69825.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/69825.html</trackback:ping><description><![CDATA[
		<p>作者： Deepak Vohra</p>
		<p>SQLExplorer是Eclipse集成开发环境的一种插件，它可以被用来从Eclipse连接到一个数据库。SQLExplorer插件提供了一个使用SQL语句访问数据库的图形用户接口（GUI）。通过使用SQLExplorer，你能够显示表格、表格结构和表格中的数据，以及提取、添加、更新或删除表格数据。SQLExplorer同样能够生成SQL脚本来创建和查询表格。所以，与命令行客户端相比，使用SQLExplorer可能是更优越的选择。在这篇指南中，我们将使用SQLExplorer插件建立一个从Eclipse3.0到开源数据库MySQL的JDBC连接。<br /><br />这篇指南有如下章节：<br /><br />1.概览<br />2.预备安装<br />3.配置 SQLExplorer<br />4.访问数据库数据<br /><br /><strong><span style="FONT-SIZE: 16px">概   览</span></strong><br />通过在集成开发环境中加入一个SQLExplorer视窗，SQLExplorer插件为Eclipse配置了一个访问数据库的SQL客户端。<br /><br />为了演示SQLExplorer插件的使用，我们将在开源数据库MySQL中创建一个示例表，并且建立一个从Eclipse到MySQL数据库的JDBC连接。接着，我们将在SQLExplorer的图形SQL客户端中提取和显示示例数据。同样，我们也将通过更新和删除示例表中的数据来演示SQLExplorer插件的不同特点。<br /><br /><strong><span style="FONT-SIZE: 16px">预 备 安 装</span></strong><br /><br />1. 下载并安装 <a href="http://www.eclipse.org/" target="_new">Eclipse 3.02</a><br />2. 下载<a href="https://sqlexplorer.dev.java.net/" target="_new">SQLExplorer</a>文件 net.sourceforge.sqlexplorer_2.2.3.zip.<br />3. 解压 SQLExplorer .zip 文件到 &lt;Eclipse&gt;/eclipse 目录。 &lt;Eclipse&gt; 是Eclipse安装的目录。 这将把SQLExplorer插件的 features 和 plugins 目录添加到Eclipse中的 features 和 plugins 目录。（译者注：这里说得不是十分清楚，其实是先将SQLExplorer .zip文件解压，然后分别把features 和 plugins 目录中的所有文件拷贝到Eclipse中对应的features 和 plugins 目录中，这是安装Eclipse插件的常用方法，当然也可以使用link方式安装插件，请参阅网上相应文档）<br />4. 重启Eclipse.<br />5. 安装<a href="http://www.mysql.com/" target="_new">MySQL</a>数据库。<br />6. 下载<a href="http://www.mysql.com/products/connector/j/" target="_new">Connector/J</a>，通过使用包含在其中的一个 .jar文件中的JDBC驱动来连接MySQL数据库。<br />7. 作为一个root用户登陆到MySQL数据库，命令如下：<br />   <br />   <span style="COLOR: blue">&gt;mysql -u root</span><br /><br />   root用户没有设定密码。需要通过密码登陆到数据库时，指定如下命令：<br /><br />   <span style="COLOR: blue">&gt;mysql -u root -p</span><br /><br />8. 使用如下命令连接到test数据库，这是一个示例数据库实例：<br /><br />   <span style="COLOR: blue">&gt;use test</span><br /><br />9. 在test数据库中创建一个示例表。示例表 Catalog 由ONJava上的文章名称组成。用来创建示例表的SQL脚本列在下面：<br /><br />   </p>
		<pre class="overflow">CREATE TABLE Catalog(CatalogId INTEGER, Journal VARCHAR(25),<br />      Publisher Varchar(25), <br />      Date VARCHAR(25), Title Varchar(45), Author Varchar(25));<br /><br />   INSERT INTO Catalog VALUES('1', 'onjava',  <br />      'OReilly', 'April 2005', 'Five Favorite Features from 5.0', <br />      'David Flanagan');<br /><br />   INSERT INTO Catalog VALUES('2', 'onjava',    <br />      'OReilly', 'Feb 2005', 'Introducing JBoss Remoting', <br />      'John Mazzitelli');<br /><br />   INSERT INTO Catalog VALUES('3', 'onjava',   <br />      'OReilly', 'March 2005', 'Aspect-Oriented Annotations', <br />      'Bill Burke');</pre>
		<p>
				<br />
				<br />
				<strong>
						<span style="FONT-SIZE: 16px">配置 SQLExplorer</span>
				</strong>
				<br />
				<br />安装了SQLExplorer插件后，我们将要在Eclipse 3.02中配置SQLExplorer.首先，在Eclipse中打开SQLExplorer视窗。在Eclipse 集成开发环境中单击 “Open a perspective”按扭来打开一个视窗。图1说明了“Open a perspective”按扭。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_225343_bBPFZMUdSH.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 1. 打开视窗</center>
		<p>
				<br />
				<br />在条目列表中，选择“Other...”来显示SQLExplorer插件，如图2所示。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_225521_EzmCVualXK.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 2. “ other… ”菜单项</center>
		<p>
				<br />
				<br />在 Select Perspective框中，选择SQLExplorer视窗，如图3所示。通过选择SQLExplorer视窗，SQLExplorer插件的功能部件在Eclipse中变得可用。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_225705_IklAlPSQNA.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 3. SQLExplorer 视窗</center>
		<p>
				<br />
				<br />Drivers 标签显示了不同的数据库驱动，它们被用来连接不同的数据库。现在可用的数据库包括DB2, MySQL, Oracle, Sybase, HSQLDB, SQLServer 和 PostgreSQL。针对MySQL，我们需要配置SQLExplorer。为了配置MySQL驱动，右击 MMMySQL Driver 结点， 并且选择 Change the Selected Driver, 如图4所示。<br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_225751_GpUQMFOOcK.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 4. 修改驱动</center>
		<p>
				<br />
				<br />在 Modify Driver框中，选择 Extra Class Path 标签，并且单击 Add 按扭将 MySQL 驱动 .jar 文件（为下载的 Connector/J 的一部分）添加到类路径中。图5阐明了将MySQL 的 JDBC 驱动加到 Eclipse 的类路径中。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_230105_qfdstgvJpq.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 5. 设置驱动</center>
		<p>
				<br />
				<br />添加 MySQL Connector/J 驱动 .jar 文件，mysql-connector-java-3.0.16-ga-bin.jar，到类路径中。在 Example URL 域中， 指定连接到数据库的 URL。一个连接到 test 数据库的JDBC连接将被创建，test数据库已经在MySQL安装的时候预先创建了。连接到 test 数据库的 URL 为 jdbc:mysql://localhost/test。在 Driver Class Name 域中，指定MySQL JDBC 驱动为 com.mysql.jdbc.Driver。MMMySQL 驱动按如图6所示的设置配置。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_230212_zgkkDxANRd.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 6. 设定 MySQL JDBC 设置</center>
		<p>
				<br />
				<br />想要连接到 MySQL 数据库并提取其中的表格，我们需要为连接建立一个别名。一个连接的别名说明了连接设置，JDBC 驱动，URL，用户名和密码。在SQLExplorer视窗中选择 Aliases 标签。单击 “Create new Alias” 按扭来创建一个新的别名，如图7所示。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_230254_MSaUrfJVgP.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 7. 创建一个新的别名</center>
		<p>
				<br />
				<br />在“Create new Alias"框中，指定一个别名。选择MMMySQL Driver 来为MySQL数据库创建一个别名。在 URL 域中指定 test 数据库的连接 URL, jdbc:mysql://localhost/test。图8展示了MySQL 别名的设置。<br /><br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_230323_gYSqOUPKzI.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 8. 创建一个新的别名</center>
		<p>
				<br />
				<br />
				<br />以上操作将一个MySQL的别名加入到 Aliases 标签中，正如图9所示。想要修改一个别名，右击别名结点并选择 “Change the selected Alias.”<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_230354_SgseoemzdT.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 9. MySQL 别名</center>
		<p>
				<br />
				<br />MySQL 别名用来连接到 MySQL 数据库并且从中提取数据。要想打开数据库连接，右击 MySQL 别名结点并选择 Open，如图10所示。<br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_230449_WzgrudgdpN.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 10. 打开别名</center>
		<p>
				<br />
				<br />在 Connection 框中，指定登陆到 MySQL 数据库使用的用户名和密码，然后单击 OK 按扭。图11展示了登陆的设置。缺省情况下，对于 root 用户不需要密码。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_230528_gcVOHZxPux.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 11. 打开连接</center>
		<p>
				<br />
				<br />一个与 MySQL 数据库的 JDBC 连接就这样建立了。一旦连接上了，Eclipse 就会显示 MySQL 数据库中的不同的数据库模式，如图12所示。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_230630_qWLVuLGUoc.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 12. 列出数据库模式</center>
		<p>
				<br />
				<br />
				<strong>
						<span style="FONT-SIZE: 14px">对其他数据库的支持</span>
				</strong>
				<br />
				<br />这个 JDBC 连接的例子是关于配置与 MySQL 数据库连接的。通过在 Drivers 标签中为数据库选择合适的驱动，可以配置与其他数据库的 JDBC 连接。只需为选定的数据库指定驱动类和连接URL，就可以配置与该数据库的 JDBC 连接。以下列出的是其他数据库的驱动类、连接URL和驱动 .jar 文件。<br /><br />DB2 <br />o        Driver Class: COM.ibm.db2.jdbc.app.DB2Driver <br />o        Connection URL: jdbc:db2:&lt;database&gt; <br />o        Driver .jar/.zip: db2java.zip<br /><br />Sybase <br />o        Driver Class: com.sybase.jdbc2.jdbc.SybDriver <br />o        Connection URL: jdbc:sybase:Tds:&lt;host&gt;:&lt;port&gt;/&lt;database&gt; <br />o        Driver .jar/.zip: jconn2.jar<br /><br />Oracle <br />o        Driver Class: oracle.jdbc.driver.OracleDriver <br />o        Connection URL: jdbc:oracle:thin:@ &lt;host&gt;:&lt;port&gt;:&lt;sid&gt; <br />o        Driver .jar/.zip: classes12.zip<br /><br />SQLServer <br />o        Driver Class: com.microsoft.jdbc.sqlserver.SQLServerDriver <br />o        Connection URL: jdbc:microsoft:sqlserver://localhost:1433 <br />o        Driver .jar/.zip: mssqlserver.jar, msbase.jar, msutil.jar<br /><br />PostgreSQL <br />o        Driver Class: org.postgresql.Driver <br />o        Connection URL: jdbc:postgresql://&lt;server&gt;:&lt;port&gt;/&lt;database&gt; <br />o        Driver .jar/.zip: postgresql.jar<br /><br />在如上列表中，&lt;database&gt; 是指数据库实例，&lt;port&gt; 是数据库连接端口，&lt;sid&gt; 是数据库的SID，&lt;server&gt; 是数据库服务器。<br /><br /><strong><span style="FONT-SIZE: 16px">访问数据库数据</span></strong><br />在上一节中我们在 Eclipse 中配置了 SQLExplorer 插件。下面，我们将从示例表 Catalog 中提取并修改数据。如果是从一个命令行 SQL 客户端访问数据库，则使用如下命令来提取数据（在一行中）：<br /><br /><span style="COLOR: blue">SQL&gt;SELECT catalogId, journal, publisher, date,<br />title, author from Catalog;</span><br /><br />这将以文本表的形式显示数据。使用图形 SQL 客户端 SQLExplorer,数据将以结构表的形式显示。SQLExplorer 同样也会生成创建表和从中提取数据的 SQL 脚本。如果使用 DESC 命令在一个命令行客户端中显示表格的结构，只有列名，列数据的类型，列数据的长度大小以及非空的值会被显示。有了 SQLExplorer, 索引、主键和外键值都会被显示。<br /><br />在 Eclipse 的 SQLExplorer 视窗中选择 Database Structure View 标签。为了显示表 Catalog 的结构，在 Database Structure View 中选择 Database&gt;test&gt;TABLE&gt;Catalog 结点。图13显示了表 Catalog 的结构。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_230848_sUYCgNfAGR.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 13. Database Structure View</center>
		<p>
				<br />
				<br />Columns 标签显示了下表中列出的列：<br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_233019_mKXTqFqzic.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
				<br />为了显示选中的表格中的数据，请选择 Preview 标签。图14显示了表 Catalog 中的数据。关于表格的其他的信息分别在 Indexes, Primary Key, Foreign Key 和 Row Count 标签中显示。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" height="450" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231157_hMNHvYKlAW.gif" width="484" onload="javascript:imgLoad(this);" border="0" resized="1" />
		</center>
		<p>
				<br />
		</p>
		<center>图 14. 显示表格数据</center>
		<p>
				<br />
				<br />若想得到创建表格的 SQL 脚本，右击表结点并且选择 Create Table Script,如图15所示。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231226_fdGYxlGUTs.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 15. 生成建表脚本</center>
		<p>
				<br />
				<br />如图16所示，这将生成创建被选表格的 SQL 脚本， 并将其显示在 SQLExplorer 视窗中的 SQL Editor 中。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231327_yjgaQDNFMB.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 16. 建表脚本</center>
		<p>
				<br />
				<br />Database Structure View 的 Preview 标签中的数据是使用缺省的 Select 查询提取的，它包括了表格中所有的列。要想显示缺省的 Select 查询语句，右击表结点并且选择 “Generate Select in Sql Editor”，如图17所示。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231423_olemCtxtRk.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 17. 生成缺省 select 查询语句</center>
		<p>
				<br />如图18所示，SQL Editor 中显示了从表 Catalog 中提取数据的缺省查询语句。注意：显示在 SQL Editor 中的 SELECT 查询语句的结尾没有分号（；）。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" height="450" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231502_AYdCXusCXz.gif" width="382" onload="javascript:imgLoad(this);" border="0" resized="1" />
		</center>
		<p>
				<br />
		</p>
		<center>图 18. Select 查询语句</center>
		<p>
				<br />
				<br />查询语句可能被定制为只显示表格中的几列数据。比如，修改 Select 语句使其显示除了 CatalogId 列的其他所有列。选择 Execute SQL 按扭来运行 SQL 脚本。由修改后的 select 语句得到的数据显示在 SQL Results 框中，如图19所示。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" height="450" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231703_suAZvTQclg.gif" width="382" onload="javascript:imgLoad(this);" border="0" resized="1" />
		</center>
		<p>
				<br />
		</p>
		<center>图 19. 使用定制的 SELECT 查询语句提取表中数据</center>
		<p>
				<br />
				<br />接下来，SQL Editor 中的一条 SQL 脚本将会更新表 Catalog。例如，把标题“Five Favorite Features from 5.0”修改为“New Features in JDK 5.0”。如图20所示，在 SQL Editor 中运行更新表 Catalog 的脚本<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231725_uUNsVvlcpW.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 20. 更新 SQL 脚本</center>
		<p>
				<br />
				<br />表格中数据被更新了。在修改后的表格上运行缺省的 select 查询，修改后的数据将被显示在 SQL Results 框中。图21显示了表 Catalog 修改后的数据。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231754_kZeLYRrMFy.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 21. 修改表格数据</center>
		<p>
				<br />
				<br />接着，使用 DELETE SQL语句从表中删除一行数据，如图22所示。CatalogId='3'的行将从表中删除。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231838_DHGCPWAFbE.gif" onload="javascript:imgLoad(this);" border="0" resized="0" />
		</center>
		<p>
				<br />
		</p>
		<center>图 22. DELETE SQL 脚本</center>
		<p>
				<br />
				<br />运行缺省的 select 查询语句来显示修改后的表中的数据。SQL Results 框中的表格不再包括被删除的行了，如图23所示。<br /><br /></p>
		<center>
				<img style="DISPLAY: inline" onclick="javascript:imgClick(this);" height="450" alt="image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_21_231903_IbYFNsTify.gif" width="383" onload="javascript:imgLoad(this);" border="0" resized="1" />
		</center>
		<p>
				<br />
		</p>
		<center>图 23. 删除了一行后的表格数据</center>
		<p>
				<br />
				<br />通过在 Eclipse 中配置 SQLExplorer 插件，该集成开发环境获得了图形用户界面（GUI）较之命令行客户端的许多优点。<br /><br /><br /><strong><span style="FONT-SIZE: 16px">总   结</span></strong><br /><br />例子中，我们与 MySQL 数据库建立了一个 JDBC 连接，并访问其中的一个示例数据库。SQL Explorer 同样可以被用来配置与其他数据库的连接，包括 DB2, Sybase, Oracle, HSQLDB, SQL Server 和 PostgreSQL。 </p>
		<br />
		<br />
		<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1175433</p>
<img src ="http://www.blogjava.net/zqli/aggbug/69825.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-09-15 10:44 <a href="http://www.blogjava.net/zqli/archive/2006/09/15/69825.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] Java多线程程序设计详细解析</title><link>http://www.blogjava.net/zqli/archive/2006/09/08/68530.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 08 Sep 2006 07:40:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/09/08/68530.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/68530.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/09/08/68530.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/68530.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/68530.html</trackback:ping><description><![CDATA[一、理解多线程<br /><br />　　多线程是这样一种机制，它允许在程序中并发执行多个指令流，每个指令流都称为一个线程，彼此间互相独立。<br /><br />　　线程又称为轻量级进程，它和进程一样拥有独立的执行控制，由操作系统负责调度，区别在于线程没有独立的存储空间，而是和所属进程中的其它线程共享一个存储空间，这使得线程间的通信远较进程简单。<br /><br />　　多个线程的执行是并发的，也就是在逻辑上“同时”，而不管是否是物理上的“同时”。如果系统只有一个CPU，那么真正的“同时”是不可能的，但是由于CPU的速度非常快，用户感觉不到其中的区别，因此我们也不用关心它，只需要设想各个线程是同时执行即可。<br /><br />　　多线程和传统的单线程在程序设计上最大的区别在于，由于各个线程的控制流彼此独立，使得各个线程之间的代码是乱序执行的，由此带来的线程调度，同步等问题，将在以后探讨。<br /><br />　　二、在Java中实现多线程<br /><br />　　我们不妨设想，为了创建一个新的线程，我们需要做些什么？很显然，我们必须指明这个线程所要执行的代码，而这就是在Java中实现多线程我们所需要做的一切！<br /><br />　　真是神奇！Java是如何做到这一点的？通过类！作为一个完全面向对象的语言，Java提供了类java.lang.Thread来方便多线程编程，这个类提供了大量的方法来方便我们控制自己的各个线程，我们以后的讨论都将围绕这个类进行。<br /><br />　　那么如何提供给 Java 我们要线程执行的代码呢？让我们来看一看 Thread 类。Thread 类最重要的方法是run()，它为Thread类的方法start()所调用，提供我们的线程所要执行的代码。为了指定我们自己的代码，只需要覆盖它！<br /><br />　　方法一：继承 Thread 类，覆盖方法 run()，我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可。下面是一个例子：<br /><br />　　public class MyThread extends Thread<br />　　{<br />　　int count= 1, number;<br />　　public MyThread(int num)<br />　　{<br />　　number = num;<br />　　System.out.println<br />　　("创建线程 " + number);<br />　　}<br />　　public void run() {<br />　　while(true) {<br />　　System.out.println<br />　　("线程 " + number + ":计数 " + count);<br />　　if(++count== 6) return;<br />　　}<br />　　}<br />　　public static void main(String args[])<br />　　{<br />　　for(int i = 0;<br />　　i 〈 5; i++) new MyThread(i+1).start();<br />　　}<br />　　}<br />　　<br />　　这种方法简单明了，符合大家的习惯，但是，它也有一个很大的缺点，那就是如果我们的类已经从一个类继承（如小程序必须继承自 Applet 类），则无法再继承 Thread 类，这时如果我们又不想建立一个新的类，应该怎么办呢？<br /><br />　　我们不妨来探索一种新的方法：我们不创建Thread类的子类，而是直接使用它，那么我们只能将我们的方法作为参数传递给 Thread 类的实例，有点类似回调函数。但是 Java 没有指针，我们只能传递一个包含这个方法的类的实例。<br /><br />　　那么如何限制这个类必须包含这一方法呢？当然是使用接口！（虽然抽象类也可满足，但是需要继承，而我们之所以要采用这种新方法，不就是为了避免继承带来的限制吗？）<br /><br />　　Java 提供了接口 java.lang.Runnable 来支持这种方法。<br /><br />　　方法二：实现 Runnable 接口<br /><br />　　Runnable接口只有一个方法run()，我们声明自己的类实现Runnable接口并提供这一方法，将我们的线程代码写入其中，就完成了这一部分的任务。但是Runnable接口并没有任何对线程的支持，我们还必须创建Thread类的实例，这一点通过Thread类的构造函数 public Thread(Runnable target);来实现。下面是一个例子：<br /><br />　　public class MyThread implements Runnable<br />　　{<br />　　int count= 1, number;<br />　　public MyThread(int num)<br />　　{<br />　　number = num;<br />　　System.out.println("创建线程 " + number);<br />　　}<br />　　public void run()<br />　　{<br />　　while(true)<br />　　{<br />　　System.out.println<br />　　("线程 " + number + ":计数 " + count);<br />　　if(++count== 6) return;<br />　　}<br />　　}<br />　　public static void main(String args[])<br />　　{<br />　　for(int i = 0; i 〈 5;<br />　　i++) new Thread(new MyThread(i+1)).start();<br />　　}<br />　　}<br />　　<br />　　严格地说，创建Thread子类的实例也是可行的，但是必须注意的是，该子类必须没有覆盖 Thread 类的 run 方法，否则该线程执行的将是子类的 run 方法，而不是我们用以实现Runnable 接口的类的 run 方法，对此大家不妨试验一下。<br /><br />　　使用 Runnable 接口来实现多线程使得我们能够在一个类中包容所有的代码，有利于封装，它的缺点在于，我们只能使用一套代码，若想创建多个线程并使各个线程执行不同的代码，则仍必须额外创建类，如果这样的话，在大多数情况下也许还不如直接用多个类分别继承 Thread 来得紧凑。<br /><br />　　综上所述，两种方法各有千秋，大家可以灵活运用。<br /><br />　　下面让我们一起来研究一下多线程使用中的一些问题。<br /><br />　　三、线程的四种状态<br /><br />　　1. 新状态：线程已被创建但尚未执行（start() 尚未被调用）。<br /><br />　　2. 可执行状态：线程可以执行，虽然不一定正在执行。CPU 时间随时可能被分配给该线程，从而使得它执行。<br /><br />　　3. 死亡状态：正常情况下 run() 返回使得线程死亡。调用 stop()或 destroy() 亦有同样效果，但是不被推荐，前者会产生异常，后者是强制终止，不会释放锁。<br /><br />　　4. 阻塞状态：线程不会被分配 CPU 时间，无法执行。<br /><br />　　四、线程的优先级<br /><br />　　线程的优先级代表该线程的重要程度，当有多个线程同时处于可执行状态并等待获得 CPU 时间时，线程调度系统根据各个线程的优先级来决定给谁分配 CPU 时间，优先级高的线程有更大的机会获得 CPU 时间，优先级低的线程也不是没有机会，只是机会要小一些罢了。<br /><br />　　你可以调用 Thread 类的方法 getPriority() 和 setPriority()来存取线程的优先级，线程的优先级界于1(MIN_PRIORITY)和10(MAX_PRIORITY)之间，缺省是5(NORM_PRIORITY)。<br /><br />　　五、线程的同步<br /><br />　　由于同一进程的多个线程共享同一片存储空间，在带来方便的同时，也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突，有效避免了同一个数据对象被多个线程同时访问。<br /><br />　　由于我们可以通过 private 关键字来保证数据对象只能被方法访问，所以我们只需针对方法提出一套机制，这套机制就是 synchronized 关键字，它包括两种用法：synchronized 方法和 synchronized 块。<br /><br />　　1. synchronized 方法：通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如：<br /><br />　　public synchronized void accessVal(int newVal);<br />　　<br />　　 synchronized 方法控制对类成员变量的访问：每个类实例对应一把锁，每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行，否则所属线程阻塞，方法一旦执行，就独占该锁，直到从该方法返回时才将锁释放，此后被阻塞的线程方能获得该锁，重新进入可执行状态。<br /><br />　　这种机制确保了同一时刻对于每一个类实例，其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态（因为至多只有一个能够获得该类实例对应的锁），从而有效避免了类成员变量的访问冲突（只要所有可能访问类成员变量的方法均被声明为 synchronized）。<br /><br />　　在 Java 中，不光是类实例，每一个类也对应一把锁，这样我们也可将类的静态成员函数声明为 synchronized ，以控制其对类的静态成员变量的访问。<br /><br />　　synchronized 方法的缺陷：若将一个大的方法声明为synchronized 将会大大影响效率，典型地，若将线程类的方法 run() 声明为 synchronized ，由于在线程的整个生命期内它一直在运行，因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中，将其声明为 synchronized ，并在主方法中调用来解决这一问题，但是 Java 为我们提供了更好的解决办法，那就是 synchronized 块。<br /><br />　　2. synchronized 块：通过 synchronized关键字来声明synchronized 块。语法如下：<br /><br />　　synchronized(syncObject)<br />　　{<br />　　//允许访问控制的代码<br />　　}<br />　　<br />　　synchronized 块是这样一个代码块，其中的代码必须获得对象 syncObject （如前所述，可以是类实例或类）的锁方能执行，具体机制同前所述。由于可以针对任意代码块，且可任意指定上锁的对象，故灵活性较高。<br /><br />　　六、线程的阻塞<br /><br />　　为了解决对共享存储区的访问冲突，Java 引入了同步机制，现在让我们来考察多个线程对共享资源的访问，显然同步机制已经不够了，因为在任意时刻所要求的资源不一定已经准备好了被访问，反过来，同一时刻准备好了的资源也可能不止一个。为了解决这种情况下的访问控制问题，Java 引入了对阻塞机制的支持。<br /><br />　　阻塞指的是暂停一个线程的执行以等待某个条件发生（如某资源就绪），学过操作系统的同学对它一定已经很熟悉了。Java 提供了大量方法来支持阻塞，下面让我们逐一分析。<br /><br />　　1. sleep() 方法：sleep() 允许指定以毫秒为单位的一段时间作为参数，它使得线程在指定的时间内进入阻塞状态，不能得到CPU 时间，指定的时间一过，线程重新进入可执行状态。典型地，sleep() 被用在等待某个资源就绪的情形：测试发现条件不满足后，让线程阻塞一段时间后重新测试，直到条件满足为止。<br /><br />　　2. suspend() 和 resume() 方法：两个方法配套使用，suspend()使得线程进入阻塞状态，并且不会自动恢复，必须其对应的resume() 被调用，才能使得线程重新进入可执行状态。典型地，suspend() 和 resume() 被用在等待另一个线程产生的结果的情形：测试发现结果还没有产生后，让线程阻塞，另一个线程产生了结果后，调用 resume() 使其恢复。<br /><br />　　3. yield() 方法：yield() 使得线程放弃当前分得的 CPU 时间，但是不使线程阻塞，即线程仍处于可执行状态，随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程。<br /><br />　　4. wait() 和 notify() 方法：两个方法配套使用，wait() 使得线程进入阻塞状态，它有两种形式，一种允许指定以毫秒为单位的一段时间作为参数，另一种没有参数，前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态，后者则必须对应的 notify() 被调用。<br /><br />　　初看起来它们与 suspend() 和 resume() 方法对没有什么分别，但是事实上它们是截然不同的。区别的核心在于，前面叙述的所有方法，阻塞时都不会释放占用的锁（如果占用了的话），而这一对方法则相反。<br /><br />　　上述的核心区别导致了一系列的细节上的区别。<br /><br />　　首先，前面叙述的所有方法都隶属于 Thread 类，但是这一对却直接隶属于 Object 类，也就是说，所有对象都拥有这一对方法。初看起来这十分不可思议，但是实际上却是很自然的，因为这一对方法阻塞时要释放占用的锁，而锁是任何对象都具有的，调用任意对象的 wait() 方法导致线程阻塞，并且该对象上的锁被释放。<br /><br />　　而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞（但要等到获得锁后才真正可执行）。<br /><br />　　其次，前面叙述的所有方法都可在任何位置调用，但是这一对方法却必须在 synchronized 方法或块中调用，理由也很简单，只有在synchronized 方法或块中当前线程才占有锁，才有锁可以释放。<br /><br />　　同样的道理，调用这一对方法的对象上的锁必须为当前线程所拥有，这样才有锁可以释放。因此，这一对方法调用必须放置在这样的 synchronized 方法或块中，该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件，则程序虽然仍能编译，但在运行时会出现 IllegalMonitorStateException 异常。<br /><br />　　wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用，将它们和操作系统的进程间通信机制作一个比较就会发现它们的相似性：synchronized方法或块提供了类似于操作系统原语的功能，它们的执行不会受到多线程机制的干扰，而这一对方法则相当于 block 和wakeup 原语（这一对方法均声明为 synchronized）。<br /><br />　　它们的结合使得我们可以实现操作系统上一系列精妙的进程间通信的算法（如信号量算法），并用于解决各种复杂的线程间通信问题。关于 wait() 和 notify() 方法最后再说明两点：<br /><br />　　第一：调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的，我们无法预料哪一个线程将会被选择，所以编程时要特别小心，避免因这种不确定性而产生问题。<br /><br />　　第二：除了 notify()，还有一个方法 notifyAll() 也可起到类似作用，唯一的区别在于，调用 notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然，只有获得锁的那一个线程才能进入可执行状态。<br /><br />　　谈到阻塞，就不能不谈一谈死锁，略一分析就能发现，suspend() 方法和不指定超时期限的 wait() 方法的调用都可能产生死锁。遗憾的是，Java 并不在语言级别上支持死锁的避免，我们在编程中必须小心地避免死锁。<br /><br />　　以上我们对 Java 中实现线程阻塞的各种方法作了一番分析，我们重点分析了 wait() 和 notify()方法，因为它们的功能最强大，使用也最灵活，但是这也导致了它们的效率较低，较容易出错。实际使用中我们应该灵活使用各种方法，以便更好地达到我们的目的。<br /><br />　　七、守护线程<br /><br />　　守护线程是一类特殊的线程，它和普通线程的区别在于它并不是应用程序的核心部分，当一个应用程序的所有非守护线程终止运行时，即使仍然有守护线程在运行，应用程序也将终止，反之，只要有一个非守护线程在运行，应用程序就不会终止。守护线程一般被用于在后台为其它线程提供服务。<br /><br />　　可以通过调用方法 isDaemon() 来判断一个线程是否是守护线程，也可以调用方法 setDaemon() 来将一个线程设为守护线程。<br /><br />　　八、线程组<br /><br />　　线程组是一个 Java 特有的概念，在 Java 中，线程组是类ThreadGroup 的对象，每个线程都隶属于唯一一个线程组，这个线程组在线程创建时指定并在线程的整个生命期内都不能更改。<br /><br />　　你可以通过调用包含 ThreadGroup 类型参数的 Thread 类构造函数来指定线程属的线程组，若没有指定，则线程缺省地隶属于名为 system 的系统线程组。<br /><br />　　在 Java 中，除了预建的系统线程组外，所有线程组都必须显式创建。在 Java 中，除系统线程组外的每个线程组又隶属于另一个线程组，你可以在创建线程组时指定其所隶属的线程组，若没有指定，则缺省地隶属于系统线程组。这样，所有线程组组成了一棵以系统线程组为根的树。<br /><br />　　Java 允许我们对一个线程组中的所有线程同时进行操作，比如我们可以通过调用线程组的相应方法来设置其中所有线程的优先级，也可以启动或阻塞其中的所有线程。<br /><br />　　Java 的线程组机制的另一个重要作用是线程安全。线程组机制允许我们通过分组来区分有不同安全特性的线程，对不同组的线程进行不同的处理，还可以通过线程组的分层结构来支持不对等安全措施的采用。<br /><br />　　Java 的 ThreadGroup 类提供了大量的方法来方便我们对线程组树中的每一个线程组以及线程组中的每一个线程进行操作。<br /><br />　　九、总结<br /><br />　　在本文中，我们讲述了 Java 多线程编程的方方面面，包括创建线程，以及对多个线程进行调度、管理。我们深刻认识到了多线程编程的复杂性，以及线程切换开销带来的多线程程序的低效性，这也促使我们认真地思考一个问题：我们是否需要多线程？何时需要多线程？<br /><br />　　多线程的核心在于多个代码块并发执行，本质特点在于各代码块之间的代码是乱序执行的。我们的程序是否需要多线程，就是要看这是否也是它的内在特点。<br /><br />　　假如我们的程序根本不要求多个代码块并发执行，那自然不需要使用多线程；假如我们的程序虽然要求多个代码块并发执行，但是却不要求乱序，则我们完全可以用一个循环来简单高效地实现，也不需要使用多线程；只有当它完全符合多线程的特点时，多线程机制对线程间通信和线程管理的强大支持才能有用武之地，这时使用多线程才是值得的。  <br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1155150</p><img src ="http://www.blogjava.net/zqli/aggbug/68530.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-09-08 15:40 <a href="http://www.blogjava.net/zqli/archive/2006/09/08/68530.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]方便 Ajax 与 Java EE 的集成</title><link>http://www.blogjava.net/zqli/archive/2006/09/08/68520.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 08 Sep 2006 07:12:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/09/08/68520.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/68520.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/09/08/68520.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/68520.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/68520.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<p>
						<a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#author">
								<font color="#996699">Patrick Gan</font>
						</a> (<a href="mailto:patgan@us.ibm.com?subject=方便 Ajax 与 Java EE 的集成"><font color="#5c81a7">patgan@us.ibm.com</font></a>), 应用程序卓越创新服务中心的高级 IT 专家, IBM</p>
				<p>Asynchronous JavaScript + XML （Ajax）是个相当新的术语（有些人说它是旧酒装新瓶），在不同的 Web 开发社区中，都引起了很大的争议，其中包括 Java EE 社区。Ajax 技术通过消除过多的 Web 页面刷新，提高了应用程序的可用性。而且 Ajax 二者通吃的技术，同时利用了客户端和服务器端代码，向 Web 用户呈现了几乎无缝的用户界面。Ajax 被鼓吹成 Web 开发复兴（或称为 Web 2.0）的一个主要推动者。 </p>
				<p>作为用心的 Java EE 开发人员，您可能已经阅读了许多关于 Ajax 的 how-to 文章，并对它会给应用程序带来的可能改进而兴奋。但是 Ajax 基于异步通信的模式要怎样才适合您的 Java EE 应用程序呢？这篇文章通过研究在 Java EE 应用程序的设计、开发、执行和测试各阶段引入 Ajax 会带来的影响，将帮助您回答这个问题。我的目的不是不鼓励使用 Ajax 或者暗示您可能遇到的问题是 Ajax 技术固有的问题。相反，我是为了帮助您规划并减轻这些问题，好让您更有效而顺利地利用 Ajax。</p>
				<p>
						<a name="N10050">
								<span class="atitle">
										<strong>
												<font size="4">解决设计缺陷</font>
										</strong>
								</span>
						</a>
				</p>
				<p>相当一段时间以来，Java 社区一直在努力把好的设计模式应用到与 Web 有关的应用程序开发上。其中使用最广泛的一个模式就是模型-视图-控制器（MVC）。一些开放源码框架，例如 Apache Struts，就基于这个设计模式/架构（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>）。MVC 的众多优势包括：<em>问题隔离</em> 和减少冗余代码。</p>
				<p>问题隔离在整个应用程序架构中使用预先协商好的接口，从而让应用程序开发项目中的每个开发人员都专注于自己特定的角色。例如，模型层的开发人员侧重于 JDBC、企业 JavaBean（EJB）组件或者与底层数据持久技术接口的 Java 类这一类的技术。视图层开发人员侧重于 Java 服务器页面（JSP）技术、标记库和其他与表示有关的技术。控制器层隔离及协调模型和视图，把进入的请求路由到后端持久性调用，同时维护问题的清晰隔离。图 1 演示了 MVC 架构：</p>
				<p>
						<br />
						<a name="N10065">
								<strong>图 1. MVC 架构</strong>
						</a>
						<br />
						<img height="156" alt="MVC 架构" src="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/reference_mvc.gif" width="477" />
						<br />
				</p>
				<p>把 Ajax 引入 Java EE Web 应用程序对于问题的隔离（以及开发人员角色的隔离）是有意义的。在某些情况下，Ajax 会把大量 JavaScript 代码带回视图层（JSP）页面。表 1 描述了没有 Ajax 的视图层，还指出了需要的代码（假设控制器层由 servlet 实现，视图层由 JSP 技术实现。（在下一节 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#developmentSection"><font color="#996699">处理开发困境</font></a> 我将解释同步和异步请求的区别。）</p>
				<p>
						<br />
						<a name="table1">
								<strong>表 1. 没有 Ajax 的 MVC：与典型的视图层序列有关的代码数量</strong>
						</a>
						<br />
				</p>
				<table class="data-table-2" cellspacing="0" cellpadding="0" width="100%" summary="MVC without Ajax" border="0">
						<tbody>
								<tr>
										<th>序列</th>
										<th>说明</th>
										<th>要求代码？</th>
								</tr>
								<tr>
										<td class="tb-row">在调用同步请求之前</td>
										<td>准备表单提交需要的脚本代码</td>
										<td>否</td>
								</tr>
								<tr>
										<td class="tb-row">调用异步请求</td>
										<td>由按钮或链接调用引起表单提交；DOM 元素的值自动设置到 <code><font face="Courier" size="2">HttpRequest</font></code>（通过 <code><font face="Courier" size="2">GET</font></code> 或 <code><font face="Courier" size="2">POST</font></code>）。</td>
										<td>否：所需要的只是调用页面提交的途径。</td>
								</tr>
								<tr>
										<td class="tb-row">处理同步请求的响应</td>
										<td>在服务器端代码执行完成后，通常会向 JSP 发送回一个对象（通过 <code><font face="Courier" size="2">HttpRequest</font></code> 或保存在 <code><font face="Courier" size="2">HttpSession</font></code> 中）。这时，在 JSP 中可以通过 <code><font face="Courier" size="2">HttpRequest</font></code> 或 <code><font face="Courier" size="2">HttpSession</font></code> 访问这个对象（通过脚本或某些标记库），只需要编写极少的脚本就可以显示对象的内容。</td>
										<td>是：最少的脚本。</td>
								</tr>
						</tbody>
				</table>
				<br />
				<p>对比表 1 和表 2，表 2 描述了<em>有</em> Ajax 的 MVC 视图层，同样假设控制层由 servlet 实现，视图层由 JSP 技术实现。</p>
				<p>
						<br />
						<a name="table2">
								<strong>表 2. 有 Ajax 的 MVC：与典型的视图层序列有关的代码数量</strong>
						</a>
						<br />
				</p>
				<table class="data-table-2" cellspacing="0" cellpadding="0" width="100%" summary="MVC w Ajax" border="0">
						<tbody>
								<tr>
										<th>序列</th>
										<th>说明</th>
										<th>需要代码？</th>
								</tr>
								<tr>
										<td class="tb-row">在调用异步请求之前</td>
										<td>需要用 JavaScript 代码检索出 Ajax 调用需要的 DOM 元素的值。</td>
										<td>是</td>
								</tr>
								<tr>
										<td class="tb-row">调用异步请求</td>
										<td>需要用 JavaScript 代码创建 <code><font face="Courier" size="2">XMLHTTPRequest</font></code> 并把（以前搜集的）DOM 元素值与之关联并发送（<code><font face="Courier" size="2">XMLHTTPRequest.send()</font></code>）。</td>
										<td>是</td>
								</tr>
								<tr>
										<td class="tb-row">处理异步请求的响应</td>
										<td>在服务器端代码执行完成后，要用 JavaScript 代码得到请求（从 XML 响应流中）并把值相应地填充到适当的 DOM 元素。</td>
										<td>是</td>
								</tr>
						</tbody>
				</table>
				<br />
				<p>可以看出，由于使用了 Ajax，视图层的脚本编写量增加了，从而导致三个明显缺陷：</p>
				<ul>
						<li>JSP 要求大量的 JavaScript 代码。 
</li>
						<li>这个设计破坏了角色问题的隔离。 
</li>
						<li>设计重新带回了<em>单一 JSP</em>（模式 1 方法：一堆 HTML、CSS 代码、图片和脚本代码），这是一种反模式，极难阅读和维护（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>）。 </li>
				</ul>
				<p>有几个选项可以避免或者至少减轻这些设计缺陷：</p>
				<ul>
						<li>
								<strong>设计时脑子里记着重用</strong>：不幸的是，编写特定于 Ajax 支持的代码通常很难避免。请计划和设计脚本代码，以便能够最大限度地重用它。<br /><br /></li>
						<li>
								<strong>采用客户端 MVC 方法</strong>：可以合并使用客户端 MVC 方法，详见 Dave Crane 等编写的 <em>Ajax in Action</em>（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>）。这种方法可以促进问题的隔离，但是增加了复杂性，所以使用的时候要仔细考虑。<br /><br /></li>
						<li>
								<strong>使用 Ajax 框架</strong>：存在多个开放源码的 Ajax 框架，例如 Direct Web Remoting （DWR）（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>），它们做了很好的工作，可以用最少的编码，就把 Ajax 模式集成到 Java EE 应用程序。 <br /><br /></li>
						<li>
								<strong>重新评估设计的正确性</strong>：实际上，Ajax 为 Web 应用程序提供了桌面应用程序的属性。如果一个 Web 应用程序中大多数客户端交互都利用 Ajax，那么这个应用程序可能最好设计成桌面应用程序。 </li>
				</ul>
				<p>
						<a name="developmentSection">
								<span class="atitle">
										<strong>
												<font size="4">处理开发困境</font>
										</strong>
								</span>
						</a>
				</p>
				<p>在 Java Web 开发中使用 Ajax 时，重要的是完整理解<em>同步</em> 和<em>异步</em> 通信模型的区别（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>）。对异步通信模型支持的缺乏，会对客户端开发、与 Web 框架的集成、标记库的使用、IDE 的使用以及线程的行为有影响。</p>
				<p>在同步请求/响应通信模型中，总是浏览器（与 Web 服务器、应用服务器或 Web 应用程序相对）发起请求（通过 Web 用户）。接着，Web 服务器、应用服务器或 Web 应用程序响应进入的请求。在处理同步请求/响应对期间，用户不能继续使用浏览器。</p>
				<p>图 2 中的序列图演示了传统 Web 应用程序的同步通信模型。请注意在服务器的生命线上，来自客户机的数据提交和服务器端的处理是紧密耦合的。</p>
				<p>
						<br />
						<a name="fig2">
								<strong>图 2. 同步通信序列</strong>
						</a>
						<br />
						<img height="228" alt="同步通信序列" src="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/synchronous_sequence.gif" width="389" />
						<br />
				</p>
				<p>在异步请求/响应通信模型中，浏览器（通过 Web 用户）到 Web 服务器、应用服务器或 Web 应用程序的通信（以及反过来）是解耦的。在异步请求/响应对的处理中，Web 用户在当前异步请求被处理时还可以继续使用浏览器。一旦异步请求处理完成，异步响应就被通信（从 Web 服务器、应用服务器或 Web 应用程序）回客户机页面。典型情况下，在这个过程中，调用对 Web 用户没有影响；他们不需要等候响应。 </p>
				<p>图 3 的序列图演示了异步通信模型。请注意第一个 dataSubmission （由服务器端处理）和第一个返回的 dataSubmission，两个都用红圈圈上了。这些序列是解耦的。这个图示还强调了一个重要方面（后面将详细介绍，请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#threadingSection"><font color="#996699">线程问题</font></a>）：在这个模型中，可以发生多个提交（线程）。</p>
				<p>
						<br />
						<a name="fig3">
								<strong>图 3. 异步通信序列</strong>
						</a>
						<br />
						<img height="418" alt="异步通信序列" src="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/asynchronous_sequence.gif" width="342" />
						<br />
				</p>
				<p>
						<a name="N101AD">
								<span class="smalltitle">
										<strong>
												<font size="3">客户端影响</font>
										</strong>
								</span>
						</a>
				</p>
				<p>在向 Web 应用程序引入 Ajax 时，开发团队需要注意几个风险，主要与生成的 HTML 页面及其与浏览器的交互方式有关。这些问题在 Chris Laffra 两部分的 <em>Considering Ajax</em> 系列中有详细介绍（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>）。有些需要记住的要点是：</p>
				<ul>
						<li>
								<strong>可能没打开脚本功能</strong>：出于各种原因，在许多用户的浏览器上禁止了 JavaScript 支持。<br /><br /></li>
						<li>
								<strong>跨浏览器支持增加了代码需求</strong>：支持多种浏览器和多个浏览器版本的应用程序，要求的脚本代码可能会增多，因为浏览器解释 DOM 对象的方式有细微的差异（所以操作这些元素的 JavaScript 代码也有差异）。<br /><br /></li>
						<li>
								<strong>JavaScript 不安全</strong>：在多数浏览器中，可以选择查看源代码选项，查看到与 HTML 页面关联的 JavaScript 源代码。在使用 Ajax 模式时，要确保脚本代码中实现的逻辑不是敏感逻辑。 </li>
				</ul>
				<p>
						<a name="N101D3">
								<span class="smalltitle">
										<strong>
												<font size="3">与 Web 框架集成</font>
										</strong>
								</span>
						</a>
				</p>
				<p>试着把 Ajax 开发与所选的 Java EE Web 框架集成，是很自然的。但是有些 Java EE Web 框架对异步通信模型提供直接可以使用的支持。要体会这个事实的意义，需要理解 servlet 处理同步和异步通信的方式。图 4 显示了处理同步请求的传统 servlet 序列： </p>
				<p>
						<br />
						<a name="N101DE">
								<strong>图 4. 处理同步请求的 Servlet 序列</strong>
						</a>
						<br />
						<img height="299" alt="传统 Servlet 序列（同步）" src="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/servlet_synchronous_sequence.jpg" width="523" />
						<br />
				</p>
				<p>图 4 对于 Java EE Web 开发人员来说应当相当熟悉。来自浏览器的请求先由控制器 servlet 的 <code><font face="Courier" size="2">service()</font></code> 处理。servlet 可以从 <code><font face="Courier" size="2">HttpRequest</font></code> 检索到需要的任何值（以参数的形式或者以属性的形式）。一旦控制器处理完成，结果就发送回 <code><font face="Courier" size="2">HttpRequest</font></code> （或 <code><font face="Courier" size="2">HttpSession</font></code>），而 <code><font face="Courier" size="2">RequestDispatcher</font></code> 则把控制转发（或包含）回页面。 </p>
				<p>图 5 显示了处理异步请求的 servlet 序列：</p>
				<p>
						<br />
						<a name="fig5">
								<strong>图 5. 处理异步请求的 Servlet 序列</strong>
						</a>
						<br />
						<img height="403" alt="Servlet 序列（异步）" src="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/servlet_asynchronous_sequence.jpg" width="572" />
						<br />
				</p>
				<p>图 5 中的序列与同步序列略有不同。来自浏览器的请求先由控制器 servlet 的 <code><font face="Courier" size="2">service()</font></code> 处理。servlet 可以从 <code><font face="Courier" size="2">HttpRequest</font></code> 检索到需要的任何值（以参数的形式或者以属性的形式）。一旦控制器处理完成，<code><font face="Courier" size="2">HttpServletResponse</font></code> 的内容类型必须设置成 XML。而且，控制器逻辑的结果要用 <code><font face="Courier" size="2">PrintWriter</font></code> 写入。这时，<code><font face="Courier" size="2">RequestDispatcher</font></code> 的使用被越过。</p>
				<p>这个（异步序列）恰恰是多数 Java EE Web 框架不支持的，从而造成与 Ajax 的集成非常困难。不支持异步通信模型的 Portlet 和 JavaServer Faces （JSF）框架面临着同样的问题。 </p>
				<p>克服这个问题也有一些选项： </p>
				<ul>
						<li>
								<strong>与 Web 框架并存：</strong> 不必等待内置的 Ajax 支持或者在所选的框架中强行实现 Ajax 支持，可以使用独立的 servlet 来处理全部异步请求。DWR 就使用了这种方式。这种方式的不足在于 Ajax 请求不能方便地利用框架的特性。<br /><br /></li>
						<li>
								<strong>与 Web 框架集成</strong>：通过使用免费的扩展或编写定制的扩展，可以设计出与所选 Web 框架集成的途径。<br /><br /></li>
						<li>
								<strong>迁移到支持 Ajax 的框架</strong>：更新的框架开始支持异步通信模型。其中一个是 Apache Shale（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>）。 </li>
				</ul>
				<p>
						<a name="N1024B">
								<span class="smalltitle">
										<strong>
												<font size="3">使用标记库</font>
										</strong>
								</span>
						</a>
				</p>
				<p>大量使用标记库（taglib）在 Java 的 Web 应用程序开发中是很普遍的。像许多 Java EE Web 框架一样，有些标记库现在也不支持异步通信模型，没有把通过 <code><font face="Courier" size="2">XMLHttpRequest</font></code> 提交的数据转换成 <code><font face="Courier" size="2">HttpServletRequest</font></code> （以及反过来）的途径。实际上，不支持异步通信的标记库，在 Ajax <code><font face="Courier" size="2">XMLHttpRequest</font></code> 调用期间不工作。可用的选项有： </p>
				<ul>
						<li>
								<strong>放弃使用不支持异步模型的标记库</strong>：把现在由标记库生成的代码迁移到 HTML/JavaScript 代码。（如果 Web 应用程序高度依赖标记库，这种方式最终会造成视图层页面尺寸的增大。）<br /><br /></li>
						<li>
								<strong>解决问题</strong>：使用已经解决了这个问题的 Ajax 框架。示例之一就是 DWR（请参阅 <code><font face="Courier" size="2">ExecutionContext.forwardToString()</font></code>）。 在这种情况下，可以继续使用以前一直使用的标记库。<br /><br /></li>
						<li>
								<strong>使用支持 Ajax 的标记库</strong>：使用支持异步模型的标记库，例如 Ajax JSP 标记库（AjaxTags）（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>）。 </li>
				</ul>
				<p>
						<a name="N1027E">
								<span class="smalltitle">
										<strong>
												<font size="3">用 IDE 进行开发与调试</font>
										</strong>
								</span>
						</a>
				</p>
				<p>有许多 JavaScript 调试工具可以帮助开发人员开发 JavaScript 解决方案。但是，传统的 Java 开发环境不允许检查 <code><font face="Courier" size="2">XMLHTTPRequest</font></code> 和与 Ajax 相关的其他东西的值。</p>
				<p>一个解决方案是利用 AJAX Toolkit Framework（ATF）（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>）。ATF 是个 Eclipse 插件，带有增强的 JavaScript 编辑特性，例如编辑时语法检查，内嵌的 Mozilla Web 浏览器，内嵌的 DOM 浏览器，内嵌的 JavaScript 调试器。ATF 还包含 Personality Builder 功能，这个功能可以帮助任何 Ajax 运行时框架构建 IDE 特性，从而加入到 ATF 支持的运行时环境集中。 </p>
				<p>
						<a name="threadingSection">
								<span class="smalltitle">
										<strong>
												<font size="3">线程问题</font>
										</strong>
								</span>
						</a>
				</p>
				<p>在典型的同步 Web 应用程序中，有些领域对按钮或链接点击要求更长一点的处理时间。没有耐心和没经验的 Web 用户通常会不止一次地点击按钮或链接，以为可以帮助加快处理速度，从而引发多重表单提交。其他时候，用户认为需要双击（就像桌面应用程序那样）。Web 应用程序中的多重表单提交在某些情况下是无害的。而在其他情况下，副作用可能造成严重的线程问题或争用情况（此时多个线程竞争执行一个代码块）。例如，在银行应用程序中多次点击转帐按钮，可能造成不希望的多次转帐。 </p>
				<p>既支持同步通信模型又支持异步通信模型的 Web 应用程序会发现，如果它的功能没有正确分析和规划，那么自己就处在了相似的困境中。支持两种通信模型的应用程序在某个页面上可能混合了服务器端调用（即，或者同步，或者异步，或者混合了同步和异步）。就像在多重点击场景中一样，异步调用可能处理得慢些。如果应用程序不做预防，用户可能会在异步线程正在处理时又调用了一个同步调用，因为页面没有刷新，所以无法阻止页面上的进一步活动。结果是两个线程并发处理。虽然不是由 Web 页面上的同一按钮或链接引发，这类情况还是会造成服务器端的线程问题（与多重点击问题类似）。 </p>
				<p>例如，以图 6 所示的银行应用程序的转账页面为例： </p>
				<p>
						<br />
						<a name="fig6">
								<strong>图 6. 转帐示例</strong>
						</a>
						<br />
						<img height="254" alt="转账示例" src="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/transfer_funds_example.jpg" width="388" />
						<br />
				</p>
				<p>对于这个示例，用红色表示的转账按钮引发一个 Ajax 调用。退出链接（黄色）引发同步调用。如果不耐烦或没有经验的用户点击了红色按钮之后接着又点击黄色链接（假设两个链接在代码中有共同的路径），就会发生争用情况。</p>
				<p>一般来说，有两种方式可以避免这类情况发生。第一种方式是客户端解决方案。一旦点击了一个链接或按钮，就用 JavaScript 确保禁止后续的页面提交，直到当前线程执行完成。第二个解决方案是允许多线程提交，但是依赖于服务器端代码中的同步来避免争用情况。如果引入同步来解决这个问题，请记住 Java EE Web 组件（servlet、portlet、JSF 等）是多线程的。要当心大段代码的同步（特别是与请求/响应生命周期处理有关的代码）。在效果上，同步的误用，会把应用程序变成单线程应用程序，从而降低吞吐率。 </p>
				<p> </p>
				<p>
						<a name="performanceSection">
								<span class="atitle">
										<strong>
												<font size="4">克服性能缺陷</font>
										</strong>
								</span>
						</a>
				</p>
				<p>使用 Ajax 还有可能影响基于 Java EE Web 的应用程序的性能。允许每个请求上有额外线程的可能性，可能会影响两个资源。 </p>
				<p>首先，servlet 容器的<em>线程池</em> 可能受到影响。线程池指定 Web 容器中允许并发运行的线程的最大数量。每个客户机请求需要一个线程。但是，一个客户机请求不一定等于一个用户请求。浏览器可能为一个用户请求要求多个客户机请求。例如，提交表单的一个用户可能要求多个客户机请求（其中包含提交表单的值、检索 GIF 文件、检索 JavaScript 文件、检索 CSS 文件）。如果允许并发地提交同步和异步请求，就意味着每个用户请求至少要支持多出一个的线程消耗（用于 Ajax 请求）。虽然为每个用户请求多增加一个线程的可能性看起来不多，但是当应用程序处在负载之下时，影响就明显了（这时每个用户请求多出的一个额外线程乘上平均用户数量）。显示，这种情况有可能影响 servlet 容器的性能。 </p>
				<p>另一个可能受影响的资源是<em>数据库连接池</em>。典型的 Java EE Web 应用程序支持一个用户请求的两类序列：<em>浅（shallow）</em>请求和 <em>深（deep）</em>请求。浅请求是执行服务器端代码但是不访问持久性存储（例如数据库）就完成请求的 Web 页面发出的请求。深请求是执行服务器端代码并访问持久性存储才能完成请求的 Web 页面发出的请求。 </p>
				<p>在深请求序列中（假设需要数据库连接），数据库连接池的这些方面可能会由于允许多个线程而受到影响：</p>
				<ul>
						<li>等待连接的线程的平均数量 
</li>
						<li>以毫秒为单位的连接的平均等候时间 
</li>
						<li>连接被使用的平均时间 </li>
				</ul>
				<p>所以，可能需要提高连接池的平均大小或连接数量。 </p>
				<p>
						<a name="testingSection">
								<span class="atitle">
										<strong>
												<font size="4">对付测试</font>
										</strong>
								</span>
						</a>
				</p>
				<p>Java 开发人员一直在不断地努力为 Java SE 和 Java EE 代码提供单元测试工具。由于 Ajax 的引入造成浏览器内的 JavaScript 增多，对可靠的 JavaScript 单元测试框架也提出了要求。现在可用的框架有 JsUnit、Selenium 和 HttpUnit（请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-ajaxee/index.html#resources"><font color="#996699">参考资料</font></a>）。</p>
				<p>这些框架提供了为 JavaScript 函数开发单元测试的工具，可以操纵 Web 页面上的 DOM 元素。它们允许把单元测试组织成测试套件。Selenium 的浏览器兼容性测试特性允许在不同的浏览器和操作系统上测试 JavaScript 函数。它利用 JavaScript 和 Iframe 在浏览器中嵌入了测试自动引擎。这项技术应当可以在任何支持 JavaScript 的浏览器中工作，对于支持多个浏览器和浏览器版本的应用程序来说特别有用。Selenium 和 JsUnit 都支持<em>持续集成</em>：可以把 JavaScript 单元测试和测试套件集成到自动构建过程。</p>
				<p>
						<a name="N102F6">
								<span class="atitle">
										<strong>
												<font size="4">结束语</font>
										</strong>
								</span>
						</a>
				</p>
				<p>把 Ajax —— 就像其他技术或模式一样 —— 引入 Java EE 应用程序，也有它的优势和不足。本文提供了把 Ajax 集成到 Java EE Web 应用程序的概述。Ajax 的异步通信模型与传统 Java EE Web 应用程序内置就支持的同步模型有很大不同。为了避免盲目，请确保在采用 Ajax 之前对潜在的问题领域有全面的事前规划。</p>
				<p>Java EE 框架对 Ajax 的支持和工具在不断改进。未来有望会有框架自带的 Ajax 支持来降低集成的复杂性。基于 JSF 的 Apache Shale 和基于 servlet 的 DWR 是两个希望您保持关注的框架。</p>
				<br />
				<br />
				<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1155119</p>
		</div>
<img src ="http://www.blogjava.net/zqli/aggbug/68520.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-09-08 15:12 <a href="http://www.blogjava.net/zqli/archive/2006/09/08/68520.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]开发JRun的JMS服务指南</title><link>http://www.blogjava.net/zqli/archive/2006/09/08/68512.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Fri, 08 Sep 2006 06:29:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/09/08/68512.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/68512.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/09/08/68512.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/68512.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/68512.html</trackback:ping><description><![CDATA[  Java 消息服务（JMS）可以帮助我们减少应用程序间的耦合，而同时又允许应用程序间的通信以及使用对方的资源。JMS 一般都包含至少三个组成部分：两个JMS 客户和一个 JMS 服务器。两个客户通过 JMS 服务器相互通信。JMS 客户是使用 JMS API发送和接收消息的常规应用程序。<br /><br />    JMS 服务器可以是任何实现 JMS 规范的应用程序。一些 JMS 服务器是更大的应用程序的一部分；还有一些是专门负责 JMS 任务的应用程序。有很多第三方商业资源和一些开放源代码资源的 JMS 服务器可供选择使用。应用程序使用 JMS 相互通信有两个方法可以选用：JMS 主题和 JMS 队列。主题和队列只在很少一些地方有区别，其中最明显的区别是它们发送消息的方式不同。<br /><br />    JMS 主题从一个 JMS 客户接收消息然后将这些消息分发给所有注册为主题监听者的 JMS 客户。相反，JMS 队列只将消息分发给一个客户，不管有多少客户注册为队列监听者。如果两个或者多个客户注册到一个队列，同时一个消息存储在队列中，那么只有一个客户能接收到这个消息。<br /><br />    JMS 规范没有规定哪个客户将接收这个消息。不管你是使用 JMS 主题还是 JMS 队列，消息中所要传递的数据的类型都在于你自己。一些程序员通过他们的消息系统发送商业对象，而其它程序员以文本格式发送 XML 消息从而进一步地减少耦合。如果你以前没有用过 JMS，那么可能是因为你还没有一个使用它的原因。如果你以前编写过你自己的消息系统，那么很可能你将从 JMS API 中受益。<br /><br />    JRun服务器已经提供了对JMS的支持，且内置了JMS服务，以JRun4.0为例，主要配置文件有{JRun-Home}/server/servers/{server-name}/SERVER-INF/jrun-jms.xml和jrun-resources.xml，查看jrun-jms.xml文件可以知道jrun对于JMS Message的持久化有两种方式，一个是文件方式，一个是数据库方式，默认是文件来保存JMS Message：<br /><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"><div>&lt;persistence-manager&gt;            <br /> &lt;active-adapter-type&gt;file&lt;/active-adapter-type&gt;            <br /> &lt;persistence-adapter&gt;                  <br />  &lt;adapter-type&gt;file&lt;/adapter-type&gt;            <br /> &lt;/persistence-adapter&gt;            <br /> &lt;persistence-adapter&gt;                  <br />  &lt;adapter-type&gt;rdbm&lt;/adapter-type&gt;            <br /> &lt;/persistence-adapter&gt;      <br />&lt;/persistence-manager&gt;<span style="COLOR: #000000"></span></div></div><p> 这里需要注意的就是把&lt;client-jndi&gt;的注释去掉，并修改provider-url为服务器实际地址，此处为例为192.168.2.240:2908，注意2908是此Server提供的JNDI服务端口，因为JMS服务是绑定到server的JNDI服务上的，客户端需要查询JNDI。再修改run-resources.xml添加测试的JMS队列(也可以通过JRun控制台添加)</p><p> </p><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"><div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">jms</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">destination</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">                <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">jndi</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">jms</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">queue</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">testQueue</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">jndi</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">                    <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">destination</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">testQueue</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">destination</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">destination</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">type</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">javax.jms.Queue</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">destination</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">type</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">    <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">jms</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">destination</span><span style="COLOR: #000000">&gt;</span></div></div><p>再添加QueueConnectionFactory</p><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"><div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">jms</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">connection</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">factory</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">factory</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">QueueConnectionFactory</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">factory</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">jndi</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">jms</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">jndi</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">QueueConnectionFactory</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">jndi</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">name</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">type</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">javax.jms.QueueConnectionFactory</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">type</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">transport</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">RMI</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">transport</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">username</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">guest</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">username</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">password</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">guest</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">password</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">jms</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">connection</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">factory</span><span style="COLOR: #000000">&gt;</span></div></div><p> </p><p>上面transport是指传输消息所用的协议，RMI：java远程方法调用，TCP：TCP/IP协议，Intra-VM：只在本虚拟机传输消息，用户名/密码是服务验证客户端调用时使用。服务器端JMS的设置基本完成了，还需要设置jrun的安全策略。<br /><br /><span style="COLOR: blue">修改{JRun-Home}/server/security.properties,有两项jrun.subnet.restriction：子网掩码，jrun.trusted.hosts：信任主机的IP，否则远程调用可能会被拒绝。再到{JRun-Home}/bin下修改jvm.config,添加java虚拟机启动参数-Djava.rmi.server.hostname=192.168.2.240，其中192.168.2.240为主机的实际IP，不要写localhost，否则RMI的远程调用会被拒绝。也可以写一个新配置文件new-server.conf，启动时用命令jrun –config new-server.conf –start XXX指定配置文件。服务器端的设置完成。当然如果客户端程序也在此JRun中运行，可以忽略这些参数的修改和设置。</span><br /><br />    客户端的代码基本与调用其他JMS服务类似。注意要取得{JRun-Home}/lib/jrun.jar并放入到客户端环境的classpath中，代码示例</p><p> </p><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"><div><img id="_25_3166_Open_Image" onclick="this.style.display='none'; document.getElementById('_25_3166_Open_Text').style.display='none'; document.getElementById('_25_3166_Closed_Image').style.display='inline'; document.getElementById('_25_3166_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_25_3166_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_25_3166_Closed_Text').style.display='none'; document.getElementById('_25_3166_Open_Image').style.display='inline'; document.getElementById('_25_3166_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> JmsQueueTest</span><span id="_25_3166_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">...</span><span id="_25_3166_Open_Text"><span style="COLOR: #000000">{        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Context context </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> QueueConnection connection  </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> QueueSession session </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Queue queue </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> QueueSender sender  </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> String connectionFactory;        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> String queueJndiName;        <br /><img id="_398_447_Open_Image" onclick="this.style.display='none'; document.getElementById('_398_447_Open_Text').style.display='none'; document.getElementById('_398_447_Closed_Image').style.display='inline'; document.getElementById('_398_447_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_398_447_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_398_447_Closed_Text').style.display='none'; document.getElementById('_398_447_Open_Image').style.display='inline'; document.getElementById('_398_447_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> setConnectionFactory(String connectionFactory)</span><span id="_398_447_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">...</span><span id="_398_447_Open_Text"><span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.connectionFactory </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> connectionFactory;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000">        <br /><img id="_508_557_Open_Image" onclick="this.style.display='none'; document.getElementById('_508_557_Open_Text').style.display='none'; document.getElementById('_508_557_Closed_Image').style.display='inline'; document.getElementById('_508_557_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_508_557_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_508_557_Closed_Text').style.display='none'; document.getElementById('_508_557_Open_Image').style.display='inline'; document.getElementById('_508_557_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> setQueueJndiName(String queueJndiName)</span><span id="_508_557_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">...</span><span id="_508_557_Open_Text"><span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.queueJndiName </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> queueJndiName;        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000">        <br /><img id="_568_734_Open_Image" onclick="this.style.display='none'; document.getElementById('_568_734_Open_Text').style.display='none'; document.getElementById('_568_734_Closed_Image').style.display='inline'; document.getElementById('_568_734_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_568_734_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_568_734_Closed_Text').style.display='none'; document.getElementById('_568_734_Open_Image').style.display='inline'; document.getElementById('_568_734_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span id="_568_734_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">/** */</span><span id="_568_734_Open_Text"><span style="COLOR: #008000">/**</span><span style="COLOR: #008000">         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * 初始化JMS队列         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * </span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000"> ctxFactory         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * </span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000"> url         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * </span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000"> user         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * </span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000"> pwd         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * </span><span style="COLOR: #808080">@throws</span><span style="COLOR: #008000"> Exception         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    </span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">        <br /><img id="_831_1412_Open_Image" onclick="this.style.display='none'; document.getElementById('_831_1412_Open_Text').style.display='none'; document.getElementById('_831_1412_Closed_Image').style.display='inline'; document.getElementById('_831_1412_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_831_1412_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_831_1412_Closed_Text').style.display='none'; document.getElementById('_831_1412_Open_Image').style.display='inline'; document.getElementById('_831_1412_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> init(String ctxFactory,String url,String user,String pwd)</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception </span><span id="_831_1412_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">...</span><span id="_831_1412_Open_Text"><span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        Properties p </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Properties();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        p.put(Context.INITIAL_CONTEXT_FACTORY,ctxFactory);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        p.put(Context.PROVIDER_URL,url);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        p.put(Context.SECURITY_PRINCIPAL,user);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        p.put(Context.SECURITY_CREDENTIALS,pwd);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        context </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> InitialContext(p);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        QueueConnectionFactory factory </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (QueueConnectionFactory)context.lookup(connectionFactory);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        connection </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> factory.createQueueConnection();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        queue </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (Queue)context.lookup(queueJndiName);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        session </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> connection.createQueueSession(</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">,Session.AUTO_ACKNOWLEDGE);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        sender </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> session.createSender(queue);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        connection.start();        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000">        <br /><img id="_1423_1510_Open_Image" onclick="this.style.display='none'; document.getElementById('_1423_1510_Open_Text').style.display='none'; document.getElementById('_1423_1510_Closed_Image').style.display='inline'; document.getElementById('_1423_1510_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_1423_1510_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_1423_1510_Closed_Text').style.display='none'; document.getElementById('_1423_1510_Open_Image').style.display='inline'; document.getElementById('_1423_1510_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span id="_1423_1510_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">/** */</span><span id="_1423_1510_Open_Text"><span style="COLOR: #008000">/**</span><span style="COLOR: #008000">         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * 发送文本消息         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * </span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000"> txt         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * </span><span style="COLOR: #808080">@throws</span><span style="COLOR: #008000"> Exception         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    </span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">        <br /><img id="_1566_1675_Open_Image" onclick="this.style.display='none'; document.getElementById('_1566_1675_Open_Text').style.display='none'; document.getElementById('_1566_1675_Closed_Image').style.display='inline'; document.getElementById('_1566_1675_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_1566_1675_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_1566_1675_Closed_Text').style.display='none'; document.getElementById('_1566_1675_Open_Image').style.display='inline'; document.getElementById('_1566_1675_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> send(String txt)</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception </span><span id="_1566_1675_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">...</span><span id="_1566_1675_Open_Text"><span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        TextMessage tmsg </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> session.createTextMessage();        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        tmsg.setText(txt); sender.send(tmsg);        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000">        <br /><img id="_1686_1754_Open_Image" onclick="this.style.display='none'; document.getElementById('_1686_1754_Open_Text').style.display='none'; document.getElementById('_1686_1754_Closed_Image').style.display='inline'; document.getElementById('_1686_1754_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_1686_1754_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_1686_1754_Closed_Text').style.display='none'; document.getElementById('_1686_1754_Open_Image').style.display='inline'; document.getElementById('_1686_1754_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span id="_1686_1754_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">/** */</span><span id="_1686_1754_Open_Text"><span style="COLOR: #008000">/**</span><span style="COLOR: #008000">         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * 查询队列中保存的消息         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * </span><span style="COLOR: #808080">@throws</span><span style="COLOR: #008000"> Exception         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    </span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">        <br /><img id="_1802_2058_Open_Image" onclick="this.style.display='none'; document.getElementById('_1802_2058_Open_Text').style.display='none'; document.getElementById('_1802_2058_Closed_Image').style.display='inline'; document.getElementById('_1802_2058_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_1802_2058_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_1802_2058_Closed_Text').style.display='none'; document.getElementById('_1802_2058_Open_Image').style.display='inline'; document.getElementById('_1802_2058_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> browser()</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception</span><span id="_1802_2058_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">...</span><span id="_1802_2058_Open_Text"><span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        QueueBrowser browser </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> session.createBrowser(queue);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        Enumeration </span><span style="COLOR: #0000ff">enum</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> browser.getEnumeration();System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">QueueBrowser</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img id="_1973_2028_Open_Image" onclick="this.style.display='none'; document.getElementById('_1973_2028_Open_Text').style.display='none'; document.getElementById('_1973_2028_Closed_Image').style.display='inline'; document.getElementById('_1973_2028_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_1973_2028_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_1973_2028_Closed_Text').style.display='none'; document.getElementById('_1973_2028_Open_Image').style.display='inline'; document.getElementById('_1973_2028_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">enum</span><span style="COLOR: #000000">.hasMoreElements())</span><span id="_1973_2028_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">...</span><span id="_1973_2028_Open_Text"><span style="COLOR: #000000">{        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />            System.out.println(</span><span style="COLOR: #0000ff">enum</span><span style="COLOR: #000000">.nextElement());<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span></span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        browser.close();        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000">        <br /><img id="_2069_2131_Open_Image" onclick="this.style.display='none'; document.getElementById('_2069_2131_Open_Text').style.display='none'; document.getElementById('_2069_2131_Closed_Image').style.display='inline'; document.getElementById('_2069_2131_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_2069_2131_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_2069_2131_Closed_Text').style.display='none'; document.getElementById('_2069_2131_Open_Image').style.display='inline'; document.getElementById('_2069_2131_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span id="_2069_2131_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">/** */</span><span id="_2069_2131_Open_Text"><span style="COLOR: #008000">/**</span><span style="COLOR: #008000">         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * 接收消息         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    * </span><span style="COLOR: #808080">@throws</span><span style="COLOR: #008000"> Exception         <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    </span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">        <br /><img id="_2179_2459_Open_Image" onclick="this.style.display='none'; document.getElementById('_2179_2459_Open_Text').style.display='none'; document.getElementById('_2179_2459_Closed_Image').style.display='inline'; document.getElementById('_2179_2459_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_2179_2459_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_2179_2459_Closed_Text').style.display='none'; document.getElementById('_2179_2459_Open_Image').style.display='inline'; document.getElementById('_2179_2459_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> receive()</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception</span><span id="_2179_2459_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">...</span><span id="_2179_2459_Open_Text"><span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        QueueReceiver receiver </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> session.createReceiver(queue);<br /><img id="_2252_2428_Open_Image" onclick="this.style.display='none'; document.getElementById('_2252_2428_Open_Text').style.display='none'; document.getElementById('_2252_2428_Closed_Image').style.display='inline'; document.getElementById('_2252_2428_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_2252_2428_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_2252_2428_Closed_Text').style.display='none'; document.getElementById('_2252_2428_Open_Image').style.display='inline'; document.getElementById('_2252_2428_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />        </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">)</span><span id="_2252_2428_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">...</span><span id="_2252_2428_Open_Text"><span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />            TextMessage message </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (TextMessage)receiver.receiveNoWait();        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(message </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />            System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">receive message:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> message.getText());<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span></span><span style="COLOR: #000000"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        receiver.close();        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000">        <br /><img id="_2505_2594_Open_Image" onclick="this.style.display='none'; document.getElementById('_2505_2594_Open_Text').style.display='none'; document.getElementById('_2505_2594_Closed_Image').style.display='inline'; document.getElementById('_2505_2594_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_2505_2594_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_2505_2594_Closed_Text').style.display='none'; document.getElementById('_2505_2594_Open_Image').style.display='inline'; document.getElementById('_2505_2594_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> close()</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception</span><span id="_2505_2594_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">...</span><span id="_2505_2594_Open_Text"><span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        sender.close();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        session.close();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        connection.close();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        context.close();        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span><span style="COLOR: #000000"><br /><img id="_2652_3165_Open_Image" onclick="this.style.display='none'; document.getElementById('_2652_3165_Open_Text').style.display='none'; document.getElementById('_2652_3165_Closed_Image').style.display='inline'; document.getElementById('_2652_3165_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_2652_3165_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_2652_3165_Closed_Text').style.display='none'; document.getElementById('_2652_3165_Open_Image').style.display='inline'; document.getElementById('_2652_3165_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> main(String[] args)</span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception </span><span id="_2652_3165_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">...</span><span id="_2652_3165_Open_Text"><span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        String ctxFactory </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">jrun.naming.JRunContextFactory</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        String url </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">192.168.2.240:2908</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        String user </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">guest</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        String pwd </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">guest</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        String connectionFactoryJndi </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">jms/jndi-QueueConnectionFactory</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        String queueJndi </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">jms/queue/testQueue</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        JmsQueueTest test </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> JmsQueueTest();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        test.setConnectionFactory(connectionFactoryJndi);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        test.setQueueJndiName(queueJndi);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        test.init(ctxFactory,url,user,pwd);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        test.send(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">java共舞JMS消息</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        test.browser();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        test.receive();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        test.close();        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span></span></span></div></div><br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1151182</p><img src ="http://www.blogjava.net/zqli/aggbug/68512.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-09-08 14:29 <a href="http://www.blogjava.net/zqli/archive/2006/09/08/68512.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]获取 Web 设计的免费资源</title><link>http://www.blogjava.net/zqli/archive/2006/08/29/66394.html</link><dc:creator>放水老倌</dc:creator><author>放水老倌</author><pubDate>Tue, 29 Aug 2006 05:05:00 GMT</pubDate><guid>http://www.blogjava.net/zqli/archive/2006/08/29/66394.html</guid><wfw:comment>http://www.blogjava.net/zqli/comments/66394.html</wfw:comment><comments>http://www.blogjava.net/zqli/archive/2006/08/29/66394.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zqli/comments/commentRss/66394.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zqli/services/trackbacks/66394.html</trackback:ping><description><![CDATA[
		<div class="postText">
				<p>
						<a href="http://www-128.ibm.com/developerworks/cn/web/wa-freeweb/#author" target="_blank">
								<font color="#996699">Uche Ogbuji</font>
						</a> (<a href="mailto:uche@ogbuji.net?subject=获取 Web 设计的免费资源&amp;cc=htc@us.ibm.com"><font color="#5c81a7">uche@ogbuji.net</font></a>), 首席顾问, Fourthougth, Inc.<br /></p>
				<p>2006 年 7 月 31 日</p>
				<p>拥有大量预算作为后盾的 Web 设计人员可以获得任何所需的资源，从而可以把他们的想像力付诸于 Web 体验。他们可以聘请专业摄像师来制作引人注目的照片；可以请最好的 HTML 和 CSS 专家来创建适用于多种浏览器的复杂布局；可以指导图形艺术家根据企业服装来创作华丽的装饰物；可以聘请专业文案人员起草迷人的散文。最大的好处是，他们能雇佣大量测试用户和关注小组来确保网站吸引人、便于使用并能按照预期进行工作。</p>
				<p>但是，并不是所有的 Web 设计人员都这样幸运！不幸的是，有些设计人员必须用很少的钱来创建网站，并且对 Web 体验的预期并不见得很低。在这种情况下，您必须寻求一切可以获得的帮助。多半来说，Web 开发人员和设计人员在与同事共享知识和成就方面是非常慷慨的。当您共享时，同事们通常会努力地纠正并增强您的作品，使其变得更加精致、bug 更少，并会提供您自己的关注小组和质量保证。这意味着您可以找到大量免费材料。如果您知道去哪里找的话，就可以填补低预算 Web 开发运营情况下的一些漏洞。在本文中，我将介绍各类免费的 Web 资源，以及对一些貌似免费，实其不然的 Web 资源的警告。</p>
				<p>
						<a name="N10061">
								<span class="atitle">
										<font size="4">创造性的公用</font>
								</span>
						</a>
				</p>
				<p>首先介绍 <a href="http://creativecommons.org/" target="_blank"><font color="#5c81a7">Creative Commons</font></a>(CC)，它本身不是免费资源的来源，而是提供免费资源的人们所使用的许可证的来源。用他们自己的话说：CC 是一个非营利性组织，为创造性作品提供灵活的版权许可。您可以选择一个 CC 许可，以允许所有者要求您在使用所有者的作品或修改他们的作品时给予他们荣誉（归属条款）；可以限制自己作品仅用于非营利性组织；可以要求任何对您作品所作的更改必须在与原条款相同的条款下共享（类似共享的条款）。还有其他条款，您可以组合这些条款。例如，一个常见的 CC 许可是<em>Attribution Share Alike</em> 许可。</p>
				<p>CC 已取得了巨大成功 —— 来自 CC 许可的作品主体十分庞大，并且每天都在扩大。文学、图像、音乐等作品都可以在 CC 许可下提供。只要满足限制，您可以自由地在网站上使用任何这些作品。要了解如何找到 Web 设计的任何免费产品，第一步是了解如何搜索在 CC 许可下提供的材料。您可以使用 CC 搜索引擎页面直接获得来源，这允许您利用搜索引擎（如 Google 和 Flickr）和免费资源收集（如 Flick 和 DMusic) 的专业搜索功能。</p>
				<p>
						<a name="N10075">
								<span class="atitle">
										<font size="4">样式元素</font>
								</span>
						</a>
				</p>
				<p>好的样式表是好网站的骨架 —— 尤其是层叠样式表 (CSS)。不幸的是，浏览器中多变的支持意味着很难开发好的样式表。依靠免费样式表，至少是样式元素的免费模块，您可以省去大量精力和测试工作。许多站点提供 CSS 说明和示例，但我的关注点是我找到的站点，大多数都有 CSS 材料，您可以用于快速地组装成自己的站点。有一个由顶级 Web 专业人士开办的以期刊形式出现的站点：<a href="http://www.alistapart.com/" target="_blank"><font color="#5c81a7">A List Apart</font></a>，着重于 Code 和 Design 主题。<a href="http://www.intensivstation.ch/en/templates/" target="_blank"><font color="#5c81a7">CSS Intensivstation Templates</font></a> 专注于几个用于结构化站点的主要的布局样式。 </p>
				<p>最有名的 CSS 交换地是 <a href="http://www.csszengarden.com/" target="_blank"><font color="#5c81a7">CSS Zen Garden</font></a>，但您在使用此网站时必须格外小心。CSS Zen Garden 旨在展示 CSS 的强大功能。CSS 是分离内容和形式的好方法。但起初许多 Web 开发人员回避 CSS，因为他们认为如果不用传统的 HTML 技巧（如布局表格和隐藏图像），就创建不出同样令人难忘的效果。CSS Zen Garden 通过漂亮的样式证明这一认识是错误的。其中有一个单独且共享的内容片段，Web 设计人员创建了页面来以某种独特方式显示这些内容。他们使用巧妙的布局、迷人的图像和颜色，通常创作出某种主题，如大海或博物馆风格的主题。CSS Zen Garden 不能作为模板的集合。您可以在大多数 CSS 贡献中显示的警告中看到以下说明： </p>
				<blockquote>此设计不是模板。未经设计者的书面许可，不得复制。但是，可以随意研究 CSS 并在其他地方使用学到的技术。 </blockquote>
				<p>此外，许多贡献者使用非免费的图像。站点维护人员请求贡献者在非商业 Creative Commons 许可下提供他们的 CSS（参见 <font color="#996699">参考资料</font>），所以复制 CSS 通常是安全的做法，但要确保检查贡献者 CSS 文件的开头部分。 </p>
				<p>
						<a name="N10097">
								<span class="atitle">
										<font size="4">图像</font>
								</span>
						</a>
				</p>
				<p>专业网站会使用各种图像，从照片到艺术家的绘画到图标和符号，等等。一些站点提供免版税的图像。有一个项目值得您关注，即 <a href="http://www.openclipart.org/" target="_blank"><font color="#5c81a7">Open Clip Art Library</font></a>，它是一个贡献的、可下载的剪贴画的集合。图像的范围包括从小而简单的图像到大而复杂的图像。大多数图像是可缩放矢量图形 (SVG) 格式，它是一种开放的、基于 XML 的格式。SVG 增强了对浏览器的支持，但它尚不通用，所以 Open Clip Art Library 包括每个图像的 PNG 版本。您可以浏览或搜索网站上的图像，但可能只想下载一个发行版，所以可以脱机浏览。图形的质量类似于您在商店购买的许多剪贴画集合中找到的图像的质量。当我需要符号、图标和其他资源（如高亮显示）时，通常会浏览 Open Clip Art Library，但 <a href="http://www.maxpower.ca/free-icons/2006/03/05/" target="_blank"><font color="#5c81a7">MaxPower Free Icons</font></a> 是一组很好的到免费图标集合的链接。说到商店里的剪贴画集合，即使已经购买，仍有许多限制。一些剪贴画需要商业使用版税。如果购买此类集合，请确保检查 End User License Agreements。 </p>
				<p>当需要照片时，我经常会访问前面提到过的 Flickr 的 CC 照片库，但是我通常是通过 <a href="http://yotophoto.com/" target="_blank"><font color="#5c81a7">Yotophoto</font></a> 到达那里的，Yotophoto 是从 CC 变体到 Public Domain 的一个免费许可照片的搜索聚合地。我最喜欢的一个资源站点是 <a href="http://www.sxc.hu/" target="_blank"><font color="#5c81a7">stock.xchng</font></a>。此站点包括大量极高品质的照片，并有一个非常好用的搜索引擎。不是所有的照片都是免版税的，但大多数是！您甚至可以查看是否有照片的模型发行，这是决定使用包含人像的照片时要考虑的一个重要因素。一个规模较小、尚不精致，但仍十分有用的站点是 <a href="http://openphoto.net/" target="_blank"><font color="#5c81a7">Open Photo</font></a>，它只包含经 CC 许可的照片。我还使用 <a href="http://www.morguefile.com/" target="_blank"><font color="#5c81a7">MorgueFile</font></a>，这个站点类似于 stock.xchng 站点，具有搜索和丰富元数据方面的类似优点。MorgueFile 上的所有图像受到专门许可（不基于 CC）的约束，但免除了个人或商业作品的版税。我喜欢 MorgueFile FAQ 中针对他们为什么提供免费图像的解答： 此网站遵循传统的万维网。它致力于倡导自由观点和交换。 </p>
				<p>
						<a name="N100BE">
								<span class="atitle">
										<font size="4">设计工具</font>
								</span>
						</a>
				</p>
				<p>一些 Web 设计人员和公司提供联机工具来帮助其他用户并提高他们自己的社区形象。最常用的是颜色方案工具，它允许您为自己的站点选择富有美感的、令人愉快的一组颜色。在搭配颜色方面，我的确没有世上最好的眼力，所以我感谢诸如 Wellstyled.com 的 <a href="http://wellstyled.com/tools/colorscheme2/index-en.html" target="_blank"><font color="#5c81a7">Color Scheme Generator</font></a> 这样的网站。另一个提供更多有关如何组装方案的站点是 <a href="http://www.siteprocentral.com/html_color_code.html" target="_blank"><font color="#5c81a7">SiteProCentral.com's HTML Color Code Combination Chooser</font></a>。 </p>
				<p>最流行的 Web 浏览器也是最奇怪的浏览器。多年来，Web 设计人员不得不应对 Microsoft Internet Explorer 5 和 6，包括 Macintosh 和 Windows 版本之间的差异。Microsoft 正在开发 7 版浏览器，他们承诺新版本具有更好的标准兼容性，但是另一方面 Dean Edwards 已经开发了 <a href="http://dean.edwards.name/IE7/" target="_blank"><font color="#5c81a7">JavaScript 解决方案</font></a>。引用该网站的话： </p>
				<blockquote>[Dean Edwards'] IE7 是一个 JavaScript 库，使 IE 的行为像标准兼容的浏览器。它修复了许多 CSS 问题并使透明 PNG 在 IE5 和 IE6 下正常工作。 </blockquote>
				<p>当您设计网站时，记住 Macintosh 用户是十分重要的。如果购买测试用的 Mac 机不是一个选择的话，您应感谢 Daniel Vine，因为他创建了 <a href="http://www.danvine.com/icapture/" target="_blank"><font color="#5c81a7">iCapture</font></a>。您可以在此站点指定 URL、搜索看上去像 Mac 机上的 Safari Web 浏览器显示的 PNG 图像。Edwards 还提供 <a href="http://www.danvine.com/iecapture/" target="_blank"><font color="#5c81a7">ieCapture</font></a>，允许查看您的站点在 Macintosh IE7 beta 中的显示效果。</p>
				<p>
						<a name="N100E4">
								<span class="atitle">
										<font size="4">完全 Web 布局和模板</font>
								</span>
						</a>
				</p>
				<p>有时即使获得以上所有帮助，我还是不能创建引人注目的网页。我可能想要一切，幸运的是可以在一些网站中找到免费的完整页面布局，包含 HTML（经常是 XHTML）模板、图形、样式表、高亮显示等。<a href="http://www.openwebdesign.org/" target="_blank"><font color="#5c81a7">Open Web Design</font></a> 有近 2000 个各种品质的完整模板。该网站有一个评级系统，有时会进行设计人员竞赛来扩大其收集量。<a href="http://www.oswd.org/" target="_blank"><font color="#5c81a7">Open Source Web Design</font></a> 是一个具有类似规模的网站。 </p>
				<p>
						<a name="N100F5">
								<span class="atitle">
										<font size="4">结束语</font>
								</span>
						</a>
				</p>
				<p>在本文中，您了解了许多资源，可以从中获得免费资料和工具以改进您的网站。即使您有预算来得到顶级的专业帮助，如果熟悉 Web 设计的最新技术，还是会很有帮助的。所幸的是，最新技术几乎不被隐藏或无法访问，它们总是免费的。如果有机会，我还鼓励您进行共享，比如为我提到的网站做贡献。毕竟，Web 美学的浪潮会水涨船高</p>
				<br />
				<br />
				<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1009638</p>
		</div>
<img src ="http://www.blogjava.net/zqli/aggbug/66394.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zqli/" target="_blank">放水老倌</a> 2006-08-29 13:05 <a href="http://www.blogjava.net/zqli/archive/2006/08/29/66394.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>