<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://tangl99.spaces.live.com/mmm2008-07-24_12.50/rsspretty.aspx?rssquery=en-US;http%3a%2f%2ftangl99.spaces.live.com%2fcategory%2fJava%e6%8a%80%e6%9c%af%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Tang Liang's notebook: Java技术</title><description /><link>http://tangl99.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&amp;_c=BlogPart&amp;partqs=catJava%25E6%258A%2580%25E6%259C%25AF</link><language>en-US</language><pubDate>Mon, 18 Aug 2008 14:23:05 GMT</pubDate><lastBuildDate>Mon, 18 Aug 2008 14:23:05 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><cf:parentRSS>http://tangl99.spaces.live.com/blog/feed.rss</cf:parentRSS><live:type>blogcategory</live:type><live:identity><live:id>-508484562895931526</live:id><live:alias>tangl99</live:alias></live:identity><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>jigloo插件简介</title><link>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!534.entry</link><description>&lt;div&gt;
&lt;h1 align=center&gt;jigloo插件简介&lt;/h1&gt;
&lt;h2&gt;一 3大GUI开发插件的特色&lt;/h2&gt;
&lt;p&gt;   Eclipse并不自带GUI的可视化开发工具，那么如果要在Eclipse进行可视化的GUI开发，就需要依靠第三方的插件。
&lt;h3&gt; 1. Visual Editor&lt;/h3&gt;
&lt;p&gt;    Eclipse官方提供了一个叫做Visual Editor(VE)的开源GUI插件，功能还是比较强。可以根据用户的界面GUI设计，自动生成相应的JAVA代码。同样也可以通过相应的JAVA代码，生成其匹配的可视化GUI编辑界面。不过VE缺点比较大，我从3.1到3.2之前一直在用VE，没有多少改观。VE是通过另外启动一个JVM来模拟执行GUI的class，然后在Eclipse的界面内生成一个可视化效果。
&lt;p&gt;   回顾一下Visual C++,NetBeans等其它IDE进行GUI可视化的方法，都是基于另外一个界面管理资源文件，非用户可以直接修改的。而直接通过程序代码来管理可视化的GUI编辑器，就需要极强的代码parse能力。很可惜，VE想这样做，确没有能够做到。
&lt;p&gt;  VE使用起来问题很多，网上有网友直接评价说VE是“可用性不强”。我自己用起来的感觉，问题就出在一下几个方面： 
&lt;p&gt;   1). 另外启动JVM速度很慢，而且如果要同时打开几个Visual Class，那么就要启动几个JVM，内存消耗也大。而且，有些时候,反复打开关闭一个Visual Class，JVM还启动不起来。 
&lt;p&gt;   2). 对于用户自己编辑的可视化Java代码的parse能力很弱。常见的错误就是，明明是正确的可视化GUI代码，但是VE里面窗口打开半天，结果只能显示一把叉。很多时候，就根本不能显示出一个完整的可视化窗口。而对于窗口上某个控件的定位能力不强，用户自己的代码稍微转几道弯儿，VE就不知道这个控件是在哪里产生的了，顶多只能显示出来，但是无法可视化编辑。
&lt;p&gt;   4).  3.1的VE编辑的代码到了3.2的VE里面，显示出来完全不一样了。
&lt;p&gt;   5).  安装比较麻烦，还需要用户自行去安装不只一个的辅助插件。
&lt;p&gt;   综上所述，VE真的“可用性不强”
&lt;h3&gt;2. SWT-Designer&lt;/h3&gt;
&lt;p&gt;   SWT-Designer是大家公认的，最强的Eclipse下开发GUI的插件&lt;a href="http://www.swt-designer.com/"&gt;&lt;u&gt;&lt;font color="#800080"&gt;http://www.swt-designer.com/&lt;/font&gt;&lt;/u&gt;&lt;/a&gt;。很多Eclipse书籍上都是直接拿SWT-Designer来讲解如何在Eclipse开发GUI界面程序。不过SWT-Designer是一个收费的插件。不收费的是基础版本，功能受到很大的限制。当然，网上也有完整版的破解版。SWT-Designer做得比较大，6.0最新的安装文件有几十M，可想其功能之强大。
&lt;h3&gt;3. jigloo&lt;/h3&gt;
&lt;p&gt;   jigloo严格意义上来说也是收费的，不过他提供了non_commercial的版本，而这个版本的功能和commercial是完全一样的&lt;a href="http://www.cloudgarden.com/jigloo/"&gt;&lt;u&gt;&lt;font color="#800080"&gt;http://www.cloudgarden.com/jigloo/&lt;/font&gt;&lt;/u&gt;&lt;/a&gt;。作为个人开发来说，是不受限制的。jigloo很小，最新的版本才3MB多，安装也比较简单。
&lt;p&gt;  jigloo同时支持SWT和Swing。
&lt;p&gt;   jigloo也是完全基于Java代码的，不过它的code parse的能力远比VE要强，也要快。至少我很多在VE下出现问题，不能显示的Visual Class可以很好地在jigloo下编辑，至今还没有遇到jigloo不能编辑，parse出错的时候。而jigloo还可以集成了一写比较好的Java GUI风格代码的支持，功能上比VE要强大一些。
&lt;p&gt;    当然，3MB多的插件，再强也强不过SWT-Designer完整版的，但是比其基础版的要好很多。而SWT-Designer也并不是完全基于JAVA开发的，比如Windows版本的，还携带了dll文件。而jigloo是完全基于JAVA开发的，下载下来只有一个class的zip文件，也支持Eclipse的在线安装。
&lt;h2&gt;二 jigloo的安装和使用&lt;/h2&gt;
&lt;p&gt;   jigloo的安装很简单，和其它Eclipse插件一样，不需要任何安装程序，直接解压出来就行了。
&lt;p&gt;   创建新的窗口，直接输入File-&amp;gt;New-&amp;gt;Others-&amp;gt;GUI Forms就可以了。
&lt;p&gt;   而如果要打开一个已经存在的Visual Class，可以直接右键点击，选择Open With-&amp;gt;Form Editor打开就可以了。打开后，首先要进行code parse，不过这个速度很快，也不需要像VE那样还启动一个JVM。
&lt;p&gt;   下面是我的Eclipse下使用jigloo的截图:
&lt;p&gt; &lt;img src="http://p.blog.csdn.net/images/p_blog_csdn_net/tangl_99/jigloo_eclipse_01.JPG"&gt;
&lt;p&gt;&lt;img src="http://p.blog.csdn.net/images/p_blog_csdn_net/tangl_99/jigloo_eclipse_02.JPG"&gt;   
&lt;p&gt;&lt;img src="http://p.blog.csdn.net/images/p_blog_csdn_net/tangl_99/jigloo_eclipse_03.JPG"&gt;
&lt;p&gt; 
&lt;h2&gt;三. 总结&lt;/h2&gt;
&lt;p&gt;    根据3大Eclipse的GUI开发插件可以看出，基本都是基于Java code的GUI编辑管理。这种编辑器管理，当然就比以前Visual C++那样管理Windows界面程序要困难很多。但是，现行的很多IDE，比如Visual Studio .NET,2005都还是能够做得比较快。主要的就是要看起code parsing的能力。
&lt;p&gt;    VE前面的缺点已经总结得比较多，不知道这个官方的插件什么时候才能让人真正放心。作为开发者来说，心里还是最想给VE加把劲的，毕竟VE是开源的，随便用的。
&lt;p&gt;   SWT-Designer功能最强大，可惜价格不低。而jigloo可谓介于两者之间，对于个人开发者来说，可以免费使用，而且其功能也足够到开发各种大型的GUI应用程序了，应该是一个合适的选择。 &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-508484562895931526&amp;page=RSS%3a+jigloo%e6%8f%92%e4%bb%b6%e7%ae%80%e4%bb%8b&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=tangl99.spaces.live.com&amp;amp;GT1=tangl99"&gt;</description><comments>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!534.entry#comment</comments><guid isPermaLink="true">http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!534.entry</guid><pubDate>Sun, 19 Nov 2006 14:39:04 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://tangl99.spaces.live.com/blog/cns!F8F17FFBEED1777A!534/comments/feed.rss</wfw:commentRss><wfw:comment>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!534.entry#comment</wfw:comment><dcterms:modified>2006-11-19T14:39:04Z</dcterms:modified></item><item><title>Java对象序列化给分布式计算带来的方便</title><link>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!479.entry</link><description>&lt;div&gt;
&lt;div style="text-indent:21pt"&gt;在面向对象程序语言中做分布式计算的时候，经常需要将对象在不同的主机之间传输，我这次在实现分布式计算的时候，需要将一个计算对象从中央服务器Server分发给所有的客户端client。&lt;/div&gt;
&lt;div style="text-indent:21pt"&gt;通过网络TCP，建立Socket，传输一个对象，就需要将对象转换成一段字节流，也就叫做对象的序列化。同时，也要求可以从这段字节流，创建出对应的对象出来。&lt;/div&gt;
&lt;div style="text-indent:21pt"&gt;C++里面的做法就是在每个类里面实现两个接口函数，自己通过写读和写对象的方法，来实现序列化。因为每个类的成员变量的值和成员变量的类型作者自己肯定晓得，所以就需要自己来通过把一个个成员变量写到流里面，最终实现了对象到字节流的转换。&lt;/div&gt;
&lt;div style="text-indent:21pt"&gt;C++里面针对纯数据类型的结构体，就是成员变量没有指针的对象的话，还可以通过拷贝内存块到字节流的方法memcpy，也可以很容易实现序列化，但是这只能是针对成员变量都是数据类型，没有指针类型的对象。 &lt;/div&gt;
&lt;div style="text-indent:21pt"&gt;在Java里面就比较方便了，直接通过实现java.io.Serializable接口，JVM就能自动来将类实现序列化。同时，java.io.Serializable接口没有任何接口函数，只是一个空接口，唯一的作用就是标志一下这个类是可以序列化。&lt;/div&gt;
&lt;div style="text-indent:21pt"&gt;其实，Java里面的对象序列化，是JVM在做的，因为JVM可以掌控整个对象的内部数据结构，就可以简单遍历树的方法，来实现把一个对象的所有成员变量写到字节流里面。当然，居然怎么做的，我也不太清楚，但是所有JVM来说，要做这一点还是很容易的。&lt;/div&gt;
&lt;div style="text-indent:21pt"&gt;Java里面，几乎所有的类只要实现了java.io.Serializable接口，就可以实现序列化。但是要求这个类里面的所有成员变量也是可以序列化的。比如类A有个成员变量对象是类B，如果A能序列化，要求B也要能够序列化，也就是A实现了java.io.Serializable，要求B也一定实现java.io.Serializable。&lt;/div&gt;
&lt;div style="text-indent:21pt"&gt;网上关于具体实现序列化的Sample代码很多了，我这里只是贴出一段参考：&lt;/div&gt;
&lt;div style="text-indent:21pt"&gt;序列化对象都是通过Java的ObjectInputStream和ObjectOutputStream来实现的。&lt;/div&gt;
&lt;div style="text-indent:21pt"&gt;写：&lt;/div&gt;
&lt;div&gt;&lt;span&gt;        
&lt;div&gt;
&lt;div&gt;&lt;img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top&gt;&lt;span style="color:#000000"&gt;ObjectOutputStream oos &lt;/span&gt;&lt;span style="color:#000000"&gt;=&lt;/span&gt;&lt;span style="color:#000000"&gt; &lt;/span&gt;&lt;span style="color:#0000ff"&gt;new&lt;/span&gt;&lt;span style="color:#000000"&gt; ObjectOutputStream(os);&lt;br&gt;&lt;img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top&gt;oos.writeObject(A);&lt;br&gt;&lt;img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;读:&lt;/div&gt;
&lt;div&gt;&lt;span&gt;  
&lt;div&gt;
&lt;div&gt;&lt;img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top&gt;&lt;span style="color:#000000"&gt;ObjectInputStream ios &lt;/span&gt;&lt;span style="color:#000000"&gt;=&lt;/span&gt;&lt;span style="color:#0000ff"&gt;new&lt;/span&gt;&lt;span style="color:#000000"&gt; ObjectInputStream(is);&lt;br&gt;&lt;img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top&gt;A a&lt;/span&gt;&lt;span style="color:#000000"&gt;=&lt;/span&gt;&lt;span style="color:#000000"&gt;(A)ios.readObject();&lt;br&gt;&lt;img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt; &lt;/div&gt;&lt;br&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-508484562895931526&amp;page=RSS%3a+Java%e5%af%b9%e8%b1%a1%e5%ba%8f%e5%88%97%e5%8c%96%e7%bb%99%e5%88%86%e5%b8%83%e5%bc%8f%e8%ae%a1%e7%ae%97%e5%b8%a6%e6%9d%a5%e7%9a%84%e6%96%b9%e4%be%bf&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=tangl99.spaces.live.com&amp;amp;GT1=tangl99"&gt;</description><comments>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!479.entry#comment</comments><guid isPermaLink="true">http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!479.entry</guid><pubDate>Mon, 21 Aug 2006 09:52:06 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://tangl99.spaces.live.com/blog/cns!F8F17FFBEED1777A!479/comments/feed.rss</wfw:commentRss><wfw:comment>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!479.entry#comment</wfw:comment><dcterms:modified>2006-08-21T09:52:06Z</dcterms:modified></item><item><title>一个简单的RMI入门例程(转贴)</title><link>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!427.entry</link><description>&lt;div&gt;
&lt;p&gt;前提，J2SDK安装， 本例使用的是1.4.2_07。
&lt;p&gt;RMI主要用在分布式应用中，一般情况下的使用是这样子，即业务逻辑在Server端的类中实现，而使用者即客户端则主要的调用Server提供的方法来得到结果。
&lt;p&gt;下面就写一下这个例子，主要实现的功能是打印个1+2=3的等式。
&lt;p&gt;哦，这儿要先想一下，即，对Client来讲，它需要知道Server提供了哪些东西，这个由一个接口来进行约束，即Server提供并实现了该接口里面的方法，而Client则参照该接口进行调用，就是这样一个思路。
&lt;p&gt;那么Client是如何得到这些方法的实现呢，这就要归功于RMI，在Server那边同时提供一个RMI端口监听程序，来接受Client的呼叫调用。RMI同时建立一个基本框架。
&lt;p&gt;这样一个思路应该比较明显，即建立一个Server程序放在RMI的框架中用于监听， 然后建立一个接口来约束基本方法的实现，Server对该接口进行了实现，Client则通过呼叫Server程序来调用该实现。
&lt;p&gt;好了，如上所示，先建立一个接口，因为这个其实才是应用的业务核心所在：
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;RMIInterface.java:&lt;/font&gt;
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;import java.rmi.*;&lt;br&gt;public interface RMIInterface extends Remote{ &lt;br&gt; // 实现一个加法&lt;br&gt; public int sum(int a, int b) throws RemoteException;&lt;br&gt;}&lt;/font&gt;
&lt;p&gt;然后对该接口实现：
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;RMIInterfaceImpl.java:&lt;/font&gt;
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;import java.rmi.*;&lt;br&gt;import java.rmi.server.*;&lt;br&gt;public class RMIInterfaceImpl extends UnicastRemoteObject implements RmiSample{ &lt;br&gt; public RMIInterfaceImpl () throws RemoteException{ super(); }&lt;br&gt; // 在这儿对该方法进行了实现&lt;br&gt; public int sum(int a, int b) throws RemoteException{ &lt;br&gt;  return a + b; &lt;br&gt;  }&lt;br&gt;}&lt;/font&gt;
&lt;p&gt;这样实现了以后，在Client那边才能得到想要的结果，下面建立RMIServer程序，如下：
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;RMIServer.java:&lt;/font&gt;
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;import java.rmi.*;&lt;br&gt;import java.rmi.registry.*;&lt;br&gt;public class RMIServer{ &lt;br&gt; public static void main(String[] args) { &lt;br&gt;  try{ &lt;br&gt;   LocateRegistry.createRegistry(8808); // 注册端口&lt;br&gt;   RMIInterfaceImpl server = new RMIInterfaceImpl();&lt;br&gt;   // Binding&lt;br&gt;   Naming.rebind(&amp;quot;//localhost:8808/RMI&amp;quot;, server); // 将实现类绑到一个名字上去&lt;br&gt;   }catch(java.net.MalformedURLException me){ &lt;br&gt;   System.out.println(&amp;quot;Malformed URL:&amp;quot; + me.toString());&lt;br&gt;   }catch(RemoteException e){ &lt;br&gt;   System.out.println(&amp;quot;Remote Exception:&amp;quot; + e.toString());&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt;}&lt;/font&gt;
&lt;p&gt;这样Server端的相差程序已经建立OK啦，下面就建立Client那边的程序，其实就是一个调用，到某个地址那里去找RMI的监听，然后取得对象，来调用得到结果：
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;RMIClient.java:&lt;/font&gt;
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;import java.rmi.*;&lt;br&gt;import java.rmi.server.*;&lt;br&gt;public class RMIClient { &lt;br&gt; public static void main(String[] args){ &lt;br&gt;  try { &lt;br&gt;   String url = &amp;quot;//190.0.0.112:8808/SAMPLE-SERVER&amp;quot;;&lt;br&gt;   RMIInterface RMIObject = (RMIInterface)Naming.lookup(url); // 寻得对象&lt;br&gt;   System.out.println(&amp;quot; 1 + 2 = &amp;quot; + RMIObject.sum(1,2) );&lt;br&gt;   } catch (RemoteException exc) { &lt;br&gt;   System.out.println(&amp;quot;Lookup error: &amp;quot; + exc.toString());&lt;br&gt;   } catch (java.net.MalformedURLException ex) { &lt;br&gt;   System.out.println(&amp;quot;Malformed URL: &amp;quot; + ex.toString());&lt;br&gt;   } catch (java.rmi.NotBoundException e) { &lt;br&gt;   System.out.println(&amp;quot;Not Bound: &amp;quot; + e.toString());&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt;}&lt;/font&gt;
&lt;p&gt;这里可能会有一个问题，就是对于这一句不免会有一点想法：
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt; RMIInterface RMIObject = (RMIInterface)Naming.lookup(url); // 寻得对象&lt;/font&gt;
&lt;p&gt;嘿嘿，这个嘛，偶目前也有点不清楚，怎么用接口来取得对象。
&lt;p&gt;好了，程序已经编完啦，只有四个类，下面编译，在本例中，四个类都放在缺省包下，编写一个用于编译的批处理文件，和这四个JAVA文件放在一起，至于这个并不重要，只是因为懒一点，所以写了，省得每次打那么多字：
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;Compile.bat:&lt;/font&gt;
&lt;blockquote dir=ltr&gt;
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;javac *.java&lt;br&gt;rmic -d . RMIInterfaceImpl&lt;/font&gt;&lt;/blockquote&gt;
&lt;p&gt;编译完成后会出现六个类，这是怎么回事儿吶，原来多了两个类：
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt; RMIInterfaceImpl_Skel.class&lt;br&gt; RMIInterfaceImpl_Stub.class&lt;/font&gt;
&lt;p&gt;就是RMI的框架需要的类啦，不过在这里，Client只需要stub类就行了，别问我为什么，不知道，哈哈。
&lt;p&gt;好了，下面就是分成两组，这儿可能.NET的兄弟又在说J2EE就是麻烦，呵呵，这是最无聊且没营养的一种说法，技术本身没有绝对的优劣，只有适合不适合于应用。
&lt;p&gt;这六个类文件，其中Client端需要三个：&lt;br&gt;&lt;font face="courier new,courier,monospace"&gt; RMIInterface.class&lt;br&gt; RMIClient.class&lt;br&gt; RMIInterfaceImpl_Stub.class&lt;/font&gt;
&lt;p&gt;服务端则需要五个文件：&lt;br&gt;&lt;font face="courier new,courier,monospace"&gt; RMIInterface.class&lt;br&gt; RMIInterfaceImpl.class&lt;br&gt; RMIServer.class&lt;br&gt; RMIInterfaceImpl_Skel.class&lt;br&gt; RMIInterfaceImpl_Stub.class&lt;/font&gt;
&lt;p&gt;这儿可能再建立两个文件夹来分别copy一下，分成server和client应该比较容易理解和发布吧，呵呵，这个动作完全可以随手写个程序来完成的，由于偶没什么大的应用，所以就懒得写啦。
&lt;p&gt;该动作的程序思路应该是这样子，即生成接口，在编译接口的时候，C和S各一份，然后做实现和Server程序，扔S那里去，而做Client调用程序的时候则扔C那里去，在用RMIC对实现建立框架的时候，则C和S也各一份，如此，就形成服务端和客户端分开的情况了。
&lt;p&gt;当然Server的监听程序和Client的调用程序自动生成的东西比较多，嘿嘿
&lt;p&gt;好了，对每个目录进行打包：&lt;br&gt;&lt;font face="courier new,courier,monospace"&gt; /server&lt;br&gt; Jar cvf server.jar *.class&lt;/font&gt;
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt; /client&lt;br&gt; Jar cvf server.jar *.class&lt;/font&gt;
&lt;p&gt;这儿其实可以不用打包，直接来用，不这不利于发布，也就写一下吧。&lt;br&gt;在生成server.jar和client.jar后，就可以进行“分布式”应用啦，哈哈，分布式其实挺简单的，就是在不同的机器单元上协同起来做同一件事情嘛。&lt;br&gt;分别为Server和Client写一个批处理，该例中，批处理和相应的jar文件是放在一起的：&lt;br&gt;&lt;font face="courier new,courier,monospace"&gt; Server.bat:&lt;br&gt; java -classpath &amp;quot;server.jar&amp;quot; RMIServer&lt;/font&gt;
&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt; Client.bat:&lt;br&gt; java -classpath &amp;quot;client.jar&amp;quot; RMIClient&lt;/font&gt;
&lt;p&gt;OK，先运行server.bat，然后运行N次client.bat，不过每次的结果都是一样的，呵呵&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-508484562895931526&amp;page=RSS%3a+%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84RMI%e5%85%a5%e9%97%a8%e4%be%8b%e7%a8%8b(%e8%bd%ac%e8%b4%b4)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=tangl99.spaces.live.com&amp;amp;GT1=tangl99"&gt;</description><comments>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!427.entry#comment</comments><guid isPermaLink="true">http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!427.entry</guid><pubDate>Wed, 12 Jul 2006 11:51:09 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://tangl99.spaces.live.com/blog/cns!F8F17FFBEED1777A!427/comments/feed.rss</wfw:commentRss><wfw:comment>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!427.entry#comment</wfw:comment><dcterms:modified>2006-07-12T11:51:09Z</dcterms:modified></item><item><title>自己写的一个JSP上传文件和下载文件的JavaBean</title><link>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!205.entry</link><description>&lt;div&gt;这个周末终于可以好好锻炼一下我的IBM ThinkPad T43了。今天看了一些关于JSP，Servlet方面的资料，写了简单的两个JavaBean。一个是UpLoad,一个是DownLoad。写得很简单，没有使用其它任何组件，自己做的。大家可以来看看。 
&lt;h2&gt;1.RunningUpLoader上传Bean&lt;/h2&gt;
&lt;p&gt;  首先是RunningUpLoader.java，代码有些多，因为我是自己来解析输入流的。
&lt;p&gt;package testupload;&lt;br&gt;import java.io.*;&lt;br&gt;import javax.servlet.http.HttpServletRequest;
&lt;p&gt;&lt;br&gt;public class RunningUpLoader {&lt;br&gt;    public RunningUpLoader() {&lt;br&gt;    }
&lt;p&gt;    /**&lt;br&gt;     * 上传文件&lt;br&gt;     * @param request HttpServletRequest Servlet的请求对象&lt;br&gt;     * @param name String 要上传的文件在表单中的参数名&lt;br&gt;     * @param fileName String 保存在服务器上的文件名&lt;br&gt;     * @throws IOException&lt;br&gt;     */&lt;br&gt;    public void doUpload(HttpServletRequest request, String name,String fileName) throws&lt;br&gt;            IOException {&lt;br&gt;        InputStream in = request.getInputStream();&lt;br&gt;        byte[] buffer = getFileContent(name,in);&lt;br&gt;        FileOutputStream fos = new FileOutputStream(fileName);&lt;br&gt;        fos.write(buffer,0,buffer.length-2);&lt;br&gt;        fos.close();&lt;br&gt;    }
&lt;p&gt;    /**&lt;br&gt;     * 获取上传的文件buffer,结尾处将多2个字节&lt;br&gt;     * @param name String 文件上传参数的名字&lt;br&gt;     * @param is InputStream 服务器对话的输入流&lt;br&gt;     * @return byte[] 返回获取的文件的buffer,结尾处将多2个字节&lt;br&gt;     * @throws IOException&lt;br&gt;     */&lt;br&gt;    private byte[] getFileContent(String name, InputStream is) throws IOException{&lt;br&gt;        int index;&lt;br&gt;        boolean isEnd = false;&lt;br&gt;        byte[] lineSeparatorByte;&lt;br&gt;        byte[] lineData;&lt;br&gt;        String content_disposition;&lt;br&gt;        ByteArrayOutputStream bos = new ByteArrayOutputStream();&lt;br&gt;        BufferedInputStream bis = new BufferedInputStream(is);
&lt;p&gt;        lineSeparatorByte = readStreamLine(bis);&lt;br&gt;        while(!isEnd) {&lt;br&gt;            lineData = readStreamLine(bis);&lt;br&gt;            if(lineData == null) {&lt;br&gt;                break;&lt;br&gt;            }&lt;br&gt;            content_disposition = new String(lineData,&amp;quot;ASCII&amp;quot;);&lt;br&gt;            index = content_disposition.indexOf(&amp;quot;name=\&amp;quot;&amp;quot; + name + &amp;quot;\&amp;quot;&amp;quot;);&lt;br&gt;            if (index &amp;gt;= 0 &amp;amp;&amp;amp; index &amp;lt; content_disposition.length()) {&lt;br&gt;                readStreamLineAsString(bis); // skip a line&lt;br&gt;                readStreamLineAsString(bis); // skip a line
&lt;p&gt;                while ((lineData = readStreamLine(bis)) != null) {&lt;br&gt;                    System.out.println(new String(lineData));&lt;br&gt;                    if (isByteArraystartWith(lineData, lineSeparatorByte)) { // end&lt;br&gt;                        isEnd = true;&lt;br&gt;                        break;&lt;br&gt;                    } else {&lt;br&gt;                        bos.write(lineData);&lt;br&gt;                    }&lt;br&gt;                }&lt;br&gt;            }else {&lt;br&gt;                lineData = readStreamLine(bis);&lt;br&gt;                if(lineData == null)&lt;br&gt;                    return null;&lt;br&gt;                while(!isByteArraystartWith(lineData, lineSeparatorByte)) {&lt;br&gt;                    lineData = readStreamLine(bis);&lt;br&gt;                    if(lineData == null)&lt;br&gt;                        return null;&lt;br&gt;                }&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;        return bos.toByteArray();&lt;br&gt;    }
&lt;p&gt;    private byte[] readStreamLine(BufferedInputStream in) throws IOException{&lt;br&gt;        ByteArrayOutputStream bos = new ByteArrayOutputStream();&lt;br&gt;        int b = in.read();&lt;br&gt;        if(b== -1)&lt;br&gt;            return null;&lt;br&gt;        while(b != -1) {&lt;br&gt;            bos.write(b);&lt;br&gt;            if(b == '\n') break;&lt;br&gt;            b = in.read();&lt;br&gt;        }&lt;br&gt;        return bos.toByteArray();&lt;br&gt;    }
&lt;p&gt;    private String readStreamLineAsString(BufferedInputStream in) throws IOException {&lt;br&gt;        return new String(readStreamLine(in),&amp;quot;ASCII&amp;quot;);&lt;br&gt;    }
&lt;p&gt;    private boolean isByteArraystartWith(byte[] arr,byte[] pat) {&lt;br&gt;        int i;&lt;br&gt;        if(arr == null || pat == null)&lt;br&gt;            return false;&lt;br&gt;        if(arr.length &amp;lt; pat.length)&lt;br&gt;            return false;&lt;br&gt;        for(i=0;i&amp;lt;pat.length;i++) {&lt;br&gt;            if(arr[i] != pat[i])&lt;br&gt;                return false;&lt;br&gt;        }&lt;br&gt;        return true;&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;
&lt;p&gt;上传文件文件的时候，需要在之前的html中增加一个form表单，里面需要有个&amp;lt;input type=&amp;quot;file&amp;quot; name=&amp;quot;fileUpload&amp;quot; &amp;gt;的输入按钮。这样，浏览器才会将要上传的文件递交给服务器。 其中name=&amp;quot;fileUpload&amp;quot;的名字，就是RunnningUpLoader.doUpload函数中的name参数。
&lt;p&gt;使用的时候直接用bean就OK了。比如upload.jsp如下：
&lt;p&gt;&amp;lt;jsp:useBean id=&amp;quot;upBean&amp;quot; scope=&amp;quot;page&amp;quot; class=&amp;quot;testupload.RunningUpLoader&amp;quot; /&amp;gt;
&lt;p&gt;&amp;lt;%
&lt;p&gt;upBean.doUpload(request,&amp;quot;fileupload&amp;quot;,&amp;quot;runningUpLoad.txt&amp;quot;);
&lt;p&gt;%&amp;gt;
&lt;p&gt; 
&lt;h2&gt;2. RunningDownLoader下载Bean&lt;/h2&gt;
&lt;p&gt;package testupload;&lt;br&gt;import java.io.*;&lt;br&gt;import javax.servlet.http.HttpServletResponse;&lt;br&gt;import java.net.URLEncoder;
&lt;p&gt;public class RunningDownLoader {&lt;br&gt;    public RunningDownLoader() {&lt;br&gt;    }
&lt;p&gt;    public void doDownload(HttpServletResponse response, String filePath,String fileName) throws&lt;br&gt;            IOException {&lt;br&gt;        response.reset();//可以加也可以不加&lt;br&gt;     response.setContentType(&amp;quot;application/x-download&amp;quot;);//设置为下载application/x-download&lt;br&gt;     System.out.println(this.getClass().getClassLoader().getResource(&amp;quot;/&amp;quot;).getPath());&lt;br&gt;     String filenamedownload = filePath;&lt;br&gt;     String filenamedisplay = fileName;//系统解决方案.txt&lt;br&gt;     filenamedisplay = URLEncoder.encode(filenamedisplay,&amp;quot;UTF-8&amp;quot;);&lt;br&gt;     response.addHeader(&amp;quot;Content-Disposition&amp;quot;,&amp;quot;attachment;filename=&amp;quot; + filenamedisplay);
&lt;p&gt;     OutputStream output = null;&lt;br&gt;     FileInputStream fis = null;&lt;br&gt;     try&lt;br&gt;     {&lt;br&gt;         output  = response.getOutputStream();&lt;br&gt;         fis = new FileInputStream(filenamedownload);
&lt;p&gt;         byte[] b = new byte[1024];&lt;br&gt;         int i = 0;
&lt;p&gt;         while((i = fis.read(b)) &amp;gt; 0)&lt;br&gt;         {&lt;br&gt;             output.write(b, 0, i);&lt;br&gt;         }&lt;br&gt;         output.flush();&lt;br&gt;     }&lt;br&gt;     catch(Exception e)&lt;br&gt;     {&lt;br&gt;         System.out.println(&amp;quot;Error!&amp;quot;);&lt;br&gt;         e.printStackTrace();&lt;br&gt;     }&lt;br&gt;     finally&lt;br&gt;     {&lt;br&gt;         if(fis != null)&lt;br&gt;         {&lt;br&gt;             fis.close();&lt;br&gt;             fis = null;&lt;br&gt;         }&lt;br&gt;         if(output != null)&lt;br&gt;         {&lt;br&gt;             output.close();&lt;br&gt;             output = null;&lt;br&gt;         }&lt;br&gt;     }
&lt;p&gt;    }
&lt;p&gt; 
&lt;p&gt;}&lt;br&gt; 
&lt;p&gt;  下载文件，最好是做到Servlet上。直接在Servlet的doGet下面增加如下代码即可
&lt;p&gt;//Process the HTTP Get request&lt;br&gt;    public void doGet(HttpServletRequest request, HttpServletResponse response) throws&lt;br&gt;            ServletException, IOException {&lt;br&gt;        RunningDownLoader downloader= new RunningDownLoader();&lt;br&gt;        downloader.doDownload(response,&amp;quot;E:\\MyProjects\\testupload.rar&amp;quot;,&amp;quot;upload.bin&amp;quot;);&lt;br&gt;    }&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-508484562895931526&amp;page=RSS%3a+%e8%87%aa%e5%b7%b1%e5%86%99%e7%9a%84%e4%b8%80%e4%b8%aaJSP%e4%b8%8a%e4%bc%a0%e6%96%87%e4%bb%b6%e5%92%8c%e4%b8%8b%e8%bd%bd%e6%96%87%e4%bb%b6%e7%9a%84JavaBean&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=tangl99.spaces.live.com&amp;amp;GT1=tangl99"&gt;</description><comments>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!205.entry#comment</comments><guid isPermaLink="true">http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!205.entry</guid><pubDate>Sun, 16 Apr 2006 13:21:32 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://tangl99.spaces.live.com/blog/cns!F8F17FFBEED1777A!205/comments/feed.rss</wfw:commentRss><wfw:comment>http://tangl99.spaces.live.com/Blog/cns!F8F17FFBEED1777A!205.entry#comment</wfw:comment><dcterms:modified>2006-04-16T14:27:42Z</dcterms:modified></item></channel></rss>