﻿<?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-风之语-随笔分类-收藏</title><link>http://www.blogjava.net/gf7/category/3534.html</link><description>&lt;a href="http://www.keepc.com/voip/?t=1&amp;id=6125" target="_blank"&gt;&lt;img src="http://union.keepc.com/templates/default/images/1/950X90.gif" alt="KC网络电话，中国最优秀的网络电话" width="950" height="90" border="0"&gt;&lt;/a&gt;</description><language>zh-cn</language><lastBuildDate>Tue, 23 Aug 2011 13:35:50 GMT</lastBuildDate><pubDate>Tue, 23 Aug 2011 13:35:50 GMT</pubDate><ttl>60</ttl><item><title>LoginAny 使用笔记</title><link>http://www.blogjava.net/gf7/archive/2011/08/22/357077.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Mon, 22 Aug 2011 14:52:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2011/08/22/357077.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/357077.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2011/08/22/357077.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/357077.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/357077.html</trackback:ping><description><![CDATA[<div id="msgcns!5EE1383181C65478!187" class="bvMsg">
<p><strong>LoginAny 使用笔记</strong><br />&nbsp;<br />想实现在家办公,当公司有急事的时候，可以在家就处理掉；不必在家里和公司之间copy文件，免去劳苦奔波之苦。于是开始用远程软件。<br />&nbsp;<br />1. VNN. 免费，主要面向游戏平台。<br />申请2个用户，互相加为密友，能够2台机器互访，但是只有vnnc302201-winall.zip版本能用(密友功能)，且不能升级，一旦升级之后，将没有了密友功能。<br />用了一段时间，很不错。但不久之后，本地域内3389端口封了。理解，因为远程桌面的3389是个不安全的端口。 </p>
<p>其实，把被控机器的Terminal Service 3389端口改掉, 理论上也是可行的，但是还是比较麻烦。<br />&nbsp;<br />2. Hamachi,&nbsp; 很好用的的软件。推荐，IP局域网穿透。 3389端口还是不能连接，道理同上。<br />&nbsp;<br />3. 改用LoginAny. 免费版每月只能远程桌面20分钟，文件传输3次。速度超快。 远程桌面是LoginAny开发的，所以不再用3389端口。 </p>
<p>自己研究下能否逆向工程下&#8230; </p>
<p><strong>&#8212;&#8212;&#8212;先看文件传输功能&#8212;&#8212;&#8212;&#8211;</strong><br />打开eXeScope分析资源，首先查看文字:"文件传输已经达到最大使用次数!",String Id: 484<br />得知Dialog: 1218是提示对话框， Dialog: 1219是文件传输Form. </p>
<p>打开OllyICE,反编译后，<br />- 搜索4C2(1218), 找提示对话框的代码，自己标注附近的代码，这是一个功能函数。<br />搜索4C3(1219), 找文件传输Form相关代码。<br />搜索1E4(484)， 找"文件传输已经达到最大使用次数!"的相关代码。<br />004938D0&nbsp; /$&nbsp; 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ebp<br />004938D1&nbsp; |.&nbsp; 8BEC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ebp, esp<br />004938D3&nbsp; |.&nbsp; 6A FF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; -1<br />004938D5&nbsp; |.&nbsp; 68 87C25B00&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 005BC287&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; SE 处理程序安装<br />004938DA&nbsp; |.&nbsp; 64:A1 0000000&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr fs:[0]<br />004938E0&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />004938E1&nbsp; |.&nbsp; 64:8925 00000&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr fs:[0], esp<br />004938E8&nbsp; |.&nbsp; 81EC BC000000 sub&nbsp;&nbsp;&nbsp;&nbsp; esp, 0BC<br />004938EE&nbsp; |.&nbsp; A1 BCEB6200&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [62EBBC]<br />004938F3&nbsp; |.&nbsp; 33C5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; eax, ebp<br />004938F5&nbsp; |.&nbsp; 8945 EC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-14], eax<br />004938F8&nbsp; |.&nbsp; 898D 40FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-C0], ecx<br />004938FE&nbsp; |.&nbsp; C785 4CFFFFFF&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-B4], 1<br />00493908&nbsp; |.&nbsp; 6A 01&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 1<br />0049390A&nbsp; |.&nbsp; 8B85 4CFFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [ebp-B4]<br />00493910&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />00493911&nbsp; |.&nbsp; 8B8D 40FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C0]<br /><font color="#ff0000">00493917&nbsp; |.&nbsp; E8 D4EFFFFF&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 004928F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; 关键Call !!!!</font><br />0049391C&nbsp; |.&nbsp; 85C0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp; eax, eax<br />0049391E&nbsp; |.&nbsp; 75 05&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jnz&nbsp;&nbsp;&nbsp;&nbsp; short 00493925<br />00493920&nbsp; |.&nbsp; E9 F8000000&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; 00493A1D<br />00493925&nbsp; |&gt;&nbsp; C785 48FFFFFF&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-B8], 0<br />0049392F&nbsp; |.&nbsp; 8D4D F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-10]<br />00493932&nbsp; |.&nbsp; FF15 28B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#310_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C173199<br />00493938&nbsp; |.&nbsp; C745 FC 00000&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-4], 0<br />0049393F&nbsp; |.&nbsp; 6A 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0<br />00493941&nbsp; |.&nbsp; 8D8D 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-AC]<br />00493947&nbsp; |.&nbsp; E8 64D30800&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00520CB0<br />0049394C&nbsp; |.&nbsp; C645 FC 01&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 1<br />00493950&nbsp; |.&nbsp; 8B8D 4CFFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-B4]<br />00493956&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />00493957&nbsp; |.&nbsp; 68 DD000000&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0DD<br />0049395C&nbsp; |.&nbsp; 8D55 F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; edx, dword ptr [ebp-10]<br />0049395F&nbsp; |.&nbsp; 52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; edx<br />00493960&nbsp; |.&nbsp; 8D85 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [ebp-AC]<br />00493966&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />00493967&nbsp; |.&nbsp; 8D8D 48FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-B8]<br />0049396D&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />0049396E&nbsp; |.&nbsp; 8B8D 40FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C0]<br />00493974&nbsp; |.&nbsp; E8 A7190000&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00495320&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; MessageBox &#8230;.<br />00493979&nbsp; |.&nbsp; 85C0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp; eax, eax<br />0049397B&nbsp; |.&nbsp; 75 21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jnz&nbsp;&nbsp;&nbsp;&nbsp; short 0049399E<br />0049397D&nbsp; |.&nbsp; C645 FC 00&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 0<br />00493981&nbsp; |.&nbsp; 8D8D 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-AC]<br />00493987&nbsp; |.&nbsp; E8 24D40800&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00520DB0<br />0049398C&nbsp; |.&nbsp; C745 FC FFFFF&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-4], -1<br />00493993&nbsp; |.&nbsp; 8D4D F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-10]<br />00493996&nbsp; |.&nbsp; FF15 68B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#578_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C1771B1<br />0049399C&nbsp; |.&nbsp; EB 7F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; short 00493A1D<br />0049399E&nbsp; |&gt;&nbsp; 8B95 48FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; edx, dword ptr [ebp-B8]<br />004939A4&nbsp; |.&nbsp; 52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; edx<br />004939A5&nbsp; |.&nbsp; 68 2CF16200&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0062F12C<br />004939AA&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />004939AB&nbsp; |.&nbsp; 8BCC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, esp<br />004939AD&nbsp; |.&nbsp; 89A5 44FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-BC], esp<br />004939B3&nbsp; |.&nbsp; 8D45 F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [ebp-10]<br />004939B6&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />004939B7&nbsp; |.&nbsp; FF15 38B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#297_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C14E575<br />004939BD&nbsp; |.&nbsp; 8985 3CFFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-C4], eax<br />004939C3&nbsp; |.&nbsp; 8D8D 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-AC]<br />004939C9&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />004939CA&nbsp; |.&nbsp; B9 E4F26200&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, 0062F2E4<br />004939CF&nbsp; |.&nbsp; E8 ECDAFCFF&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 004614C0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; 调用打开文件传输Form<br />004939D4&nbsp; |.&nbsp; 8985 38FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-C8], eax<br />004939DA&nbsp; |.&nbsp; 8B95 38FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; edx, dword ptr [ebp-C8]<br />004939E0&nbsp; |.&nbsp; 8995 50FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-B0], edx<br />004939E6&nbsp; |.&nbsp; 6A 05&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 5<br />004939E8&nbsp; |.&nbsp; 8B8D 50FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-B0]<br />004939EE&nbsp; |.&nbsp; E8 6DCC1100&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; &lt;jmp.&amp;MFC71.#6090_CWnd::ShowWindow&gt;<br />004939F3&nbsp; |.&nbsp; 8B8D 50FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-B0]<br />004939F9&nbsp; |.&nbsp; E8 12D8FAFF&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00441210<br />004939FE&nbsp; |.&nbsp; C645 FC 00&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 0<br />00493A02&nbsp; |.&nbsp; 8D8D 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-AC]<br />00493A08&nbsp; |.&nbsp; E8 A3D30800&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00520DB0<br />00493A0D&nbsp; |.&nbsp; C745 FC FFFFF&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-4], -1<br />00493A14&nbsp; |.&nbsp; 8D4D F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-10]<br />00493A17&nbsp; |.&nbsp; FF15 68B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#578_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C1771B1<br />00493A1D&nbsp; |&gt;&nbsp; 8B4D F4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C]<br />00493A20&nbsp; |.&nbsp; 64:890D 00000&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr fs:[0], ecx<br />00493A27&nbsp; |.&nbsp; 8B4D EC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-14]<br />00493A2A&nbsp; |.&nbsp; 33CD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; ecx, ebp<br />00493A2C&nbsp; |.&nbsp; E8 5ADE1100&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 005B188B<br />00493A31&nbsp; |.&nbsp; 8BE5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; esp, ebp<br />00493A33&nbsp; |.&nbsp; 5D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp;&nbsp; ebp<br />00493A34&nbsp; \.&nbsp; C3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; retn<br />&nbsp;<br />在0049 3917发现关键Call.<br />决定修改其后的跳转，<br />00493920&nbsp; |.&nbsp; E9 F8000000&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; 00493A1D&nbsp; 这一行是跳过调用打开文件传输Form的代码。<br />把它改为：<br />00493920&nbsp; |.&nbsp; 90 90909090&nbsp;&nbsp; Nop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 什么也不做<br />经试验，文件传输功能可以超过3次的使用了。 </p>
<p>&nbsp; </p>
<p>&nbsp; </p>
<p><strong>&#8212;&#8212;&#8212;远程桌面的功能&#8212;&#8212;&#8212;-</strong> </p>
<p><strong></strong><br />远程桌面的功能只能连接20分钟。 解决办法还是老一套：<br />打开eXeScope分析资源，找到对话框：远程桌面,ID=1306. </p>
<p>打开OllyICE,搜索常量1306，很快定位下面代码： </p>
<p>00493670&nbsp; /$&nbsp; 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ebp<br />00493671&nbsp; |.&nbsp; 8BEC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ebp, esp<br />00493673&nbsp; |.&nbsp; 6A FF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; -1<br />00493675&nbsp; |.&nbsp; 68 69C25B00&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 005BC269&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; SE 处理程序安装<br />0049367A&nbsp; |.&nbsp; 64:A1 0000000&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr fs:[0]<br />00493680&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />00493681&nbsp; |.&nbsp; 64:8925 00000&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr fs:[0], esp<br />00493688&nbsp; |.&nbsp; 81EC D4000000 sub&nbsp;&nbsp;&nbsp;&nbsp; esp, 0D4<br />0049368E&nbsp; |.&nbsp; A1 BCEB6200&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [62EBBC]<br />00493693&nbsp; |.&nbsp; 33C5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; eax, ebp<br />00493695&nbsp; |.&nbsp; 8945 EC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-14], eax<br />00493698&nbsp; |.&nbsp; 898D 30FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-D0], ecx<br />0049369E&nbsp; |.&nbsp; C785 50FFFFFF&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-B0], 0<br />004936A8&nbsp; |.&nbsp; 6A 01&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 1<br />004936AA&nbsp; |.&nbsp; 8B85 50FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [ebp-B0]<br />004936B0&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />004936B1&nbsp; |.&nbsp; 8B8D 30FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-D0]<br /><font color="#ff0000">004936B7&nbsp; |.&nbsp; E8 34F2FFFF&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 004928F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; 关键Call&#8211;remote desk.</font><br />004936BC&nbsp; |.&nbsp; 85C0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp; eax, eax<br />004936BE&nbsp; |.&nbsp; 75 05&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jnz&nbsp;&nbsp;&nbsp;&nbsp; short 004936C5<br />004936C0&nbsp; |.&nbsp; E9 F0010000&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; 004938B5<br />004936C5&nbsp; |&gt;&nbsp; C785 4CFFFFFF&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-B4], 0<br />004936CF&nbsp; |.&nbsp; 6A 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0<br />004936D1&nbsp; |.&nbsp; 8D8D 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-AC]<br />004936D7&nbsp; |.&nbsp; E8 D4D50800&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00520CB0<br />004936DC&nbsp; |.&nbsp; C745 FC 00000&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-4], 0<br />004936E3&nbsp; |.&nbsp; 8D4D F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-10]<br />004936E6&nbsp; |.&nbsp; FF15 28B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#310_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C173199<br />004936EC&nbsp; |.&nbsp; C645 FC 01&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 1<br />004936F0&nbsp; |.&nbsp; 8B8D 50FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-B0]<br />004936F6&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />004936F7&nbsp; |.&nbsp; 68 19010000&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 119<br />004936FC&nbsp; |.&nbsp; 8D55 F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; edx, dword ptr [ebp-10]<br />004936FF&nbsp; |.&nbsp; 52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; edx<br />00493700&nbsp; |.&nbsp; 8D85 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [ebp-AC]<br />00493706&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />00493707&nbsp; |.&nbsp; 8D8D 4CFFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-B4]<br />0049370D&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />0049370E&nbsp; |.&nbsp; 8B8D 30FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-D0]<br />00493714&nbsp; |.&nbsp; E8 071C0000&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00495320&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; 消息处理<br />00493719&nbsp; |.&nbsp; 85C0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp; eax, eax<br />0049371B&nbsp; |.&nbsp; 75 24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jnz&nbsp;&nbsp;&nbsp;&nbsp; short 00493741<br />0049371D&nbsp; |.&nbsp; C645 FC 00&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 0<br />00493721&nbsp; |.&nbsp; 8D4D F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-10]<br />00493724&nbsp; |.&nbsp; FF15 68B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#578_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C1771B1<br />0049372A&nbsp; |.&nbsp; C745 FC FFFFF&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-4], -1<br />00493731&nbsp; |.&nbsp; 8D8D 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-AC]<br />00493737&nbsp; |.&nbsp; E8 74D60800&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00520DB0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; 字符处理<br />0049373C&nbsp; |.&nbsp; E9 74010000&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; 004938B5<br />00493741&nbsp; |&gt;&nbsp; 817D A4 01030&gt;cmp&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-5C], 90301<br />00493748&nbsp; |.&nbsp; 0F83 E8000000 jnb&nbsp;&nbsp;&nbsp;&nbsp; 00493836<br />0049374E&nbsp; |.&nbsp; 8B95 4CFFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; edx, dword ptr [ebp-B4]<br />00493754&nbsp; |.&nbsp; 52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; edx<br />00493755&nbsp; |.&nbsp; 6A 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0<br />00493757&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />00493758&nbsp; |.&nbsp; 8BCC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, esp<br />0049375A&nbsp; |.&nbsp; 89A5 38FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-C8], esp<br />00493760&nbsp; |.&nbsp; 8D45 F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [ebp-10]<br />00493763&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />00493764&nbsp; |.&nbsp; FF15 38B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#297_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C14E575<br />0049376A&nbsp; |.&nbsp; 8985 2CFFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-D4], eax<br />00493770&nbsp; |.&nbsp; 8D8D 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-AC]<br />00493776&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />00493777&nbsp; |.&nbsp; B9 E4F26200&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, 0062F2E4<br />0049377C&nbsp; |.&nbsp; E8 BFD7FCFF&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00460F40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; ???? XX new opeator<br />00493781&nbsp; |.&nbsp; 8985 28FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-D8], eax<br />00493787&nbsp; |.&nbsp; 8B95 28FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; edx, dword ptr [ebp-D8]<br />0049378D&nbsp; |.&nbsp; 8995 48FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-B8], edx<br />00493793&nbsp; |.&nbsp; 83BD 48FFFFFF&gt;cmp&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-B8], 0<br />0049379A&nbsp; |.&nbsp; 0F85 94000000 jnz&nbsp;&nbsp;&nbsp;&nbsp; 00493834<br />004937A0&nbsp; |.&nbsp; 8D8D 40FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C0]<br />004937A6&nbsp; |.&nbsp; FF15 28B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#310_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C173199<br />004937AC&nbsp; |.&nbsp; C645 FC 02&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 2<br />004937B0&nbsp; |.&nbsp; 8D8D 44FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-BC]<br />004937B6&nbsp; |.&nbsp; FF15 28B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#310_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C173199<br />004937BC&nbsp; |.&nbsp; C645 FC 03&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 3<br />004937C0&nbsp; |.&nbsp; FF15 90AA5C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;KERNEL32.GetLastError&gt;]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; [GetLastError<br />004937C6&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />004937C7&nbsp; |.&nbsp; 68 42010000&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 142<br />004937CC&nbsp; |.&nbsp; 8D85 44FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [ebp-BC]<br />004937D2&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />004937D3&nbsp; |.&nbsp; FF15 3CB95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#2321_ATL::CStringT&lt;char,StrTra&gt;;&nbsp; MFC71.7C18B260<br />004937D9&nbsp; |.&nbsp; 83C4 0C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; esp, 0C<br />004937DC&nbsp; |.&nbsp; 68 00E00000&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0E000<br />004937E1&nbsp; |.&nbsp; 8D8D 40FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C0]<br />004937E7&nbsp; |.&nbsp; FF15 2CB95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#4035_ATL::CStringT&lt;char,StrTra&gt;;&nbsp; MFC71.7C153789<br />004937ED&nbsp; |.&nbsp; 6A 40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 40<br />004937EF&nbsp; |.&nbsp; 8D8D 40FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C0]<br />004937F5&nbsp; |.&nbsp; FF15 30B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#876_ATL::CSimpleStringT&lt;char,1&gt;;&nbsp; MFC71.7C158BCD<br />004937FB&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />004937FC&nbsp; |.&nbsp; 8D8D 44FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-BC]<br />00493802&nbsp; |.&nbsp; FF15 30B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#876_ATL::CSimpleStringT&lt;char,1&gt;;&nbsp; MFC71.7C158BCD<br />00493808&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />00493809&nbsp; |.&nbsp; 8B8D 30FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-D0]<br />0049380F&nbsp; |.&nbsp; E8 5ECE1100&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; &lt;jmp.&amp;MFC71.#4104_CWnd::MessageBoxA&gt;<br />00493814&nbsp; |.&nbsp; C645 FC 02&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 2<br />00493818&nbsp; |.&nbsp; 8D8D 44FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-BC]<br />0049381E&nbsp; |.&nbsp; FF15 68B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#578_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C1771B1<br />00493824&nbsp; |.&nbsp; C645 FC 01&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 1<br />00493828&nbsp; |.&nbsp; 8D8D 40FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C0]<br />0049382E&nbsp; |.&nbsp; FF15 68B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#578_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C1771B1<br />00493834&nbsp; |&gt;&nbsp; EB 60&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; short 00493896&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<br />00493836&nbsp; |&gt;&nbsp; 8B8D 4CFFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-B4]<br />0049383C&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />0049383D&nbsp; |.&nbsp; 68 2CF16200&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 0062F12C<br />00493842&nbsp; |.&nbsp; 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ecx<br />00493843&nbsp; |.&nbsp; 8BCC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, esp<br />00493845&nbsp; |.&nbsp; 89A5 34FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-CC], esp<br />0049384B&nbsp; |.&nbsp; 8D55 F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; edx, dword ptr [ebp-10]<br />0049384E&nbsp; |.&nbsp; 52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; edx<br />0049384F&nbsp; |.&nbsp; FF15 38B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#297_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C14E575<br />00493855&nbsp; |.&nbsp; 8985 24FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-DC], eax<br />0049385B&nbsp; |.&nbsp; 8D85 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; eax, dword ptr [ebp-AC]<br />00493861&nbsp; |.&nbsp; 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; eax<br />00493862&nbsp; |.&nbsp; B9 E4F26200&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, 0062F2E4<br />00493867&nbsp; |.&nbsp; E8 74D9FCFF&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 004611E0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;&nbsp; 调用1：远程桌面的Form<br />0049386C&nbsp; |.&nbsp; 8985 20FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-E0], eax<br />00493872&nbsp; |.&nbsp; 8B8D 20FFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-E0]<br />00493878&nbsp; |.&nbsp; 898D 3CFFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-C4], ecx<br />0049387E&nbsp; |.&nbsp; 6A 05&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; 5<br />00493880&nbsp; |.&nbsp; 8B8D 3CFFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C4]<br />00493886&nbsp; |.&nbsp; E8 D5CD1100&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; &lt;jmp.&amp;MFC71.#6090_CWnd::ShowWindow&gt;<br />0049388B&nbsp; |.&nbsp; 8B8D 3CFFFFFF mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C4]<br />00493891&nbsp; |.&nbsp; E8 1A72F9FF&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 0042AAB0<br />00493896&nbsp; |&gt;&nbsp; C645 FC 00&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; byte ptr [ebp-4], 0<br />0049389A&nbsp; |.&nbsp; 8D4D F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-10]<br />0049389D&nbsp; |.&nbsp; FF15 68B95C00 call&nbsp;&nbsp;&nbsp; dword ptr [&lt;&amp;MFC71.#578_ATL::CStringT&lt;char,StrTrai&gt;;&nbsp; MFC71.7C1771B1<br />004938A3&nbsp; |.&nbsp; C745 FC FFFFF&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-4], -1<br />004938AA&nbsp; |.&nbsp; 8D8D 54FFFFFF lea&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-AC]<br />004938B0&nbsp; |.&nbsp; E8 FBD40800&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 00520DB0<br />004938B5&nbsp; |&gt;&nbsp; 8B4D F4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-C]<br />004938B8&nbsp; |.&nbsp; 64:890D 00000&gt;mov&nbsp;&nbsp;&nbsp;&nbsp; dword ptr fs:[0], ecx<br />004938BF&nbsp; |.&nbsp; 8B4D EC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, dword ptr [ebp-14]<br />004938C2&nbsp; |.&nbsp; 33CD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xor&nbsp;&nbsp;&nbsp;&nbsp; ecx, ebp<br />004938C4&nbsp; |.&nbsp; E8 C2DF1100&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 005B188B<br />004938C9&nbsp; |.&nbsp; 8BE5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; esp, ebp<br />004938CB&nbsp; |.&nbsp; 5D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp;&nbsp; ebp<br />004938CC&nbsp; \.&nbsp; C3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; retn </p>
<p>找到关键Call.<br />004936B7&nbsp; |.&nbsp; E8 34F2FFFF&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; 004928F0&nbsp;&nbsp;&nbsp; ;&nbsp; 关键Call&#8211;remote desk.</p>
<p>修改关键call之后的跳转：</p>
<p>004936C0&nbsp; |.&nbsp; E9 F0010000&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; 004938B5<br />修改为什么都不作。免得它影响后面的代码。<br />用9090909090 填充。 </p>
<p>经试验，远程桌面功能可以超过20分钟的使用了。 </p>
<p>实际摸索中还是走了不少弯路，总结经验为：在OllyDbg中，看过的弄明白的函数，要自己加上注释。 在看其他相关的代码的时候，极有可能就碰到了自己曾经注释过的代码，这样一下子就全通了。</p></div><img src ="http://www.blogjava.net/gf7/aggbug/357077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2011-08-22 22:52 <a href="http://www.blogjava.net/gf7/archive/2011/08/22/357077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>资源管理器搜索包含文字的文件找不到的解决方法</title><link>http://www.blogjava.net/gf7/archive/2010/11/04/337258.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Thu, 04 Nov 2010 12:24:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2010/11/04/337258.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/337258.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2010/11/04/337258.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/337258.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/337258.html</trackback:ping><description><![CDATA[<p>今天在修改一些网页代码时用资源管理器搜索包含文字时，明明有文件里包含了这些文字，但XP就是找不到，后来经过摸索找到以下解决方法。<br />
资源管理器的搜索功能，搜索包含某个字符的文件时，为&#8220;提高效率&#8221;，取消了对所有文件类型中字符的搜索支持，只有部分文件类型中的字符可以被搜索。<br />
</p>
解决办法：<br />
运行regedit，编辑注册表<br />
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ContentIndex<br />
右侧FilterFilesWithUnknownExtensions子键（REG_DEWORD类型）<br />
的键值改为1。
<img src ="http://www.blogjava.net/gf7/aggbug/337258.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2010-11-04 20:24 <a href="http://www.blogjava.net/gf7/archive/2010/11/04/337258.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>xp下删除windows7，无法删除windows7文件夹，无法删除windows7文件，双系统卸载，取得文件权限</title><link>http://www.blogjava.net/gf7/archive/2010/08/30/330277.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Mon, 30 Aug 2010 06:19:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2010/08/30/330277.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/330277.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2010/08/30/330277.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/330277.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/330277.html</trackback:ping><description><![CDATA[<p style="line-height: 19.2pt; text-indent: 20pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 10pt"><font size="3"><font face="宋体">一些网友在Xp下安装了Windows 7（适用于Vista/WS2008）双系统，试用一段时间之后，新鲜过了，就准备卸载掉Windows 7。下面我把我在xp-windows 7双系统中卸载windows 7的方法写下来与大家分享！其中第1-5步网上很多，恕不详述，本文重点讲述第6步，即xp-windows 7（适用于Vista/WS2008）双系统在卸载windows 7后删除xp系统主引导分区的残留文件的详细步骤（注：本方法也即取得对系统文件完全控制的方法）</font></font></span></p>
<p style="line-height: 19.2pt; text-indent: 20pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 10pt"><font size="3"><font face="宋体">启动电脑进入Xp系统后按以下步骤操作，</font></font></span></p>
<font size="3"><span style="font-size: 10pt">
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><font face="宋体"><span style="font-size: 12pt">1.</span><span style="font-size: 12pt">插入刻好的 Windows 7 安装光盘(或者用虚拟光驱加载Windows 7镜像)。</span></font></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><font face="宋体"><span style="font-size: 12pt">2.</span><span style="font-size: 12pt">依次单击&#8220;开始&#8221;按钮 、&#8220;所有程序&#8221;、&#8220;附件&#8221;，右键单击&#8220;命令提示符&#8221;，然后单击&#8220;用管理员帐户运行&#8221;。</span></font></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><font face="宋体"><span style="font-size: 12pt">3.</span><span style="font-size: 12pt">键入 X:"boot"bootsect.exe /nt52 all /force，然后按 Enter。注：X："代表你的光驱盘符，或者虚拟光驱盘符。</span></font></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 12pt"><font face="宋体">例如，如果 DVD 驱动器号是 F，则键入 F:"boot"bootsect.exe /nt52 ALL /force。</font></span></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><font face="宋体"><span style="font-size: 12pt">4.</span><span style="font-size: 12pt">弹出 Windows Vista 安装光盘。</span></font></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><font face="宋体"><span style="font-size: 12pt">5.</span><span style="font-size: 12pt">重新启动计算机。</span></font></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 12pt"><font face="宋体">计算机将使用已安装的以前版本的 Windows 启动。Windows 7系统的启动项不见了，Early　Version windows也不见了，只剩下Windows xp的启动项了，基本成功。</font></span></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><font face="宋体"><span style="font-size: 12pt">6</span><span style="font-size: 12pt">、删除在启动盘中的：</span></font></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 12pt"><font face="宋体">　　*Boot 文件夹</font></span></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 12pt"><font face="宋体">　　*Boot.BAK </font></span></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 12pt"><font face="宋体">　　*bootmgr</font></span></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 12pt"><font face="宋体">　　*BOOTSECT.BAK </font></span></p>
<p style="line-height: 19.2pt; text-indent: 24pt; margin: 0cm 0cm 0pt" class="MsoNormal"><font face="宋体"><span style="font-size: 12pt">7</span><span style="font-size: 12pt">、格式化windows 7所在的分区，或者修改权限后删除Vista的文件夹。</span></font></p>
<p style="line-height: 19.2pt; text-indent: 20pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 10pt"><font size="3" face="宋体">下面详述第6步即取得对系统文件（夹）完全控制权限的方法：</font><br />
<font size="3" face="宋体">&nbsp;&nbsp;&nbsp; </font><font size="3" face="宋体">新的Vista/WS2008/Win 7系统启动与XP等之前系统已经有了很大改变，用一个启动引导程序代替了以前单一的boot.ini文件。删除系统之后，在C盘XP系统分区留下了Boot 文件夹、Boot.BAK、bootmgr和BOOTSECT.BAK一个文件夹，三个文件。其中boot.bak和bootsect.bak很容易删除，剩下的boot文件夹和bootmgr文件删除时，却会提示出错信息。查看了文件和文件夹权限，发现已经被锁定，所以，思路就是通过修改文件夹权限使得当前用户可以正常删除文件。以下即为详细操作步骤：</font><br />
<font face="宋体"><font size="3">&nbsp;&nbsp;&nbsp; （1）</font></font><font size="3" face="宋体">、首先请用管理员帐户登录XP系统。</font><br />
<font face="宋体"><font size="3">&nbsp;&nbsp;&nbsp; （2）</font></font><font size="3" face="宋体">、进入我的电脑--工具--文件夹选项--查看，把&#8220;使用简单文件共享（推荐）&#8221;前面的勾去掉。这样，你才能进入属性里的&#8220;安全&#8221;选项卡，修改文件和文件夹权限。</font><br />
<font size="3" face="宋体">&nbsp;&nbsp;&nbsp; </font><font size="3" face="宋体">删除boot文件夹：</font><br />
<font face="宋体"><font size="3">&nbsp;&nbsp;&nbsp; （3）</font></font><font size="3" face="宋体">、右键点击boot文件夹--属性--安全--高级。此时，你所有的权限都无法编辑。</font><br />
<font face="宋体"><font size="3">&nbsp;&nbsp;&nbsp; （4）</font></font><font size="3" face="宋体">、在&#8220;所有者&#8221;选项卡中，先将文件夹的所有者移交给&#8220;Administrators&#8221;组，记得选择下面的&#8220;替换子容器及对象的所有者&#8221;。</font><br />
<font face="宋体"><font size="3">&nbsp;&nbsp;&nbsp; （5)</font></font><font size="3" face="宋体">、再打开&#8220;审核&#8221;选项卡，将&#8220;用在此显示的那些可以应用到子对象的项目替代所有子对象的审核项目&#8221;。点击&#8220;添加&#8221;按钮，在文本框内输入&#8220;administrators&#8221;，再点击右侧的&#8220;检查名称&#8221;，&#8220;确定&#8221;，进入审核项目权限设置，选择成功和失败都是&#8220;完全控制&#8221;，&#8220;应用&#8221;，退出boot文件夹属性。可能会有提示让你配置本地计算机策略，不用管它。</font><br />
<font face="宋体"><font size="3">&nbsp;&nbsp;&nbsp; (6）</font></font><font size="3" face="宋体">、再次进入boot文件夹属性--安全，你会发现对于当前管理员帐户，你已经可以选择对该文件夹的控制权限了，当然选择允许&#8220;完全控制&#8221;。另外，你在&#8220;组或用户名称&#8221;这里还会发现类似S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464这样的用户，这应该就是原来的vista/ws2008/win7的用户。</font><br />
<font face="宋体"><font size="3">&nbsp;&nbsp;&nbsp; （7）</font></font><font size="3" face="宋体">、还没完，你还需要再次进入高级--权限选项卡，对于&#8220;Administrators&#8221;用户组，将下面的两个选项都勾上，目的是将对boot文件夹的权限设置，被所有子文件和文件夹所继承（原来其子文件夹和文件并没有完全继承）。确定，退出。</font><br />
<font size="3" face="宋体">好了，这回，你终于可以把boot文件夹删除了！</font><br />
<font size="3" face="宋体">&nbsp;&nbsp;&nbsp; </font><font face="宋体"><font size="3">由于操作过程中没想到贴图，只有全部操作完成之后，boot文件夹权限相关信息：</font></font></span></p>
<span style="font-size: 10pt"><font face="宋体">
<p align="center"><img border="0" src="http://images.cnblogs.com/cnblogs_com/feichangcai/boot文件夹属性.jpg" width="367" height="450"  alt="" /></p>
<p align="center"><font face="Verdana">图1 Boot文件夹属性</font></p>
<p align="center"><img border="0" src="http://images.cnblogs.com/cnblogs_com/feichangcai/权限.jpg" width="554" height="445"  alt="" /></p>
<p align="center"><font face="Verdana">图2 Boot文件夹权限选项卡</font></p>
<p align="center"><font face="Verdana"><img border="0" src="http://images.cnblogs.com/cnblogs_com/feichangcai/审核.jpg" width="552" height="443"  alt="" /></font></p>
<p align="center"><font face="Verdana">图3 Boot文件夹审核选项卡</font></p>
<p align="center"><font face="Verdana"><img border="0" src="http://images.cnblogs.com/cnblogs_com/feichangcai/所有者.jpg" width="553" height="444"  alt="" /></font></p>
<p align="center"><font face="Verdana">图4 Boot文件夹所有者选项卡</font></p>
<p style="line-height: 19.2pt; text-indent: 20pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 10pt"><font face="宋体"><font size="3"><span style="font-size: 10pt"><font face="宋体"><font size="3">删除bootmgr文件：</font></font></span></font></font></span></p>
<p style="line-height: 19.2pt; text-indent: 20pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 10pt"><font face="宋体"><font size="3">只需要做删除boot文件夹的（3）、（4）、（5）、（6）步即可，而且由于只有单个文件，简单很多，不再赘述。</font></font></span></p>
<p style="line-height: 19.2pt; text-indent: 20pt; margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-size: 10pt"><font size="3" face="宋体">总结：其实对于多分区中安装多系统来说，经常会遇到这样的情况。我在以前的本本上装XP和WS2003双系统，WS2003想要查看XP分区music中的音乐文件，也需要夺权，只是没有现在这么麻烦罢了。Anyway，简单来说，就那么几步：添加当前XP管理员用户至审核组以获得审核权限--&gt;夺取文件所有者权限--&gt;删除原所有者--&gt;完全控制，并应用到子文件和文件夹--&gt;删除！</font></span></p>
</font></span></span></font>
<img src ="http://www.blogjava.net/gf7/aggbug/330277.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2010-08-30 14:19 <a href="http://www.blogjava.net/gf7/archive/2010/08/30/330277.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用windows系统ftp命令编写的BAT文件上传[转] </title><link>http://www.blogjava.net/gf7/archive/2010/07/21/326690.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Tue, 20 Jul 2010 21:16:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2010/07/21/326690.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/326690.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2010/07/21/326690.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/326690.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/326690.html</trackback:ping><description><![CDATA[<div class="postTitle"><a id="ctl04_TitleUrl" class="postTitle2" href="http://www.cnblogs.com/MeChecksV/articles/1364243.html">利用windows系统ftp命令编写的BAT文件上传[转]</a> </div>
在开发中往往需要将本地的程序上传到服务器，而且用惯了linux命令的人来说。在windows下就比较麻烦了。为了方便特编写一个BAT程序来帮助需要这样功能的人。如果用其他IDE工具自带的FTP功能也可以，^_^！<br />
&nbsp;&nbsp;&nbsp;&nbsp; 命令： todev.bat /index.asp&nbsp; 默认d:\cnweb为网站的根目录。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 我的 <a href="http://www.lawcar.cn/">http://www.lawcar.cn/</a> <a href="http://www.myitcar.com/">http://www.myitcar.com/</a> <a href="http://www.stockcar.cn/">http://www.stockcar.cn/</a> <a href="http://www.lunwencar.com/">http://www.lunwencar.com/</a> 都是靠这样的方法维护。<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><span style="color: #000000">@</span><span style="color: #0000ff">IF</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">%1</span><span style="color: #000000">"</span><span style="color: #000000">==</span><span style="color: #000000">""</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;error_parm<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #0000ff">IF</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">%2</span><span style="color: #000000">"</span><span style="color: #000000">==</span><span style="color: #000000">""</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;error_parm<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@SETLOCAL<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #0000ff">set</span><span style="color: #000000">&nbsp;server</span><span style="color: #000000">=</span><span style="color: #000000">192.168</span><span style="color: #000000">.</span><span style="color: #000000">10.199</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #0000ff">set</span><span style="color: #000000">&nbsp;username</span><span style="color: #000000">=</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #0000ff">set</span><span style="color: #000000">&nbsp;password</span><span style="color: #000000">=</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;是否上传&nbsp;d:</span><span style="color: #000000">\</span><span style="color: #000000">cnweb</span><span style="color: #000000">\</span><span style="color: #000000">%</span><span style="color: #000000">1</span><span style="color: #000000">\</span><span style="color: #000000">%</span><span style="color: #000000">2</span><span style="color: #000000">&nbsp;到dev服务器!<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;off<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />CHOICE&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">C&nbsp;YN&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">M&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">确认请按&nbsp;Y，否请按N退出</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;errorlevel&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;no<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;errorlevel&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;no<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;errorlevel&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;yes&nbsp;<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />:no<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;</span><span style="color: #0000ff">on</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;没有任何文件上传到DEV.<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">end</span><span style="color: #000000">&nbsp;<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />:yes<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">IF</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">not</span><span style="color: #000000">&nbsp;EXIST&nbsp;d:</span><span style="color: #000000">\</span><span style="color: #000000">cnweb</span><span style="color: #000000">\</span><span style="color: #000000">%</span><span style="color: #000000">1</span><span style="color: #000000">\</span><span style="color: #000000">%</span><span style="color: #000000">2</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;error2<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;open&nbsp;%server%&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;user&nbsp;%username%&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;%password%&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;cd&nbsp;%</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;bye</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />ftp&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">s:ftp.txt&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">n&nbsp;|&nbsp;find&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">550</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">not</span><span style="color: #000000">&nbsp;errorlevel&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;@</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">error</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #008000">rem</span><span style="color: #008000">&nbsp;del&nbsp;ftp.txt&nbsp;ftperror.txt</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;open&nbsp;%server%&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;user&nbsp;%username%&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;%password%&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;cd&nbsp;%</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;put&nbsp;d:</span><span style="color: #000000">\</span><span style="color: #000000">cnweb</span><span style="color: #000000">\</span><span style="color: #000000">%</span><span style="color: #000000">1</span><span style="color: #000000">\</span><span style="color: #000000">%</span><span style="color: #000000">2</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />echo&nbsp;bye</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;ftp.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />ftp&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">s:ftp.txt&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">n&nbsp;|&nbsp;find&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Invalid</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">not</span><span style="color: #000000">&nbsp;errorlevel&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;@</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;error3<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #008000">rem</span><span style="color: #008000">&nbsp;del&nbsp;ftp.txt&nbsp;ftperror.txt</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;</span><span style="color: #0000ff">on</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;上传DEV完成.<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;putok&nbsp;<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />:</span><span style="color: #0000ff">error</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;服务器目录错误&nbsp;%</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #008000">rem</span><span style="color: #008000">&nbsp;del&nbsp;ftp.txt&nbsp;ftperror.txt</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #000000">@</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">end</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />:error2<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;本地目录错误&nbsp;d:</span><span style="color: #000000">\</span><span style="color: #000000">cnweb</span><span style="color: #000000">\</span><span style="color: #000000">%</span><span style="color: #000000">1</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@del&nbsp;ftp.txt&nbsp;ftperror.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">end</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />:error3<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;上传文件错误&nbsp;d:</span><span style="color: #000000">\</span><span style="color: #000000">cnweb</span><span style="color: #000000">\</span><span style="color: #000000">%</span><span style="color: #000000">1</span><span style="color: #000000">\</span><span style="color: #000000">%</span><span style="color: #000000">2</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />del&nbsp;ftp.txt&nbsp;ftperror.txt<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">end</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />:putok<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;上传成功&nbsp;%</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;%</span><span style="color: #000000">2</span><span style="color: #000000">&nbsp;！<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #008000">rem</span><span style="color: #008000">&nbsp;del&nbsp;ftp.txt&nbsp;ftperror.txt</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #000000">@</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">end</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />:error_parm<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;参数错误，正确格式:&nbsp;todev&nbsp;相对路径&nbsp;文件名<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@</span><span style="color: #0000ff">goto</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">end</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />:</span><span style="color: #0000ff">end</span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@echo&nbsp;Bye.<br />
<img alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" />@ENDLOCAL</span></div>
<div style="display: none" id="c_jquery_test"></div>
<script type="text/javascript">
if ($ != jQuery) {
	$ = jQuery.noConflict();
}
</script>
<img src ="http://www.blogjava.net/gf7/aggbug/326690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2010-07-21 05:16 <a href="http://www.blogjava.net/gf7/archive/2010/07/21/326690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jxl操作excel例子（转） </title><link>http://www.blogjava.net/gf7/archive/2009/05/18/271408.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Mon, 18 May 2009 14:15:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2009/05/18/271408.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/271408.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2009/05/18/271408.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/271408.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/271408.html</trackback:ping><description><![CDATA[<u>
<h2><a id="viewpost1_TitleUrl" href="http://www.blogjava.net/freeman1984/archive/2009/03/31/263180.html">jxl操作excel例子（转）</a> </h2>
<p>package com.dbs.vote.common.test.excel;</p>
<p>import java.io.File;&nbsp;&nbsp; <br />
import java.io.FileOutputStream;&nbsp;&nbsp; <br />
import java.io.OutputStream;&nbsp;&nbsp; <br />
import java.util.ArrayList;&nbsp;&nbsp; <br />
import java.util.Date;&nbsp;&nbsp; <br />
&nbsp; <br />
import jxl.Cell;&nbsp;&nbsp; <br />
import jxl.CellType;&nbsp;&nbsp; <br />
import jxl.Sheet;&nbsp;&nbsp; <br />
import jxl.Workbook;&nbsp;&nbsp; <br />
import jxl.WorkbookSettings;&nbsp;&nbsp; <br />
import jxl.format.Alignment;&nbsp;&nbsp; <br />
import jxl.format.Border;&nbsp;&nbsp; <br />
import jxl.format.BorderLineStyle;&nbsp;&nbsp; <br />
import jxl.format.Colour;&nbsp;&nbsp; <br />
import jxl.format.VerticalAlignment;&nbsp;&nbsp; <br />
import jxl.write.Formula;&nbsp;&nbsp; <br />
import jxl.write.Label;&nbsp;&nbsp; <br />
import jxl.write.NumberFormat;&nbsp;&nbsp; <br />
import jxl.write.WritableCellFeatures;&nbsp;&nbsp; <br />
import jxl.write.WritableCellFormat;&nbsp;&nbsp; <br />
import jxl.write.WritableFont;&nbsp;&nbsp; <br />
import jxl.write.WritableSheet;&nbsp;&nbsp; <br />
import jxl.write.WritableWorkbook;&nbsp;&nbsp; <br />
import jxl.write.WriteException;&nbsp;&nbsp; <br />
&nbsp; <br />
public class JExcelUtils {&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; * 生成Excel文件&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param path&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文件路径&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param sheetName&nbsp;&nbsp;&nbsp; 工作表名称&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param dataTitles&nbsp;&nbsp; 数据标题&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public void createExcelFile(String path,String sheetName,String[] dataTitles){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WritableWorkbook workbook;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OutputStream os=new FileOutputStream(path);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; workbook=Workbook.createWorkbook(os);&nbsp;&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WritableSheet sheet = workbook.createSheet(sheetName, 0); //添加第一个工作表&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initialSheetSetting(sheet);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Label label;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i=0; i&lt;dataTitles.length; i++){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Label(列号,行号,内容,风格)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label = new Label(i, 0, dataTitles[i],getTitleCellFormat());&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.addCell(label);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //插入一行&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertRowData(sheet,1,new String[]{"200201001","张三","100","60","100","260"},getDataCellFormat(CellType.STRING_FORMULA));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //一个一个插入行&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label = new Label(0, 2,"200201002",getDataCellFormat(CellType.STRING_FORMULA));&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.addCell(label);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label = new Label(1, 2,"李四",getDataCellFormat(CellType.STRING_FORMULA));&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.addCell(label);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertOneCellData(sheet,2,2,70.5,getDataCellFormat(CellType.NUMBER));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertOneCellData(sheet,3,2,90.523,getDataCellFormat(CellType.NUMBER));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertOneCellData(sheet,4,2,60.5,getDataCellFormat(CellType.NUMBER));&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertFormula(sheet,5,2,"C3+D3+E3",getDataCellFormat(CellType.NUMBER_FORMULA));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //插入日期&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mergeCellsAndInsertData(sheet, 0, 3, 5, 3, new Date(), getDataCellFormat(CellType.DATE));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; workbook.write();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; workbook.close();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp; * 初始化表格属性&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param sheet&nbsp; <br />
&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public void initialSheetSetting(WritableSheet sheet){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //sheet.getSettings().setProtected(true); //设置xls的保护，单元格为只读的&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.getSettings().setDefaultColumnWidth(10); //设置列的默认宽度&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //sheet.setRowView(2,false);//行高自动扩展&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //setRowView(int row, int height);--行高&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //setColumnView(int&nbsp; col,int width); --列宽&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.setColumnView(0,20);//设置第一列宽度&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp; * 插入公式&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param sheet&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param col&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param row&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param formula&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param format&nbsp; <br />
&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public void insertFormula(WritableSheet sheet,Integer col,Integer row,String formula,WritableCellFormat format){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Formula f = new Formula(col, row, formula, format);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.addCell(f);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp; * 插入一行数据&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param sheet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 工作表&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param row&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 行号&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param content&nbsp;&nbsp;&nbsp;&nbsp; 内容&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param format&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 风格&nbsp; <br />
&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public void insertRowData(WritableSheet sheet,Integer row,String[] dataArr,WritableCellFormat format){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Label label;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;dataArr.length;i++){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label = new Label(i,row,dataArr[i],format);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.addCell(label);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp; * 插入单元格数据&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param sheet&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param col&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param row&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param data&nbsp; <br />
&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public void insertOneCellData(WritableSheet sheet,Integer col,Integer row,Object data,WritableCellFormat format){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(data instanceof Double){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.write.Number&nbsp; labelNF = new jxl.write.Number(col,row,(Double)data,format);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.addCell(labelNF);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else if(data instanceof Boolean){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.write.Boolean labelB = new jxl.write.Boolean(col,row,(Boolean)data,format);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.addCell(labelB);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else if(data instanceof Date){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.write.DateTime labelDT = new jxl.write.DateTime(col,row,(Date)data,format);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.addCell(labelDT);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setCellComments(labelDT, "这是个创建表的日期说明！");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Label label = new Label(col,row,data.toString(),format);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.addCell(label);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp; * 合并单元格，并插入数据&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param sheet&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param col_start&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param row_start&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param col_end&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param row_end&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param data&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param format&nbsp; <br />
&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public void mergeCellsAndInsertData(WritableSheet sheet,Integer col_start,Integer row_start,Integer col_end,Integer row_end,Object data, WritableCellFormat format){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheet.mergeCells(col_start,row_start,col_end,row_end);//左上角到右下角&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertOneCellData(sheet, col_start, row_start, data, format);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp; * 给单元格加注释&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param label&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param comments&nbsp; <br />
&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public void setCellComments(Object label,String comments){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WritableCellFeatures cellFeatures = new WritableCellFeatures();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cellFeatures.setComment(comments);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(label instanceof jxl.write.Number){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.write.Number num = (jxl.write.Number)label;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; num.setCellFeatures(cellFeatures);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else if(label instanceof jxl.write.Boolean){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.write.Boolean bool = (jxl.write.Boolean)label;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool.setCellFeatures(cellFeatures);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else if(label instanceof jxl.write.DateTime){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.write.DateTime dt = (jxl.write.DateTime)label;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dt.setCellFeatures(cellFeatures);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Label _label = (Label)label;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _label.setCellFeatures(cellFeatures);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp; * 读取excel&nbsp; <br />
&nbsp;&nbsp; * @param inputFile&nbsp; <br />
&nbsp;&nbsp; * @param inputFileSheetIndex&nbsp; <br />
&nbsp;&nbsp; * @throws Exception&nbsp; <br />
&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public ArrayList&lt;String&gt; readDataFromExcel(File inputFile, int inputFileSheetIndex){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ArrayList&lt;String&gt; list = new ArrayList&lt;String&gt;();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Workbook book = null;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cell cell = null;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WorkbookSettings setting = new WorkbookSettings();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.util.Locale locale = new java.util.Locale("zh","CN");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setting.setLocale(locale);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setting.setEncoding("ISO-8859-1");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; book = Workbook.getWorkbook(inputFile, setting);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet sheet = book.getSheet(inputFileSheetIndex);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int rowIndex = 0; rowIndex &lt; sheet.getRows(); rowIndex++) {//行&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int colIndex = 0; colIndex &lt; sheet.getColumns(); colIndex++) {//列&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cell = sheet.getCell(colIndex, rowIndex);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //System.out.println(cell.getContents());&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(cell.getContents());&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; book.close();&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return list;&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp; * 得到数据表头格式&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @return&nbsp; <br />
&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public WritableCellFormat getTitleCellFormat(){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WritableCellFormat wcf = null;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //字体样式&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WritableFont wf = new WritableFont(WritableFont.TIMES,12, WritableFont.NO_BOLD,false);//最后一个为是否italic&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wf.setColour(Colour.RED);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf = new WritableCellFormat(wf);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //对齐方式&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setAlignment(Alignment.CENTRE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setVerticalAlignment(VerticalAlignment.CENTRE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //边框&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setBorder(Border.ALL,BorderLineStyle.THIN);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //背景色&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setBackground(Colour.GREY_25_PERCENT);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (WriteException e) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return wcf;&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp; * 得到数据格式&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @return&nbsp; <br />
&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public WritableCellFormat getDataCellFormat(CellType type){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WritableCellFormat wcf = null;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //字体样式&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(type == CellType.NUMBER || type == CellType.NUMBER_FORMULA){//数字&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NumberFormat nf = new NumberFormat("#.00");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf = new WritableCellFormat(nf);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else if(type == CellType.DATE || type == CellType.DATE_FORMULA){//日期&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.write.DateFormat df = new jxl.write.DateFormat("yyyy-MM-dd hh:mm:ss");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf = new jxl.write.WritableCellFormat(df);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WritableFont wf = new WritableFont(WritableFont.TIMES,10, WritableFont.NO_BOLD,false);//最后一个为是否italic&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf = new WritableCellFormat(wf);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //对齐方式&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setAlignment(Alignment.CENTRE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setVerticalAlignment(VerticalAlignment.CENTRE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //边框&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setBorder(Border.LEFT,BorderLineStyle.THIN);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setBorder(Border.BOTTOM,BorderLineStyle.THIN);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setBorder(Border.RIGHT,BorderLineStyle.THIN);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //背景色&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setBackground(Colour.WHITE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wcf.setWrap(true);//自动换行&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (WriteException e) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return wcf;&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp; * 打开文件看看&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param exePath&nbsp; <br />
&nbsp;&nbsp;&nbsp; * @param filePath&nbsp; <br />
&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp; public void openExcel(String exePath,String filePath){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Runtime r=Runtime.getRuntime();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String cmd[]={exePath,filePath};&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r.exec(cmd);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; public static void main(String[] args){&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String[] titles = {"学号","姓名","语文","数学","英语","总分"};&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JExcelUtils jxl = new JExcelUtils();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String filePath = "E:/test.xls";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.createExcelFile(filePath,"成绩单",titles);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.readDataFromExcel(new File(filePath),0);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jxl.openExcel("C:/Program Files/Microsoft Office/OFFICE11/EXCEL.EXE",filePath);&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp; <br />
}&nbsp; <br />
</p>
</u>
<img src ="http://www.blogjava.net/gf7/aggbug/271408.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2009-05-18 22:15 <a href="http://www.blogjava.net/gf7/archive/2009/05/18/271408.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>I18N-国际化消息和日志</title><link>http://www.blogjava.net/gf7/archive/2008/11/04/238649.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Tue, 04 Nov 2008 09:23:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2008/11/04/238649.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/238649.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2008/11/04/238649.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/238649.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/238649.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 对于许多软件开发者来说，一提到国际化(亦称为 i18n)支持就会感到害怕。 要使编写的代码能够面向外国使用者，确实需要费一翻思量，因为在现有软件的代码中添加国际化支持可不是一件轻而易举的事。 &nbsp;&nbsp;<a href='http://www.blogjava.net/gf7/archive/2008/11/04/238649.html'>阅读全文</a><img src ="http://www.blogjava.net/gf7/aggbug/238649.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2008-11-04 17:23 <a href="http://www.blogjava.net/gf7/archive/2008/11/04/238649.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 AppFuse 的七个理由</title><link>http://www.blogjava.net/gf7/archive/2008/06/15/208002.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sun, 15 Jun 2008 03:14:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2008/06/15/208002.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/208002.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2008/06/15/208002.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/208002.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/208002.html</trackback:ping><description><![CDATA[<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="100%">
            <h1>使用 AppFuse 的七个理由</h1>
            <p id="subtitle"><em>学习 Java 开放源码工具 —— 并使用这些工具提高生产效率</em></p>
            <img class="display-img" height="6" alt="" src="http://www.ibm.com/i/c.gif" width="1" /></td>
            <td class="no-print" width="192"><img height="18" alt="developerWorks" src="http://www.ibm.com/developerworks/i/dw.gif" width="192" /></td>
        </tr>
    </tbody>
</table>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td width="100%">
            <table class="no-print" cellspacing="0" cellpadding="0" width="160" align="right" border="0">
                <tbody>
                    <tr>
                        <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
                        <td>
                        <table cellspacing="0" cellpadding="0" width="150" border="0">
                            <tbody>
                                <tr>
                                    <td class="v14-header-1-small">文档选项</td>
                                </tr>
                            </tbody>
                        </table>
                        <table class="v14-gray-table-border" cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td class="no-padding" width="150">
                                    <table cellspacing="0" cellpadding="0" width="143" border="0">
                                        <img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" />
                                        <form name="email" action="https://www.ibm.com/developerworks/secure/email-it.jsp" cm1="1">
                                            <input type="hidden" value="开始学习在 Java 平台上使用诸如 Spring、Hibernate 或 MySQL 之类的开放源码工具时可能非常困难。再加上 Ant 或 Maven，以及与 DWR 一起的小 Ajax，还有 Web 框架 —— 即 JSF，我们必须睁大眼睛盯着如何配置应用程序。AppFuse 减少了集成开放源码项目的痛苦。它可以把测试变成一等公民，让我们可以从数据库表生成整个 UI，并使用 XFire 来支持 Web 服务。另外，AppFuse 的社区也非常健全，这是不同 Web 框架用户可以一起融洽相处的地方之一。" name="body" cM3 cm1="1" cm2="0" /><input type="hidden" value="使用 AppFuse 的七个理由" name="subject" cM3 cm1="1" cm2="1" /><input type="hidden" value="cn" name="lang" cM3 cm1="1" cm2="2" /> <script language="JavaScript" type="text/javascript">
<!-- document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt="" /></td><td width="16"><img src="//www.ibm.com/i/v14/icons/em.gif" height="16" width="16" vspace="3" alt="将此页作为电子邮件发送"  /></td><td width="122"><p><a class="smallplainlink" href="javascript:document.email.submit();"><strong>将此页作为电子邮件发送</strong></a></p></td></tr>');
//-->
</script>
                                            <tbody>
                                                <tr valign="top">
                                                    <td width="8"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" /></td>
                                                    <td width="16"><img height="16" alt="将此页作为电子邮件发送" src="http://www.ibm.com/i/v14/icons/em.gif" width="16" vspace="3" /></td>
                                                    <td width="122">
                                                    <p><a class="smallplainlink" href="javascript:document.email.submit();" cmimpressionsent="1"><strong>将此页作为电子邮件发送</strong></a></p>
                                                    </td>
                                                </tr>
                                                <noscript>
                                                <tr valign="top">
                                                    <td width="8"><img alt="" height="1" width="8" src="//www.ibm.com/i/c.gif"  /></td>
                                                    <td width="16"><img alt="" width="16" height="16" src="//www.ibm.com/i/c.gif"  /></td>
                                                    <td class="small" width="122">
                                                    <p><span class="ast">未显示需要 JavaScript 的文档选项</span></p>
                                                    </td>
                                                </tr>
                                                </noscript>
                                            </form>
                                        </tbody>
                                    </table>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas --><!--end RESERVED FOR FUTURE USE INCLUDE FILES--><br />
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>级别： 初级</p>
            <p><a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#author" cmimpressionsent="1">Matt Raible</a> (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#114;&#97;&#105;&#98;&#108;&#101;&#64;&#118;&#105;&#114;&#116;&#117;&#97;&#115;&#46;&#99;&#111;&#109;&#63;&#115;&#117;&#98;&#106;&#101;&#99;&#116;&#61;&#20351;&#29992;&#32;&#65;&#112;&#112;&#70;&#117;&#115;&#101;&#32;&#30340;&#19971;&#20010;&#29702;&#30001;&#38;&#97;&#109;&#112;&#59;&#99;&#99;&#61;&#106;&#97;&#108;&#111;&#105;&#64;&#117;&#115;&#46;&#105;&#98;&#109;&#46;&#99;&#111;&#109;" cmimpressionsent="1">mraible@virtuas.com</a>), 开放源码实践先驱, Virtuas Open Source Solutions<br />
            </p>
            <p>2006 年 8 月 31 日</p>
            <blockquote>开始学习在 Java&#8482; 平台上使用诸如 Spring、Hibernate 或 MySQL 之类的开放源码工具时可能非常困难。再加上 Ant 或 Maven，以及与 DWR 一起的小 Ajax，还有 Web 框架 —— 即 JSF，我们必须睁大眼睛盯着如何配置应用程序。AppFuse 减少了集成开放源码项目的痛苦。它可以把测试变成一等公民，让我们可以从数据库表生成整个 UI，并使用 XFire 来支持 Web 服务。另外，AppFuse 的社区也非常健全，这是不同 Web 框架用户可以一起融洽相处的地方之一。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
            <p>AppFuse 是一个开放源码的项目和应用程序，它使用了在 Java 平台上构建的开放源码工具来帮助我们快速而高效地开发 Web 应用程序。我最初开发它是为了减少在为客户构建新 Web 应用程序时所花费的那些不必要的时间。从核心上来说，AppFuse 是一个项目骨架，类似于通过向导创建新 Web 项目时 IDE 所创建的东西。当我们使用 AppFuse 创建一个项目时，它会提示我们将使用开放源码框架，然后才创建项目。它使用 Ant 来驱动测试、代码生成、编译和部署。它提供了目录和包结构，以及开发基于 Java 语言的 Web 应用程序所需要的库。</p>
            <p>与大部分 &#8220;new project&#8221; 向导不同，AppFuse 创建的项目从最开始就包含很多类和文件。这些文件用来实现特性，不过它们同时也会在您开发应用程序时被用作示例。通过使用 AppFuse 启动新项目，我们通常可以减少一到两周的开发时间。我们不用担心如何将开放源码框架配置在一起，因为这都已经完成了。我们的项目都已提前配置来与数据库进行交互，它会部署到应用服务器上，并对用户进行认证。我们不必实现安全特性，因为这都早已集成了。</p>
            <p>当我最初开发 AppFuse 时，它只支持 Struts 和 Hibernate。经过几年的努力，我发现了比 Struts 更好的 Web 框架，因此我还添加了为这些 Web 框架使用的选项。现在，AppFuse 可以支持 Hibernate 或 iBATIS 作为持久性框架。对于 Web 框架来说，我们可以使用 JavaServer Faces（JSF）、Spring MVC、Struts、Tapestry 或 WebWork。</p>
            <p>AppFuse 提供了很多应用程序需要的一些特性，包括：</p>
            <ul>
                <li>认证和授权
                <li>用户管理
                <li>Remember Me（这会保存您的登录信息，这样就不用每次都再进行登录了）
                <li>密码提醒
                <li>登记和注册
                <li>SSL 转换
                <li>E-mail
                <li>URL 重写
                <li>皮肤
                <li>页面修饰
                <li>模板化布局
                <li>文件上载 </li>
            </ul>
            <p>这种 &#8220;开箱即用&#8221; 的功能是 AppFuse 与其他 <em>CRUD 代</em> 框架的区别之一（CRUD 取自<em>创建、检索、更新</em> 和<em>删除</em> 几个操作的英文首字母），包括 Ruby on Rails、Trails 和 Grails。上面提到的这些框架，以及 AppFuse，都让我们可以从数据库表或现有的模型对象中生成主页/细节页。</p>
            <p>图 1 阐述了一个典型 AppFuse 应用程序的概念设计：</p>
            <br />
            <a name="fig1"><strong>图 1. 典型的 AppFuse 应用程序</strong></a><br />
            <img height="547" alt="典型的 AppFuse 应用程序" src="http://www.ibm.com/developerworks/cn/java/j-appfuse/appfuse_application.gif" width="572" /> <br />
            <p>清单 1 给出了我们在创建 <em>devworks</em> 项目时所使用的命令行交互操作，同时还给出了所生成的结果。这个项目使用了 WebWork 作为自己的 Web 框架（请参考下面 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a> 一节给出的链接）。</p>
            <br />
            <a name="listing1"><strong>清单 1. 使用 AppFuse 创建新项目</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">alotta:~/dev/appfuse mraible$ ant new
                        Buildfile: build.xml
                        clean:
                        [echo] Cleaning build and distribution directories
                        init:
                        new:
                        [echo]
                        [echo] +-------------------------------------------------------------+
                        [echo] |    -- Welcome to the AppFuse New Application Wizard! --     |
                        [echo] |                                                             |
                        [echo] | To create a new application, please answer the following    |
                        [echo] | questions.                                                  |
                        [echo] +-------------------------------------------------------------+
                        [input] What would you like to name your application [myapp]?
                        devworks
                        [input] What would you like to name your database [mydb]?
                        devworks
                        [input] What package name would you like to use [org.appfuse]?
                        com.ibm
                        [input] What web framework would you like to use [webwork,tapestry,spring,js
                        f,struts]?
                        webwork
                        [echo] Creating new application named 'devworks'...
                        [copy] Copying 359 files to /Users/mraible/Work/devworks
                        [copy] Copying 181 files to /Users/mraible/Work/devworks/extras
                        [copy] Copying 1 file to /Users/mraible/Work/devworks
                        [copy] Copying 1 file to /Users/mraible/Work/devworks
                        install:
                        [echo] Copying WebWork JARs to ../../lib
                        [copy] Copying 6 files to /Users/mraible/Work/devworks/lib
                        [echo] Adding WebWork entries to ../../lib.properties
                        [echo] Adding WebWork classpath entries
                        [echo] Removing Struts-specific JARs
                        [delete] Deleting directory /Users/mraible/Work/devworks/lib/struts-1.2.9
                        [delete] Deleting directory /Users/mraible/Work/devworks/lib/strutstest-2.1.3
                        [echo] Deleting struts_form.xdt for XDoclet
                        [delete] Deleting directory /Users/mraible/Work/devworks/metadata/templates
                        [echo] Deleting Struts merge-files in metadata/web
                        [delete] Deleting 7 files from /Users/mraible/Work/devworks/metadata/web
                        [echo] Deleting unused Tag Libraries and Utilities
                        [delete] Deleting 2 files from /Users/mraible/Work/devworks/src/web/org/appfu
                        se/webapp
                        [echo] Modifying appgen for WebWork
                        [copy] Copying 12 files to /Users/mraible/Work/devworks/extras/appgen
                        [echo] Replacing source and test files
                        [delete] Deleting directory /Users/mraible/Work/devworks/src/web/org/appfuse/
                        webapp/form
                        [delete] Deleting directory /Users/mraible/Work/devworks/src/web/org/appfuse/
                        webapp/action
                        [copy] Copying 13 files to /Users/mraible/Work/devworks/src
                        [delete] Deleting directory /Users/mraible/Work/devworks/test/web/org/appfuse
                        /webapp/form
                        [delete] Deleting directory /Users/mraible/Work/devworks/test/web/org/appfuse
                        /webapp/action
                        [copy] Copying 5 files to /Users/mraible/Work/devworks/test
                        [echo] Replacing web files (images, scripts, JSPs, etc.)
                        [delete] Deleting 1 files from /Users/mraible/Work/devworks/web/scripts
                        [copy] Copying 34 files to /Users/mraible/Work/devworks/web
                        [delete] Deleting: /Users/mraible/Work/devworks/web/WEB-INF/validator-rules-c
                        ustom.xml
                        [echo] Modifying Eclipse .classpath file
                        [echo] Refactoring build.xml
                        [echo] ----------------------------------------------
                        [echo] NOTE: It's recommended you delete extras/webwork as you shouldn't ne
                        ed it anymore.
                        [echo] ----------------------------------------------
                        [echo] Repackaging info written to rename.log
                        [echo]
                        [echo] +-------------------------------------------------------------+
                        [echo] |           -- Application created successfully! --           |
                        [echo] |                                                             |
                        [echo] | Now you should be able to cd to your application and run:   |
                        [echo] | &gt; ant setup test-all                                        |
                        [echo] +-------------------------------------------------------------+
                        BUILD SUCCESSFUL
                        Total time: 15 seconds</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
                <tbody>
                    <tr>
                        <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
                        <td>
                        <table cellspacing="0" cellpadding="5" width="100%" border="1">
                            <tbody>
                                <tr>
                                    <td bgcolor="#eeeeee"><a name="sidebar1"><strong>为什么使用 WebWork？</strong></a><br />
                                    Struts 社区最近在热情地拥抱 WebWork，这种结合导致为 Java 平台提供了一个非常优秀的新 Web 框架：Struts 2。当然，Spring MVC 是一个非常优秀的基于请求的框架，但是它不能像 Struts 2 一样支持 JSF。基于内容的框架（例如 JSF 和 Tapestry）也都很好，但是我发现 WebWork 更为直观，更容易使用（更多有关 Structs 2 和 JSF 的内容请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a>）。 </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>在创建一个新项目之后，我们就得到了一个类似于图 2 所示的目录结构。Eclipse 和 Intellij IDEA 项目文件都是作为这个过程的一部分创建的。</p>
            <br />
            <a name="fig2"><strong>图 2. 项目的目录结构</strong></a><br />
            <img height="366" alt="项目的目录结构" src="http://www.ibm.com/developerworks/cn/java/j-appfuse/project_directory_structure.jpg" width="173" /> <br />
            <p>这个目录结构与 Sun 为 Java 2 Platform Enterprise Edition（J2EE）Web 应用程序推荐的目录结构非常类似。在 2.0 版本的 AppFuse 中，这个结构会变化成适合 Apache Maven 项目的标准目录结构（有关这两个目录介绍的内容，请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a> 中的链接）。AppFuse 还会从 Ant 迁移到 Maven 2 上，从而获得相关下载的能力和对生成 IDE 项目文件的支持。目前基于 Ant 的系统要求提交者维护项目文件，而 Maven 2 可以通过简单地使用项目的 pom.xml 文件生成 IDEA、Eclipse 和 NetBeans 项目文件。（这个文件位于您项目的根目录中，是使用 Maven 构建应用程序所需要的主要组件）。它与利用 Ant 所使用的 build.xml 文件非常类似。）</p>
            <p>现在我们对 AppFuse 是什么已经有一点概念了，在本文剩下的部分中，我们将介绍使用 AppFuse 的 7 点理由。即使您选择不使用 AppFuse 来开始自己的项目，也会看到 AppFuse 可以为您提供很多样板代码，这些代码可以在基于 Java 语言的 Web 应用程序中使用。由于它是基于 Apache 许可证的，因此非常欢迎您在自己的应用程序中重用这些代码。</p>
            <p><a name="1"><span class="atitle">理由 1：测试</span></a></p>
            <p>测试是在软件开发项目中很少被给予足够信任的一个环节。注意我并不是说在软件开发的一些刊物中没有得到足够的信任！很多文章和案例研究都给出了测试优先的开发方式和足够的测试覆盖面以提高软件的质量。然而，测试通常都被看作是一件只会延长项目开发时间的事情。实际上，如果我们使用测试优先的方法在编写代码之前就开始撰写测试用例，我相信我们可以发现这实际上会<em>加速</em> 开发速度。另外，测试优先也可以使维护和重用<em>更加</em> 容易。如果我们不编写代码来测试自己的代码，那么就需要手工对应用程序进行测试 —— 这通常效率都不高。自动化才是关键。</p>
            <p>当我们首次开始使用 AppFuse 时，我们可能需要阅读这个项目 Web 站点上提供的快速入门指南和教程（请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a> 中的链接）。这些教程的编写就是为了您可以首先编写测试用例；它们直到编写接口和/或实现之后才能编译。如果您有些方面与我一样，就会在开始编写代码之前就已经编写好测试用例了；这是真正可以加速编写代码的惟一方式。如果您首先编写了代码的实现，通过某种方式验证它可以工作，那么您可能会对自己说，&#8220;哦，看起来不错 —— 谁需要测试呢？我还有更多的代码需要编写！&#8221;这种情况不幸的一面是您通常都会做<em>一些事情</em> 来测试自己的代码；您简单地跳过了可以自动化进行测试的地方。</p>
            <p>AppFuse 的文档展示了如何测试应用程序的<em>所有</em> 层次。它从数据库层开始入手，使用了 DbUnit（请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a>）在运行测试之前提前使用数据来填充自己的数据库。在数据访问（DAO）层，它使用了 Spring 的 <code>AbstractTransactionalDataSourceSpringContextTests</code> 类（是的，这的确是一个类的名字！）来允许简单地加载 Spring 上下文文件。另外，这个类对每个 <code>testXXX()</code> 方法封装了一个事务，并当测试方法存在时进行回滚。这种特性使得测试 DAO 逻辑变得非常简单，并且不会对数据库中的数据造成影响。</p>
            <p>在服务层，jMock （请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a>）用来编写那些可以消除 DAO 依赖的<em>真正</em> 单元测试。这允许进行验证业务逻辑正确的快速测试；我们不用担心底层的持久性逻辑。</p>
            <table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
                <tbody>
                    <tr>
                        <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
                        <td>
                        <table cellspacing="0" cellpadding="5" width="100%" border="1">
                            <tbody>
                                <tr>
                                    <td bgcolor="#eeeeee"><a name="sidebar2"><strong>HtmlUnit 支持</strong></a><br />
                                    HtmlUnit 团队在 1.8 发行版中已经完成了相当多的工作来确保包可以与流行的 Ajax 框架（Prototype 和 Scriptaculous）很好地工作。 </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>在 Web 层，测试会验证操作（Struts/WebWork）、控件（Spring MVC）、页面（Tapestry）和管理 bean（JSF）如我们所期望的一样进行工作。Spring 的 spring-mock.jar 可以非常有用地用来测试所有这些框架，因为它包含了一个 Servlet API 的仿真实现。如果没有这个有用的库，那么测试 AppFuse 的 Web 框架就会变得非常困难。</p>
            <p>UI 通常是开发 Web 应用程序过程中最为困难的一部分。它也是顾客最经常抱怨的地方 —— 这既是由于它并不是非常完美，也是由于它的工作方式与我们期望的并不一样。另外，没有什么会比在客户面前作演示的过程中看到看到异常堆栈更糟糕的了！您的应用程序可能会非常可怕，但是客户可能会要求您做到十分完美。永远不要让这种事情发生。Canoo WebTest 可以对 UI 进行测试。它使用了 HtmlUnit 来遍历测试 UI，验证所有的元素都存在，并可以填充表单的域，甚至可以验证一个假想的启用 Ajax 的 UI 与我们预期的工作方式一样。（有关 WebTest 和 HTMLUnit 的链接请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a>。）</p>
            <p>为了进一步简化 Web 的测试，Cargo（请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a>）对 Tomcat 的启动和停止（分别在运行 WebTest 测试之前和之后）进行了自动化。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="2"><span class="atitle">理由 2：集成</span></a></p>
            <p>正如我在本文简介中提到的一样，很多开放源码库都已经预先集成到 AppFuse 中了。它们可以分为以下几类： </p>
            <ul>
                <li><strong>编译、报告和代码生成：</strong>Ant、Ant Contrib Tasks、Checkstyle、EMMA、Java2Html、PMD 和 Rename Packages
                <li><strong>测试框架：</strong>DbUnit、Dumbster、jMock、JUnit 和 Canoo WebTest
                <li><strong>数据库驱动程序：</strong>MySQL 和 PostgreSQL
                <li><strong>持久性框架：</strong>Hibernate 和 iBATIS
                <li><strong>IoC 框架：</strong>Spring
                <li><strong>Web 框架：</strong>JSF、Spring MVC、Struts、Tapestry 和 WebWork
                <li><strong>Web 服务：</strong>XFire
                <li><strong>Web 工具：</strong>Clickstream、Display Tag、DWR、JSTL、SiteMesh、Struts Menu 和 URL Rewrite Filter
                <li><strong>Security：</strong>Acegi Security
                <li><strong>JavaScript 和 CSS：</strong>Scriptaculous、Prototype 和 Mike Stenhouse 的 CSS Framework </li>
            </ul>
            <p>除了这些库之外，AppFuse 还使用 Log4j 来记录日志，使用 Velocity 来构建 e-mail 和菜单模板。Tomcat 可以支持最新的开发，我们可以使用 1.4 或 5 版本的 Java 平台来编译或构建程序。我们应该可以将 AppFuse 部署到任何 J2EE 1.3 兼容的应用服务器上；这已经经过了测试，我们知道它在所有主要版本的 J2EE 服务器和所有主要的 servlet 容器上都可以很好地工作。</p>
            <p>图 3 给出了上面创建的 <em>devworks</em> 项目的 lib 目录。这个目录中的 lib.properties 文件控制了每个依赖性的版本号，这意味着我们可以简单地通过把这些包的新版本放到这个目录中并执行诸如 <code>ant test-all -Dspring.version=2.0</code> 之类的命令来测试这些包的新版本。</p>
            <br />
            <a name="fig3"><strong>图 3. 项目依赖性</strong></a><br />
            <img height="598" alt="AppFuse 项目依赖性" src="http://www.ibm.com/developerworks/cn/java/j-appfuse/project_lib_directory.jpg" width="197" /> <br />
            <p>预先集成这些开放源码库可以在项目之初极大地提高生产效率。尽管我们可以找到很多文档介绍如何集成这些库，但是定制工作示例并简单地使用它来开发应用程序要更加简单。</p>
            <p>除了可以简化 Web 应用程序的开发之外，AppFuse 让我们还可以将 Web 服务简单地集成到自己的项目中。尽管 XFire 也在 AppFuse 下载中一起提供了，不过如果我们希望，也可以自己集成 Apache Axis（请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a> 中有关 Axis 集成的教程）。另外，Spring 框架和 XFire 可以一起将服务层作为 Web 服务非常简单地呈现出来，这就为我们提供了开发面向服务架构的能力。</p>
            <p>另外，AppFuse 并不会将我们限定到任何特定的 API 上。它只是简单地对可用的最佳开放源码解决方案重新进行打包和预先集成。AppFuse 中的代码可以处理这种集成，并实现了 AppFuse 的基本安全性和可用性特性。只要可能，就会减少代码，以便向 AppFuse 的依赖框架添加一个特性。例如，AppFuse 自带的 Remember Me 和 SSL 切换特性最近就因为类似的特性而从 Acegi Security 中删除了。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="3"><span class="atitle">理由 3：自动化</span></a></p>
            <p>Ant 使得简化了从编译到构建再到部署的自动化过程。Ant 是 AppFuse 中的一等公民，这主要是因为我发现在命令行中执行操作比从 IDE 中更加简单。我们可以使用 Ant 实现编译、测试、部署和执行任何代码生成的任务。</p>
            <p>尽管这种能力对于有些人来说非常重要，但是它并不适用于所有的人。很多 AppFuse 用户目前都使用 Eclipse 或 Intellij IDEA 来构建和测试自己的项目。在这些 IDE 中运行 Ant 的确可以工作，但是这样做的效率通常都不如使用 IDE 内置的 JUnit 支持来运行测试效率高。</p>
            <p>幸运的是，AppFuse 支持在 IDE 中运行测试，不过管理这种特性对于 AppFuse 开发人员来说就变得非常困难了。最大的痛苦在于 XDoclet 用来生成 Hibernate 映射文件和 Web 框架所使用的一些工件（例如 ActionForms 和 Struts 使用的 struts-config.xml）。IDE 并不知道需要生成的代码，除非我们配置使用 Ant 来编译它们，或者安装了一些可以认识 XDoclet 的插件。</p>
            <p>这种对知识的缺乏是 AppFuse 2.0 切换到 JDK 5 和 Maven 2 上的主要原因。JDK 5、注释和 Struts 2 将让我们可以摆脱 XDoclet。Maven 2 将使用这些生成的文件和动态类路径来生成 IDE 项目文件，这样对项目的管理就可以进行简化。目前基于 Ant 的编译系统已经为不同的层次生成了一些工件（包括 dao.jar、service.jar 和 webapp.war），因此切换到 Maven 的模型上应该是一个非常自然的调整。</p>
            <p>除了 Ant 之外（它对于编译、测试、部署和报告具有丰富的支持），对于 CruiseControl 的支持也构建到了 AppFuse 中。CruiseControl 是一个 Continuous Integration 应用程序，让我们可以在源代码仓库中代码发生变化时自动运行所有的测试。extras/cruisecontrol 目录包含了我们为基于 AppFuse 的项目快速、简单地设置 Continuous Integration 时所需要的文件。</p>
            <p>设置 Continuous Integration 是软件开发周期中我们首先要做的事情之一。它不但激发程序员去编写测试用例，而且还通过 &#8220;You broke the build!&#8221; 游戏促进了团队之间的合作和融合。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="4"><span class="atitle">理由 4：安全特性和可扩展性</span></a></p>
            <p>AppFuse 最初是作为我为 Apress 编写的书籍 <em>Pro JSP</em> 中示例应用程序的一部分开发的。这个示例应用程序展示了很多安全特性和用于简化 Struts 开发的特性。这个应用程序中的很多安全特性在 J2EE 的安全框图中都不存在。使用容器管理认证（CMA）的认证方法非常简单，但是 Remember Me、密码提示、SSL 切换、登记和用户管理等功能却都不存在。另外，基于角色的保护方法功能在非 EJB 环境中也是不可能的。</p>
            <p>最初，AppFuse 使用自己的代码和用于 CMA 的解决方案完全实现了这些特性。我在 2004 年年初开始学习 Spring 时就听说过有关 Acegi Security 的知识。我对 Acegi 所需要的 XML 的行数（175）与 web.xml 中所需要的 CMA 的行数（20）进行了比较，很快就决定丢弃 Acegi 了，因为它太过复杂了。</p>
            <p>一年半之后 —— 在为另外一本书 <em>Spring Live</em> 中编写了一章有关使用 Acegi Security 的内容之后 —— 我就改变了自己的想法。Acegi <em>的确</em>（目前仍然）需要很多 XML，但是一旦我们理解了这一点，它实际上是相当简单的。当我们最终作出改变，使用 Acegi Security 的特性来全部取代 AppFuse 的特性之后，我们最终删除了大量的代码。类之上的类都已经没有了，&#8220;Acegi handles that now&#8221; 中消失的部分现在全部进入了 CVS 的 Attic 中了。</p>
            <p>Acegi Security 是 J2EE 安全模型中曾经出现过的最好模型。它让我们可以实现很多有用的特性，这些特性在 Servlet API 的安全模型中都不存在：认证、授权、角色保护方法、Remember Me、密码加密、SSL 切换、用户切换和注销。它让我们还可以将用户证书存储到 XML 文件、数据库、LDAP 或单点登录系统（例如 Yale 的 Central Authentication Service (CAS) 或者 SiteMinder）中。</p>
            <p>AppFuse 对很多与安全性相关的特性的实现从一开始都是非常优秀的。现在 AppFuse 使用了 Acegi Security，这些特性 —— 以及更多特性 —— 都非常容易实现。Acegi 有很多地方都可以进行扩充：这是它使用巨大的 XML 配置文件的原因。正如我们已经通过去年的课程对 Acegi 进行集成一样，我们已经发现对很多 bean 的定义进行定制可以更加紧密地与 AppFuse 建立联系。</p>
            <p>Spring IoC 容器和 Acegi Security 所提供的简单开发、容易测试的代码和松耦合特性的组合是 AppFuse 是这么好的一种开发平台的主要原因。这些框架都是不可插入的，允许生成干净的可测试代码。AppFuse 集成了很多开放源码项目，依赖注入允许对应用程序层进行简单的集成。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="5"><span class="atitle">理由 5：使用 AppGen 生成代码</span></a></p>
            <p>有些人会将代码生成称为<em>代码气味的散播（code smell）</em>。在他们的观点中，如果我们需要生成代码，那么很可能就会做一些错事。我倾向于这种确定自己代码使用的模式和自动化生成代码的能力应该称为<em>代码香味的弥漫（code perfume）</em>。如果我们正在编写类似的 DAO、管理器、操作或控件，并且不想为它们生成代码，那么这就需要根据代码的气味来生成代码。当然，当语言可以为我们提供可以简化任务的特性时，一切都是那么美好；不过代码生成通常都是一个必需 —— 通常其生产率也非常高 —— 的任务。</p>
            <p>AppFuse 中提供了一个基于 Ant 和 XDoclet 的代码生成工具，名叫 <em>AppGen</em>。默认情况下，常见的 DAO 和管理器都可以允许我们对任何普通老式 Java 对象（POJO）进行 CRUD 操作，但是在 Web 层上这样做有些困难。AppGen 有几个特性可以用来执行以下任务：</p>
            <ul>
                <li>（使用 Middlegen 和 Hibernate 工具）从数据库表中生成 POJO
                <li>从 POJO 生成 UI
                <li>为 DAO、管理器、操作/控制器和 UI 生成测试 </li>
            </ul>
            <p>在运行 AppGen 时，您会看到提示说 AppGen 要从数据库表或 POJO 中生成代码。如果在命令行中执行 <code>ant install-detailed</code>，AppGen 就会安装 POJO 特定的 DAO、管理器以及它们的测试。运行 <code>ant install</code> 会导致 Web 层的类重用通用的 DAO 和默认存在的管理器。</p>
            <p>为了阐述 AppGen 是如何工作的，我们在 <em>devworks</em> MySQL 数据库中创建了如清单 2 所示的表：</p>
            <br />
            <a name="listing2"><strong>清单 2. 创建一个名为 cat 的数据库表</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">    create table cat (
                        cat_id int(8) auto_increment,
                        color varchar(20) not null,
                        name varchar(20) not null,
                        created_date datetime not null,
                        primary key (cat_id)
                        ) type=InnoDB;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>在 extras/appgen 目录中，运行 <code>ant install-detailed</code>。这个命令的输出结果对于本文来说实在太长了，不过我们在清单 3 中给出了第一部分的内容：</p>
            <br />
            <a name="listing3"><strong>清单 3. 运行 AppGen 的 install-detailed 目标</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">$ ant install-detailed
                        Buildfile: build.xml
                        init:
                        [mkdir] Created dir: /Users/mraible/Work/devworks/extras/appgen/build
                        [echo]
                        [echo] +-------------------------------------------------------+
                        [echo] |             -- Welcome to the AppGen! --              |
                        [echo] |                                                       |
                        [echo] | Use the "install" target to use the generic DAO and   |
                        [echo] | Manager, or use "install-detailed" to general a DAO   |
                        [echo] | and Manager specifically for your model object.       |
                        [echo] +-------------------------------------------------------+
                        [input] Would you like to generate code from a table or POJO? (table,pojo)
                        table
                        [input] What is the name of your table (i.e. person)?
                        cat
                        [input] What is the name, if any, of the module for your table (i.e. organization)?
                        [echo] Running Middlegen to generate POJO...
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>要对 cat 表使用这个新生成的代码，我们需要修改 src/dao/com/ibm/dao/hibernate/applicationContext-hibernate.xml，来为 Hibernate 添加 Cat.hbm.xml 映射文件。清单 3 给出了我们修改后的 <code>sessionFactory</code> bean 的样子：</p>
            <br />
            <a name="listing4"><strong>清单 4. 将 Cat.hbm.xml 添加到 sessionFactory bean 中</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">    &lt;bean id="sessionFactory" class="..."&gt;
                        &lt;property name="dataSource" ref="dataSource"/&gt;
                        &lt;property name="mappingResources"&gt;
                        &lt;list&gt;
                        &lt;value&gt;com/ibm/model/Role.hbm.xml&lt;/value&gt;
                        &lt;value&gt;com/ibm/model/User.hbm.xml&lt;/value&gt;
                        <span class="boldcode">&lt;value&gt;com/ibm/model/Cat.hbm.xml&lt;/value&gt;</span>
                        &lt;/list&gt;
                        &lt;/property&gt;
                        ...
                        &lt;/bean&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>在运行 <code>ant setup deploy</code> 之后，我们就应该可以在部署的应用程序中对 cat 表执行 CRUD 操作了：</p>
            <br />
            <a name="fig4"><strong>图 4. Cat 列表</strong></a><br />
            <img height="379" alt="所生成的主屏幕" src="http://www.ibm.com/developerworks/cn/java/j-appfuse/cat_list.jpg" width="572" /> <br />
            <br />
            <a name="fig5"><strong>图 5. Cat 表单</strong></a><br />
            <img height="379" alt="所生成的详细屏幕" src="http://www.ibm.com/developerworks/cn/java/j-appfuse/cat_detail.jpg" width="572" /> <br />
            <p>我们在上面的屏幕快照中看到的记录都是作为代码生成的一部分创建的，因此现在就有测试数据了。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="6"><span class="atitle">理由 6：文档</span></a></p>
            <p>我们可以找到 AppFuse 各个风味的教程，并且它们都以 6 种不同的语言给出了：中文、德语、英语、韩语、葡萄牙语和西班牙语。使用<em>风味（flavor）</em> 一词，我的意思是不同框架的组合，例如 Spring MVC 加上 iBATIS、Spring MVC 加上 Hibernate 或 JSF 加上 Hibernate。使用这 5 种 Web 框架和两种持久框架，可以有好几种组合。有关它们的翻译，AppFuse 为自己的默认特性提供了 8 种翻译。可用语言包括中文、荷兰语、德语、英语、法语、意大利语、葡萄牙语和西班牙语。</p>
            <p>除了核心教程之外，还添加了很多教程（请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a>） 来介绍与各种数据库、应用服务器和其他开放源码技术（包括 JasperReports、Lucene、Eclipse、Drools、Axis 和 DWR）的集成。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="7"><span class="atitle">理由 7：社区</span></a></p>
            <p>Apache 软件基金会对于开放源码有一个有趣的看法。它对围绕开放源码项目开发一个开放源码社区最感兴趣。它的成员相信如果社区非常强大，那么产生高质量的代码就是一个自然的过程。下面的内容引自 Apache 主页：</p>
            <blockquote>&#8220;我们认为自己不仅仅是一组共享服务器的项目，而且是一个开发人员和用户的社区。&#8221; </blockquote>
            <p>AppFuse 社区从 2003 年作为 SourceForge 上的一个项目（是 struts.sf.net 的一部分）启动以来，已经获得了极大的增长。通过在 2004 年 3 月转换到 java.net 上之后，它已经成为这里一个非常流行的项目，从 2005 年 1 月到 3 月成为访问量最多的一个项目。目前它仍然是一个非常流行的项目（有关 java.net 项目统计信息的链接，请参看 <a href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#resources" cmimpressionsent="1">参考资料</a>），不过在这个站点上它正在让位于 Sun 赞助的很多项目。</p>
            <p>在 2004 年年末，Nathan Anderson 成为继我之后第一个提交者。此后有很多人都加入了进来，包括 Ben Gill、David Carter、Mika G?ckel、Sanjiv Jivan 和 Thomas Gaudin。很多现有的提交者都已经通过各种方式作出了自己的贡献，他们都帮助 AppFuse 社区成为一个迅速变化并且非常有趣的地方。</p>
            <p>邮件列表非常友好，我们试图维护这样一条承诺 &#8220;没有问题是没有人理会的问题&#8221;。我们的邮件列表归档文件中惟一一条 &#8220;RTFM&#8221; 是从用户那里发出的，而不是从开发者那里发出的。我们绝对信奉 Apache 开放源码社区的哲学。引用我最好的朋友 Bruce Snyder 的一句话，&#8220;我们为代码而来，为人们而留下&#8221;。目前，大部分开发者都是用户，我们通常都喜欢有一段美妙的时间。另外，大部分文档都是由社区编写的；因此，这个社区的知识是非常渊博的。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www.ibm.com/developerworks/cn/java/j-appfuse/index.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="8"><span class="atitle">结束语</span></a></p>
            <p>我们应该尝试使用 AppFuse 进行开发，这是因为它允许我们简单地进行测试、集成、自动化，并可以安全地生成 Web 应用程序。其文档非常丰富，社区也非常友好。随着其支撑框架越来越好，AppFuse 也将不断改进。</p>
            <p>从 AppFuse 2.0 开始，我们计划迁移到 JDK 5（仍然支持部署到 1.4）和 Maven 2 上去。这些工具可以简化使用 AppFuse 的开发、安装和升级。我们计划充分利用 Maven 2 的功能来处理相关依赖性。我们将碰到诸如 appfuse-hibernate-2.0.jar 和 appfuse-jsf-2.0.jar 之类的工件。这些工件都可以在 pom.xml 文件中进行引用，它们负责提取其他相关依赖性。除了在自己的项目中使用 AppFuse 基类之外，我们还可以像普通的框架一样在 JAR 中对这些类简单地进行扩展，这应该会大大简化它的升级过程，并鼓励更多用户将自己希望的改进提交到这个项目中。</p>
            <p>如果没有其他问题，使用 AppFuse 可以让您始终处于 Java Web 开发的技术前沿上 —— 就像我们一样！</p>
            <br />
            <br />
            <p><a name="resources"><span class="atitle">参考资料 </span></a></p>
            <strong>学习</strong><br />
            <ul>
                <li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/java/library/j-appfuse/index.html?S_TACT=105AGX52&amp;S_CMP=cn-a-j" target="_blank" cmimpressionsent="1">英文原文</a> 。<br />
                <br />
                <li><a href="http://appfuse.org/" cmimpressionsent="1">AppFuse</a>：该项目的主页。 <br />
                <br />
                <li><a href="http://appfuse.org/demos.html" cmimpressionsent="1">AppFuse Demos</a>：查看演示和视频。 <br />
                <br />
                <li><a href="http://jroller.com/page/mrdon?entry=unification_struts_action_and_jsf" cmimpressionsent="1">Struts 2 和 JSF</a>：了解为什么要将这些技术放到一起工作。 <br />
                <br />
                <li><a href="http://java.sun.com/blueprints/code/projectconventions.html" cmimpressionsent="1">Sun 的 J2EE 项目目录结构指南</a>：AppFuse 非常接近于这些指南。 <br />
                <br />
                <li><a href="http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html" cmimpressionsent="1">Maven 的 Standard Directory Layout</a>：AppFuse 2.0 将转换到这个目录结构上。 <br />
                <br />
                <li><a href="http://appfuse.org/wiki/QuickStart.html" cmimpressionsent="1">AppFuse 快速入门指南</a>：快速入门并使用 AppFuse。 <br />
                <br />
                <li><a href="http://appfuse.org/wiki/Articles.html" cmimpressionsent="1">AppFuse 教程</a>：深入学习更多有关使用 AppFuse 的知识。 <br />
                <br />
                <li><a href="http://raibledesigns.com/wiki/AppFuseAxis.html" cmimpressionsent="1">Apache Axis 集成</a>：如何将 Apache Axis 集成到自己的 AppFuse 项目中。 <br />
                <br />
                <li>Java.net 项目状态：请查看 2005 年 <a href="http://community.java.net/projects/toparchive.csp?year=2005&amp;month=January" cmimpressionsent="1">1 月</a>、<a href="http://community.java.net/projects/toparchive.csp?year=2005&amp;month=February" cmimpressionsent="1">2 月</a> 和 <a href="http://community.java.net/projects/toparchive.csp?year=2005&amp;month=March" cmimpressionsent="1">3 月</a> 的动态。还可以查看 <a href="http://community.java.net/projects/top.csp" cmimpressionsent="1">java.net 上的最佳项目 </a>。 <br />
                <br />
                </li>
            </ul>
            <br />
            <strong>获得产品和技术</strong><br />
            <ul>
                <li><a href="https://appfuse.dev.java.net/servlets/ProjectDocumentList" cmimpressionsent="1">AppFuse on java.net</a>：下载不同风味的 AppFuse。 <br />
                <br />
                <li><a href="http://opensymphony.com/webwork" cmimpressionsent="1">WebWork</a>：了解这个易于使用的 Web 框架。 <br />
                <br />
                <li><a href="http://www.dbunit.org/" cmimpressionsent="1">DbUnit</a>：查看更多有关 JUnit 扩展的内容。 <br />
                <br />
                <li><a href="http://www.jmock.org/" cmimpressionsent="1">jMock</a>：创建动态仿真对象来简化真正的单元测试。 <br />
                <br />
                <li><a href="http://webtest.canoo.com/" cmimpressionsent="1">Canoo WebTest</a>：自动化 Web 应用程序的 UI 测试。 <br />
                <br />
                <li><a href="http://htmlunit.sf.net/" cmimpressionsent="1">HtmlUnit</a>：WebTest 的优秀 JavaScript 支持背后的基础。 <br />
                <br />
                <li><a href="http://cargo.codehaus.org/" cmimpressionsent="1">Cargo</a>：自动启动和停止容器。 <br />
                <br />
                <li><a href="http://greenbox.dev.java.net/" cmimpressionsent="1">Greenbox</a>：一种代码生成框架。 <br />
                <br />
                </li>
            </ul>
            <br />
            <strong>讨论</strong><br />
            <ul>
                <li><a href="http://www.nabble.com/AppFuse-f2369.html" cmimpressionsent="1">AppFuse 论坛</a>：与同行开发人员交流技巧。</li>
            </ul>
            <br />
            <br />
            <p><a name="author"><span class="atitle">关于作者</span></a></p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td colspan="3"><img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /></td>
                    </tr>
                    <tr valign="top" align="left">
                        <td>
                        <p><img height="80" alt="" src="http://www.ibm.com/developerworks/i/p-mraible.jpg" width="64" align="left" /></p>
                        </td>
                        <td><img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="4" /></td>
                        <td width="100%">
                        <p>Matt Raible 居住在美国科罗拉多州的丹佛，他在那里是 Spring 和 Web 框架对 <a href="http://virtuas.com/" cmimpressionsent="1">Virtuas Open Source Solutions</a> 的实践先驱。他在开放源码领域具有丰富的经验，是这个领域的专家。他在这个领域中既是用户，又是一名开发人员。Matt 是 <a href="http://sourcebeat.com/" cmimpressionsent="1">SourceBeat Publishing</a> 上 <em><a href="http://springlive.com/" cmimpressionsent="1">Spring Live</a></em> 的作者。他还为 Apress 的书籍 <em><a href="http://www.apress.com/book/bookDisplay.html?bID=256" cmimpressionsent="1">Pro JSP Third Edition</a></em> 作出了很大的贡献。他是很多开放源码会议的积极倡导者，包括 ApacheCon、MySQL User's Conference 和 OSCON，同时他还是 <a href="http://raibledesigns.com/" cmimpressionsent="1">http://raibledesigns.com</a> 上一名非常活跃的博客。Raible 的大部分生活都被计算机所包围了，尽管他是在连电都没有的 Montana 长大的。当不工作的时候时，他总是试图让妻子 Julie 成为世界上最幸福的女人，或者与他们的孩子 Abbie 和 Jack 一起玩耍。</p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
  <img src ="http://www.blogjava.net/gf7/aggbug/208002.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2008-06-15 11:14 <a href="http://www.blogjava.net/gf7/archive/2008/06/15/208002.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Office (2007) Open XML 文件格式简介</title><link>http://www.blogjava.net/gf7/archive/2008/05/17/201045.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sat, 17 May 2008 01:42:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2008/05/17/201045.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/201045.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2008/05/17/201045.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/201045.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/201045.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Office (2007) Open XML 文件格式简介发布日期： 2007-07-06 | 更新日期： 2007-07-06Frank Rice, Microsoft Corporation学习Office Open XML格式的优势。用户可以在Office应用程序和企业系统之间使用XML和ZIP技术来交换数据。文档是全局可以访问的。并且，您还可以减少文件损坏的风险。适用于...&nbsp;&nbsp;<a href='http://www.blogjava.net/gf7/archive/2008/05/17/201045.html'>阅读全文</a><img src ="http://www.blogjava.net/gf7/aggbug/201045.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2008-05-17 09:42 <a href="http://www.blogjava.net/gf7/archive/2008/05/17/201045.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Reporting Services与相关产品的比较</title><link>http://www.blogjava.net/gf7/archive/2007/10/19/154275.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Fri, 19 Oct 2007 09:03:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2007/10/19/154275.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/154275.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2007/10/19/154275.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/154275.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/154275.html</trackback:ping><description><![CDATA[<strong>
<div class="storytext"><font color="#002c99"></font><br />
Microsoft SQL Server 2000报表服务是服务器端的完整平台，它对传统纸面报表以及可交互的基于Web的报表都可以进行建立、管理和发布。它是微软已有的商业智能与数据仓库解决方案产品——Microsoft Office、Microsoft Business Solutions与Microsoft SQL Server的有益补充。<br />
<br />
Microsoft Office Web Component（OWC）包含在Microsoft Office 2000以后的产品中。在使用Microsoft Internet Explorer浏览包含Office Web组件的Web页时，您可以直接在Internet Explorer中处理显示的数据，如对数据进行排序和筛选，输入新的数值，展开和折叠明细数据，进行行列旋转以查看源数据的不同汇总信息等。由于Office Web组件是完全可编程的，可以在很多设计环境中使用这些组件来建立复杂的、交互的和基于Web的解决方案。这些设计环境包括Microsoft FrontPage、Microsoft Access数据访问页以及Microsoft Visual Basic。您也可以使用最小的设计设置直接在Microsoft Excel中发布这些Office Web组件。<br />
<br />
笔者根据所参与的项目及以前的应用经验，对Microsoft SQL Server Reporting Services、OWC和Microsoft SQL Server组成的微软企业级报表解决方案与相关产品的解决方案作了一个简单比较。
<p><strong>与Cognos公司产品的比较</strong><br />
Cognos的产品简介<br />
Cognos公司的产品Cognos Suite是由一系列的功能模块组合而成的套件，包括ImpromptU、Powerplay和Scenario等模块。<br />
Impromptu提供查询、报表功能，针对关系型数据。可以将Powerplay的数据形成报表，这是Cognos公司的集成。Impromptu Web Reports（WR）在Web上为大量报表用户提供易于打印的管理报表。用户可以订阅已发布报表，对其进行定制来满足特定的需要。<br />
Powerplay提供OLAP分析功能，针对多维数据PowerCube（Cognos定义的多维数据结构）。在Powerplay中可以钻取到Impromptu中。这是Cognos公司的集成。<br />
Transformer将Impromptu及其他数据源中的数据形成PowerCube，以备Powerplay使用。Scenari是数据挖掘工具。4Thought是采用神经网络技术的建模与预测模块。</p>
<p><strong>Cognos报表解决方案与Reporting Services的不同点</strong>Cognos的解决方案不是集成的产品（将查询、报表作一个工具，分析作一个工具，Cognos的理由是先分析再做表）；没有类似于Designer的专门设计模块，在Impromptu模块中完成数据库的连接与catalog的定义，因此Impromptu的使用要求用户具备数据库专业知识；没有对报表的集中管理、分发和调配的功能。目前引进中国的只有Impromptu、Powerplay。</p>
<p><strong>Reporting Services的特点</strong><br />
1）Reporting Services是集查询、报表和分析于一体的产品，只需学习一个工具的使用、在一个界面上操作，易用性强。符合查询、分析、再查询、再分析循环往复的决策思维方式； Impromptu和Powerplay所使用的数据层不同，不能共用，Powerplay使用的多维数据由其它模块生成，是静态的多维立方体，维的改变需切换到其它模块。<br />
2）Reporting Services的几大模块在SQL Server数据库引擎的管理下形成一个统一完整的系统，具有统一的用户与资源管理，安全性高。<br />
3）文档共享方面，Reporting Services提供输出多种格式或Email等多种方式。<br />
4）Reporting Services是32位结构，Impromptu是16位结构。数据量大时，使用Impromptu不稳定，会出现死机等。</p>
<p><strong>与SAS的比较</strong><br />
SAS简介<br />
SAS以统计分析软件包起家，在统计分析方面具备很强实力。发展到现在，SAS成为一个包含许多模块与功能的庞大的软件包，有两种使用方式：一是直接使用一些应用模块对存于SAS自己数据库中的数据进行多种多样的统计分析，这些应用模块包括统计分析STAT、财务分析ETS、运筹学OR等等。利用这些模块要求用户具备较高的数学尤其是统计分析专业知识，同时要具备较高的计算机操作能力。而且如果数据存在其它数据源中，需要利用SAS进行预先转换，这需要用户具备数据库专业知识。二是用户单位的计算机人员利用SAS的若干模块编程，为最终用户提供特定的应用系统。这样做的优点是可以为最终用户提供所要求的简便界面，但对技术人员的要求很高，培训时间也很长；而且灵活性差：一旦用户需求有改变，需要重新编程。SAS对数据的处理能力很强，但需要用户长时间的培训才能应用起来。</p>
<p><strong>SAS与微软的企业级报表解决方案的比较</strong><br />
SAS与微软的企业级报表解决方案不是同类产品。<br />
1）易用性相差很大，从而面向的用户对象不同<br />
SAS功能很多，提供算法很多，因此易用性差，要求用户具备很扎实的数学基础、统计分析基础和计算机基础。<br />
2）若利用SAS开发一套系统，优势是贴切需求，但对应用需求的提出、开发、实施和相关厂商的技术支持要求很高，并且开发系统的开放性、稳定性、可移植性、灵活性上比商业软件要差，尤其国内现阶段的开发手段相对比较落后。<br />
与Pilot产品的比较<br />
Pilot公司的产品包含服务器端和客户端，其服务器端的产品是多维数据库。客户端产品功能与Microsoft SQL Server Reporting Services相似，有如下不同之处：<br />
l）Microsoft SQL Server Reporting Services不但支持关系型数据，而且支持来自第三方的多维数据。而Pilot的客户端产品只支持自己格式的多维数据。因此关系型数据用户必须先将数据导入Pilot的多维数据库中。用户工作量很大，相当于重新建立多维数据库，这样不如选择其它产品构建数据仓库，以Reporting Services做前端展现。<br />
2）Pilot的多维数据的维的改动很难，不灵活。<br />
3）Pilot客户端产品的易用性差，需要编程，工作量大，后期维护难。</p>
<p><strong>与Oracle公司产品的比较</strong><br />
Oracle公司的Discoverer与Reporting Services功能近似，但两者也有一些区别。<br />
Reporting Services支持的数据源更为广泛，可以是数据仓库，也可以是大型关系数据库如 Sybase、Oracle、Informix、SQL Server、DB2，单机数据库如Access、Foxpro、dBase等，多维数据库如Essbase、Express，常用应用软件如SAP R／3、Peoplesoft或Oracle的一些常用应用软件包，数据文件如Excel、TXT文件等，只要有相应的驱动即可。<br />
Discoverer 3是针对关系数据库的，不适用于数据仓库和多维数据库，即使对Oracle自己的多维数据库Express也不支持。<br />
Reporting Services对Oracle、SQL Server数据库有内部直接连接，其他较为流行的大型数据库Sybase、Informix、DB2可以通过OLEDB连接。Discoverer 3只能通过ODBC与数据库连接，因此查询数据的速度相对较慢。<br />
Discoverer 3不能在一个文件中同时用表和统计图表示数据。<br />
Discoverer 3不能在统计图上对数据进行钻取。<br />
Discoverer 3的安全控制弱，不能定义用户及用户组的不同描述文件，既不能对哪些用户使用哪些模块进行控制，也不能对一些敏感数据进行进一步的控制。而Reporting Services可以对整个报表运行系统进行管理，对权限及某些数据进行控制。<br />
Reporting Services还可以对报表集中分发、管理。例如用户可以规定刷新和发送报表的时间，如每小时、每天、每周、每月等刷新发送一次，或在现定时间只发送一次。通过一些简单的属性设置，还可以发送报表到Web页面上，并定时刷新。Discoverer 3没有对报表文件的集中批处理。<br />
Discoverer3可以将文件转为HTML格式，但不支持定时刷新。</p>
<p><strong>与Seagate公司产品的比较</strong><br />
公司简介<br />
希捷公司由Alan Shugart创建于1979年，最初主要生产数据存储设备，在随后的发展过程中，逐渐由硬件设备厂商扩展为&#8220;数据技术公司&#8221;。1994到1997年间，相继收购了Crystal Service（Crystal Report，Crystal Info产品的创建公司）、Holistic Systems（Holos OLAP Server产品的创建公司）等公司来扩展其软件产品系列。</p>
<p><strong>解决方案</strong><br />
<strong>产品线：</strong><br />
Seagate Info——包括查询、报表和多维分析，以及安全管理，其中包含Seagate Analysis模块；支持多种关系型数据、多维数据库；<br />
Seagate Analysis——提供查询、报表和多维分析；<br />
Seagate Crystal Reports——报表制作工具，提供查询、报表功能和API接口，可以在开发工具中集成；<br />
Seagate Holos——OLAP Server。</p>
<p><strong>相关比较</strong><br />
Seagate Info没有语义层技术，无论是使用Seagate Info还是Crystal Reports，都需要让用户自己从数据库选择表，构造SQL语句，因此用户必须了解数据库技术。<br />
Crystal Reports主要是为专业计算机人员提供的报表制作工具，有较强的二次开发能力，因此它作为报表工具组件曾被集成到多种开发工具和应用程序中，如Microsoft Visual Studio.NET。但考虑到相关的使用许可，Crystal Reports是一个相对昂贵的选择。</p>
<p><strong>与MicroStrategy公司产品的比较</strong><br />
MicroStrategy公司由Michael J．Savior创建于1989年，最初主要是作为一家决策支持领域的咨询公司，在随后的发展过程中，于1993年推出了第一个产品包：MicroStrategy Agent，以后相继推出一系列产品：MicroStrategy Web、MicroStrategy Broadcaster、MicroStrategy Telecaster等，现新产品包称为MicroStrategy7，致力于提供面向个性化的电子商务智能解决方案。</p>
<p><strong>MicroStrategy解决方案的产品线包括：</strong><br />
MicroStrategy Intelligence Server——整个产品中的核心产品，多层体系结构下的中间应用服务器，为各种前端应用提供中间应用层能力。<br />
MicroStrategy Web——Web体系下的应用服务器，提供基于Web体系下的查询、电算表格和多维分析能力。<br />
MicroStrategy Agent——数据挖掘、应用开发工具，提供API接口。<br />
MicroStrategy InfoCenter——企业级报表、门户工具。<br />
MicroStrategy Architect——商业对象抽象层设计工具。<br />
MicroStrategy Desktop——MicroStrategy Agent、MicroStrategy Architect和MicroStrategy Administration Utility的集成化应用环境</p>
<p>MicroStrategy有较弱的语义层技术，称之为企业商业体系，但能力比较弱，无法支持复杂的语义表达。<br />
前端工具MicroStrategy Desktop的易用性较差，Businessobjects是唯一在决策支持工具中获得Microsoft office兼容认证的产品，易用性同Office类似，同时支持Microsoft VBA二次开发技术。<br />
前端工具MicroStrategy Desktop对灵活查询支持较弱。<br />
MicroStrategy不具备企业级特征，对企业级报表制作、企业信息共享与分发、企业级维护与管理支持较弱，管理复杂。<br />
MicroStrategy整个产品学习和使用较为困难，需要更多的技术支持。<br />
Reporting Services有支持XML的designer和应用模板（Wizard），使得用户只需按照自己的需求稍做调整，就可以达到应用效果，MicroStrategy没有提供类似能力。<br />
MicroStrategy采用了N-tier体系结构，在构架的灵活性上与微软的企业级报表解决方案相当</p>
</div>
</strong>
<img src ="http://www.blogjava.net/gf7/aggbug/154275.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2007-10-19 17:03 <a href="http://www.blogjava.net/gf7/archive/2007/10/19/154275.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自定义file类型input框样式的方法 </title><link>http://www.blogjava.net/gf7/archive/2007/09/10/144065.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Mon, 10 Sep 2007 10:31:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2007/09/10/144065.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/144065.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2007/09/10/144065.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/144065.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/144065.html</trackback:ping><description><![CDATA[<table cellspacing="0" cellpadding="3" width="100%" border="0">
    <tbody>
        <tr>
            <td valign="top" align="center" bgcolor="#ffffff" height="32"><font color="#0099cc" size="5"><strong>自定义file类型input框样式的方法</strong></font></td>
        </tr>
        <tr>
            <td valign="top" bgcolor="#ffffff" height="350"><font class="fonttitle1" id="zoom" style="font-size: 15px"><br />
            在WEB上传文件时，要用到上传框：
            <p>&lt;input type="file" id="f" name="f"&gt;</p>
            <p>这东东在IE(其他偶没经过测试)中是一个非常特殊的对象。</p>
            <p>如果是您手动写入的或其他对象经过某些事件触发填入的值</p>
            <p>由于安全问题，在进行提交表单时，往往会被清空，所以上传失败。</p>
            <p>简单点说，除非你的鼠标亲自点到了上传框f上，IE才会给你上传文件！</p>
            <p>哪怕你将 f 的onclick句柄赋给某个对象，如：<br />
            &lt;input type="file" id="f" name="f"&gt;<br />
            &lt;input onclick="f.click()" value="点击"&gt;</p>
            <p>你 &#8220;点击&#8221; 后，同样会弹出文件选择对话框，可惜失望地：你照样不能上传文件！</p>
            <p>怎么办呢？</p>
            <p>看下这段：<br />
            &lt;BODY onmousemove="f.style.pixelLeft=event.x-200;f.style.pixelTop=event.y-10;"&gt;<br />
            &lt;input type="text"&gt;&lt;input type="button" onmousemove=""&gt;<br />
            &lt;input type="file" id="f" name="f" style="position:absolute;"&gt;<br />
            &lt;/BODY&gt;</p>
            <p>随便点击鼠标，看到效果了吧？</p>
            <p>基于上面的思路，偶们就可以把它弄到一个button下面就OK了！！</p>
            <p>&lt;style&gt;<br />
            input{border:1px solid green;}<br />
            &lt;/style&gt;<br />
            &lt;BODY&gt;<br />
            &lt;BR&gt;&lt;BR&gt;&lt;BR&gt;<br />
            &lt;form method="post" action="" enctype="multipart/form-data"&gt;<br />
            &lt;input type="text" id="txt" name="txt"&gt;<br />
            &amp;nbsp;&amp;nbsp;&lt;input type="button" onmousemove="f.style.pixelLeft=event.x-60;f.style.pixelTop=this.offsetTop;" value="请选择文件" size="30"&gt;<br />
            &lt;input type="file" id="f" name="f" style="position:absolute;" size="1" onChange="txt.value=this.value"&gt;&lt;BR&gt;<br />
            &lt;INPUT TYPE="submit"&gt;<br />
            &lt;/form&gt;<br />
            &lt;/BODY&gt;</p>
            <p>为了达到真正模拟的效果，还得要把f给隐藏，加个不透明的alpha 滤镜即可，再加上 hidefocus 属性，隐藏f的虚线：</p>
            <p>&lt;style&gt;<br />
            input{border:1px solid green;}<br />
            &lt;/style&gt;<br />
            &lt;BODY&gt;<br />
            &lt;BR&gt;&lt;BR&gt;&lt;BR&gt;<br />
            &lt;form method="post" action="" enctype="multipart/form-data"&gt;<br />
            &lt;input type="text" id="txt" name="txt"&gt;<br />
            &amp;nbsp;&amp;nbsp;&lt;input type="button" onmousemove="f.style.pixelLeft=event.x-60;f.style.pixelTop=this.offsetTop;" value="请选择文件" size="30" onclick="f.click()"&gt;<br />
            &lt;input type="file" id="f" onchange="txt.value=this.value" name="f" style="position:absolute;filter:alpha(opacity=0);" size="1" hidefocus&gt;&lt;BR&gt;<br />
            &lt;INPUT TYPE="submit"&gt;<br />
            &lt;/form&gt;<br />
            &lt;/BODY&gt;</p>
            <p>可以看下opacity=0改为稍大些的效果。</p>
            <p>OK了，现在你就可以控制它们的样式、位置了。。。 </p>
            </font></td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/gf7/aggbug/144065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2007-09-10 18:31 <a href="http://www.blogjava.net/gf7/archive/2007/09/10/144065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>商业智能平台研究 (十) ETL 选型</title><link>http://www.blogjava.net/gf7/archive/2007/08/30/141356.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Thu, 30 Aug 2007 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2007/08/30/141356.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/141356.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2007/08/30/141356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/141356.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/141356.html</trackback:ping><description><![CDATA[<div align=center><font size=4>商业智能平台研究 (十) ETL 选型<br></font>
<div align=left><font size=4>ETL (Extract-Transform-Load的缩写，即数据抽取、转换、装载的过程)作为BI/DW（Business Intelligence）的核心和灵魂，能够按照统一的规则集成并提高数据的价值，是负责完成数据从数据源向目标数据仓库转化的过程，是实施数据仓库的重要步骤。如果说数据仓库的模型设计是一座大厦的设计蓝图，数据是砖瓦的话，那么ETL就是建设大厦的过程。在整个项目中最难部分是用户需求分析和模型设计，而ETL规则设计和实施则是工作量最大的，约占整个项目的60%～80%，这是国内外从众多实践中得到的普遍共识。<br><br>ETL工具从厂商来分为两种,一种是数据库厂商自带的ETL工具,Oracle warehouse builder 就是这种,另外一种是第三方工具提供商.开源世界也有一大票的ETL工具,功能各异,强弱不一,你可以从一下地址找到开源ETL工具的列表 http://www.manageability.org/blog/stuff/open-source-etl/view&nbsp; , 提醒一句,选用工具的时候要慎重,真的,千万要慎重,不管你是选用商业的ETL工具(一般比较贵),还是开源的工具,都要在你充分了解产品的特性才去选择,千万不要听某某人说什么这个工具好,就购买了那个工具,一定要自己了解产品.<br><br>开源的ETL工具的列表 (排名是乱排的)<br>kettle&nbsp; http://kettle.pentaho.org/&nbsp; ,pentaho官方的ETL工具,是一个metadata-driven 的ETL工具,不需要自己写code .<br>talend&nbsp; http://www.talend.com/&nbsp;&nbsp;&nbsp; talend是talend自己公司的产品,宣传的是全功能的Data Integration 解决方案,基于eclipse 平台,包括很多的模块来实现商业流程建模,数据流程建模,最后输出的是perl 和 Java code<br>jasperETL&nbsp; http://www.jaspersoft.com/&nbsp;&nbsp; JasperETL是基于talend的平台,不太清楚有什么区别,jaspersoft开发的ETL产品.<br>Octopus&nbsp;&nbsp; http://www.enhydra.org/tech/octopus/index.html&nbsp;&nbsp;&nbsp; octopuc是enhydra 的一个ETL工具,enhydra是一个产品跨度非常大的开源站点,它有个开源的Workflow ,Shark ,pentaho就是使用的这个Workflow ,这个组织从workflow 到application server , 从ETL工具到application framework ,还有一些其他的中间件,octopus非常的原始,支持任何的JDBC数据源,用XML语言来定义的.也支持JDBC-DOBC ,和excel 和 access ,csv-files, XML files ,用Ant 和 JUnit 来创建表和测试.<br>CloverETL http://cloveretl.berlios.de/&nbsp;&nbsp; CloverETL是提供给你一组API,用XML来定义ETL过程,同样支持JDBC数据源, CloverETL是开源的,但是它是没有图形界面的,它提供一个有图形界面的CloverGUI 来进行ETL的图形化开发过程,但是不是开源的,需要购买商业许可证.<br>KETL&nbsp;&nbsp; http://www.ketl.org/&nbsp;&nbsp;&nbsp; 听说是几个前IBM员工做出来的ETL产品,<br>另外还有很多.不一一写介绍了,只列个表吧,<br>Joost&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://joost.sourceforge.net/&nbsp;&nbsp;&nbsp; 最近有个web2.0 网站也叫Joost,名字相同而已.<br>Xineo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://software.xineo.net/xil.jspx<br>BabelDoc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://sourceforge.net/projects/babeldoc<br>CB2XML&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://sourceforge.net/projects/cb2xml<br>mec-eagle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://sourceforge.net/projects/mec-eagle/<br>Transmorpher&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://transmorpher.inrialpes.fr/<br>XPipe&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://xpipe.sourceforge.net/Articles/Miscellaneous/fog0000000018.html<br>DataSift&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.datasift.org/<br>Xephyrus Flume&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.xephyrus.com/flume/flume-intro.Prlx<br>Smallx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; https://smallx.dev.java.net/<br>Nux&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://dsd.lbl.gov/nux/index.html<br>Netflux&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.netflux.org/<br>OpenDigger&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; https://opendigger.dev.java.net/<br>ServingXML&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://servingxml.sourceforge.net/<br>Scriptella&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://scriptella.javaforge.com/<br>ETL Integrator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.glassfishwiki.org/jbiwiki/Wiki.jsp?page=ETLSE<br>Jitterbit&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.jitterbit.com/<br>Apatar&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://www.apatar.com/<br>Spring Batch&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; http://static.springframework.org/spring-batch/<br><br>大多数站点都是在sf.net上的.其中最后一个是Spring的,大名鼎鼎的Spring 也往ETL插一脚.实在是..........<br>根据talend官方介绍的数据,ETL工具的市场份额在2006好像是有160多亿美元.由于BI项目的成功,ETL的这一市场份额还会扩大,这也不难理解,为什么这么多的公司都在做ETL工具了.开源世界也免不了想要分一杯羹.再次废话一句,开源的东西你可以免费得到和使用,但是当你想应用到企业级开发的时候,省钱可不是唯一应该考虑的因素.还是那句话,慎重呀慎重.<br><br>下一篇介绍BI的基本概念.</font></div>
</div>
<img src ="http://www.blogjava.net/gf7/aggbug/141356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2007-08-30 13:52 <a href="http://www.blogjava.net/gf7/archive/2007/08/30/141356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开源BI系统简述</title><link>http://www.blogjava.net/gf7/archive/2007/08/28/140613.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Tue, 28 Aug 2007 10:09:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2007/08/28/140613.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/140613.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2007/08/28/140613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/140613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/140613.html</trackback:ping><description><![CDATA[<p class=MsoNormal align=center><a name=_Toc146945204><strong><span><font color=#000000>开源</font></span></strong></a><span><strong><span lang=EN-US>BI</span></strong></span><span><strong><span>系统简述</span></strong></span><span></span><strong><span lang=EN-US><o:p></o:p></span></strong></p>
<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>
<h1><span lang=EN-US><span>1.<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp;&nbsp; </span></span></span><span>概述</span></h1>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">开源的</span><span lang=EN-US>BI</span><span>项目在在</span><span lang=EN-US>2005</span><span>年之前并没有太大的发展，到了</span><span lang=EN-US>2005</span><span>年才开始呈现繁荣之势，并在</span><span lang=EN-US>2006</span><span>年蓬勃发展。这些众多的</span><span lang=EN-US>BI</span><span>项目从规模和对</span><span lang=EN-US>BI</span><span>系统支撑的完善程度上来说，大体可以分为</span><span lang=EN-US>Framework</span><span>、</span><span lang=EN-US>Stand-alone Tools</span><span>和</span><span lang=EN-US>BI Suit</span><span>三种类型。</span></p>
<p class=MsoNormal><span lang=EN-US style="FONT-FAMILY: wingdings"><span>l<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang=EN-US>Framework</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">开源框架，这是在商业</span><span lang=EN-US>BI</span><span>系统中所没有的。我们可以使用它们来构建自己的</span><span lang=EN-US>BI</span><span>工具，或者增强和扩展我们的</span><span lang=EN-US>BI</span><span>解决方案。</span></p>
<p class=MsoNormal><span lang=EN-US style="FONT-FAMILY: wingdings"><span>l<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang=EN-US>Stand-alone Tools</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">独立的</span><span lang=EN-US>BI</span><span>工具，这是开源项目中数量最多的一类。很多工具只侧重</span><span lang=EN-US>BI</span><span>系统中的某个环节和方面，如</span><span lang=EN-US>ETL</span><span>、</span><span lang=EN-US>Report</span><span>、</span><span lang=EN-US>OLAP</span><span>和</span><span lang=EN-US>Database</span><span>等等。</span></p>
<p class=MsoNormal><span lang=EN-US style="FONT-FAMILY: wingdings"><span>l<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang=EN-US>BI Suit</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">在统一的架构下提供了多种</span><span lang=EN-US>BI</span><span>系统的特性的工具集合。就目前的情况看，不管是商业软件还是开源软件，还没有任何一个套件提供了完整的端到端的</span><span lang=EN-US>BI</span><span>解决方案。这些开源的</span><span lang=EN-US>BI Suit</span><span>是通过连接多个其他的组件和工具的方式形成套件的，由于</span><span lang=EN-US>BI</span><span>系统涉及到的工具是非常多的，所以整合一套完整的</span><span lang=EN-US>BI</span><span>解决方案是很困难的。</span></p>
<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>
<h1><a name=_Toc146945205><font color=#000000><span lang=EN-US><span>2.<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp;&nbsp; </span></span></span><span lang=EN-US>BI</span></font></a><span><span>解决方案中的工具</span></span></h1>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">一个完整的</span><span lang=EN-US>BI</span><span>解决方案中有多种工具来完成</span><span lang=EN-US>BI</span><span>系统中各个阶段的工作。</span></p>
<h2><a name=_Toc146945206><font color=#000000><span lang=EN-US><span><font face=Arial>2.1.</font><span Times New Roman?; font-size-adjust: none; font-stretch: normal?> </span></span></span><span lang=EN-US><font face=Arial>ETL</font></span></font></a><span><span>工具</span></span></h2>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">数据抽取、转换和加载工具。优秀的</span><span lang=EN-US>ETL</span><span>工具应该具有以下特性：</span></p>
<p class=MsoNormal><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>Workflow Management, Job Execution and Scheduling Manager</span><span>。能方便地定义流程并自动化执行</span><span lang=EN-US>ETL</span><span>任务。</span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>Centralized Metadata Repository and Management</span><span>。集中存储和管理符合业界标准的元数据。</span></p>
<p class=MsoNormal><span lang=EN-US><span>3、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>Data Profile and Validation</span><span>。可以检验数据的质量。</span></p>
<p class=MsoNormal><span lang=EN-US><span>4、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>High Performance</span><span>。在大负荷的任务执行中仍然有良好的性能。</span></p>
<p class=MsoNormal><span lang=EN-US><span>5、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>Scalable, Platform Independent</span><span>。具有良好的弹性，支持多种操作系统和数据库系统，能操作多种异构的数据源。</span></p>
<p class=MsoNormal><span lang=EN-US><span>6、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>Open Architecture and API</span><span>。具有开放的架构和易于使用的二次开发接口。</span></p>
<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">目前较为知名的开源</span><span lang=EN-US>ETL</span><span>工具有：</span></p>
<p class=MsoNormal><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US><a href="http://www.kineticnetworks.com/"><font color=#0066aa><u>KETL</u></font></a></span><span>，由具有</span><span lang=EN-US>IBM</span><span>和</span><span lang=EN-US>KPMG</span><span>背景的</span><span lang=EN-US>Kinetic Networks</span><span>公司开发，现在已经有三年多的产品应用历史，成功应用于一些产品中，在点击流（</span><span lang=EN-US>ClickStream</span><span>）分析应用中表现出色。</span><span lang=EN-US>KETL</span><span>采用</span><span lang=EN-US>Plug-in</span><span>的架构，使用</span><span lang=EN-US>Java</span><span>开发。</span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US><a href="http://www.kettle.be/"><font color=#0066aa><u>KETTLE</u></font></a></span><span>，为一个元数据驱动的</span><span lang=EN-US>ETL</span><span>工具。已经加入</span><span lang=EN-US>Pentaho</span><span>。</span></p>
<p class=MsoNormal><span lang=EN-US><span>3、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US><a href="http://cloveretl.berlios.de/"><font color=#0066aa><u>Clover ETL</u></font></a></span><span>，为一个基于</span><span lang=EN-US>Java</span><span>的</span><span lang=EN-US>ETL Framework</span><span>，可以用来开发自己的</span><span lang=EN-US>ETL</span><span>应用。</span></p>
<p class=MsoNormal><span lang=EN-US><span>4、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US><a href="http://www.enhydra.org/tech/octopus/index.html"><font color=#0066aa><u>Enhydra Octopus</u></font></a></span><span>，为一个基于</span><span lang=EN-US>Java</span><span>的</span><span lang=EN-US>ETL</span><span>工具，使用</span><span lang=EN-US>JDBC</span><span>来连接各种数据源，易于使用和部署。曾有人应用于电信网络资源分析系统中。</span></p>
<h2><a name=_Toc146945207><font color=#000000><span lang=EN-US><span><font face=Arial>2.2.</font><span Times New Roman?; font-size-adjust: none; font-stretch: normal?> </span></span></span><span>报表工具</span></font></a></h2>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">优秀的报表工具通常具有以下特性：</span></p>
<p class=MsoNormal><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>支持多种数据源。</span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>直观的可视化设计器，简单易用的报表定制功能。</span></p>
<p class=MsoNormal><span lang=EN-US><span>3、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>方便的数据访问和格式化，丰富的数据呈现方式。</span></p>
<p class=MsoNormal><span lang=EN-US><span>4、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>符合数据呈现的通用标准，能和应用程序很好地进行结合。</span></p>
<p class=MsoNormal><span lang=EN-US><span>5、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>易于扩展和部署。</span></p>
<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">目前较为知名的开源报表工具有：</span></p>
<p class=MsoNormal><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US><a href="http://jasperreports.sourceforge.net/" target=_new><font color=#0066aa><u>JasperReports</u></font></a></span><span>，一个优秀的</span><span lang=EN-US>Java</span><span>报表工具，始于</span><span lang=EN-US>2001</span><span>，现在</span><span lang=EN-US>JasperSoft</span><span>公司持续开发和支持该工具。该工具类似于商业软件</span><span lang=EN-US>Crystal Report</span><span>，支持</span><span lang=EN-US>PDF</span><span>、</span><span lang=EN-US>HTML</span><span>、</span><span lang=EN-US>XLS</span><span>、</span><span lang=EN-US>CSV</span><span>和</span><span lang=EN-US>XML</span><span>文件输出格式，现在是</span><span lang=EN-US>Java</span><span>开发者最常用的报表工具。</span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US><a href="http://www.oreports.com/" target=_new><font color=#0066aa><u>OpenReports</u></font></a></span><span>，提供基于</span><span lang=EN-US>web</span><span>的灵活报表解决方案，通过浏览器自动生成动态</span><span lang=EN-US>PDF,XLS,HTMLCSV </span><span>和</span><span lang=EN-US>Chart</span><span>报表，它是用</span><span lang=EN-US>Java</span><span>开发的，使用</span><span lang=EN-US>JasperReports </span><span>作为报表引擎，利用到的开源技术有</span><span lang=EN-US>Hibernate,Veloctiy,Webwork</span><span>。</span></p>
<p class=MsoNormal><span lang=EN-US><span>3、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US><a href="http://www.jfree.org/jfreereport" target=_new><font color=#0066aa><u>JFreeReport</u></font></a></span><span>，现在是</span><span lang=EN-US>Pentaho</span><span>的一部分，它是一个优秀的用来生成报表的</span><span lang=EN-US>Java</span><span>类库。它为</span><span lang=EN-US>Java</span><span>应用程序提供一个灵活的打印</span> <span>功能并支持输出到打印机和</span><span lang=EN-US>PDF, Excel, HTML</span><span>和</span><span lang=EN-US>XHTML, PlainText, XML</span><span>和</span><span lang=EN-US>CSV</span><span>文件中。</span></p>
<p class=MsoNormal><span lang=EN-US><span>4、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US><a href="http://www.eclipse.org/birt/" target=_new><font color=#0066aa><u>Eclipse BIRT</u></font></a></span><span>，是</span><span lang=EN-US>Eclipse</span><span>下面的一个企业智能和报表</span> <span>工具，能为</span><span lang=EN-US>J2EE</span><span>的</span><span lang=EN-US>WEB</span><span>应用程序创建漂亮醒目的</span><span lang=EN-US>PDF</span><span>或者</span><span lang=EN-US>HTML</span><span>格式的报表，它提供了核心的报表功能。</span></p>
<h2><a name=_Toc146945208><font color=#000000><span lang=EN-US><span><font face=Arial>2.3.</font><span Times New Roman?; font-size-adjust: none; font-stretch: normal?> </span></span></span><span lang=EN-US><font face=Arial>OLAP</font></span></font></a><span><span>工具</span></span></h2>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">联机分析处理工具。目前开源的</span><span lang=EN-US>OLAP</span><span>工具也分为</span><span lang=EN-US>MOLAP</span><span>、</span><span lang=EN-US>ROLAP</span><span>和</span><span lang=EN-US>HOLAP</span><span>，优秀的</span><span lang=EN-US>OLAP</span><span>工具通常有以下特性：</span></p>
<p class=MsoNormal><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>良好的执行性能，能快速地进行分析处理工作。</span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>良好的适用性和可伸缩性。</span></p>
<p class=MsoNormal><span lang=EN-US><span>3、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>开放式接口和丰富的</span><span lang=EN-US>API</span><span>。</span></p>
<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">目前较为知名的开源</span><span lang=EN-US>OLAP</span><span>工具有：</span></p>
<p class=MsoNormal><span class=style7><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span></span><span lang=EN-US><a href="http://mondrian.sourceforge.net/" target=_new><font color=#0066aa><u>Mondrian</u></font></a></span><span>，是</span><span lang=EN-US>Pentaho</span><span>的一部分，为一个用</span><span lang=EN-US>Java</span><span>开发的</span><span lang=EN-US>OLAP</span><span>服务器，<span class=style7>实现了</span></span><span class=style7><span lang=EN-US>MDX</span></span><span class=style7><span>语言、</span><span lang=EN-US>XML</span></span><span class=style7><span>解析和</span><span lang=EN-US>JOLAP</span></span><span class=style7><span>规范，可以不写</span><span lang=EN-US>SQL</span></span><span class=style7><span>就能分析存储于</span><span lang=EN-US>SQL </span></span><span class=style7><span>数据库的庞大数据集，可以封装</span><span lang=EN-US>JDBC</span></span><span class=style7><span>数据源并把数据以多维的方式展现出来。</span><span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US><a href="http://jpivot.sourceforge.net/" target=_new><font color=#0066aa><u>JPivot</u></font></a></span><span>，<span class=style7>是一个</span></span><span class=style7><span lang=EN-US>JSP </span></span><span class=style7><span>自定制的标签库，可以绘制一个</span><span lang=EN-US>OLAP</span></span><span class=style7><span>表格和图表。用户可以执行</span> </span><span class=style7><span>典型的</span><span lang=EN-US>OLAP</span></span><span class=style7><span>导航，如下钻，切片和方块。它使用</span><span lang=EN-US>Mondrian </span></span><span class=style7><span>作为其</span><span lang=EN-US>OLAP</span></span><span class=style7><span>服务器。它使用</span><span lang=EN-US>WCF (Web Component Framework) </span></span><span class=style7><span>，基于</span><span lang=EN-US>XML/XSLT</span></span><span class=style7><span>来渲染</span><span lang=EN-US>Web UI</span></span><span class=style7><span>组件。</span><span lang=EN-US>JPivot</span></span><span class=style7><span>在元数据缓存方面的过于简化的整体性初始化装载的做法将限制它只能处理很小的立方体（</span><span lang=EN-US>Cube</span></span><span class=style7><span>）。</span></span></p>
<h2><a name=_Toc146945209><font color=#000000><span lang=EN-US><span><font face=Arial>2.4.</font><span Times New Roman?; font-size-adjust: none; font-stretch: normal?> </span></span></span><span>数据库</span></font></a></h2>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">开源的数据库也有很多，大多数为关系型数据库，少数为应用于数据仓库环境做了专门的优化工作。</span><span lang=EN-US>Bizgres</span><span>以</span><span lang=EN-US>PostgreSQL</span><span>为基础进行了数据仓库环境下的优化，提高了分析查询性能。</span></p>
<h1><a name=_Toc146945210><font color=#000000><span lang=EN-US><span>3.<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp;&nbsp; </span></span></span><span>开源</span><span lang=EN-US>BI</span></font></a><span><span>套件</span></span></h1>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">下面列出相对成熟和完整，并且有借鉴意义的开源</span><span lang=EN-US>BI</span><span>套件。</span></p>
<h2><a name=_Toc146945211><font color=#000000><span lang=EN-US><span><font face=Arial>3.1.</font><span Times New Roman?; font-size-adjust: none; font-stretch: normal?> </span></span></span><span lang=EN-US><font face=Arial>Bizgres</font></span></font></a></h2>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">为</span><span lang=EN-US>GreenPlum</span><span>公司主导的开源项目，和</span><span lang=EN-US>Sun</span><span>公司达成合作关系。</span><span lang=EN-US>Bizgres</span><span>为</span><span lang=EN-US>BI</span><span>应用而对</span><span lang=EN-US>PostgreSQL</span><span>做了优化，提高了大负荷的并行计算能力，在</span><span lang=EN-US>BI</span><span>环境中，相对于普通的关系型数据库具有卓越的数据处理性能。</span><span lang=EN-US>Bizgres</span><span>的数据库平台可以和</span><span lang=EN-US>KETL</span><span>和</span><span lang=EN-US>JasperReports</span><span>进行整合，从而形成一个</span><span lang=EN-US>BI</span><span>套件：</span></p>
<p class=MsoNormal><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>数据库：</span><span lang=EN-US>BI</span><span>专业数据库</span><span lang=EN-US>Bizgres</span><span>，或者大型应用中的高性能服务器</span><span lang=EN-US>Bizgres MPP</span><span>，能比普通关系数据库快</span><span lang=EN-US>20</span><span>倍</span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>ETL</span><span>工具：</span><span lang=EN-US>KETL</span></p>
<p class=MsoNormal><span lang=EN-US><span>3、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>报表工具：</span><span lang=EN-US>JasperReports</span></p>
<h2><a name=_Toc146945212><font color=#000000><span lang=EN-US><span><font face=Arial>3.2.</font><span Times New Roman?; font-size-adjust: none; font-stretch: normal?> </span></span></span><span lang=EN-US><font face=Arial>Openi</font></span></font></a></h2>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">是一个</span><span lang=EN-US>Java</span><span>开发的</span><span lang=EN-US>Web</span><span>应用，能对</span><span lang=EN-US>OLAP</span><span>服务器、关系数据库和数据挖掘服务器进行分析和报表展示，非常易于使用和部署，界面美观友好，后续还将支持数据挖掘和</span><span lang=EN-US>ETL</span><span>等。</span><span lang=EN-US>Open<em>i</em></span><span>主要包括：</span></p>
<p class=MsoNormal><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>OLAP</span><span>展示：</span><span lang=EN-US>JPivot</span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>报表工具：</span><span lang=EN-US>JFreeChart</span></p>
<p class=MsoNormal><span lang=EN-US><span>3、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>分析数据源连接器</span></p>
<h2><a name=_Toc146945213><font color=#000000><span lang=EN-US><span><font face=Arial>3.3.</font><span Times New Roman?; font-size-adjust: none; font-stretch: normal?> </span></span></span><span lang=EN-US><font face=Arial>Pentaho</font></span></font></a></h2>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">是一个以工作流为核心的、强调面向解决方案而非工具组件的</span><span lang=EN-US>BI</span><span>套件，整合了多个开源项目，目标是和商业</span><span lang=EN-US>BI</span><span>相抗衡。它包括：</span></p>
<p class=MsoNormal><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>工作流引擎：</span><span lang=EN-US>Shark and JaWE</span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>数据库：</span><span lang=EN-US>Firebird RDBMS</span></p>
<p class=MsoNormal><span lang=EN-US><span>3、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>集成管理和开发环境：</span><span lang=EN-US>Eclipse</span></p>
<p class=MsoNormal><span lang=EN-US><span>4、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>报表工具：</span><span lang=EN-US>Eclipse BIRT</span></p>
<p class=MsoNormal><span lang=EN-US><span>5、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>ETL</span><span>工具：</span><span lang=EN-US>Enhydra/Kettle</span></p>
<p class=MsoNormal><span lang=EN-US><span>6、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>OLAP Server</span><span>：</span><span lang=EN-US>Mondrian</span></p>
<p class=MsoNormal><span lang=EN-US><span>7、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>OLAP</span><span>展示：</span><span lang=EN-US>JPivot</span></p>
<p class=MsoNormal><span lang=EN-US><span>8、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>数据挖掘组件：</span><span lang=EN-US>Weka</span></p>
<p class=MsoNormal><span lang=EN-US><span>9、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>应用服务器和</span><span lang=EN-US>Portal</span><span>服务器：</span><span lang=EN-US>JBoss</span></p>
<p class=MsoNormal><span lang=EN-US><span>10、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>单点登陆服务及</span><span lang=EN-US>LDap</span><span>认证：</span><span lang=EN-US>JOSSO</span></p>
<p class=MsoNormal><span lang=EN-US><span>11、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>自定义脚本支持：</span><span lang=EN-US>Mozilla Rhino Javascript</span><span>脚本处理器</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">由上可见</span><span lang=EN-US>Pentaho</span><span>是一个很完善的</span><span lang=EN-US>BI</span><span>解决方案。</span><span lang=EN-US>Pentaho</span><span>偏向于与业务流程相结合的</span><span lang=EN-US>BI</span><span>解决方案，侧重于大中型企业应用。</span></p>
<h2><a name=_Toc146945214><font color=#000000><span lang=EN-US><span><font face=Arial>3.4.</font><span Times New Roman?; font-size-adjust: none; font-stretch: normal?> </span></span></span><span lang=EN-US><font face=Arial>SpagoBI</font></span></font></a></h2>
<p class=MsoNormal><span lang=EN-US>SpagoBI </span><span>集成了</span><span lang=EN-US>Mondrain</span><span>和</span><span lang=EN-US>JProvit</span><span>，能够通过</span><span lang=EN-US>OpenLaszlo</span><span>产生实时报表。</span><span lang=EN-US>SpagoBI</span><span>使用</span><span lang=EN-US>java</span><span>开发，不依赖于具体的操作系统，有很强的扩展能力。它主要包括：</span></p>
<p class=MsoNormal><span lang=EN-US><span>1、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>报表工具：</span><span lang=EN-US>JasperReports /Eclipse BIRT/ iReport</span></p>
<p class=MsoNormal><span lang=EN-US><span>2、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>OLAP Server</span><span>：</span><span lang=EN-US>Mondrian</span></p>
<p class=MsoNormal><span lang=EN-US><span>3、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>OLAP</span><span>展示：</span><span lang=EN-US>JPivot</span></p>
<p class=MsoNormal><span lang=EN-US><span>4、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>数据挖掘组件：</span><span lang=EN-US>Weka</span></p>
<p class=MsoNormal><span lang=EN-US><span>5、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>Map</span><span>引擎：</span><span lang=EN-US>Geo</span></p>
<p class=MsoNormal><span lang=EN-US><span>6、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>ETL</span><span>：</span><span lang=EN-US>BIE</span></p>
<p class=MsoNormal><span lang=EN-US><span>7、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span>搜索引擎：</span><span lang=EN-US>Lucene</span></p>
<p class=MsoNormal><span lang=EN-US><span>8、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>Dashboard</span><span>：</span><span lang=EN-US>OpenLaszlo</span></p>
<p class=MsoNormal><span lang=EN-US><span>9、<span Times New Roman?; font-size-adjust: none; font-stretch: normal?>&nbsp; </span></span></span><span lang=EN-US>Portal Server</span><span>：</span><span lang=EN-US>JBoss/ Tomcat/ JOnAS</span></p>
<p class=MsoNormal><span style="FONT-FAMILY: 宋体">根据其</span><span lang=EN-US>Roadmap</span><span>可以看出，</span><span lang=EN-US>SpagoBI</span><span>将融入更多的</span><span lang=EN-US>BI</span><span>功能，甚至</span><span lang=EN-US>BI</span><span>之外的功能。</span></p>
<img src ="http://www.blogjava.net/gf7/aggbug/140613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2007-08-28 18:09 <a href="http://www.blogjava.net/gf7/archive/2007/08/28/140613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于Weblogic Server 8.1 ant工具开发Web Service</title><link>http://www.blogjava.net/gf7/archive/2007/02/25/100533.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sun, 25 Feb 2007 02:30:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2007/02/25/100533.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/100533.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2007/02/25/100533.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/100533.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/100533.html</trackback:ping><description><![CDATA[
		<p>　　前言：本文不是专门讲述Web Service技术的，读者在阅读本文之前需要具备一定的SOAP和Web Service知识基础，同时对Weblogic Server的使用也应该熟悉。如果要自己动手实践本文的例子，就需要安装Weblogic Server 81,尽管本文是以weblogic server 81为测试环境，但是针对weblogic server 7下也是差不多的。本文只是起个抛砖引玉的作用，如果想深入研究Web Service的开发，还需要参考、学习相关的资料，包括Weblogic Service的相关文档。</p>
		<p>
				<strong>一、概述</strong>
		</p>
		<p>　　在JBuilder中也支持开发基于weblogic的web service，不过实际上在JBuilder下开发web service也是基于ant任务来生成和构造web service的。但是，当初笔者在一个项目中使用JBuilder下自动生成构造ant脚本生成的web service时碰到了一个问题，通过JBuilder生成的web service，如果你的web service调用接口中存在一个或者多个String类型参数的时候，在生成的wsdl文件中对该接口的参数命名不会按照你的后端组件对应方法中参数的名字，而是以string、string0、string1…等形式命名的。而在那个项目中需要在Delphi环境中调用web service，问题就出现了，string在Delphi中是关键词，产生了冲突，不能进行调用。于是笔者决定采用自编写ant脚本的方式来生成和构造web service来解决前面所述Delphi调用的问题。</p>
		<p>　　BEA Weblogic提供了一些Ant任务，用来帮助开发者生成、构造一个Web服务的重要部件，（例如：序列化类、客户端jar支持库、以及web-services.xml描述文件），并且把一个Weblogic Web 服务的所有部分打包成一个可部署的EAR文件。</p>
		<p>　　BEA Weblogic所提供的Web服务Ant任务，支持从实现了Web Service接口的普通JAVA源文件和EJB jar生成Web Service部件，也支持从WSDL描述文件生成，同时支持基于http/https传输协议和JMS传输协议的Web Service。在这一节我们只讲述通过基于一个普通JAVA类作为后端组件来实现的Web Service，传输协议使用http（基于https的方式将在后述关于Web Service安全的部分讲述）。</p>
		<p>
				<strong>二、使用Weblogic ant工具生成Web Service</strong>
		</p>
		<p>　　我们先建立D:\wls_ws_demo的工作目录，在此目录下分别建立src、build、ddfiles、webapp、test目录。具体用途后文会涉及到。</p>
		<p>　　首先我们编写一个实现了两个Web Service接口的普通JAVA类： </p>
		<pre class="code">package com.wnetw.ws.demo;

public class HelloWorldWS{

  public String sayHello(){
	return "Hello World!";
  }

  public String welcome(String name){
	return "Hello " + name + ",Welcome to WebService!";
  }

}
</pre>
		<p>　　上面两个方法就不需要解释了，很简单。把此类按封装包一致的路径放置在src目录下。</p>　　下面是本示例中ant脚本文件内的属性设置： <pre class="code">&lt;property name="build.compiler" value="modern"/&gt;
  &lt;property name="src.dir" value="src"/&gt;
  &lt;property name="build.dir" value="build"/&gt;
  &lt;property name="war.file" value="${build.dir}/
　applications/HelloWorldWS.war" /&gt;
  &lt;property name="ear.file" value="${build.dir}/<br />applications/HelloWorldWS.ear" /&gt;
  &lt;property name="clients.lib" value="${build.dir}/<br />clientslib/HelloWorldWS_clients.jar"/&gt;
  &lt;property name="bea.home" value="D:/bea"/&gt;
  &lt;property name="wls.dir" value="${bea.home}/weblogic81/server"/&gt;
  &lt;property name="wlslib.dir" value="${wls.dir}/lib"/&gt;
  &lt;property name="wlsext.dir" value="${wls.dir}/ext"/&gt;
  &lt;property name="namespace" value="http://www.wnetw.com/demo/"/&gt;
  &lt;path id="classpath"&gt;
    &lt;dirset dir="${build.dir}/classes"&gt;
      &lt;include name="**"/&gt;
    &lt;/dirset&gt;
    &lt;fileset dir="${wlslib.dir}"&gt;
      &lt;include name="**/weblogic.jar"/&gt;
      &lt;include name="**/webservices.jar"/&gt;
    &lt;/fileset&gt;
  &lt;/path&gt;
  &lt;property name="javac.fork" value="no"/&gt;
  &lt;property name="javac.debug" value="no"/&gt;
  &lt;property name="javac.optimize" value="on"/&gt;
  &lt;property name="javac.listfiles" value="yes"/&gt;
  &lt;property name="javac.failonerror" value="yes"/&gt;
</pre><p>　　上面的属性应该不是很难理解，关键的是对于bea weblogic server安装目录和构造生成文件的路径说明，其次是对classpath的设置，需要用到的两个weblogic库是weblogic.jar和webservices.jar。</p><p>　　接着我们看看我们在本节中使用的Weblogic提供的Ant任务：</p><p><strong>1、source2wsdd</strong></p><p>　　source2wsdd Ant任务最基本的功能是根据我们编写的普通JAVA类源文件生成一个Web Service所必需的两个部件：web-services.xml和.wsdl描述文件。</p>　　下面是针对上面HelloWorldWS.java对应的Ant脚本： <pre class="code">&lt;target name="genwsdd"&gt;
    &lt;source2wsdd javaSource="${src.dir}/com/wnetw/ws/<br />demo/HelloWorldWS.java"
             ddFile="${build.dir}/wsddfiles/web-services.xml"
             wsdlFile="${build.dir}/wsddfiles/HelloWorldWS.wsdl"
             serviceURI="/HelloWorldWS"&gt;
      &lt;classpath refid="classpath"/&gt;
    &lt;/source2wsdd&gt;
  &lt;/target&gt;
</pre><p><strong>属性说明</strong></p><p><strong>　　javaSource</strong>：指定web service的实现后端组件，这里是普通JAVA类com.wnetw.ws.demo HelloWorldWS.java。注意属性里面是对源文件目录路径设置，而不是包路径。</p><p><strong>　　ddFile</strong>：生成的web service部署描述符文件web-services.xml的存放路径。</p><p><strong>　　wsdlFile</strong>：生成的.wsdl文件存放的路径和名字。</p><p><strong>　　serviceURI</strong>：客户应用程序调用此Web服务的URL中的Web Service URI部分。注意：必须以“/”开头。例如：/ HelloWorldWS 。同时这个URI属性也会成为生成的web-services.xml 部署描述符文件中&lt;web-service&gt;元素的uri属性。</p><p>　　例如：本机访问本web service例子的url是http://localhost:7001/ WSDemo/ HelloWorldWS</p><p>　　上面的serviceURI属性就指定了上述url中的/ HelloWorldWS这一部分。</p><p><strong>2、clientgen</strong></p><p>　　clientgen可以用来生成JAVA环境下客户端应用调用一个Web Service客户端jar支持库。可以通过wsdl文件来生成，也可以通过一个包含web service实现的ear文件来生成。</p>　　下面是clientgen ant任务的脚本示例： <pre class="code">&lt;target name="genclient"&gt;
    &lt;clientgen wsdl="${build.dir}/wsddfiles/HelloWorldWS.wsdl"
               packageName="com.wnetw.ws.demo.client"
               clientJar="${clients.lib}"
               keepGenerated="false"&gt;
      &lt;classpath refid="classpath"/&gt;
    &lt;/clientgen&gt;
  &lt;/target&gt;
</pre><p>　　这里采用从前面source2wsdd任务生成的wsdl文件来生成客户端jar支持库。通过wsdl属性指定。</p><p><strong>3、war</strong></p><p>　　这是ant提供的标准任务，这里与其他普通的war包有一点区别是，需要把web-services.xml文件打包到war中去。</p><p>　　说明：需要准备web.xml，后面对于安全设置的时候还需要weblogic.xml文件，这里先都打包进去，这些文件都需要提前编辑准备好：</p><pre class="code">---Web.xml---
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web <br />Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;
&lt;web-app&gt;
  &lt;mime-mapping&gt;
    &lt;extension&gt;wsdl&lt;/extension&gt;
    &lt;mime-type&gt;text/xml&lt;/mime-type&gt;
  &lt;/mime-mapping&gt;
&lt;/web-app&gt;

---weblogic.xml---
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web <br />Application 7.0//EN" "http://www.bea.com/servers/wls700<br />/dtd/weblogic700-web-jar.dtd"&gt;
&lt;weblogic-web-app&gt;
&lt;/weblogic-web-app&gt;
</pre><p>　　这个文件没设置，在后面关于安全的处理里面需要这里配置角色映射。</p><p>　　下面是war ant脚本示例：</p><pre class="code">&lt;target name="genwar"&gt;
    &lt;war destfile="${war.file}" webxml="webapp/WEB-INF/web.xml"&gt;
      &lt;classes dir="${build.dir}/classes"/&gt;
      &lt;webinf dir="${build.dir}/wsddfiles"&gt;
        &lt;include name="web-services.xml"/&gt;
      &lt;/webinf&gt;
      &lt;webinf dir="webapp/WEB-INF"&gt;
        &lt;include name="weblogic.xml"/&gt;
      &lt;/webinf&gt;
    &lt;/war&gt;
  &lt;/target&gt;
</pre><p><strong>4、ear</strong></p><p>　　这也是ant标准任务，需要注意的是必须提前编写application.xml文件，下面针对本文例子的application.xml文件： </p><pre class="code">&lt;!DOCTYPE application PUBLIC '-//Sun Microsystems, Inc.//DTD J2EE <br />Application 1.3//EN' 'http://java.sun.com/dtd/application_1_3.dtd'&gt;
&lt;application&gt;
  &lt;display-name&gt;&lt;/display-name&gt;
  &lt;module&gt;
    &lt;web&gt;
      &lt;web-uri&gt;HelloWorldWS.war&lt;/web-uri&gt;
      &lt;context-root&gt;WSDemo&lt;/context-root&gt;
    &lt;/web&gt;
  &lt;/module&gt;
&lt;/application&gt;
</pre><p>　　说明：context-root元素指定此Web Service所在Web应用的应用根。</p><p>　　例如：本机访问本web service例子的url是http://localhost:7001/<br />WSDemo/ HelloWorldWS</p><p>　　上面的context-root元素就指定了上述url中的WSDemo这一部分。</p><p>　　下面是本文例子的ear ant任务脚本：</p><pre class="code">&lt;target name="genear"&gt;
    &lt;ear destfile="${ear.file}" appxml="ddfiles/application.xml"&gt;
      &lt;fileset dir="${build.dir}/applications" includes="*.war"/&gt;
    &lt;/ear&gt;
  &lt;/target&gt;
</pre><p>　　核心的ant任务说明完了，下面是完整的ant脚本文件：</p><pre class="code">--- build_wls_all.xml---
&lt;project name="wls_ws_demo" default="all" basedir="."&gt;

  &lt;property name="build.compiler" value="modern"/&gt;
  &lt;property name="src.dir" value="src"/&gt;
  &lt;property name="build.dir" value="build"/&gt;
  &lt;property name="war.file" value="${build.dir}/applications/<br />HelloWorldWS.war" /&gt;
  &lt;property name="ear.file" value="${build.dir}/applications/<br />HelloWorldWS.ear" /&gt;
  &lt;property name="clients.lib" value="${build.dir}/clientslib/<br />HelloWorldWS_clients.jar"/&gt;
  &lt;property name="bea.home" value="D:/bea"/&gt;
  &lt;property name="wls.dir" value="${bea.home}/weblogic81/server"/&gt;
  &lt;property name="wlslib.dir" value="${wls.dir}/lib"/&gt;
  &lt;property name="wlsext.dir" value="${wls.dir}/ext"/&gt;
  &lt;property name="namespace" value="http://www.wnetw.com/demo/"/&gt;
  &lt;path id="classpath"&gt;
    &lt;dirset dir="${build.dir}/classes"&gt;
      &lt;include name="**"/&gt;
    &lt;/dirset&gt;
    &lt;fileset dir="${wlslib.dir}"&gt;
      &lt;include name="**/weblogic.jar"/&gt;
      &lt;include name="**/webservices.jar"/&gt;
    &lt;/fileset&gt;
  &lt;/path&gt;
  &lt;property name="javac.fork" value="no"/&gt;
  &lt;property name="javac.debug" value="no"/&gt;
  &lt;property name="javac.optimize" value="on"/&gt;
  &lt;property name="javac.listfiles" value="yes"/&gt;
  &lt;property name="javac.failonerror" value="yes"/&gt;

  &lt;target name="all" depends="clean,mdir,compile,genwsdd,<br />genclient,genwar,genear"/&gt;
  
  &lt;target name="clean"&gt;
    &lt;delete dir="${build.dir}"/&gt;
  &lt;/target&gt;
  
  &lt;target name="mdir"&gt;
    &lt;mkdir dir="${build.dir}"/&gt;
    &lt;mkdir dir="${build.dir}/classes"/&gt;
    &lt;mkdir dir="${build.dir}/applications"/&gt;
    &lt;mkdir dir="${build.dir}/clientslib"/&gt;
    &lt;mkdir dir="${build.dir}/wsddfiles"/&gt;
  &lt;/target&gt;
  
  &lt;target name="compile"&gt;
    &lt;javac encoding="GBK" srcdir="${src.dir}" destdir=<br />"${build.dir}/classes"&gt;
      &lt;classpath refid="classpath"/&gt;
    &lt;/javac&gt;
  &lt;/target&gt;

  &lt;target name="genwsdd"&gt;
    &lt;source2wsdd javaSource="${src.dir}/com/wnetw/ws/<br />demo/HelloWorldWS.java"
                 ddFile="${build.dir}/wsddfiles/web-services.xml"
                 wsdlFile="${build.dir}/wsddfiles/HelloWorldWS.wsdl"
                 serviceURI="/HelloWorldWS"&gt;
      &lt;classpath refid="classpath"/&gt;
    &lt;/source2wsdd&gt;
  &lt;/target&gt;

  &lt;target name="genclient"&gt;
    &lt;clientgen wsdl="${build.dir}/wsddfiles/HelloWorldWS.wsdl"
               packageName="com.wnetw.ws.demo.client"
               clientJar="${clients.lib}"
               keepGenerated="false"&gt;
      &lt;classpath refid="classpath"/&gt;
    &lt;/clientgen&gt;
  &lt;/target&gt;

  &lt;target name="genwar"&gt;
    &lt;war destfile="${war.file}" webxml="webapp/WEB-INF/web.xml"&gt;
      &lt;classes dir="${build.dir}/classes"/&gt;
      &lt;webinf dir="${build.dir}/wsddfiles"&gt;
        &lt;include name="web-services.xml"/&gt;
      &lt;/webinf&gt;
      &lt;webinf dir="webapp/WEB-INF"&gt;
        &lt;include name="weblogic.xml"/&gt;
      &lt;/webinf&gt;
    &lt;/war&gt;
  &lt;/target&gt;
  
  &lt;target name="genear"&gt;
    &lt;ear destfile="${ear.file}" appxml="ddfiles/application.xml"&gt;
      &lt;fileset dir="${build.dir}/applications" includes="*.war"/&gt;
    &lt;/ear&gt;
  &lt;/target&gt;

&lt;/project&gt;
</pre><p>　　运行ant生成Web Service：</p><p>　　打开命令行窗口，转到工作目录D:\wls_ws_demo下，在此目录下先运行D:\bea\weblogic81\server\bin\setWLSEnv.cmd（此cmd文件具体路径与你的weblogic platform81实际安装目录相关）进行环境设置，然后运行：D:\bea\weblogic81\server\bin\ant.bat -buildfile build_wls_all.xml。</p><p>　　运行结束，出现“BUILD SUCCESSFUL”，那就代表OK了。转到工作目录下的build目录，你就会看到HelloWorldWS.ear这个文件。</p><p><strong>三、测试Web Service</strong></p><p>　　本节将讲述对前一节里生成的Web Service HelloWorldWS进行测试。</p><p>　　启动Weblogic Server，进入Weblogic Server控制台，在Deployments-&gt;Applications下部署上节生成的HelloWorldWS.ear。</p><p><strong>1、通过Weblogic自动生成的测试主页测试</strong></p><p>　　部署成功后，在浏览器中输入http://localhost:7001/WSDemo/HelloWorldWS访问Weblogic Server默认生成的上述HelloWorldWS Web Service的测试主页。</p><p>如下图： </p><p><img height="279" src="http://dev2dev.bea.com.cn/images/051019/0510190101.jpg" width="372" /></p><p>　　图上列出了HelloWorldWS Web Service上的两个方法：welcome和sayHello。</p><p>　　点击welcome连接进入wecome方法的测试页，如下图： </p><p><img height="252" src="http://dev2dev.bea.com.cn/images/051019/0510190102.jpg" width="336" /></p><p>　　在上述页面输入“老Z”，提交后就会看到如下图页面： </p><p><img height="252" src="http://dev2dev.bea.com.cn/images/051019/0510190103.jpg" width="336" /></p><p>　　测试的结果跟上节中的HelloWorldWS.java实现此方法的结果是一样的。测试sayHello方法跟上面过程一样。</p><p>　　在测试主页中还能看到在JAVA环境下，基于clientgen ant任务生成的jar客户端stub支持库调用此HelloWorldWS Web服务的代码示例。</p><p><strong>2、使用JAVA程序调用Web Service</strong></p><p>　下面实际编写一个java测试程序来调用上述Web Service。 </p><pre class="code">--- HelloWorldWSTest.java ---
import com.wnetw.was.demo.client.*;

public class HelloWorldWSTest {

  public static void main(String[] args){
    try{
      HelloWorldWS_Impl ws = new HelloWorldWS_Impl("http://localhost:7001<br />/WSDemo/HelloWorldWS?WSDL");
      HelloWorldWSPort port = ws.getHelloWorldWSPort();
      System.out.println(port.welcome(“老Z”));
    }catch(Exception e){
      e.printStackTrace();
      System.out.println(e);
    }
  }

}
</pre><p>　　编译、运行上述测试程序的时候首先需要weblogic客户端webservice支持库webserviceclient.jar，还需要前面clientgen ant任务生成的jar客户端stub支持库HelloWorldWS_clients.jar。在下面的编译、运行测试程序的ant脚本中可以看到在classpath中引入了上述两个jar。</p><p>　　编译、运行测试程序的ant脚本如下： </p><pre class="code">&lt;project name="wls_ws_demo" default="all" basedir="."&gt;

  &lt;property name="build.compiler" value="modern"/&gt;
  &lt;property name="bea.home" value="D:/bea"/&gt;
  &lt;property name="wls.dir" value="${bea.home}/weblogic81/server"/&gt;
  &lt;property name="wlslib.dir" value="${wls.dir}/lib"/&gt;
  &lt;property name="wlsext.dir" value="${wls.dir}/ext"/&gt;
  &lt;path id="classpath"&gt;
    &lt;fileset dir="${wlslib.dir}"&gt;
      &lt;include name="**/webserviceclient.jar"/&gt;
    &lt;/fileset&gt;
    &lt;fileset dir="build/clientslib"&gt;
      &lt;include name="**/HelloWorldWS_clients.jar"/&gt;
    &lt;/fileset&gt;
    &lt;pathelement path="test"/&gt;
  &lt;/path&gt;
  &lt;property name="javac.fork" value="no"/&gt;
  &lt;property name="javac.debug" value="no"/&gt;
  &lt;property name="javac.optimize" value="on"/&gt;
  &lt;property name="javac.listfiles" value="yes"/&gt;
  &lt;property name="javac.failonerror" value="yes"/&gt;

  &lt;target name="all" depends="compile,run"/&gt;
  
  &lt;target name="compile"&gt;
    &lt;javac encoding="GBK" srcdir="test" destdir="test"&gt;
      &lt;classpath refid="classpath"/&gt;
    &lt;/javac&gt;
  &lt;/target&gt;

  &lt;target name="run"&gt;
    &lt;java classname="HelloWorldWSTest"&gt;
      &lt;classpath refid="classpath"/&gt;
    &lt;/java&gt;
  &lt;/target&gt;

&lt;/project&gt;
</pre>　　运行上述ant脚本后，如果成功的话，应该得到类似下图结果： <img height="211" src="http://dev2dev.bea.com.cn/images/051019/0510190104.jpg" width="324" /><p><strong>3、在VB下调用Web Service</strong></p><p>　　下面我在VB环境下来调用下这个Web Service，笔者使用的是Visual Basic 6.0，要在VB下调用Web Service需要先安装Microsoft SOAP toolkit。</p><p>　　新建一个VB工程，然后把Microsoft Soap Type Library引用进来，如下图： </p><p><img height="261" src="http://dev2dev.bea.com.cn/images/051019/0510190105.jpg" width="348" /></p><p>　　新建一个form1，添加一个按钮command1，在form1源代码窗口中整个拷贝如下代码：</p><pre class="code">Dim soap As MSSOAPLib.SoapClient
Private Sub Command1_Click()

MsgBox soap.sayHello()
MsgBox soap.welcome("老Z")

If Err &lt;&gt; 0 Then
    MsgBox "Web Service调用失败： " + Err.Description
End If
End Sub

Private Sub Form_Load()
Set soap = New MSSOAPLib.SoapClient

On Error Resume Next

Call soap.mssoapinit("http://localhost:7001/WSDemo/HelloWorldWS?WSDL")

If Err &lt;&gt; 0 Then
    MsgBox "初始化SOAP失败： " + Err.Description
End If

End Sub
</pre><p>　　然后运行工程，点击窗口上的按钮就开始调用前面部署的Web Service（确保Weblogic Server在运行中），成功的话会得到如下图的两个MessageBox： </p><p><img height="257" src="http://dev2dev.bea.com.cn/images/051019/0510190106.jpg" width="312" /></p><p><img height="239" src="http://dev2dev.bea.com.cn/images/051019/0510190107.jpg" width="288" /></p><p><strong>四、使用非内建数据类型</strong></p><p>　　前面例子中的Web Service方法中使用的参数和返回值都是String，类似String，int等数据类型是属于Weblogic web service所支持的内建类型，关于Weblogic web service所支持的内建数据类型请参见：<a href="http://e-docs.bea.com/wls/docs81/webserv/implement.html#1054236">http://e-docs.bea.com/wls/docs81/webserv/implement.html#1054236</a></p><p>　　所支持的XML非内建类型请参见：</p><p><a href="http://e-docs.bea.com/wls/docs81/webserv/assemble.html#1060805" target="_blank">http://e-docs.bea.com/wls/docs81/webserv/assemble.html#1060805</a></p><p>　　所支持的Java非内建数据类型请参见：</p><p><a href="http://e-docs.bea.com/wls/docs81/webserv/assemble.html#1068595" target="_blank">http://e-docs.bea.com/wls/docs81/webserv/assemble.html#1068595</a></p><p>　　WebLogic Server能够对内建数据类型进行XML与Java表示之间的转换。但是，如果你在web service操作中使用了非内建数据类型，那么你必须提供以下信息，以确保weblogic server能够正确地进行转换。</p><ul><li>用于处理数据的Java表示与XML之间的转换的序列化类； 
</li><li>包含了数据类型Java表示的Java类； 
</li><li>数据类型的XML Schema表示； 
</li><li>web-services.xml部署描述文件中的数据类型映射信息。 </li></ul><p>　　Weblogic Server中带有servicegen和autotype Atn任务，这两个任务通过对web service的无状态EJB或者Java类后端组件的内省，从而自动生成上述部件。上述Ant任务能够处理许多非内建数据类型，所以大多数的开发者并不需要手工生成上述的部件。</p><p>　　有时，你可能也需要手工去创建非内建数据类型部件。因为你的数据类型可能很复杂，以致Ant任务不能正确生成前述部件。你也可能想要自己控制数据在XML和Java表示之间的转换过程，而不依赖Weblogic Server所使用的缺省转换程序。</p><p>　　本节将演示在Weblogic web service中如何处理非内建(自定义)的数据类型。</p><p>　　我们先编写一个数值Bean类UserInfo，如下： </p><pre class="code">package com.wnetw.ws.demo;

import java.util.*;

public class UserInfo{
  private Integer userid;
  private String username;
  private String sex;
  private Date birthday;
  private int level;
  private double salary;
  private telcodes list;

  public UserInfo(){}

  public Integer getUserid(){
	return userid;
  }

  public void setUserid(Integer userid){
	this.userid = userid;
  }

  public String getUsername(){
	return username;
  }

  public void setUsername(String username){
	this.username = username;
  }

  public String getSex(){
	return sex;
  }

  public void setSex(String sex){
	this.sex = sex;
  }

  public Date getBirthday(){
	return birthday;
  }

  public void setBirthday(Date birthday){
	this.birthday = birthday;
  }

  public int getLevel(){
	return level;
  }

  public void setLevel(int level){
	this.level = level;
  }

  public double getSalary(){
	return salary;
  }

  public void setSalary(double salary){
	this.salary = salary;
  }

  public List getTelcodes(){
	return telcodes;
  }

  public void setTelcodes (List telcodes){
	this. telcodes = telcodes;
  }

}
</pre><p>　　在前文中的后端组件类HelloWorldWS.java中增加一个方法：</p><pre class="code">public UserInfo getUserInfo(Integer userid){
	UserInfo userinfo = new UserInfo();
	userinfo.setUserid(userid);
	userinfo.setUsername("李泽林");
	userinfo.setSex("男");
	userinfo.setBirthday(new Date());
	userinfo.setLevel(2);
	userinfo.setSalary(1000.51);
	List telcodes = new ArrayList();
	telcodes.add("123");
	telcodes.add("321");
	userinfo.setTelcodes (telcodes);
    return userinfo;
  }
</pre><p>　　在这个方法里，返回值是UserInfo，这是我们前面定义的数值Bean，由于这是非内建类型，而且也不属于受支持的非内建类型，所以需要我们必须自己来处理XML和UserInfo Java表示数据类型之间的转换。</p><p>　　在本文的例子中，我们使用Weblogic Server的autotype任务来做这件事情。我们先在build目录建一个autotype目录，然后在前文中ant完整脚本中的compile任务之后增加下述脚本： </p><pre class="code">&lt;target name="gentypeinfo"&gt;
    &lt;autotype javatypes="com.wnetw.ws.demo.UserInfo"
              targetNamespace="${namespace}"
              packageName="com.wnetw.ws.demo"
              destDir="${build.dir}/autotype"
              keepGenerated="true"&gt;
      &lt;classpath refid="classpath"/&gt;
    &lt;/autotype&gt;
    &lt;copy todir="${build.dir}/classes"&gt;
      &lt;fileset dir="${build.dir}/autotype"&gt;
        &lt;include name="**/*.class"/&gt;
      &lt;/fileset&gt;
    &lt;/copy&gt;
  &lt;/target&gt;</pre><p>　　autotype Ant任务有几个常用属性，下面简要说明下：</p><p><strong>　　javatypes</strong>：需要进行类型转换的非内建（自定义）数据类型java类，注意取值是全限定类名，不需要带上java或者class扩展名。如果存在多个这样的数据类型类，用逗号“,”隔开；</p><p><strong>　　targetNamespace</strong>：在对数据类型映射到XML的时候使用的命名空间；</p><p><strong>　　packageName</strong>：生成的序列化相关类的封装包；</p><p><strong>　　destDir</strong>：生成的序列化相关类存放的目录；</p><p><strong>　　keepGenerated</strong>：是否保留中间java源文件，取值为：true或者false。</p><p>　　关于autotype任务的详细信息请参考：</p><p><a href="http://e-docs.bea.com/wls/docs81/webserv/anttasks.html#1080062" target="_blank">http://e-docs.bea.com/wls/docs81/webserv/anttasks.html#1080062</a></p><p>　　上述ant任务成功运行后就会生成build/autotype/目录下生成types.xml文件以及按包封装的数据转换类的源文件和class文件。</p><p>　　由于增加了自定义数据类型，所以我们还得更新source2wsdd任务脚本，以下是增加了自定义数据类型处理后的source2wsdd任务脚本： </p><pre class="code">&lt;target name="genwsdd"&gt;
    &lt;source2wsdd javaSource="${src.dir}/com/wnetw/ws/demo/HelloWorldWS.java"
                 typesInfo="${build.dir}/autotype/types.xml"
                 ddFile="${build.dir}/wsddfiles/web-services.xml"
                 wsdlFile="${build.dir}/wsddfiles/HelloWorldWS.wsdl"
                 serviceURI="/HelloWorldWS"&gt;
      &lt;classpath refid="classpath"/&gt;
    &lt;/source2wsdd&gt;
  &lt;/target&gt;
</pre><p>　　跟以前的脚本相比，增加了typesInfo属性来指定自定义数据类型的XML描述文件。</p><p>　　增加了对自定义数据类型支持后的完整脚本请参考本文代码下载文件。</p><p>　　按照第一节所述方法运行ant脚本build_wls_all.xml后，再部署build\applications\目录下的HelloWorldWS.ear。就可以按照以前说的方法进行测试了。</p><p>　　这一次在Weblogic Server自动生成的web service测试主页：</p><p>http://localhost:7001/WSDemo/HelloWorldWS</p><p>　　可以发现多了一个叫getUserInfo的方法连接，进入此方法的调用测试页面，调用此方法后就可以看到此web service方法的调用结果，以下是结果截图： </p><p><img height="442" src="http://dev2dev.bea.com.cn/images/051019/0510190108.jpg" width="384" /></p><p>　　从调用测试结果页面可以看到，这一次的Return Value是：</p><p>com.wnetw.ws.demo.UserInfo@82d235</p><p>　　这正是我们的web service方法返回值类型类型的一个对象，图中的下面也以SOAP消息的形式描述了调用的输入和返回结果。</p><p>　　我们接着修改测试类HelloWorldWSTest.java，如以下： </p><pre class="code">import com.wnetw.ws.demo.client.*;

import com.wnetw.ws.demo.UserInfo;

public class HelloWorldWSTest {

  public static void main(String[] args){
    try{
      HelloWorldWS_Impl ws = new HelloWorldWS_Impl("http://localhost:7001<br />/WSDemo/HelloWorldWS?WSDL");
      HelloWorldWSPort port = ws.getHelloWorldWSPort();
      System.out.println(port.sayHello());
      System.out.println(port.welcome("老Z"));
      System.out.println("开始测试自定义数据类型的返回值。。。");
	  UserInfo info = port.getUserInfo(100);
	  System.out.println(info);
      System.out.println(info.getUsername());

    }catch(Exception e){
      e.printStackTrace();
      System.out.println(e);
    }
  }

}
</pre><p>　　看看以下代码好像有点问题，UserInfo info = port.getUserInfo(123);我们在HelloWorldWS.java类中定义的对应方法是getUserInfo(Integer userid)，参数是Integer的，但是上述测试类代码中却使用int类型，这是正确的。我们可以把clientgen任务中的keepGenerated属性设为true，把自动生成的java源代码保留下来，build成功后，我们打开build\clientslib目录下HelloWorldWS_clients.jar文件中的com.wnetw.ws.demo.client.HelloWorldWSPor.java源文件，可以看到如下代码：</p><pre class="code">package com.wnetw.ws.demo.client;

/**
 * Generated interface, do not edit.
 *
 * This stub interface was generated by weblogic
 * webservice stub gen on Sat Sep 17 16:11:21 CST 2005 */

public interface HelloWorldWSPort extends java.rmi.Remote{

  /**
   * welcome 
   */

  public java.lang.String welcome(java.lang.String name) 
       throws java.rmi.RemoteException ;
  /**
   * sayHello 
   */

  public java.lang.String sayHello() 
       throws java.rmi.RemoteException ;
  /**
   * getUserInfo 
   */

  public com.wnetw.ws.demo.UserInfo getUserInfo(int userid) 
       throws java.rmi.RemoteException ;
}</pre><p>　　其中的getUserInfo(int userid)方法是使用int参数的！如果你使用Integer类型参数，反而会编译通不过！只能认为这是weblogic server ant任务对数据类型映射的具体实现了，如果你仔细看了本节前面所述对java内建数据类型的支持列表，那么也是好理解的，因为java数据类型到XML Schema数据类型映射中，java中的int和java.lang.Integer都映射到了int。所以web service服务端接收到的SOAP消息中只会是XML Schema int类型，无法区分客户端使用的会是int或者java.lang.Integer，所以在ant工具根据wsdl文件自动生成客户端支持类的时候就只能使用int了，没法区分int或者java.lang.Integer。这是个有意思的问题^-^一不小心也许会在你工作中浪费不必要的时间。当然如果有必要，你完全可以手动修改、甚至完全自己来生成客户端支持库和数据类型转换类。不过嘛，除了出于研究和特殊情况外这是没有必要的。</p><p>　　我们接着看看HelloWorldWS_clients.jar中还有什么东西，发现有个language_builtins这样的包，从包名也许你能猜到这是干什么的，是对java语言内建数据类型处理的包，此包下面是util包，里面有ListCodec.class类。看看我们的UserInfo类，里面使用了List类，这个包里面的类正是用来处理java.util.List数据类型的，java.util.List属于Weblogic server web service所支持的非内建数据类型，也就是说不需要通过autotype明确来标志生成相关的数据转换类和类型信息。但是，java.util.List又有别于int、java.lang.String等wls web service所支持的内建类型，对于java.util.List等受支持的非内建类型由ant任务自动生动相关数据类型处理信息，不需要手工干预。对比来看，int、java.lang.String等wls web service所支持的内建类型是直接映射，不需要数据类型转换相关类。Java.util.List最终映射成了XML Shema SOAP Array类型。其他类型请参考：<a href="http://e-docs.bea.com/wls/docs81/webserv/assemble.html#1068595" target="_blank">http://e-docs.bea.com/wls/docs81/webserv/assemble.html#1068595</a></p><p>　　运行修改后的build_wls_test.xml脚本，成功的话应该得到如下图类似结果：</p><p><img height="246" src="http://dev2dev.bea.com.cn/images/051019/0510190109.jpg" width="372" /></p><p>　　增加了自定义数据类型后，VB测试客户端的处理也得增加一些处理来测试返回值为UserInfo的web service方法，如下面代码：</p><p>Set Nodes = soap.getUserInfo(100)</p><p>MsgBox Nodes(0).nodeName + ":" + Nodes(0).Text</p><p>MsgBox Nodes(1).nodeName + ":" + Nodes(1).Text</p><p>MsgBox Nodes(2).nodeName + ":" + Nodes(2).xml</p><p>MsgBox Nodes(3).nodeName + ":" + Nodes(3).Text</p><p>MsgBox Nodes(4).nodeName + ":" + Nodes(4).Text</p><p>MsgBox Nodes(5).nodeName + ":" + Nodes(5).Text</p><p>MsgBox Nodes(6).nodeName</p><p>　　完整VB测试客户端代码请见本文附带下载代码。 </p><p><strong>五、配置Web Service安全</strong></p><p>　　Weblogic Web Service包括三种不同概念的安全设置：</p><ul><li>消息层安全：对SOAP消息中数据的数字签名或者加密； 
</li><li>传输层安全：使用SSL来保证客户应用与Web Service之间连接的安全性； 
</li><li>访问控制：指定何种用户、组、角色被允许访问该Web Service。 </li></ul><p>　　在这里我们主要针对访问控制概念上的安全处理。</p><p>　　Weblogic Web Service最终是作为一个标准的J2EE ear打包文件提供进行部署的，其中包含了一个war包，也就是说web service是以web应用的形式提供并部署的，这从前面的章节就可以看出。</p><p>　　所以，针对web service的访问控制安全处理与J2EE中对于Web资源的访问控制处理是一样的。具体的说就是对特定Web资源增加安全约束。具体配置就是通过在Web应用部署描述符web.xml增加相应的元素：需要进行安全约束的资源集合、授权访问的角色列表、对用户数据的安全约束、角色映射等信息。</p><p>　　在这里，我们需要对前面用到的web.xml文件进行修改，如下所示：</p><pre class="code">&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web <br />Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;
&lt;web-app&gt;

  &lt;mime-mapping&gt;
    &lt;extension&gt;wsdl&lt;/extension&gt;
    &lt;mime-type&gt;text/xml&lt;/mime-type&gt;
  &lt;/mime-mapping&gt;
  
  &lt;security-constraint&gt;
    &lt;display-name&gt;SecurityConstraint&lt;/display-name&gt;
    &lt;web-resource-collection&gt;
      &lt;web-resource-name&gt;HelloWorldWS&lt;/web-resource-name&gt;
      &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
      &lt;http-method&gt;GET&lt;/http-method&gt;
      &lt;http-method&gt;POST&lt;/http-method&gt;
    &lt;/web-resource-collection&gt;
    &lt;auth-constraint&gt;
      &lt;role-name&gt;testrole&lt;/role-name&gt;
    &lt;/auth-constraint&gt;
  &lt;/security-constraint&gt;

  &lt;security-role&gt;
    &lt;role-name&gt;testrole&lt;/role-name&gt;
  &lt;/security-role&gt;
  
&lt;/web-app&gt;
</pre><p>　　然后运行ant构造脚本，部署ear。部署成功后，你会在weblogic server运行命令行窗口中看到如下类似信息：</p><pre class="code">&lt;2005-9-24 下午22时03分45秒 CST&gt; &lt;Warning&gt; &lt;HTTP&gt; &lt;BEA-101304&gt; <br />&lt;Webapp: ServletC
ontext(id=11680063,name=WSDemo,context-path=/WSDemo), <br />the role: testrole defined
 in web.xml has not been mapped to principals in <br />security-role-assignment in web
logic.xml. Will use the rolename itself as the principal-name.&gt;
</pre><p>　　这是因为没有进行角色映射，所以直接使用角色名作为用户名了。这只是一个警告信息，没有关系。后面将会讲述怎么进行角色映射。</p><p>　　然后进入weblogic server Console，新建一个名叫testrole的用户。接着在左侧目录树中一次展开Deployments-Applications- HelloWorldWS- WSDemo，在WSDemo节点上鼠标右击，选择Define Security Policy… </p><p><img height="224" src="http://dev2dev.bea.com.cn/images/051019/0510190110.jpg" width="348" /></p><p><img height="270" src="http://dev2dev.bea.com.cn/images/051019/0510190111.jpg" width="360" /></p><p>　　在Policy Condition项选择User name of the caller，点击增加，在接着出现的窗口中填入testrole,OK之后，点击上图页面中的Apply。接下来就可以跟以前一样测试了。</p><p>　　浏览器中输入<a href="http://localhost:7001/WSDemo/HelloWorldWS" target="_blank">http://localhost:7001/WSDemo/HelloWorldWS</a>，这个时候会弹出来一个登陆框，如下图： </p><p><img height="278" src="http://dev2dev.bea.com.cn/images/051019/0510190112.jpg" width="372" /></p><p>　　现在可以看到，访问控制起作用了。输入testrole以及拟增加用户的时候指定的密码后，就能进入到和以前一样的测试主页了。</p><p>　　上面那种使用角色名和用户名对应的方式显示在实际应用中是不方便的，因为具体会有什么样的用户会访问此web service在构建时是不确定的。我们可以使用角色映射的方式来避免这个问题。</p><p>　　进行角色映射需要在weblogic.xml文件中配置，下面我将对testrole映射到一个group，weblogic.xml文件如下所示： </p><pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web<br /> Application 7.0//EN" "http://www.bea.com/servers/wls700/dtd<br />/weblogic700-web-jar.dtd"&gt;

&lt;weblogic-web-app&gt;

  &lt;security-role-assignment&gt;
    &lt;role-name&gt;testrole&lt;/role-name&gt;
    &lt;principal-name&gt;test_group&lt;/principal-name&gt;
  &lt;/security-role-assignment&gt;

&lt;/weblogic-web-app&gt;
</pre><p>　　在web.xml文件中指定的授权访问角色testrole映射到了test_group，也就是说test_group组中的所有用户都有权访问。这样一来用户授权和实现就解耦了。</p><p>　　使用ant脚本重新构建，然后部署ear。接着进入weblogic server console，删除testrole用户，新建test_group组，新建一个叫test_user的用户，并指派给test_group组。接着按照前面一样Define Security Policy，这一次在Policy Condition部分选择Caller is member of the group，然后点Add进入授权group指定页面，输入test_group，点增加-点OK，回到Define Security Policy主页面，点击Apply就好了。</p><p>　　然后我们在浏览中进入<a href="http://localhost:7001/WSDemo/HelloWorldWS" target="_blank">http://localhost:7001/WSDemo/HelloWorldWS</a>，弹出登陆框，这一次我们可以使用test_group中的任何成员用户来登陆了，前面例子是test_user。这样在以后，需要分配新的用户授权访问此Web Service的时候就知需要在Cosole在test_group中增加一个成员就行了，不需要重新构建web service了。</p><p>　　加入了访问控制后，在调用web service的时候就需要提供授权凭证了，下面是需要增加的代码信息：</p><ul><li>JAVA客户 
<p>HelloWorldWS_Impl ws = new HelloWorldWS_Impl("http://localhost:7001/WSDemo/HelloWorldWS?WSDL");<br />HelloWorldWSPort port = ws.getHelloWorldWSPort("test_user","test_user");<br />改成<br />HelloWorldWS_Impl ws = new HelloWorldWS_Impl();<br />//因为加入了访问控制，所以对于<a href="http://localhost:7001/WSDemo/HelloWorldWS?WSDL" target="_blank">http://localhost:7001/WSDemo/HelloWorldWS?WSDL</a>的访问也需授权，所以我们使用缺省构建器，这样就会使用客户端支持库jar中的静态wsdl文件了。<br />HelloWorldWSPort port = ws.getHelloWorldWSPort(“test_user”, “test_user”);<br />//后面的参数是test_user的密码，根据你具体的密码更改</p></li><li>VB客户端 
<p>Call soap.mssoapinit("HelloWorldWS.wsdl")<br />‘由于<a href="http://localhost:7001/WSDemo/HelloWorldWS?WSDL" target="_blank">http://localhost:7001/WSDemo/HelloWorldWS?WSDL</a>需要授权访问，所以我们把脚本生成的HelloWorldWS.wsdl文件直接拷贝到VB项目目录下，使用这个静态文件来初始化soap对象。<br />‘后面增加下属代码<br />soap.ConnectorProperty("AuthUser") = "test_user"<br />soap.ConnectorProperty("AuthPassword") = "test_user"</p></li></ul><p>　　在我们运行上述两个测试程序的时候会发现调用不成功。原因接下来进行说明。</p><p>　　我们打开工作目录中下build\wsddfiles这个目录中的HelloWorldWS.wsdl这个文件，在最后可以看到下面的service元素内容，如下：</p><pre class="code">&lt;service   name="HelloWorldWS"&gt;
  &lt;port    name="HelloWorldWSPort"
    binding="tns:HelloWorldWSPort"&gt;
   &lt;soap:address  location="http://pls.set.the.end.point.address/"&gt;
   &lt;/soap:address&gt;
  &lt;/port&gt;
 &lt;/service&gt;
</pre><p>　　问题就出在这里，soap:address节点的location属性有问题，因为客户端soap初始化后，会使用这个URL来调用本wsdl中描述的web service操作，显然这个地址与我们部署的实际地址是不一样的。所以我们把location属性改为我们部署的web service实际访问URL：</p><p><a href="http://localhost:7001/WSDemo/HelloWorldWS" target="_blank">http://localhost:7001/WSDemo/HelloWorldWS</a>。这就是上述两个测试程序不能正确运行的原因。</p><p>　　笔者也没有找到如何在生成web service部件时设置此正确属性的方法，正是因为需要修改上述wsdl文件属性，所以我们需要把build脚本分成两部分来执行，先生成相关部件，然后修改wsdl文件的上述属性，最后才进行打包和客户端支持库的生成，把build_wls_all.xml分开成了build_wls_1.xml和build_wls_2.xml两个build脚本文件。在运行完后build_wls_1.xml修改上述属性，然后运行build_wls_2.xml即可。</p><p>　　部署成功后，就可以测试上面两个调用例子了，注意把修改好的wsdl文件拷贝到VB项目目录中去。</p><p>　　如果在web.xml中&lt;security-constraint&gt;元素里加入下述项目 </p><pre class="code">&lt;user-data-constraint&gt;
      &lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;
&lt;/user-data-constraint&gt;</pre><p>　　那就会强制要求客户端使用https进行访问，其他更多信息请参考J2EE中Web应用安全方面的资料。</p><p><strong>六、杂项设置</strong></p><p>　　本节要说的实际也是安全性方面的问题，只不过和一般的安全性概念不一样，这里讲的是针对在生产部署环境下的考虑。</p><p><strong>1、定制主页</strong></p><p>　　在生产环境下，一般是不允许公开web service默认主页的。其次由于通过主页：</p><p><a href="http://localhost:7001/WSDemo/HelloWorldWS?WSDL" target="_blank">http://localhost:7001/WSDemo/HelloWorldWS?WSDL</a></p><p>　　访问的wsdl描述符文件是动态生成，同时加入了访问控制安全约束后，客户程序访问此文件也存在问题，所以通常在生产环境下将禁止访问web service默认主页以及动态wsdl文件，可以使用专门的静态web站点来提供必要的信息，以及通过静态web站点来发布wsdl。</p><p>　　要禁用默认主页以及wsdl文件，需要在web-services.xml描述符文件中进行设置。如下所示在web-service节点中加入下面两个属性：</p><p>exposeWSDL="False"</p><p>exposeHomePage="False"</p><p>修改后类似下面示例： </p><pre class="code">。。。
&lt;web-services&gt;
 &lt;web-service   name="HelloWorldWS"
   targetNamespace="http://tempuri.org/"
   uri="/HelloWorldWS"
   exposeWSDL="False"
   exposeHomePage="False"&gt;
。。。

</pre><p>　　这个修改也需要在运行build_wls_1.xml之后进行修改，才能保证应用打包部署后使得此设置生效。</p><p>　　在禁止了默认主页和WSDL文件后，为了保证web service更新后不需要更新客户程序的文件，所以最好建立一个静态web站点来发布web service，也就是发布wsdl文件。在用于发布wsdl的web应用中需要在web.xml中加入以下的Mime类型映射： </p><pre class="code">&lt;mime-mapping&gt;
&lt;extension&gt;wsdl&lt;/extension&gt;
&lt;mime-type&gt;text/xml&lt;/mime-type&gt;
&lt;/mime-mapping&gt;

</pre><p><strong>2、启用https协议</strong></p><p>　　除了上一节中在web.xml中加入 </p><pre class="code">&lt;user-data-constraint&gt;
      &lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;
&lt;/user-data-constraint&gt;
</pre><p>　　来启用https通讯协议外，还可以在通过在web-service.xml文件中，在web-service（注意不是web-services）节点中加入下面属性：</p><p>protocol="https"</p><p>　　上述属性能保证客户端必须使用https来访问本web service。</p><p><strong>七、结束语</strong></p><p>　　本文只是针对很小的一方面来讲述基于weblogic ant任务开发web service的，只是起个抛砖引玉的作用。其次，通过本文你也能了解到web service的本质过程，无论通过什么工具来开发，本质上都是生成基础部件，然后打包。如果需要全面了解weblogic server web service开发方面的知识请参考bea文档：</p><p><a href="http://e-docs.bea.com/wls/docs81/webservices.html" target="_blank">http://e-docs.bea.com/wls/docs81/webservices.html</a></p><p>　　同时本文使用的环境是window 2000 server和weblogic platform8.1英文版。</p><p>　　本文示例项目代码可从以下地址下载：</p><p><a href="http://www.wnetw.com/jclub_resources/technology/attachfiles/wls_ws_demo.rar" target="_blank">http://www.wnetw.com/jclub_resources/technology/attachfiles/wls_ws_demo.rar</a></p><img src ="http://www.blogjava.net/gf7/aggbug/100533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2007-02-25 10:30 <a href="http://www.blogjava.net/gf7/archive/2007/02/25/100533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Framework中的面向方面编程（AOP），第二部分</title><link>http://www.blogjava.net/gf7/archive/2007/01/29/96471.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Mon, 29 Jan 2007 04:00:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2007/01/29/96471.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/96471.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2007/01/29/96471.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/96471.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/96471.html</trackback:ping><description><![CDATA[时间：2005-12-23<br />作者：<a href="http://dev2dev.bea.com.cn/author/431.html">Russell Miles</a><br />浏览次数：
<script language="JavaScript" src="/beadevcount.jsp?d_id=162099" type="text/JavaScript"></script>
 3616 <br />本文关键字：<a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=Spring">Spring</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=Java">Java</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=AOP">AOP</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=crosscutting">crosscutting</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=面向方面编程">面向方面编程</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=横切">横切</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=Cuckoo's Egg模式">Cuckoo's Egg模式</a><br /><p>　　在本系列的<a href="http://dev2dev.bea.com.cn/techdoc/20051216709.html" target="_blank">第一部分</a>，我介绍了如何实现面向方面领域的“HelloWorld”：跟踪和记录方面。利用<a href="http://www.springframework.org/" target="_blank">Spring框架</a>所提供的面向方面编程(Aspect-Oriented Programming，AOP)功能，您看到了如何使用before-、after-和基于异常的通知，以及如何使用基于正则表达式的简单切入点。跟踪和记录方面提供了非常不错的上手例子，而本文将进一步介绍一种新的通知形式：around通知。</p><p>　　比起第一部分中介绍的那些通知类型，around形式的通知是一种更具侵入性也更强大的面向对象概念。本文将描述around通知的每个特性，以便您可以在自己的Spring AOP应用程序中正确地使用它。在本文最后，我将向您展示如何使用around通知来截获和改变应用程序中各个特性相互作用的方式，以便实现Cuckoo's Egg（杜鹃的蛋）面向方面设计模式。</p><p><strong>概述Spring AOP、IoC和代理</strong><br />　　<a href="http://dev2dev.bea.com.cn/techdoc/20051216709.html" target="_blank">在第一部分</a>，我们快速浏览了Spring的一些AOP特性，而没有阐明Spring如何实现AOP的细节。要理解Spring框架如何运转，尤其是它如何实现其AOP功能，首先您要明白，Spring是一个依赖于控制反转(Inversion of Control，IoC)设计模式的轻量级框架。</p><p>　　注意：本文的目的不是要深入介绍IoC模式，介绍IoC只是为了使您明白该设计模式是如何影响Spring AOP实现的。有关IoC模式的更详细的介绍请参见本文末尾的<a href="http://www.onjava.com/pub/a/onjava/2004/10/20/springaop2.html?page=2#resources" target="_blank">参考资料</a>。</p><p>　　IoC设计模式的出现已经有一段时间了。一个最明显的例子就是<a href="http://www.onjava.com/pub/a/onjava/2004/10/20/springaop2.html#" target="_blank">J2EE</a>架构本身。随着企业开发尤其是J2EE平台的出现，应用程序开始依赖于由外部容器所提供的一些特性，比如bean创建、持久性、消息传递、会话以及事务管理。</p><p>　　IoC引入了一个新概念：由组件构成的框架，它与J2EE容器有许多类似之处。IoC框架分离了组件所依赖的功能，并且，根据Sam Newman文章中的说法，提供了“连接组件的‘胶水’”。</p><p>　　对组件所依赖特性的控制 被反转 了，这样外部框架就可以尽可能透明地提供这些特性了。IoC模式真正意识到了从传统的由依赖于功能的组件来负责这些功能，到由独立的框架来配置和提供这些功能的方式转变。</p><p>　　图1显示了一些构成IoC模式的不同组件角色的例子。</p><p align="center"><img height="216" alt="Figure 1" src="http://dev2dev.bea.com.cn/images/image051222002.jpg" width="534" /><br />图1. 没有对BusinessLogic bean应用方面时的顺序图.</p><p>　　图字：</p><p>　　Component：组件</p><p>　　Provides Facilities：提供功能</p><p>　　Relies on and conforms to：依赖于并服从</p><p>　　Manages the services the framework can then use to provide facilities：管理框架随后可以用来提供功能的服务</p><p>　　Service：服务</p><p>　　Your Component：您的组件</p><p>　　IoC Framework：IoC框架</p><p>　　External services：外部服务</p><p>　　IoC模式使用3种不同的方法来解除组件与服务控制的耦合：类型1、类型2和类型3。</p><ul><li>类型1：接口注入<br />这是大部分J2EE实现所使用的方法。组件显式地服从于一组接口，带有关联的配置元数据，以便允许框架对它们进行正确的管理。 
</li><li>类型2：Setter注入<br />外部元数据被用来配置组件相互作用的方式。在<a href="http://dev2dev.bea.com.cn/techdoc/20051216709.html" target="_blank">第一部分</a>中，我们就是使用这种IoC方法利用springconfig.xml文件来配置Spring组件的。 
</li><li>类型3：构造函数注入<br />组件（包括构造组件时要用的参数）注册到框架，而框架提供组件的实例以及所有要应用的指定功能。 </li></ul><p>　　IoC在组件开发和企业开发中越来越受欢迎。IoC的实际例子包括传统的J2EE解决方案，比如：<a href="http://www.jboss.org/" target="_blank">JBoss</a>、Apache基金会的<a href="http://avalon.apache.org/" target="_blank">Avalon</a>项目以及本文的Spring框架。实际上，Spring框架构建于IoC模式的基础上是为了帮助将它的轻量级功能注入到它的相关应用程序的组件中。</p><p>　　那么IoC对于Spring AOP有何意义呢？Spring的IoC特性是使用IoC springconfig.xml配置文件对应用程序应用方面的推动因素之一。springconfig.xml配置文件通知Spring框架运行时有关应用程序的组件要被注入的功能类型的信息，所以自然轻量级的AOP功能就以同样的方式应用了。然后Spring使用代理模式围绕现有的类和bean实现指定的AOP功能。</p><p>　　图2显示了Spring及其IoC框架如何使用代理对象提供AOP功能（根据springconfig.xml文件中的IoC配置。）</p><p align="center"><a href="http://www.onjava.com/onjava/2004/10/20/graphics/fig2_full.png" target="_blank"><img height="292" alt="Click for larger view" src="http://dev2dev.bea.com.cn/images/image051222004.gif" width="432" border="0" /></a><br />图2. springconfig.xml配置文件改变了Spring框架IoC，以便随后向第一部分中的一个顺序图提供AOP代理（单击图像查看大图）</p><p>　　在本系列下面的部分，您将不断看到现在包含在顺序图中的代理对象。这只是为了说明对于Spring AOP来说没有“魔法”，实际上只有一个面向对象设计模式的良好例子。</p><p><strong>回到AOP：使用around通知的积极方面</strong><br />　　在<a href="http://dev2dev.bea.com.cn/techdoc/20051216709.html" target="_blank">第一部分</a>，您看到了如何使用Spring AOP来实现跟踪和记录方面。跟踪和记录都是“消极”方面，因为它们的出现并不会对应用程序的其他行为产生影响。它们都使用了消极的before和after形式的通知。</p><p>　　但是如果您希望改变应用程序的常规行为呢？例如说，您希望重写一个方法？这样的话，您就需要使用更积极的around形式的通知。</p><p>　　<a href="http://dev2dev.bea.com.cn/techdoc/20051216709.html" target="_blank">第一部分</a>的简单例子应用程序包括IbusinessLogic接口、BusinessLogic类和MainApplication类，如下所示：</p><pre class="code">public interface IBusinessLogic
{
  public void foo();
}


public class BusinessLogic 
  implements IBusinessLogic
{
  public void foo() 
  {
     System.out.println(
       "Inside BusinessLogic.foo()");
  }
}

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MainApplication
{
  public static void main(String [] args)
  {
    // Read the configuration file
    ApplicationContext ctx = 
      new FileSystemXmlApplicationContext(
        "springconfig.xml");

    //Instantiate an object
    IBusinessLogic testObject = 
      (IBusinessLogic) ctx.getBean(
        "businesslogicbean");

    // Execute the public 
    // method of the bean
    testObject.foo();
  }
}
</pre><p>　　要对一个BusinessLogic类的实例彻底重写对foo()方法的调用，需要创建around通知，如下面的AroundAdvice类所示：</p><pre class="code">import org.aopalliance.intercept.MethodInvocation;
import org.aopalliance.intercept.MethodInterceptor;

public class AroundAdvice 
   implements MethodInterceptor
{
   public Object invoke(
      MethodInvocation invocation)
      throws Throwable
   {
      System.out.println(
         "Hello world! (by " + 
         this.getClass().getName() + 
         ")");

      return null;
   }
}
</pre><p>　　要在Spring中用作around通知，AroundAdvice类必须实现MethodInterceptor接口和它的invoke(..)方法。每当截获到方法的重写，invoke(..)方法就会被调用。最后一步是改变包含在应用程序的springconfig.xml文件中的Spring运行时配置，以便可以对应用程序应用AroundAdvice。</p><pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE beans PUBLIC  "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd"&gt;

&lt;beans&gt;

   &lt;!-- Bean configuration --&gt;
   &lt;bean id="businesslogicbean"
   class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
      &lt;property name="proxyInterfaces"&gt;
         &lt;value&gt;IBusinessLogic&lt;/value&gt;
      &lt;/property&gt;
      &lt;property name="target"&gt;
         &lt;ref local="beanTarget"/&gt;
      &lt;/property&gt;
      &lt;property name="interceptorNames"&gt;
         &lt;list&gt;
            &lt;value&gt;theAroundAdvisor&lt;/value&gt;
         &lt;/list&gt;
         &lt;/property&gt;
   &lt;/bean&gt;
   &lt;!-- Bean Classes --&gt;
   &lt;bean id="beanTarget"
   class="BusinessLogic"/&gt;

   &lt;!-- Advisor pointcut definition for around advice --&gt;
   &lt;bean id="theAroundAdvisor"
      class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt;
      &lt;property name="advice"&gt;
         &lt;ref local="theAroundAdvice"/&gt;
      &lt;/property&gt;
      &lt;property name="pattern"&gt;
         &lt;value&gt;.*&lt;/value&gt;
      &lt;/property&gt;
   &lt;/bean&gt;
	
   &lt;!-- Advice classes --&gt;
   &lt;bean id="theAroundAdvice"
      class="AroundAdvice"/&gt;

&lt;/beans&gt;
</pre><p>　　根据该springconfig.xml配置文件，theAroundAdvisor截获所有对BusinessLogic类的方法的调用。接下来，theAroundAdvisor被关联到theAroundAdvice，表明当截获一个方法时，就应该使用在AroundAdvice类中指定的通知。既然已经指定了around通知的正确配置，下一次执行MainApplication类时，BusinessLogic bean的foo()方法就会被截获并重写，如图3所示：</p><p align="center"><img height="223" alt="Figure 3" src="http://dev2dev.bea.com.cn/images/image051222006.jpg" width="550" /><br />图3. 使用around通知重写对BusinessLogic类中的foo()方法的调用</p><p>　　前面的例子显示，BusinessLogic类中的foo()方法可以通过AroundAdvice类中的invoke(..)方法彻底重写。原来的foo()方法完全不能被invoke(..)方法调用。如果希望从around通知内调用foo()方法，可以使用proceed()方法，可从invoke(..)方法的MethodInvocation参数中得到它。</p><pre class="code">public class AroundAdvice 
   implements MethodInterceptor
{
   public Object invoke(
      MethodInvocation invocation) 
      throws Throwable
   {
      System.out.println(
         "Hello world! (by " + 
         this.getClass().getName() + 
         ")");

      invocation.proceed();

      System.out.println("Goodbye! (by " + 
         this.getClass().getName() + 
         ")");

      return null;
   }
}
</pre><p>　　图4显示了对proceed()的调用如何影响操作的顺序（与图3所示的初始around通知执行相比较）。</p><p align="center"><img height="203" alt="Figure 4" src="http://dev2dev.bea.com.cn/images/image051222008.jpg" width="550" /><br />图4. 从around通知内使用proceed()调用原来的方法</p><p>　　当调用proceed()时，实际是在指示被截获的方法（在本例中是foo()方法）利用包含在MethodInvocation对象中的信息运行。您可以通过调用MethodInvocation类中的其他方法来改变该信息。</p><p>　　您可能希望更改包含在MethodInvocation类中的信息，以便在使用proceed()调用被截获的方法之前对被截获方法的参数设置新值。</p><p>　　通过对MethodInvocation对象调用getArguments()方法，然后在返回的数组中设置其中的一个参数对象，最初传递给被截获的方法的参数可以被更改。</p><p>　　如果IbusinessClass和BusinessLogic类的foo()方法被更改为使用整型参数，那么就可以将传递给被截获的调用的值由在AroundAdvice的notify(..)方法中传递改为在foo(int)中传递。</p><pre class="code">public class AroundAdvice 
   implements MethodInterceptor
{
   public Object invoke(
      MethodInvocation invocation) 
      throws Throwable
   {
      System.out.println(
         "Hello world! (by " + 
         this.getClass().getName() + 
         ")");
      
      invocation.getArguments()[0] = new Integer(20);
      
      invocation.proceed();
      
      System.out.println(
         "Goodbye! (by " + 
         this.getClass().getName() + 
         ")");
      
      return null;
   }
}
</pre><p>　　在本例中，被截获的方法的第一个形参被假设为int。实参本身是作为对象传递的，所以通过将其包装在Integer类实例中的方法，基本的int类型的形参被改为对应数组中的新值。如果您将该参数设置为一个非Integer对象的值，那么在运行时就会抛出IllegalArgumentException异常。</p><p>　　您还将注意到，invoke(..)方法必须包含一个return语句，因为该方法需要返回值。但是，被重写的foo()方法并不返回对象，所以invoke(..)方法可以以返回null结束。如果在foo()方法不需要的情况下，您仍然返回了一个对象，那么该对象将被忽略。</p><p>　　如果foo()方法确实需要返回值，那么需要返回一个与foo()方法的初始返回类型在同一个类或其子类中的对象。如果foo()方法返回一个简单类型，例如，一个integer，那么您需要返回一个Integer类的对象，当方法被重写时，该对象会自动由AOP代理拆箱，如图5所示：</p><p align="center"><img height="294" alt="Figure 5" src="http://dev2dev.bea.com.cn/images/image051222010.jpg" width="550" /><br />图5. around通知的装箱和自动拆箱</p><p>　　图字：</p><p>　　Object invoke：对象调用</p><p>　　The integer return value is boxed in a Integer object in the AroundAdvice and then unboxed by the AOP Proxy：整型返回值被装箱在AroundAdvic通知的一个Integer对象中，然后由AOP代理拆箱。</p><p>　　面向方面编程还是一个比较新的领域，尤其是与衍生出它的面向对象编程相比。设计模式通常被认为是常见问题的通用解决方案，因为面向方面发展的时间还不长，所以已发现的面向方面设计模式比较少。</p><p>　　此处要介绍的是一种正在浮现的模式，即Cuckoo's Egg设计模式。该模式还有其他的叫法，它在面向对象领域的对等体包括模仿对象（Mock Object）和模仿测试（Mock Testing），甚至代理模式也与它有一些类似之处。</p><p>　　Cuckoo's Egg面向方面设计模式可以被定义为应用程序上下文中功能部件的透明和模块化的置换。就像杜鹃偷偷地把自己的蛋放在另一种鸟的巢中一样，Cuckoo's Egg设计模式用一个替代功能部件实现置换现有的功能部件,而使造成的干扰尽可能少。</p><p>　　这种置换的实现方式可以是静态的、动态的、部分的、完全的，针对一个对象的多个部分，或针对多个组件。使用面向方面的方法可以透明地实现功能部件的置换，而无需对应用程序的其余部分进行更改。要置换应用程序中现有功能部件的替代功能部件就是“杜鹃的蛋”。图6显示了Cuckoo's Egg设计模式中的主要组成元素。</p><p align="center"><img height="278" alt="Figure 6" src="http://dev2dev.bea.com.cn/images/image051222012.jpg" width="527" /><br />图6. Cuckoo's Egg设计模式中的主要组成元素</p><p>　　图字：</p><p>　　Application：应用程序</p><p>　　Component：组件</p><p>　　Replacement Feature：替代功能部件</p><p>　　Component 1 and 2 together encompass a distinct feature of the software：组件1和2共同包含了软件的一个独立的功能部件</p><p>　　The Cuckoo's Egg pattern transparently replaces an existing feature of the software：Cuckoo's Egg模式透明地置换了软件现有的功能部件</p><p>　　Before the pattern is applied：应用该模式前</p><p>　　After the pattern is applied：应用该模式后</p><p>　　Cuckoo's Egg设计模式依赖于around通知的概念。您需要借助于积极的和侵入性的around通知来截获并有效置换应用程序中现有的功能部件。</p><p>　　有关Cuckoo's Egg设计模式的更多信息，以及AspectJ中的一个可选实现，请参见《<a href="http://www.oreilly.com/catalog/aspectjckbk/" target="_blank">AspectJ Cookbook</a>》（O'Reilly，2004年12月出版）。</p><p>　　要使用Spring AOP实现Cuckoo's Egg设计模式，需要声明一个around通知来截获所有对要置换的功能部件的调用。与<a href="http://www.springframework.org/docs/reference/aop.html#aop-ts-swap" target="_blank">hot-swappable target sources</a>（Spring AOP的一个功能部件，将在本系列的另一篇文章中介绍）不同，around通知的显式使用使得Cuckoo's Egg实现可以有效地跨越对象边界（因此也可以跨越bean边界）进行整个功能部件的置换，如图7所示。</p><p align="center"><img height="285" alt="Figure 7" src="http://dev2dev.bea.com.cn/images/image051222014.jpg" width="293" /><br />图7. 一个跨越bean边界的组件</p><p>　　图字：</p><p>　　A feature crosses the boundaries of BusinessLogic and BusinessLogic2 by depending on behavior supplied separately by the two beans：一个功能部件通过依赖于由BusinessLogic和BusinessLogic2各自提供的行为而跨越了这两个bean的边界</p><p>　　下面的代码显示了一个具有两个bean的简单应用程序，其中有一个功能部件跨越了该应用程序的多个方面。要置换的功能部件可以被视为包含IBusinessLogic bean中的foo()方法和IBusinessLogic2 bean中的bar()方法。IBusinessLogic2 bean中的baz()方法不是 该功能部件的一部分，所以不进行置换。</p><pre class="code">public interface IBusinessLogic
{
   public void foo();
}

public interface IBusinessLogic2
{
   public void bar();
   
   public void baz();
}
</pre><p>　　该例子的完整源代码可在<a href="http://www.onjava.com/pub/a/onjava/2004/10/20/springaop2.html?page=2#resourcesresources" target="_blank">本文末尾的参考资料</a>小节中下载。</p><p>　　此处，ReplacementFeature类扮演了“杜鹃的蛋”的角色，它提供了将被透明地引入应用程序的替代实现。ReplacementFeature类实现了所有在该类引入时要被置换的方法。</p><pre class="code">public class ReplacementFeature
{
   public void foo()
   {
      System.out.println(
         "Inside ReplacementFeature.foo()");
   }
   
   public void bar()
   {
      System.out.println(
         "Inside ReplacementFeature.bar()");
   }
}
</pre><p>　　现在需要声明一个around通知来截获对跨越bean的功能部件的方法调用。CuckoosEgg类提供了某种around通知来检查被截获的方法，并将适当的方法调用传递给ReplacementFeature类的实例。</p><pre class="code">public class CuckoosEgg implements MethodInterceptor
{
   public ReplacementFeature replacementFeature =
       new ReplacementFeature();
   
   public Object invoke(MethodInvocation invocation)
       throws Throwable
   {
      if (invocation.getMethod().getName().equals("foo"))
      {
         replacementFeature.foo();
      }
      else
      {
         replacementFeature.bar();
      }
      
      return null;
   }
}
</pre><p>　　因为与Spring框架关系密切，Cuckoo's Egg设计的详细信息被放在springconfig.xml配置文件中。对springconfig.xml文件的更改将确保所有对IbusinessLogic和IBusinessLogic2 bean的foo()方法和bar()方法的调用都将被截获，并传递给CuckoosEgg类的around通知。</p><pre class="code">   ...
   
   &lt;!--CONFIG--&gt;
   &lt;bean id="businesslogicbean" 
      class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
      &lt;property name="proxyInterfaces"&gt;
         &lt;value&gt;IBusinessLogic&lt;/value&gt;
      &lt;/property&gt;
      &lt;property name="target"&gt;
         &lt;ref local="beanTarget"/&gt;
      &lt;/property&gt;
      &lt;property name="interceptorNames"&gt;
         &lt;list&gt;
            &lt;value&gt;theCuckoosEggAdvisor&lt;/value&gt;
         &lt;/list&gt;
      &lt;/property&gt;
   &lt;/bean&gt;
   
   &lt;bean id="businesslogicbean2" 
      class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
      &lt;property name="proxyInterfaces"&gt;
         &lt;value&gt;IBusinessLogic2&lt;/value&gt;
      &lt;/property&gt;
      &lt;property name="target"&gt;
         &lt;ref local="beanTarget2"/&gt;
      &lt;/property&gt;
      &lt;property name="interceptorNames"&gt;
         &lt;list&gt;
            &lt;value&gt;theCuckoosEgg2Advisor&lt;/value&gt;
         &lt;/list&gt;
      &lt;/property&gt;
   &lt;/bean&gt;

   &lt;!--CLASS--&gt;
   &lt;bean id="beanTarget" class="BusinessLogic"/&gt;
   &lt;bean id="beanTarget2" class="BusinessLogic2"/&gt;
   
   &lt;!--ADVISOR--&gt;
   &lt;bean id="theCuckoosEggAdvisor" 
      class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt;
      &lt;property name="advice"&gt;
         &lt;ref local="theReplacementFeaturePart1Advice"/&gt;
      &lt;/property&gt;
      &lt;property name="pattern"&gt;
         &lt;value&gt;IBusinessLogic.*&lt;/value&gt;
      &lt;/property&gt;
   &lt;/bean&gt;
   
   &lt;bean id="theCuckoosEgg2Advisor" 
      class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt;
      &lt;property name="advice"&gt;
         &lt;ref local="theReplacementFeaturePart2Advice"/&gt;
      &lt;/property&gt;
      &lt;property name="pattern"&gt;
         &lt;value&gt;IBusinessLogic2.bar*&lt;/value&gt;
      &lt;/property&gt;
   &lt;/bean&gt;
   
   &lt;!--ADVICE--&gt;
   &lt;bean id="theReplacementFeaturePart1Advice" class="CuckoosEgg"/&gt;
   &lt;bean id="theReplacementFeaturePart2Advice" class="CuckoosEgg"/&gt;
   
   ...
</pre><p>　　当使用修改后的springconfig.xml文件运行例子应用程序时，要替换的、被指定为功能部件的一部分的方法调用完全被截获并传递给ReplacementFeature类。</p><p>　　通常，即使在同一个实现环境中，我们也可以用不同的方法来实现同一种设计模式。实现上例的另一种方法是实现两个独立的通知。</p><p>　　最后需要注意的是，使用Cuckoo's Egg设计模式置换的功能部件，不管它是跨越bean的还是在一个类中，它的生命周期与它所置换的功能部件的目标生命周期匹配。在上例中这没什么问题，因为只有一个功能部件实例被置换了，而且唯一的Cuckoo's Egg通知只维护一个替代功能部件。</p><p>　　这个例子非常简单，而在实践中，您很可能必须处理大量需要用各自的Cuckoo's Egg实例置换的功能部件实例。在这种情况下，单个的方面实例需要被关联到单个的要置换的功能部件实例。本系列的下一篇文章将会考虑方面生命周期的用法，届时将解决这个问题。</p><p><strong>结束语</strong><br />　　本文介绍了如何在Spring框架内谨慎使用around形式的通知。around形式的通知常用于实现Cuckoo's Egg设计模式时，所以我们引入了一个例子来说明如何使用Spring AOP实现这种面向方面设计模式。</p><p>　　在本系列的第三部分中，您将看到如何使用Spring框架中其他的AOP基本概念。这些概念包括：控制方面生命周期、使用基于introduction通知的积极方面改变应用程序的静态结构，以及使用control flow切入点实现对方面编织的更细微的控制。</p><p>　　<strong>参考资料</strong></p><ul><li><a href="http://javaboutique.internet.com/tutorials/spring_frame" target="_blank">Spring框架教程</a>——向您展示Spring框架的内部运作方式 
</li><li><a href="http://www.onjava.com/onjava/2004/10/20/examples/springaoppart2source.zip" target="_blank">本文的完整源代码</a></li><li><a href="http://www.springframework.org/" target="_blank">Spring Java/J2EE框架</a></li><li><a href="http://martinfowler.com/articles/injection.html" target="_blank">“Comparing the Inversion of Control and Dependency Injection Design Patterns</a>” 
</li><li><a href="http://today.java.net/pub/a/today/2004/02/10/ioc.html" target="_blank">IoC模式概述</a></li><li><a href="http://www.springframework.org/docs/wiki/Spring_AOP_Framework.html" target="_blank">Spring框架参考文档第5章</a>——介绍Spring中的所有AOP特性 </li></ul><p>　　<strong>原文出处</strong><br />An Introduction to Aspect-Oriented Programming with the Spring Framework, Part 2 <a href="http://www.onjava.com/pub/a/onjava/2004/10/20/springaop2.html">http://www.onjava.com/pub/a/onjava/2004/10/20/springaop2.html</a></p><!--文章其他信息--><div class="dot001"><img height="1" alt="" src="http://dev2dev.bea.com.cn/images/_.gif" width="100%" /></div><table cellspacing="0" cellpadding="3" width="100%" border="0"><tbody><tr valign="bottom"><td colspan="2" height="20"> <span class="h2b">作者简介</span></td></tr><tr><td valign="top" align="middle" width="0"></td><td><a href="http://www.onjava.com/pub/au/1725" target="_blank">Russell Miles</a>是General Dynamics UK公司的一名软件工程师，他负责Java和分布式系统，但是他目前主要的兴趣在面向方面领域，尤其是AspectJ。</td></tr></tbody></table><img src ="http://www.blogjava.net/gf7/aggbug/96471.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2007-01-29 12:00 <a href="http://www.blogjava.net/gf7/archive/2007/01/29/96471.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Framework中的面向方面编程（AOP），第一部分</title><link>http://www.blogjava.net/gf7/archive/2007/01/29/96470.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Mon, 29 Jan 2007 04:00:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2007/01/29/96470.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/96470.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2007/01/29/96470.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/96470.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/96470.html</trackback:ping><description><![CDATA[时间：2005-12-16<br />作者：<a href="http://dev2dev.bea.com.cn/author/431.html">Russell Miles</a><br />浏览次数：
<script language="JavaScript" src="/beadevcount.jsp?d_id=162093" type="text/JavaScript"></script>
 5882 <br />本文关键字：<a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=Java">Java</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=Spring">Spring</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=aspect-oriented programming">aspect-oriented programming</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=AOP">AOP</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=crosscutting">crosscutting</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=面向方面编程">面向方面编程</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=横切">横切</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=延迟加载">延迟加载</a><br /><p>　　作为这个介绍<a href="http://www.springframework.org/" target="_blank">Spring框架</a>中的面向方面编程(Aspect-Oriented Programming，AOP)的系列的第一部分，本文介绍了使您可以使用Spring中的面向方面特性进行快速开发的基础知识。使用跟踪和记录方面（面向方面领域的HelloWorld）作为例子，本文展示了如何使用Spring框架所独有的特性来声明切入点和通知以便应用方面。本系列的第二部分将更深入地介绍如何运用Spring中的所有通知类型和切入点来实现更实用的方面和面向方面设计模式。对于AOP的更一般性的介绍，请查看ONJava站点上Graham O'Regan的文章，<a href="http://www.onjava.com/pub/a/onjava/2004/01/14/aop.html" target="_blank">“Introduction to Aspect-Oriented Programming</a>”。</p><p>　　本文的目的不是要介绍构成模块化J2EE系统——即Spring框架——的所有重要元素，我们将只把注意力放在Spring所提供的AOP功能上。由于Spring的模块化设计方法，我们可以只使用该框架的AOP元素，而无需对构成Spring框架的其他模块做太多考虑。</p><p><strong>在AOP方面，Spring提供了什么？</strong><br />　　“它的目标不是提供最完善的AOP实现（虽然Spring AOP非常强大）；而是要提供AOP实现与Spring IoC的紧密集成，以便帮助解决企业应用中的常见问题。”<br />Spring Framework参考文档</p><p>　　为了实现这个目标，Spring框架目前支持一组AOP概念，从切入点到通知。本文将展示如何使用Spring框架中所实现的如下AOP概念：</p><ul><li><strong>通知（Advice</strong><strong>）：</strong>如何将before通知、afterReturning通知和afterThrowing通知声明为bean。 
</li><li><strong>切入点（Pointcut</strong><strong>）：</strong>如何声明静态切入点逻辑以将XML Spring Bean Configuration文件中的所有内容联系在一起。 
</li><li><strong>Advisor</strong><strong>：</strong>关联切入点定义与通知bean的方式。 </li></ul><p><strong>设置场景：一个简单的例子应用程序</strong><br />　　“一般而言，Spring并不是预描述的。虽然使用好的实践非常容易，但是它避免强制推行一种特定的方法。”<br />Spring Framework参考文档</p><p>　　要试用Spring框架的AOP功能，首先我们要创建一个简单的Java应用程序。IbusinessLogic接口和BusinessLogic类为Spring框架中的bean提供了简易构件块。虽然该接口对于我们的简单应用程序逻辑来说不是必需的，但是它是Spring框架所推荐的良好实践。</p><pre class="code">public interface IBusinessLogic
{
    public void foo();
}

public class BusinessLogic 
    implements IBusinessLogic
{
    public void foo() 
    {
        System.out.println(
        "Inside BusinessLogic.foo()");
    }
}
</pre><p>　　可以编写MainApplication类，借此练习BusinessLogic bean的公有方法。</p><pre class="code">import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MainApplication
{
    public static void main(String [] args)
    {
        // Read the configuration file
        ApplicationContext ctx = 
          new FileSystemXmlApplicationContext(
            "springconfig.xml");

        //Instantiate an object
        IBusinessLogic testObject = 
          (IBusinessLogic) ctx.getBean("businesslogicbean");

        // Execute the public 
        // method of the bean
        testObject.foo();
    }
}
</pre><p>　　在BusinessLogic类及其关联接口中没有什么需要注意的。但是，MainApplication类初始化BusinessLogic对象的方式很有意思。通过使用ctx.getBean("businesslogicbean")调用，MainApplication将加载和管理BusinessLogic类的bean实例的任务转交给了Spring框架。</p><p>　　允许Spring控制BusinessLogic bean的初始化，这使得Spring运行时有机会在bean被返回给应用程序之前执行J2EE系统所需的所有与bean相关的管理任务。然后Spring运行时配置可以决定对bean应用哪些任务和模块。该配置信息由一个XML文件提供，类似于下面所示的：</p><pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE beans PUBLIC
    "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd"&gt;

&lt;beans&gt;

   &lt;!-- Bean configuration --&gt;
   &lt;bean id="businesslogicbean"
   class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
      &lt;property name="proxyInterfaces"&gt;
         &lt;value&gt;IBusinessLogic&lt;/value&gt;
      &lt;/property&gt;
      &lt;property name="target"&gt;
         &lt;ref local="beanTarget"/&gt;
      &lt;/property&gt;
   &lt;/bean&gt;
   &lt;!-- Bean Classes --&gt;
   &lt;bean id="beanTarget"
   class="BusinessLogic"/&gt;

&lt;/beans&gt;
</pre><p>　　该配置文件，即springconfig.xml，指定要加载一个接口与IbusinessLogic相匹配的bean。该bean随后被关联到BusinessLogic实现类。看起来好像是费了很大力气只为了加载一个简单的bean并调用一个方法，但是您要知道，这个配置文件只是使Spring框架可以透明地对应用程序应用其组件的众多特性的一个体现。</p><p>　　图1显示了基本的顺序图：MainApplication原样执行，没有应用方面。</p><p align="center"><img alt="Figure 1" src="http://dev2dev.bea.com.cn/images/image05121630001.gif" /><br />图1.没有对BusinessLogic bean应用方面时的顺序图</p><p>　　请查看本文<a href="http://www.onjava.com/pub/a/onjava/2004/07/14/springaop.html?page=2#references" target="_blank">末尾处的参考资料</a>，获取这个简单Spring应用程序的源代码。</p><p><strong>应用方法跟踪（Method Tracing）方面</strong><br />　　可能最基本的方面就是方法跟踪方面了。这可能是您找得到的最简单的方面了，因此它是研究新的AOP实现的一个很好的起点。</p><p>　　方法跟踪方面在一个目标应用程序内捕获对所跟踪的方法的调用以及方法的返回值，并以某种方式显示这种信息。在AOP中，通知的before和after类型用于捕获这些类型的联结点，因为这两种通知可以在方法调用联结点之前或之后触发。使用Spring框架，方法跟踪方面的before通知是在TracingBeforeAdvice类中声明的。</p><pre class="code">import java.lang.reflect.Method;
import org.springframework.aop. MethodBeforeAdvice;

public class TracingBeforeAdvice 
   implements MethodBeforeAdvice
{
    public void before(Method m, 
                     Object[] args, 
                     Object target) 
                     throws Throwable
    {
        System.out.println(
          "Hello world! (by " + 
          this.getClass().getName() + 
          ")");
    }
}
</pre><p>　　类似地，after通知可以在TracingAfterAdvice类中声明。</p><pre class="code">import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;

public class TracingAfterAdvice 
   implements AfterReturningAdvice
{
    public void afterReturning(Object object, 
                             Method m, 
                             Object[] args, 
                             Object target) 
                             throws Throwable
    {
        System.out.println(
          "Hello world! (by " + 
          this.getClass().getName() + 
          ")");
    }
}
</pre><p>　　这两个类都通过实现Spring框架的适当通知接口而表示了特定的通知。每种类型的通知都指定实现before(..)或afterReturning(..)方法，以便使Spring运行时可以告诉通知适当的联结点会在何时出现。值得注意的是，TracingAfterAdvice实际上是从AfterReturningAdvice扩展而来的，表示只有在联结点在无异常的情况下获得返回值时才运行通知。</p><p>　　为了将通知与应用程序中的适当联结点关联起来，必须对springconfig.xml进行一些修改。</p><pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE beans PUBLIC
    "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd"&gt;

&lt;beans&gt;

   &lt;!-- Bean configuration --&gt;
   &lt;bean id="businesslogicbean"
   class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
      &lt;property name="proxyInterfaces"&gt;
         &lt;value&gt;IBusinessLogic&lt;/value&gt;
      &lt;/property&gt;
      &lt;property name="target"&gt;
         &lt;ref local="beanTarget"/&gt;
      &lt;/property&gt;
      &lt;property name="interceptorNames"&gt;
         &lt;list&gt;
            &lt;value&gt;theTracingBeforeAdvisor&lt;/value&gt;
            &lt;value&gt;theTracingAfterAdvisor&lt;/value&gt;
         &lt;/list&gt;
         &lt;/property&gt;
   &lt;/bean&gt;
   &lt;!-- Bean Classes --&gt;
   &lt;bean id="beanTarget"
   class="BusinessLogic"/&gt;

   &lt;!-- Advisor pointcut definition for before advice --&gt;
   &lt;bean id="theTracingBeforeAdvisor"
      class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt;
      &lt;property name="advice"&gt;
         &lt;ref local="theTracingBeforeAdvice"/&gt;
      &lt;/property&gt;
      &lt;property name="pattern"&gt;
         &lt;value&gt;.*&lt;/value&gt;
      &lt;/property&gt;
   &lt;/bean&gt;
	
   &lt;!-- Advisor pointcut definition for after advice --&gt;
   &lt;bean id="theTracingAfterAdvisor"
      class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt;
      &lt;property name="advice"&gt;
         &lt;ref local="theTracingAfterAdvice"/&gt;
      &lt;/property&gt;
      &lt;property name="pattern"&gt;
         &lt;value&gt;.*&lt;/value&gt;
      &lt;/property&gt;
   &lt;/bean&lt;

   &lt;!-- Advice classes --&gt;
   &lt;bean id="theTracingBeforeAdvice"
      class="TracingBeforeAdvice"/&gt;
   &lt;bean id="theTracingAfterAdvice"
      class="TracingAfterAdvice"/&gt;

&lt;/beans&gt;
</pre><p>　　theTracingBeforeAdvisor和theTracingAfterAdvisor advisor被添加到前面所声明的businesslogicbean。每个advisor都可能截获所有bean所关联到的联结点。Advisor本身就是bean，而它唯一的作用就是将切入点定义与通知bean关联起来。本例中的切入点定义是在静态对象层次结构中指定相关联结点的正则表达式。</p><p>　　因为本例中使用了org.springframework.aop.support.RegexpMethodPointcutAdvisor切入点advisor，切入点逻辑是使用正则表达式指定的。正则表达式用于识别公有接口对IbusinessLogici接口的联结点。下面是一些可以用来指定IBusinessLogic接口上的不同联结点集合的正则表达式例子：</p><ul><li><strong>&lt;value&gt;.*&lt;/value&gt;</strong><strong>：</strong>该表达式选择advisor所关联到的一个或多个bean上的所有联结点。 
</li><li><strong>&lt;value&gt;./IBusinessLogic/.foo&lt;/value&gt;</strong><strong>：</strong>该表达式只选择IbusinessLogic接口上的foo()方法的联结点。如果是advisor所关联到的bean，则该表达式只选择IBusinessLogic接口上的联结点。 </li></ul><p>　　springconfig.xml文件中最后的bean声明指定实现通知bean的类。</p><p>　　既然已经指定了跟踪方面的正确配置，那么下一次执行MainApplication时，这些方面就会在初始化过程中被编织进去，而BusinessLogic bean中的所有方法都将被跟踪，如图2所示。</p><p align="center">　　<a href="http://www.onjava.com/onjava/2004/07/14/graphics/fig2_full.png" target="blank"><img alt="Click for larger view" src="http://dev2dev.bea.com.cn/images/image05121630002_0000.gif" /></a><br />图2. 方法跟踪方面应用到BusinessLogic bean之后的顺序图（单击图像查看大图）</p><p>　　方法跟踪方面和例子应用程序的源代码可在<a href="http://www.onjava.com/pub/a/onjava/2004/07/14/springaop.html?page=2#references" target="_blank">本文末尾的参考资料</a>小节进行下载。</p><p><strong>方面的重用</strong><br />　　可以对方法跟踪方面进行扩展，提供一个稍微复杂的记录（Logging）方面。记录方面提供了一个很不错的重用例子，因为记录方面所需的许多特性都已经包含在方法跟踪方面中了。</p><p>　　在本例中，记录方面扩展了方法跟踪方面，以便显示附加的与（在应用程序的执行过程中）所引发的异常有关的信息。</p><p>　　要完全使用记录方面，需要对应用程序做一些更改。BusinessLogicException异常类提供了一个可以由IBusinessLogicInterface接口和BusinessLogic实现类新增的void bar()方法引发的异常。</p><pre class="code">public class BusinessLogicException 
   extends Exception
{

}

public interface IBusinessLogic
{
    public void foo();
   
    public void bar() 
      throws BusinessLogicException;
}

public class BusinessLogic 
   implements IBusinessLogic
{
    public void foo() 
    {
        System.out.println(
          "Inside BusinessLogic.foo()");
    }
     
    public void bar() 
       throws BusinessLogicException
    {
        System.out.println(
        "Inside BusinessLogic.bar()");
          throw new BusinessLogicException();
    }
}
</pre><p>　　MainApplication类现在将对void bar()方法进行一次额外的调用，并处理选中的、可能由该方法引发的异常。</p><pre class="code">import org.springframeworkcontext.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class MainApplication
{
    public static void main(String [] args)
    {
        // Read the configuration file
        ApplicationContext ctx =
          new FileSystemXmlApplicationContext(
            "springconfig.xml");

       //Instantiate an object
       IBusinessLogic testObject = 
          (IBusinessLogic) ctx.getBean(
            "businesslogicbean");

       //Execute the public methods of the bean
       testObject.foo();
      
       try
       {
           testObject.bar();
       }
       catch(BusinessLogicException ble)
       {
           System.out.println(
             "Caught BusinessLogicException");
       }
    }
}
</pre><p>　　来自方法跟踪方面的TracingBeforeAdvice和TracingAfterAdvice通知可以整体重用。LoggingThrowsAdvice类为新的异常记录提供了通知。</p><pre class="code">import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;

public class LoggingThrowsAdvice 
   implements ThrowsAdvice
{
    public void afterThrowing(Method method, 
                            Object[] args, 
                            Object target, 
                            Throwable subclass)
    {
       System.out.println(
         "Logging that a " + 
         subclass + 
         "Exception was thrown.");
    }
}
</pre><p>　　应用记录方面的最后一步是修改springconfig.xml配置文件，使其包含新添加的LoggingThrowsAdvice通知。</p><p>　　图3显示了运行MainApplication并使用Spring框架应用了记录方面的UML顺序图。</p><p align="center">　　<a href="http://www.onjava.com/onjava/2004/07/14/graphics/fig3_full.png" target="_blank"><img alt="Click for larger view" src="http://dev2dev.bea.com.cn/images/image05121630003.gif" /></a><br />图3. 记录方面应用到BusinessLogic bean之后的顺序图（单击图像查看大图）</p><p>　　此处的记录方面清楚地说明了如何重用现有方面以及如何在Spring框架中使用通知的throws形式。通过为before和after通知声明新的通知来重写现有的方法跟踪方面实现，可以实现更复杂的记录方面，记录到更复杂的记录框架，比如<a href="http://logging.apache.org/log4j/docs/" target="_blank">LOG4J</a>。关于记录方面和例子应用程序的源代码，请参见<a href="http://www.onjava.com/pub/a/onjava/2004/07/14/springaop.html?page=2#references" target="_blank">本文末尾的参考资料</a>小节。</p><p><strong>结束语<br /></strong>　　本文展示了使用Spring框架中的基本AOP结构所应用的一些简单方面。在本系列的下一篇文章中，我们将介绍一些更实用的方面，探讨方面的生命周期，使用Spring框架的around通知，并使用Spring来应用AOP模式。</p><p>　　<strong>参考资料</strong></p><ul><li><a href="http://www.onjava.com/onjava/2004/07/14/examples/source.zip" target="_blank">本文的源代码</a></li><li><a href="http://www.springframework.org/" target="_blank">Spring Java/J2EE Framework</a></li><li><a href="http://www.springframework.org/docs/wiki/Spring_AOP_Framework.html" target="_blank">Spring AOP Framework</a></li><li>"<a href="http://www.onjava.com/pub/a/onjava/2004/01/14/aop.html" target="_blank">Introduction to Aspect-Oriented Programming</a>" </li></ul><p>　　原文出处:An Introduction to Aspect-Oriented Programming with the Spring Framework, Part 1<a href="http://www.onjava.com/pub/a/onjava/2004/07/14/springaop.html" target="_blank">http://www.onjava.com/pub/a/onjava/2004/07/14/springaop.html</a></p><!--文章其他信息--><div class="dot001"><img height="1" alt="" src="http://dev2dev.bea.com.cn/images/_.gif" width="100%" /></div><table cellspacing="0" cellpadding="3" width="100%" border="0"><tbody><tr valign="bottom"><td colspan="2" height="20"> <span class="h2b">作者简介</span></td></tr><tr><td valign="top" align="middle" width="0"></td><td><a href="http://www.onjava.com/pub/au/1725" target="_blank">Russell Miles</a>是General Dynamics UK公司的一名软件工程师，他负责Java和分布式系统，但是他目前主要的兴趣在面向方面领域，尤其是AspectJ。</td></tr></tbody></table><img src ="http://www.blogjava.net/gf7/aggbug/96470.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2007-01-29 12:00 <a href="http://www.blogjava.net/gf7/archive/2007/01/29/96470.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SOA实践 -- 使用IoC和AOP重构SOA应用</title><link>http://www.blogjava.net/gf7/archive/2006/12/21/89330.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Thu, 21 Dec 2006 09:33:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2006/12/21/89330.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/89330.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2006/12/21/89330.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/89330.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/89330.html</trackback:ping><description><![CDATA[
		<blockquote>在本文中，作者通过一个Web Service访问的实例，具体描述了SOA应用中所遇到的一系列具体问题，并描述如何利用IoC和AOP等技术进行代码重构，从而构建结构更加良好、灵活的SOA应用。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>
				<a name="IDA2CANB">
						<span class="atitle">
								<font face="Arial" size="4">1.引言</font>
						</span>
				</a>
		</p>
		<p>SOA是一种构造分布式系统的方法，它将业务应用功能以服务的形式提供出来，以便更好的复用、组装和与外部系统集成，从而降低开发成本，提高开发效率。SOA的目标是为企业构建一个灵活，可扩展的IT基础架构来更好地支持随需应变的商务应用。</p>
		<p>随着SOA技术和产品的不断成熟，现在越来越多的用户开始了解并认同SOA的理念，但对SOA项目的实施还缺乏信心。其主要原因是：SOA应用开发还相对比较复杂。</p>
		<p>一年多来，本文作者所在的部门已经从事了许多国内外的SOA项目的实施和支持工作，积累了许多SOA应用开发经验。我们希望能够通过一系列的文章与读者分享这些想法，帮助您更好地构建SOA应用。</p>
		<p>本文将从Web Service调用入手，在解决一系列具体问题的过程中，使用IoC (Inversion of Control) 和AOP (Aspect- Oriented Programming) 等方法重构Web Service的访问代码，使得业务逻辑与Web Service访问解耦，为您提供一个更加灵活和易于扩展的访问模式。</p>
		<p>Spring是一个流行的轻量级容器，对IoC和AOP提供了良好的支持。本文为您提供了一个基于Spring的实现供您下载学习。示例代码工程使用Eclipse3.1/3.02和JDK1.4开发, 您还需要Spring 1.2.5和Axis1.3提供的支持。详细的下载信息请参见参考资源部分。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																</td>
																<td valign="top" align="right">
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDAGDANB">
						<span class="atitle">
								<font face="Arial" size="4">2.Web Service调用</font>
						</span>
				</a>
		</p>
		<p>Web Service是目前实现SOA应用的一项基本的，适用的技术，它为服务的访问提供了一个被广泛接受的开放标准。为了便于说明问题，我们将使用XMethods 网站（<a href="http://www.xmethods.net/"><font color="#5c81a7">http://www.xmethods.net/</font></a>）发布的货币兑换服务作为示例。并针对JAX-RPC 1.1，说明如何编写Web Service 的调用代码。</p>
		<p>
				<a name="IDARDANB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">2.1 示例说明</font>
								</strong>
						</span>
				</a>
		</p>
		<p>http://xmethods.net 作为最早推出Web Service实际示例的网站，提供了很多优秀的Web Service 样例。其中有一个汇率计算服务，可以返回两个国家之间的货币兑换比例。获取该服务的详细信息，请参考该服务的服务描述文档（<a href="http://www.xmethods.net/sd/2001/CurrencyExchangeService.wsdl"><font color="#5c81a7">获取WSDL 文档</font></a>） 。在此就不具体解析该服务描述文档了。读者可以从WSDL2Java生成的接口中了解该服务的用法：</p>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">public interface CurrencyExchangePortType extends java.rmi.Remote {
public float getRate(String country1, String country2) throws java.rmi.RemoteException;
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="IDADEANB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">2.2 客户端调用方法</font>
								</strong>
						</span>
				</a>
		</p>
		<p>JAX-RPC作为Java平台的RPC服务调用标准接口，为Web Service客户端调用提供了3种方法，分别是DII，动态代理，和静态Stub。 DII（Dynamic Invocation Interface）采用直接调用方式，可以在程序中设置诸多的调用属性，使用较为灵活，但是调用过程却相对繁琐复杂，易造成代码膨胀且可重用性低，每次调用不同的Web Service都要重复进行大量编码。</p>
		<p>JAX-RPC中动态代理（Dynamic Proxy）的方法实现对Web Service的动态调用，可以在运行时根据用户定义的Client端接口创建适配对象。从而避免了直接操作底层的接口，减少了客户端的冗余，屏蔽了调用相关的复杂性。</p>
		<p>使用静态Stub和Service Locator是目前最常用的调用方式。JAX-RPC使用静态的Stub方式包装对底层接口的调用，从而提供一种更为简便的调用方式。使用该方式需要利用支持环境（比如Axis）所提供的工具根据WSDL预生成Web Service客户端的实现代码。因此如果服务的WSDL发生变化，就必须重新生成新的客户端代码并进行重新部署。</p>
		<p>为了更详细的了解静态Stub的调用方式，您可以将示例代码的WebServiceClient.jar导入到您现有Eclipse工作区之中。</p>
		<p>客户端生成代码包括如下4个类：如图 1 所示：</p>
		<br />
		<a name="IDAOEANB">
				<b>图 1： 客户端代码类图</b>
		</a>
		<br />
		<img height="269" alt="图 1： 客户端代码类图" src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image002.gif" width="476" border="0" />
		<br />
		<p>在上图中包括的几个类中：</p>
		<p>CurrencyExchangePortType：服务端点接口，定义了Web Service的方法签名。</p>
		<p>CurrencyExchangeService：Service接口，定义了获取服务端点接口的方法。</p>
		<p>CurrencyExchangeServiceLocator：ServiceLocator类，实现了Service接口。</p>
		<p>CurrencyExchangeBindingStub： Stub实现类，实现了服务端点接口，封装了对Web Service访问的底层逻辑。</p>
		<p>使用Stub调用Web Service的过程也非常简单，读者可以参考清单 1：</p>
		<br />
		<a name="IDABFANB">
				<b>清单 1：Web Service 调用代码示例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">try {
	//创建ServiceLocator
	CurrencyExchangeServiceLocator locator = new
	CurrencyExchangeServiceLocator();
	//设定端点地址
	URL endPointAddress = new URL("http://services.xmethods.net:80/soap");
	//创建Stub实例
	CurrencyExchangePortType stub =
	locator.getCurrencyExchangePort(endPointAddress);
	//设定超时为120秒
	((CurrencyExchangeBindingStub)stub).setTimeout(120000);
	//调用Web Service计算人民币与美元的汇率
	float newPrice = stub.getRate("China", "USA") * 100;
} catch (MalformedURLException mex) {
	//...
} catch (ServiceException sex) {
	//...
} catch (RemoteException rex) {
	//...
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<font face="Lucida Console">
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</font>
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<font face="Lucida Console">
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
										</font>
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<font face="Lucida Console">
																				<br />
																		</font>
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/#main">
																				<b>
																						<font color="#996699">
																						</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDAJFANB">
						<span class="atitle">
								<font face="Arial" size="4">3.重构Web Service调用代码</font>
						</span>
				</a>
		</p>
		<p>
				<a name="IDAOFANB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">3.1 实例代码中的"坏味道"</font>
								</strong>
						</span>
				</a>
		</p>
		<p>上面的基于Service Locator的Web Service访问代码虽然简单但暴露出以下几个问题：</p>
		<p>1．访问Web Service所需的配置代码被嵌入应用逻辑之中<br />在Web Service调用中，我们需要设定一系列必要的参数。比如：服务端点地址、用户名/密码、超时设定等等。这些参数在开发和运行环境中都有可能发生变化。我们必须提供一种机制：在环境变化时，不必修改源代码就可以改变Web Service的访问配置。</p>
		<p>2 客户端代码与Web Service访问代码绑定<br />在上面的代码中，业务逻辑与Web Service的Stub创建和配置代码绑定在一起。这也不是一种良好的编程方式。客户端代码只应关心服务的接口，而不应关心服务的实现和访问细节。比如，我们既可以通过Web Service的方式访问远程服务，也可以通过EJB的方式进行访问。访问方式对业务逻辑应该是透明的。</p>
		<p>这种分离客户端代码与服务访问代码的方式也有利于测试。这样在开发过程中，负责集成的程序员就可能在远程服务还未完全实现的情况下，基于服务接口编写集成代码，并通过编写POJO（Plain Old Java Object）构建伪服务实现来进行单元测试和模拟运行。这种开发方式对于保证分布式系统代码质量具有重要意义。</p>
		<p>因此，为了解决上面的问题我们需要：</p>
		<p>1、将Web Service访问的配置管理与代码分离；</p>
		<p>2、解除客户端代码与远程服务之间的依赖关系；</p>
		<p>
				<a name="IDAAGANB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">3.2 利用IoC模式进行重构代码</font>
								</strong>
						</span>
				</a>
		</p>
		<p>我们先介绍在Core J2EE Patterns一书中提到的一种业务层模式：Business Delegate。它所要解决的问题是屏蔽远程服务访问的复杂性。它的主要思想就是将Business Delegate作为远程服务的客户端抽象，隐藏服务访问细节。Business Delegate还可以封装并改变服务调用过程，比如将远程服务调用抛出的异常（例如RemoteException）转换为应用级别的异常类型。</p>
		<p>其类图如图 2 所示：</p>
		<br />
		<a name="IDAIGANB">
				<b>图 2：Business Delegate 模式的类图图解</b>
		</a>
		<br />
		<img height="154" alt="图 2：Business Delegate 模式的类图图解" src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image004.gif" width="554" border="0" />
		<br />
		<p>Business Delegate模式实现很好地实现了客户端与远程访问代码的解耦，但它并不关注Delegate与远程服务之间的解耦。为了更好解决Business Delegate和远程服务之间的依赖关系，并更好地进行配置管理，我们可以用IoC模式来加以解决。</p>
		<p>IoC（Inversion of Contro）l意为控制反转，其背后的概念常被表述为"好莱坞法则"："Don't call me, I'll call you." IoC将一部分责任从应用代码交给framework（或者控制器）来做。通过IoC可以实现接口和具体实现的高度分离，降低对象之间的耦合程度。Spring是一个非常流行的IoC容器，它通过配置文件来定义对象的生命周期和依赖关系，并提供了良好的配置管理能力。</p>
		<p>现在我们来重构我们的Web Service应用程序，我们首先为Business Delegate定义一个接口类型，它提供了一个应用级组件接口，所有客户端都应通过它来执行汇率计算，而不必关心实现细节，如清单 2 所示：</p>
		<br />
		<a name="IDAYGANB">
				<b>清单 2：接口定义的代码示例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">Public interface CurrencyExchangeManager {
	//货币兑换计算
	//新价格 = 汇率 * 价格
public float calculate(String country1, String country2, float price) 
throws CurrencyExchangeException;
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>Business Delegate的实现非常简单，主要工作是包装汇率计算 Web Service的调用，如清单 3 所示。</p>
		<br />
		<a name="IDABHANB">
				<b>清单 3：Business Delegate的代码示例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">public class CurrencyExchangeManagerImpl implements CurrencyExchangeManager {
	//服务实例
	private CurrencyExchangePortType stub;
	//获取服务实例
	public CurrencyExchangePortType getStub() {
		return stub;
	}
	//设定服务实例
	public void setStub(CurrencyExchangePortType stub) {
		this.stub = stub;
	}
	//实现货币兑换
	public float calculate(String country1, String country2, float price)
throws CurrencyExchangeException {
		try {
			//通过Stub调用WebService
			float rate = stub.getRate(country1, country2);
			return rate * price;
		} catch (RemoteException rex) {
			throw new CurrencyExchangeException(
					"Failed to get exchange rate!", rex);
		}
	}
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>下面我们需要讨论如何利用Spring的IoC机制，来创建和配置对象，并定义它们的依赖关系。</p>
		<p>Spring利用类工厂来创建和配置对象。在Spring框架中，已经为基于JAX－RPC的Web Service调用提供了一个客户端代理的类工厂实现：JaxRpcPortProxyFactoryBean。在配置文件bean.xml中，我们将使用JaxRpcPortProxyFactoryBean来创建和配置Web Service的客户端代理"CurrencyExchangeService"，如清单 5 所示。我们还将定义一个名为"CurrencyExchangeManager"的CurrencyExchangeManagerImpl实例，并建立它与CurrencyExchangeService之间的依赖关系。有关Spring 配置和JaxRpcPortProxyFactoryBean的使用细节请参见参考资料。</p>
		<br />
		<a name="IDALHANB">
				<b>清单 5：bean.xml的配置文件</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"&gt;
&lt;beans&gt;
	&lt;bean id="CurrencyExchangeService"
	class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean"&gt;
		&lt;property name="serviceInterface"&gt;	
		&lt;value&gt;net.xmethods.www.sd.CurrencyExchangeService_wsdl.
		CurrencyExchangePortType&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="wsdlDocumentUrl"&gt;		
		&lt;value&gt;http://www.xmethods.net/sd/2001/CurrencyExchangeService.
		wsdl&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="namespaceUri"&gt;
			&lt;value&gt;http://www.xmethods.net/sd/CurrencyExchangeService.
			wsdl&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="serviceName"&gt;
			&lt;value&gt;CurrencyExchangeService&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="portName"&gt;
			&lt;value&gt;CurrencyExchangePort&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="endpointAddress"&gt;
			&lt;value&gt;http://services.xmethods.net:80/soap&lt;/value&gt;		
		&lt;/property&gt;
	&lt;/bean&gt;	
	&lt;bean id="CurrencyExchangeManager"
	class="test.ws.CurrencyExchangeManagerImpl"&gt;
		&lt;property name="stub"&gt;
			&lt;ref bean="CurrencyExchangeService"/&gt;
		&lt;/property&gt;
	&lt;/bean&gt;
&lt;/beans&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>最后我们创建一个测试程序来验证我们的代码，如清单6 所示：</p>
		<br />
		<a name="IDAUHANB">
				<b>清单 6：测试代码</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">public class Main {
	// For test only
	public static void main(String[] args) {
		// Spring Framework将根据配置文件创建并配置CurrencyExchangeManager实例
		ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
		// 获取CurrencyExchangeManager实例
		CurrencyExchangeManager manager = (CurrencyExchangeManager) ctx
				.getBean("CurrencyExchangeManager");
		try {
			System.out.println(manager.calculate("China", "USA", 100));
			System.out.println(manager.calculate("China", "Japan", 200));
			System.out.println(manager.calculate("China", "USA", 200));
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>此时运行测试客户端，等待片刻将会看见测试结果，如清单 7 所示：</p>
		<br />
		<a name="IDA3HANB">
				<b>清单 7：测试结果。</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">12.34
2853.26
24.68
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>注：该结果会随着汇率的变化而出现不同的值。</p>
		<p>该程序的类图和顺序图如图3及图4所示：</p>
		<br />
		<a name="IDALQMNB">
				<b>图 3：示例程序的类图</b>
		</a>
		<br />
		<img height="223" alt="图 3：示例程序的类图" src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image006.jpg" width="553" border="0" />
		<br />
		<p>从上面的类图我们可以看到，我们的测试程序（Main.java）通过Spring框架获取了BusinessDelegate的实例。而且Spring 框架还会根据配置中的依赖关系，在运行时将Web Service的客户端代理" 注射"到CurrencyExchangeManagerImpl实例中，这就是依赖注入（<a href="http://www.martinfowler.com/articles/injection.html"><font color="#5c81a7">Dependency Injection</font></a>）。通过这种方式解决了应用逻辑和BusinessDelegate之间的依赖关系，以及BusinessDelegate的实现与远程服务之间的依赖关系，如图 4 所示。</p>
		<br />
		<a name="IDA5QMNB">
				<b>图 4: 示例程序的顺序图</b>
		</a>
		<br />
		<img height="252" alt="图 4:  示例程序的顺序图" src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image008.jpg" width="553" border="0" />
		<br />
		<p>Spring框架提供的ApplicationContext实现会根据配置文件中的描述信息来实现对象生命周期管理，配置管理以及依赖管理等功能。这一切对于应用程序是透明的，应用程序代码只依赖接口进行编程，而无需考虑其它复杂问题。无论是Web Service的配置发生变化，或是改用不同的服务实现时，都不会对客户端应用代码的产生影响。这很好地实现了业务逻辑与Web Service调用之间的解耦。</p>
		<p>
				<a name="IDANRMNB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">3.3 构建自己的 Web Service代理工厂</font>
								</strong>
						</span>
				</a>
		</p>
		<p>Spring所提供的JaxRpcPortProxyFactoryBean封装了构造Web Service客户端代理的细节，可以通过参数配置来创建Dynamic Proxy和DII类型的Web Service客户端代理。（如果您希望深入了解其实现细节可以参考org.springframework.remoting.jaxrpc包下的源代码。）但由于JaxRpcPortProxyFactoryBean需要使用者对WSDL中Port，Service，名空间等概念有深入的了解；而且如果Web Service使用了复杂数据类型，开发人员需要手工定义类型映射代码。所以JaxRpcPortProxyFactoryBean并不适合Web Service的初学者来使用。</p>
		<p>为了进一步简化Web Service代理的创建，并帮助读者更好地理解类工厂在Spring框架下的作用。我们提供了一个基于静态Stub的Web Service客户端代理工厂实现。其核心代码非常简单，就是通过ServiceLocator提供的方法来创建Web Service客户端代理。</p>
		<p>其主要代码如清单8所示：</p>
		<br />
		<a name="IDAVRMNB">
				<b>清单8：静态代理工厂的代码</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">public class WebServiceStubFactoryBean implements FactoryBean, 
InitializingBean {
	private Class serviceInterface;
	private Class serviceLocator;
	private Object stub;
     …
	public void afterPropertiesSet() throws Exception {
         //利用serviceLocator和服务接口创建Web Service客户端代理
		stub = ((javax.xml.rpc.Service)
		serviceLocator.newInstance()).getPort(serviceInterface);
	    //为Stub设定endpointAddress，usernam, 超时等参数
		preparePortStub((javax.xml.rpc.Stub) stub);
	}
	public Object getObject() {
          // 返回客户端代理
		return stub;
	}
	public Class getObjectType() {
          // 返回服务接口
		return serviceInterface;
	}
	public boolean isSingleton() {
		return true;
	}
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>我们需要修改配置文件bean.xml中有关Web Service代理创建的部分，让新的Web Service 代理工厂发挥作用。如清单9所示：</p>
		<br />
		<a name="IDA4RMNB">
				<b>清单9：修改后的bean.xml的配置文件</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;bean id="CurrencyExchangeService" class="test.ws.WebServiceStubFactoryBean"&gt;
	&lt;property name="serviceInterface"&gt;
	&lt;value&gt;net.xmethods.www.sd.CurrencyExchangeService_wsdl.CurrencyExchangePortType&lt;/value&gt;
	&lt;/property&gt;
	&lt;property name="serviceLocator"&gt;
	&lt;value&gt;net.xmethods.www.sd.CurrencyExchangeService_wsdl.CurrencyExchangeServiceLocator&lt;/value&gt;
	&lt;/property&gt;
	&lt;property name="endpointAddress2"&gt;
		&lt;value&gt;http://services.xmethods.net:80/soap&lt;/value&gt;
	&lt;/property&gt;
	&lt;property name="timeout"&gt;
		&lt;value&gt;120000&lt;/value&gt;
	&lt;/property&gt;
&lt;/bean&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>得益于Spring框架，虽然我们已经替换了对象的类工厂，却并不需要更改应用代码。通过Spring框架的IoC机制，我们可以完全使用面向接口的编程方式，而将实现的创建、配置和依赖管理交由Spring在运行时完成。即使实现发生了变化，也不需要改变应用程序结构。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/#main">
																				<b>
																						<font color="#996699">
																						</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDAHSMNB">
						<span class="atitle">
								<font face="Arial" size="4">4.新的思考</font>
						</span>
				</a>
		</p>
		<p>故事并没有结束，在开发过程中，我们又遇到了一系列关于Web Service调用的问题。</p>
		<p>
				<a name="IDANSMNB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">4.1性能</font>
								</strong>
						</span>
				</a>
		</p>
		<p>系统性能是分布式应用中的一个重要问题。许多用户都担心由Web Service技术所引入的额外开销是否会影响到产品的性能。随着技术的不断发展，Web Service引擎性能已经有了很大提高，一般来说使用Web Service的系统的性能可以满足绝大部分应用的需求。但在特定情况下，如果系统性能无法满足客户需求，我们首先需要对系统性能进行科学地分析和测定才能定位真正的性能瓶颈。这个问题在上文简单的示例中并不难解决，只需要在Web Service调用前后加入日志代码记录调用时间即可实现。但在实际系统中，比如一个产品目录的Web Service可能提供数十种查询方法，而程序中很多组件都会依赖于该服务提供的查询功能。如果在系统中所有的地方加入性能测定代码，这个工作就变得非常繁琐和困难。我们需要用一种更加优雅的解决方式，在增添新功能的同时并不影响系统代码或结构。</p>
		<p>
				<a name="IDATSMNB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">4.2缓存</font>
								</strong>
						</span>
				</a>
		</p>
		<p>在项目实践中，一个有效的改善Web Service系统性能的方法就是利用缓存来减少Web Service的重复调用。在具体实现中我们可以采用客户端缓存和服务器端缓存等不同方式，他们具有不同的特点和适用范围。在本文例子中，我们希望实现客户端缓存来提高系统性能。但由于Web Service业务逻辑的差别，我们希望能够为特定的Web Service提供特定的缓存策略，而且这些策略应该是能够被灵活配置的，它们不应于应用程序的逻辑代码耦合在一起。</p>
		<p>
				<a name="IDAZSMNB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">4.3故障恢复：</font>
								</strong>
						</span>
				</a>
		</p>
		<p>对于Web Service应用，系统的可用性也是一个需要考虑的重要问题。在运行时由于网络运行环境的复杂性和不确定性，用户希望能够对Web Service访问提供一定的故障恢复机制：比如重试或者访问备份服务（当系统在调用Web Service失败后，使用备份Web Service的服务地址来继续访问）。这些故障恢复策略应该是可配置的，对应用逻辑透明的。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/#main">
																				<b>
																						<font color="#996699">
																						</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDA5SMNB">
						<span class="atitle">
								<font face="Arial" size="4">5.使用AOP解决SOA应用中的Crosscutting Concern</font>
						</span>
				</a>
		</p>
		<p>通过对上边一系列问题的分析，读者也许会发现这些问题并不是Web Service访问的核心问题，但会影响系统中许多不同的组件。而且其中一些问题需要我们能够灵活配置不同的实现策略，因此我们不应该将处理这些问题的代码与应用代码混合。</p>
		<p>下面我们将利用AOP（Aspect-Oriented Programming）提供的方法来解决上述的问题。AOP是一种新兴的方法学，它最基本的概念就是关注隔离（Separation of Concern）。AOP提供了一系列的技术使得我们能够从代码中分离那些影响到许多系统模块的crosscutting concerns，并将他们模块化为Aspects。AOP的主要目的仍然是解耦，在分离关注点后，才能将关注点的变更控制一定范围内，增加程序的灵活性，才能使得关注能够根据需求和环境作出随时调整。</p>
		<p>我们将利用Spring所提供的AOP功能支持来解决以上问题。这里我们只简单地介绍涉及到的AOP基本概念以及实现，如果您希望更好地了解AOP的概念以及Spring AOP支持的细节请参见参考资料。</p>
		<ul>
				<li>Joinpoint 是程序的运行点。在Spring AOP中，一个Joinpoint对应着一个方法调用。 
</li>
				<li>Advice 定义了AOP框架在特定的Joinpoint的处理逻辑。Spring AOP框架通过interceptor方式实现了advice，并且提供了多种advice类型。其中最基本的"around advice"会在一个方法调用之前和之后被执行。 </li>
		</ul>
		<p>下面我们将利用Spring提供的MethodInterceptor来为Web Service调用实现我们的定义的处理逻辑。</p>
		<p>
				<a name="IDALTMNB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">5.1 PerformanceMonitorInterceptor </font>
								</strong>
						</span>
				</a>
		</p>
		<p>性能测量是AOP最简单的例子之一，我们可以直接利用Spring提供的实现在bean.xml中声明我们的WebServicePerformanceMonitorInterceptor。</p>
		<p>
				<a name="IDARTMNB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">5.2 CacheInterceptor</font>
								</strong>
						</span>
				</a>
		</p>
		<p>为了不引入缓存策略的复杂性，我们只提供了一个利用HashMap的简单实现：它利用 Web Service的调用参数列表作为HashMap键值。在Web Service调用之前，首先检查缓存中是否拥有与现在参数列表相同的项，如果有则返回缓存的结果，否则调用Web Service并将&lt;参数列表，结果&gt;记录在HashMap中。在实际应用中，您应该根据具体情况来选择、构造适合Web Service的业务特性的Cache实现，也可以采用成熟的Cache实现。</p>
		<p>在下面代码实现中有一个生成Web Service调用主键的小技巧。因为Web Service引擎要求所有调用参数必须是可序列化的，所以我们可以利用Java提供的序列化功能来实现对象的克隆。如清单10所示：</p>
		<br />
		<a name="IDAYTMNB">
				<b>清单10：SimpleCacheInterceptor的代码示例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">public class SimpleCacheInterceptor implements MethodInterceptor {
	private Map cache = new HashMap();
	private Object cloneObject(Object obj) throws Exception {
		Object newObj = null;
		if (obj != null) {
			// 通过序列化/反序列化来克隆对象
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream out = new ObjectOutputStream(bos);
			out.writeObject(obj);
			out.flush();
			out.close();
			ObjectInputStream in = new ObjectInputStream(
					new ByteArrayInputStream(bos.toByteArray()));
			newObj = in.readObject();
		}
		return newObj;
	}
	//基于参数列表数组，生成用于HashMap的键值
public Object generateKey(Object[] args) throws Exception {
		Object[] newArgs = (Object[]) cloneObject(args);
		List key = Arrays.asList(newArgs);
		return key;
	}
	//实现使用缓存技术的invoke方法
	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
		Object result = null;
		Object data = null;
		Object key = null;

		try {
			key = generateKey(methodInvocation.getArguments());
			data = cache.get(key);
		} catch (Exception ex) {
			logger.error("Failed to find from the cache", ex);
		}

		if (data == null) {
			//如果Cache中没有缓存结果，调用服务执行生成用于HashMap的键值
			result = methodInvocation.proceed();
			try {
				data = cloneObject(result);
				cache.put(key, data);
			} catch (Exception ex) {
				logger.error("Failed to cache the result!", ex);
			}
		} else {
			result = data;
		}
		return result;
	}
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="IDAAUMNB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">5.3 FailoverInterceptor</font>
								</strong>
						</span>
				</a>
		</p>
		<p>下面代码提供了一个基于服务备份切换的故障恢复实现，在运行时，如果Interceptor检测到服务调用由于网络故障抛出异常时，它将使用备份服务的端点地址并重新调用。如清单11所示：</p>
		<br />
		<a name="IDAGUMNB">
				<b>清单 11： SimpleFailoverInterceptor的代码示例</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">public class SimpleFailoverInterceptor implements MethodInterceptor {	…
     …
	//实现支持端点运行时切换的invoke方法
	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
		Object result = null;
		try {
			result = methodInvocation.proceed();
		} catch (Throwable ex) {
	        if (isNetworkFailure(ex)) {
                  //切换服务端点地址
				switchEndPointAddress((Stub) methodInvocation.getThis());
				result = methodInvocation.proceed();
			} else {
				throw ex;
			}
		}
		return result;
	}
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>为了支持备份服务切换的功能，我们在WebServicePortProxyFactoryBean中为填加了配置参数"endpointAddress2"，它会在创建的Web Service客户端代理对象中记录备份URL。</p>
		<p>我们可以在CurrencyExchangeService加入下列参数来试验SimpleFailoverInterceptor的功能。其中第一个端点地址为一个错误的URL。在第一次调用服务时，SimpleFailoverInterceptor会侦测到网络故障的发生，并自动切换使用第二个端点地址继续访问。如清单12所示：</p>
		<br />
		<a name="IDAQUMNB">
				<b>清单12：配置文件种增加的属性</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">		
&lt;property name="endpointAddress"&gt;
	&lt;value&gt;http://localhost/wrong_endpoint_address&lt;/value&gt;
&lt;/property&gt;
&lt;property name="endpointAddress2"&gt;
	&lt;value&gt;http://services.xmethods.net:80/soap&lt;/value&gt;
&lt;/property&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="IDAYUMNB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">5.4配置文件和运行结果</font>
								</strong>
						</span>
				</a>
		</p>
		<p>现在我们需要在Spring配置文件中，为所有interceptor添加定义，并描述如何为CurrencyExchangeService构建AOP Proxy。需要指出的是，我们要在interceptorName列表中声明interceptor链的调用顺序，还要将原有CurrencyExchangeManager引用的stub对象替换为新AOP Proxy。如清单13所示：</p>
		<br />
		<a name="IDA4UMNB">
				<b>清单13：修改后的配置文件片段</b>
		</a>
		<br />
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">&lt;bean id="WebServicePerformanceMonitorInterceptor"
class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"&gt;
	&lt;property name="prefix"&gt;
		&lt;value&gt;Web Service &lt;/value&gt;
	&lt;/property&gt;
	&lt;property name="suffix"&gt;
		&lt;value&gt;&lt;/value&gt;
	&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="CacheInterceptor" class="test.ws.SimpleCacheInterceptor"/&gt;
&lt;bean id="FailoverInterceptor" class="test.ws.SimpleFailoverInterceptor"/&gt;	
&lt;bean id="CurrencyExchangeProxy"
class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
	&lt;property name="proxyInterfaces"&gt;	
	&lt;value&gt;net.xmethods.www.sd.CurrencyExchangeService_wsdl.
	CurrencyExchangePortType&lt;/value&gt;
	&lt;/property&gt;
	&lt;property name="target"&gt; 
		&lt;ref local="CurrencyExchangeService"/&gt; 
	&lt;/property&gt;
	&lt;property name="interceptorNames"&gt;
		&lt;list&gt;
			&lt;value&gt;WebServicePerformanceMonitorInterceptor&lt;/value&gt;
			&lt;value&gt;CacheInterceptor&lt;/value&gt;
			&lt;value&gt;FailoverInterceptor&lt;/value&gt;
		&lt;/list&gt;
	&lt;/property&gt;
&lt;/bean&gt;	
&lt;bean id="CurrencyExchangeManager"
class="test.ws.CurrencyExchangeManagerImpl"&gt;
	&lt;property name="stub"&gt;
		&lt;ref bean="CurrencyExchangeProxy"/&gt;
	&lt;/property&gt;
&lt;/bean&gt;
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这里我们通过为AOP 的ProxyFactoryBean为 Web Service Stub创建了一个AOP代理，并且建立了一个Interceptor链。这样在调用Web Service时，Spring框架会依次调用Interceptor执行。实例执行的顺序图将如图5所示：</p>
		<br />
		<a name="IDAIVMNB">
				<b>图5系统运行顺序图</b>
		</a>
		<br />
		<img height="209" alt="图5系统运行顺序图" src="http://www-128.ibm.com/developerworks/cn/webservices/ws-refactoring/images/image010.jpg" width="554" border="0" />
		<br />
		<p>
				<a name="IDAVVMNB">
						<span class="smalltitle">
								<strong>
										<font face="Arial">5.5 Interceptor与JAX-RPC Handler的关系与区别</font>
								</strong>
						</span>
				</a>
		</p>
		<p>SOAP Message Handler是JAX-RPC为用户自定义Web Service处理过程提供的一种扩展机制。在处理Web Service请求/响应过程中，Web Service 引擎会根据部署描述中的定义，按照一定的次序调用Handler的处理代码。用户编写的Handler实现可以截获并修改Web Service消息和处理流程，从而实现对Web Service引擎处理行为的定制和增强。</p>
		<p>比如，我们可以实现一个服务器端Handler，记录Web Service在受到请求消息和发出响应消息之间的时间间隔来实现对服务器端业务性能的测定。而且我们只需在部署描述中增加Handler声明即可，无需修改任何服务器端代码。</p>
		<p>从此可以看出，JAX-RPC Handler与我们在上文中所提供的AOP Interceptor都可以帮助我们的SOA应用程序实现关注分离（Separate Concern）的目标，在不改变应用代码的同时，增强或改变Web Service服务访问的功能。虽然我们可以利用它们实现一些类似的功能，但它们具有着不同的特点和适用范围。</p>
		<p>JAX-RPC Handler是Web Service引擎的扩展机制。如果我们需要实现对SOAP消息进行的修改和处理，加入自定义的SOAP Header或对消息内容进行加密，Handler是我们的最佳选择。而AOP是针对对象级别的扩展机制，它更适合对应用层逻辑进行操作。</p>
		<p>比如，我们在上文展示的利用AOP实现的CacheInterceptor，它缓存的是Web Service调用参数和结果。而我们也可以通过JAX-RPC Handler实现一个面向SOAP消息的实现，它将缓存Web Service的请求消息和响应消息。这两个实现相比，基于AOP的实现更加简单、直观、快速、对资源消耗也比较小。而面向SOAP消息的实现则更加灵活，对于不采用RPC方式的Web Service访问也能提供支持。</p>
		<p>所以在具体的实践过程中，开发人员应该根据具体的需求选择合适的技术，也可以将这两种技术结合使用。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="IDAAWMNB">
						<span class="atitle">
								<font face="Arial" size="4">6.总结 </font>
						</span>
				</a>
		</p>
		<p>"分而治之"的方法是人们解决复杂问题的一种常见做法。而IoC、AOP等技术都体现了这种思想。通过更好的切分程序逻辑，使得程序结构更加良好，更加富有弹性，易于变化。也使得开发人员可以更加专注于业务逻辑本身，而将一部分其他逻辑交给容器和框架进行处理。</p>
		<p>在本文中，我们通过一个Web Service访问的实例，具体描述了SOA应用中所遇到的一系列具体问题，并描述如何利用IoC和AOP等技术进行代码重构，构建更加结构良好、灵活的SOA应用。综上所述，我们可以看到：</p>
		<p>1使用IoC框架来实现对象的生命周期管理、配置管理和依赖管理，可以解除业务逻辑对服务调用的依赖关系；</p>
		<p>2 使用AOP方法来解决Web Service调用中的crosscutting concerns，将为系统增加新的功能而不必更改应用程序。</p>
		<p>3通过IoC和AOP来屏蔽Web Service访问的复杂性，使得开发人员可以更加专注于业务逻辑本身，也使得系统更加稳定和富有弹性。<br /><br />代码：<a href="/Files/gf7/code.zip">下载</a></p>
<img src ="http://www.blogjava.net/gf7/aggbug/89330.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2006-12-21 17:33 <a href="http://www.blogjava.net/gf7/archive/2006/12/21/89330.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>获得汉字拼音首字母的java工具类【转载】</title><link>http://www.blogjava.net/gf7/archive/2006/12/05/85647.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Tue, 05 Dec 2006 10:35:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2006/12/05/85647.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/85647.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2006/12/05/85647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/85647.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/85647.html</trackback:ping><description><![CDATA[
		<table style="TABLE-LAYOUT: fixed; OVERFLOW: hidden" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="blog_content" colspan="2">
										<font color="#800080">
												<u>
														<br />
												</u>
												<font color="#000000">public class GetCh2Spell <br />        {<br />            public static int compare(String str1, String str2)<br />             {<br />                 int result = 0;<br />                 String m_s1 = null;<br />                 String m_s2 = null;<br />                 try<br />                 {<br />                     m_s1 = new String(str1.getBytes(_FromEncode_), _ToEncode_);<br />                     m_s2 = new String(str2.getBytes(_FromEncode_), _ToEncode_);<br />                 }<br />                 catch(Exception e)<br />                 {<br />                     return str1.compareTo(str2);<br />                 }<br />                 result = chineseCompareTo(m_s1, m_s2);<br />                 return result;<br />             }<br /><br />             public static int getCharCode(String s)<br />             {<br />                 if(s == null &amp;&amp; s.equals(""))<br />                     return -1;<br />                 byte b[] = s.getBytes();<br />                 int value = 0;<br />                 for(int i = 0; i &lt; b.length &amp;&amp; i &lt;= 2; i++)<br />                     value = value * 100 + b[i];<br /><br />                 return value;<br />             }<br /><br />             public static int chineseCompareTo(String s1, String s2)<br />             {<br />                 int len1 = s1.length();<br />                 int len2 = s2.length();<br />                 int n = Math.min(len1, len2);<br />                 for(int i = 0; i &lt; n; i++)<br />                 {<br />                     int s1_code = getCharCode(s1.charAt(i) + "");<br />                     int s2_code = getCharCode(s2.charAt(i) + "");<br />                     if(s1_code * s2_code &lt; 0)<br />                         return Math.min(s1_code, s2_code);<br />                     if(s1_code != s2_code)<br />                         return s1_code - s2_code;<br />                 }<br /><br />                 return len1 - len2;<br />             }<br /><br />             public static String getBeginCharacter(String res)<br />             {<br />                 String a = res;<br />                 String result = "";<br />                 for(int i = 0; i &lt; a.length(); i++)<br />                 {<br />                     String current = a.substring(i, i + 1);<br />                     if(compare(current, "\u554A") &lt; 0)<br />                         result = result + current;<br />                     else<br />                     if(compare(current, "\u554A") &gt;= 0 &amp;&amp; compare(current, "\u5EA7") &lt;= 0)<br />                         if(compare(current, "\u531D") &gt;= 0)<br />                             result = result + "z";<br />                         else<br />                         if(compare(current, "\u538B") &gt;= 0)<br />                             result = result + "y";<br />                         else<br />                         if(compare(current, "\u6614") &gt;= 0)<br />                             result = result + "x";<br />                         else<br />                         if(compare(current, "\u6316") &gt;= 0)<br />                             result = result + "w";<br />                         else<br />                         if(compare(current, "\u584C") &gt;= 0)<br />                             result = result + "t";<br />                         else<br />                         if(compare(current, "\u6492") &gt;= 0)<br />                             result = result + "s";<br />                         else<br />                         if(compare(current, "\u7136") &gt;= 0)<br />                             result = result + "r";<br />                         else<br />                         if(compare(current, "\u671F") &gt;= 0)<br />                             result = result + "q";<br />                         else<br />                         if(compare(current, "\u556A") &gt;= 0)<br />                             result = result + "p";<br />                         else<br />                         if(compare(current, "\u54E6") &gt;= 0)<br />                             result = result + "o";<br />                         else<br />                         if(compare(current, "\u62FF") &gt;= 0)<br />                             result = result + "n";<br />                         else<br />                         if(compare(current, "\u5988") &gt;= 0)<br />                             result = result + "m";<br />                         else<br />                         if(compare(current, "\u5783") &gt;= 0)<br />                             result = result + "l";<br />                         else<br />                         if(compare(current, "\u5580") &gt;= 0)<br />                             result = result + "k";<br />                         else<br />                         if(compare(current, "\u51FB") &gt; 0)<br />                             result = result + "j";<br />                         else<br />                         if(compare(current, "\u54C8") &gt;= 0)<br />                             result = result + "h";<br />                         else<br />                         if(compare(current, "\u5676") &gt;= 0)<br />                             result = result + "g";<br />                         else<br />                         if(compare(current, "\u53D1") &gt;= 0)<br />                             result = result + "f";<br />                         else<br />                         if(compare(current, "\u86FE") &gt;= 0)<br />                             result = result + "e";<br />                         else<br />                         if(compare(current, "\u642D") &gt;= 0)<br />                             result = result + "d";<br />                         else<br />                         if(compare(current, "\u64E6") &gt;= 0)<br />                             result = result + "c";<br />                         else<br />                         if(compare(current, "\u82AD") &gt;= 0)<br />                             result = result + "b";<br />                         else<br />                         if(compare(current, "\u554A") &gt;= 0)<br />                             result = result + "a";<br />                 }<br /><br />                 return result;<br />             }<br /><br />             public static String getFirstStr(String str)<br />             {<br />                 char a = str.charAt(0);<br />                 char aa[] = {<br />                     a<br />                 };<br />                 String sss = new String(aa);<br />                 if(Character.isDigit(aa[0]))<br />                     sss = "data";<br />                 else<br />                 if(a &gt;= 'a' &amp;&amp; a &lt;= 'z' || a &gt;= 'A' &amp;&amp; a &lt;= 'Z')<br />                     sss = "character";<br />                 else<br />                     sss = getBeginCharacter(sss);<br />                 return sss;<br />             }<br /><br />             private static String _FromEncode_ = "GBK";<br />             private static String _ToEncode_ = "GBK";<br /><br />        }</font>
												<span style="FONT-STYLE: italic; FONT-FAMILY: Courier New">
														<font color="#000000">
														</font>
														<br />
												</span>
										</font>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/gf7/aggbug/85647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2006-12-05 18:35 <a href="http://www.blogjava.net/gf7/archive/2006/12/05/85647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>收集几个所见即所得在线编辑器</title><link>http://www.blogjava.net/gf7/archive/2006/07/09/57327.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sun, 09 Jul 2006 03:48:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2006/07/09/57327.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/57327.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2006/07/09/57327.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/57327.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/57327.html</trackback:ping><description><![CDATA[先记下，以后有用得着的时候也好找。<br />所见即所得(WYSIWYG - What You See Is What You Get)<br /><br />1、<a href="http://www.ewebeditor.net/features.asp" target="_blank">eWebEditor</a>[Mode In China]<br /><br />简介：<br />　　eWebEditor是eWebSoft.com旗下eWeb团队开发的基于网页的、所见即所得的在线HTML编辑器。她能够在网页上实现许多桌面编辑软件（如：Word）所具有的强大可视编辑功能；她是一个真正的绿色软件，不需要在计算机上安装任何的客户端软件；她的易用使得WEB开发人员只要一行代码即可完成调用。<br />当前最新版本：Version 3.8 (ASP版、PHP版、JSP版、ASP.NET版) <br />对于一般站点来说，eWebEditor已经很不错了，简单易上手。<br /><br />使用方法/接口：<br /><br />在线演示：<br /><a href="http://ewebeditor.webasp.net/demo.asp" target="_blank">http://ewebeditor.webasp.net/demo.asp</a><br /><br />MailMagic下载：eWebEditor Version 2.8.0 修正版及绍文档<br />mailmagic://zoDAsdNafHdAAJzazaazvAoxzdDsadxsqdvNaxfAzfNdfxDzxqzqJzoAqiHfoioqaHxHNAnafsoNzJosfxdsDfnxxvdqvNaqnsnindNfdzsiJiaHJsAJAqzAinAHqNaoqHixiiHvAAzdNHHvnqqfxAndiHonqiAzsNdosvavAqiqvaNNJNqsqznovDqNdAvvvondaaNxiDiffdDsainsaqDifnxvJJaJADzAfafdHnJddxzJJiNHvdqqfviDvodiiAziAHxNnHnzAHnzHanvDisaDHDJHqJn<br /><br /><br />2、<a href="http://www.dynarch.com/projects/htmlarea/" target="_blank">HTMLArea</a><br />简介：<br />　　HTMLArea is a free, customizable online editor. It works inside your browser. It uses a non-standard feature implemented in Internet Explorer 5.5 or better for Windows and Mozilla 1.3 or better (any platform), therefore it will only work in one of these browsers. <br /><br />使用方法/接口：<br /><br />在线演示：<br /><a href="http://www.dynarch.com/demos/htmlarea/" target="_blank">http://www.dynarch.com/demos/htmlarea/</a><br /><br />MailMagic下载：HTMLArea release 3.0-rc1<br />mailmagic://qzsHqHnfAviDiNoqJvvisNHzsziqfzqxnzznosxnoDAvsvdxqfDqoJdiNiJnxAinsanxfznNnnAzoqvxdnqadJnnqsiJaxHsaassdaaaxAzDNxdDNHDzondfoNAJJodnaiqqzzziadsovfdfAJnoxzHAHsadosJsJffaNfHDnNoAxAvAsfnJADdqdvdsazifJNnHsxNxfavfJnzDfisnxzzfNAxfadnnvHDaxJfoqDHAzfNDsDxNNoizoviHNNaJ<br /><br /><br />3、<a href="http://www.fckeditor.net/" target="_blank">FCKeditor</a><br />简介：<br />　　This HTML text editor brings to the web many of the powerful functionalities of desktop editors like MS Word. It's lightweight and doesn't require any kind of installation on the client computer.<br />Because it is Open Source, you may use it however you want. <br /><br />使用方法/接口：<br /><br />在线演示：<br /><a href="http://www.fckeditor.net/demo/default.html" target="_blank">http://www.fckeditor.net/demo/default.html</a><br /><br />MailMagic下载：FCKeditor 2.2 released<br />mailmagic://zxsANfJqNosoAAosnqifNHnDNAxNHaadnHfdHJqAqiDNsNqJAqqqHandxADAfJodoDDzzvoqaHsNvDdvJzAJqvsdxqzasdavfsqvzaHfzHzxqaiNvvHifAzDonxqofHxzxaqDszxqfafAJffJdqsDvvNHNqJsvisooxixAAsfodfJanqfANHNzxvqsxoJszAHnNdqzqvNafaavHJovAvvxHxzqsiisHDNfHDiovfffznJxiAdNfDHxnifizDxdqq<br /><br /><br />4、<a href="http://tinymce.moxiecode.com/" target="_blank">TinyMCE</a><br />简介：<br />　　TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor control released as Open Source under LGPL by Moxiecode Systems AB. It has the ability to convert HTML TEXTAREA fields or other HTML elements to editor instances. TinyMCE is very easy to integrate into other CMS systems. <br /><br />使用方法/接口：<br /><br />在线演示：<br /><br />MailMagic下载：TinyMCE 2.0.4<br />mailmagic://JiDqnAddiHsJnDHDiiaDDAJiNAvDioAAdqNddoizHindzsDxofniHaxDzxNszxqxvavivHiNzxzisovNqqxaDadzDoaxAJdzdNdxozdfvnxozHHdfJqssaiDzvaiHNiiHdHxqzsJAHsJfdDdxHDqvADvNaJsnJovoDDAfaaDqDoiaasAqnJoAxinvssziiAqJNsxsdfvoxNNdoAoxiiDaanJnfsNAnqDnfxfazssfJssqJJzixvHnDqiaiodJiJq<br /><br /><br />5、<a href="http://www.freetextbox.com/" target="_blank">FreeTextBox</a><br />简介：<br />The no.1 free ASP.NET HTML Editor for IE and Mozilla. <br /><br />使用方法/接口：<br /><br />在线演示：<br /><a href="http://www.freetextbox.com/" target="_blank">http://www.freetextbox.com/</a><br /><br />MailMagic下载：FreeTextBox 3.0  Free License (free!)<br />mailmagic://oHNxNdiDzAxxofxiNHizdsaDADzfxoxfJsaNHdzAoaxNAdnaDvxNoxdxnxszqqANDoxJffJNAvixAoNnfiHasAzJJHAaJNJinJDNNioffviooqfHvffnnNHHxfvNfidnAoofdDfsaofAxafJoAJnNfanodovJofHAJzqanfJzqHdzvaJsosixaNaoxHNodfsHzzzdsDnovvJisNqvdqfzHNnzoaAoxiJdodoJdfiJisnvHfqdffHonsDioAvofan<br /><br /><br />6、<a href="http://www.themaninblue.com/experiment/widgEditor/" target="_blank">widgEditor</a>[<font color="red">支持XHTML</font>]<br /><br />简介：<br />　　widgEditor is an easily installed, easily customisable WYSIWYG editor for simple content. It replaces existing textareas with an improved editing pane using JavaScript, therefore if you don't have JavaScript (or your browser doesn't support HTML editing) it degrades gracefully. Try it out by typing below, and submit to see the processed output. <br /><br />使用方法/接口：<br /><br />在线演示：<br /><a href="http://www.themaninblue.com/experiment/widgEditor/" target="_blank">http://www.themaninblue.com/experiment/widgEditor/</a><br /><br />MailMagic下载：widgEditor <br />mailmagic://xxvvvsHAzAzJdAffaqNqAdxfNqvxqJsndsHNzDDJqadAAfqqzHaxnNsfdqDaxzfnNdnddzivsfnaNoixzqziDAvsiqqfqiqvAdzxfzDnvqNiNnadivAzdvqxzvoDfdJfNnxaqovnAfJfDnxiDvNDvqaAvqNizqzodfAfqHvNofzxzsivaxaqioaavHvDNqqDJJnzvqsoHxozoqniaJfavaisoHqaDJJffJdzHiHqfisisssdoDaoiAaJHiNDsddi<br /><br /><br />这篇文章对主流的在线WYSIWYG编辑器做了个详细的比较：<br /><a href="http://www.geniisoft.com/showcase.nsf/WebEditors" target="_blank">http://www.geniisoft.com/showcase.nsf/WebEditors</a><img src ="http://www.blogjava.net/gf7/aggbug/57327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2006-07-09 11:48 <a href="http://www.blogjava.net/gf7/archive/2006/07/09/57327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaScript--正则表达式 </title><link>http://www.blogjava.net/gf7/archive/2006/06/21/54351.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Wed, 21 Jun 2006 12:42:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2006/06/21/54351.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/54351.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2006/06/21/54351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/54351.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/54351.html</trackback:ping><description><![CDATA[
		<p>JavaScript--正则表达式</p>
		<p>　　正则表达式(regular expression)对象包含一个正则表达式模式(pattern)。它具有用正则表达式模式去匹</p>
		<p>配或代替一个串(string)中特定字符(或字符集合)的属性(properties)和方法(methods)。 </p>
		<p>正则表达式构造函数： new RegExp("pattern"[,"flags"]); <br />参数说明： <br />pattern -- 一个正则表达式文本 <br />flags -- 如果存在，将是以下值： <br />g: 全局匹配 <br />i: 忽略大小写 <br />gi: 以上组合 </p>
		<p>在构造函数中，一些特殊字符需要进行转意(在特殊字符前加"\")。正则表达式中的特殊字符： <br />字符  含意  <br />\ 转意，即通常在"\"后面的字符不按原来意义解释，如/b/匹配字符"b"，当b前面加了反斜杆后/\b/，转意为 </p>
		<p>匹配一个单词的边界。 <br />-或- <br />对正则表达式功能字符的还原，如"*"匹配它前面元字符0次或多次，/a*/将匹配a,aa,aaa，加了"\"后，/a\*/ </p>
		<p>将只匹配"a*"。  <br />^  匹配一个输入或一行的开头，/^a/匹配"an A"，而不匹配"An a"  <br />$  匹配一个输入或一行的结尾，/a$/匹配"An a"，而不匹配"an A"  <br />*  匹配前面元字符0次或多次，/ba*/将匹配b,ba,baa,baaa  <br />+  匹配前面元字符1次或多次，/ba*/将匹配ba,baa,baaa  <br />?  匹配前面元字符0次或1次，/ba*/将匹配b,ba  <br />(x)  匹配x保存x在名为$1...$9的变量中  <br />x|y  匹配x或y  <br />{n}  精确匹配n次  <br />{n,}  匹配n次以上  <br />{n,m}  匹配n-m次  <br />[xyz]  字符集(character set)，匹配这个集合中的任一一个字符(或元字符)  <br />[^xyz]  不匹配这个集合中的任何一个字符  <br />[\b]  匹配一个退格符 <br />\b  匹配一个单词的边界  <br />\B  匹配一个单词的非边界 <br />\cX  这儿，X是一个控制符，/\cM/匹配Ctrl-M  <br />\d  匹配一个字数字符，/\d/ = /[0-9]/  <br />\D  匹配一个非字数字符，/\D/ = /[^0-9]/  <br />\n  匹配一个换行符  <br />\r  匹配一个回车符  <br />\s  匹配一个空白字符，包括\n,\r,\f,\t,\v等  <br />\S  匹配一个非空白字符，等于/[^\n\f\r\t\v]/  <br />\t  匹配一个制表符  <br />\v  匹配一个重直制表符  <br />\w  匹配一个可以组成单词的字符(alphanumeric，这是我的意译，含数字)，包括下划线，如[\w]匹配"$5.98" </p>
		<p>中的5，等于[a-zA-Z0-9]  <br />\W  匹配一个不可以组成单词的字符，如[\W]匹配"$5.98"中的$，等于[^a-zA-Z0-9]。 </p>
		<p>
				<br />说了这么多了，我们来看一些正则表达式的实际应用的例子： <br />HTML代码的屏蔽 <br /> function mask_HTMLCode(strInput) { <br />   var myReg = /&lt;(\w+)&gt;/; <br />   return strInput.replace(myReg, "&amp;lt;$1&amp;gt;"); <br /> } <br />E-mail地址验证: <br /> function test_email(strEmail) { <br />  var myReg = /^[_a-z0-9]+@([_a-z0-9]+\.)+[a-z0-9]{2,3}$/; <br />  if(myReg.test(strEmail)) return true; <br />  return false; <br /> } </p>
		<p> </p>
		<p>正则表达式对象的属性及方法： <br />　　预定义的正则表达式拥有有以下静态属性：input, multiline, lastMatch, lastParen, leftContext, </p>
		<p>rightContext和$1到$9。其中input和multiline可以预设置。其他属性的值在执行过exec或test方法后被根据</p>
		<p>不同条件赋以不同的值。许多属性同时拥有长和短(perl风格)的两个名字，并且，这两个名字指向同一个值。(</p>
		<p>JavaScript模拟perl的正则表达式)</p>
		<p>正则表达式对象的属性： <br />属性 含义 <br />$1...$9 如果它(们)存在，是匹配到的子串  <br />$_ 参见input  <br />$* 参见multiline  <br />$&amp; 参见lastMatch  <br />$+ 参见lastParen  <br />$` 参见leftContext  <br />$''　　　　　　　　　 参见rightContext  <br />constructor　　　  创建一个对象的一个特殊的函数原型  <br />global　　　　　　  是否在整个串中匹配(bool型)  <br />ignoreCase　　　　 匹配时是否忽略大小写(bool型)  <br />input　　　　　　　 被匹配的串  <br />lastIndex　　　　  最后一次匹配的索引  <br />lastParen　　　　  最后一个括号括起来的子串  <br />leftContext　　　  最近一次匹配以左的子串  <br />multiline　　　　  是否进行多行匹配(bool型)  <br />prototype　　　　  允许附加属性给对象  <br />rightContext　　　 最近一次匹配以右的子串  <br />source　　　　　　  正则表达式模式  <br />lastIndex　　　　  最后一次匹配的索引  </p>
		<p>正则表达式对象的方法： <br />方法 含义 <br />compile　　　　　  正则表达式比较  <br />exec　　　　　　　 执行查找  <br />test　　　　　　　 进行匹配  <br />toSource　　　　　 返回特定对象的定义(literal </p>
		<p>representing)，其值可用来创建一个新的对象。重载Object.toSource方法得到的。  <br />toString　　　　　 返回特定对象的串。重载Object.toString方法得到的。  <br />valueOf　　　　　  返回特定对象的原始值。重载Object.valueOf方法得到 <br />  </p>
		<p>例子： <br />&lt;script language = "JavaScript"&gt; <br />var myReg = /(w+)s(w+)/; <br />var str  = "John Smith"; <br />var newstr = str.replace(myReg, "$2, $1"); <br />document.write(newstr); <br />&lt;/script&gt; <br />将输出"Smith, John" </p>
<img src ="http://www.blogjava.net/gf7/aggbug/54351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2006-06-21 20:42 <a href="http://www.blogjava.net/gf7/archive/2006/06/21/54351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决winxp文件内搜索搜索不到的问题！</title><link>http://www.blogjava.net/gf7/archive/2006/06/03/50127.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sat, 03 Jun 2006 06:53:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2006/06/03/50127.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/50127.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2006/06/03/50127.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/50127.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/50127.html</trackback:ping><description><![CDATA[运行regedit，编辑注册表<br />HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ContentIndex<br />右侧FilterFilesWithUnknownExtensions子键（REG_DEWORD类型）<br />的键值改为1。<img src ="http://www.blogjava.net/gf7/aggbug/50127.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2006-06-03 14:53 <a href="http://www.blogjava.net/gf7/archive/2006/06/03/50127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Axis 1.1 for Java进行Web Services开发</title><link>http://www.blogjava.net/gf7/archive/2006/02/04/29538.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sat, 04 Feb 2006 09:49:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2006/02/04/29538.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/29538.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2006/02/04/29538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/29538.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/29538.html</trackback:ping><description><![CDATA[<P>
<TABLE class=zhi14 style="WIDTH: 620px; HEIGHT: 38px" height=38 cellSpacing=0 cellPadding=0 width=620 align=center border=0>
<TBODY>
<TR>
<TD width=648 height=20>　　用Axis 1.1 for Java进行Web Services开发<BR>　　<BR>　　下面的所有几乎来自Axis1.1的文档。但不完全来自文档，本人做了部分修改，这些修改完全出自国内读者的需要。<BR>　　<BR>　　<B>什么是SOAP？</B><BR>　　<BR>　　SOAP是一个基于XML的用于应用程序之间通信数据编码的传输协议。最初由微软和Userland Software提出，随着不断地完善和改进，SOAP很快被业界广泛应用，目前完全发布版本是1.1。在其发展过程中，W3C XML标准工作小组积极促成SOAP成为一个真正的开放标准。在写作此文档之时，SOAP1.2草案已经发布，1.2对1.1中相对混乱的部分做了改进。<BR>　　<BR>　　SOAP被广泛作为新一代跨平台、跨语言分布计算Web Services的重要部分。<BR>　　<BR>　　这里太肤浅的说明，请参阅我的整理《一步一步学习SOAP》。<BR>　　<BR>　　<B>什么是Axis?</B><BR>　　<BR>　　Axis本质上就是一个SOAP引擎，提供创建服务器端、客户端和网关SOAP操作的基本框架。Axis目前版本是为Java编写的，不过为C++的版本正在开发中。<BR>　　<BR>　　但Axis并不完全是一个SOAP引擎，它还包括：<BR>　　<BR>　　是一个独立的SOAP服务器。<BR>　　<BR>　　是一个嵌入Servlet引擎（例如Tomcat）的服务器。<BR>　　<BR>　　支持WSDL。<BR>　　<BR>　　提供转化WSDL为Java类的工具。<BR>　　<BR>　　提供例子程序。<BR>　　<BR>　　提供TCP/IP数据包监视工具。<BR>　　<BR>　　Axis是第三代Apache SOAP，从2000年起，SOAP v2开发小组开始讨论如何让Axis更加灵活、可配置，以及能够处理SOAP和来自W3C的各种XML标准。通过不断地讨论和代码编写，Axis目前取得了如下成果：<BR>　　<BR>　　速度提高。 Axis通过基于事件的SAX对XML文档进行处理，从而在速度和效率上比Apache SOAP有所提高。<BR>　　<BR>　　灵活性提高。<BR>　　<BR>　　稳定性提高。<BR>　　<BR>　　提供面向组件的部署。<BR>　　<BR>　　提供一个简洁的传输抽象框架。其核心引擎完全于传输方式独立。从而使基于何种协议传输的选择更加灵活。<BR>　　<BR>　　支持WSDL。包括到处WSDL和客户代理生成等。<BR>　　<BR>　　<B>在目前发行1.1版本中有什么东西？</B><BR>　　<BR>　　SOAP1.1/1.2引擎。<BR>　　<BR>　　灵活的配置和部署系统。<BR>　　<BR>　　支持及时自动生成SOAP服务（JWS）。<BR>　　<BR>　　支持所有的基本数据类型，为自定义串行操作提供类型映射系统。<BR>　　<BR>　　JavaBean的自动串行操作，包括将自定义属性类型映射到XML的属性和元素。<BR>　　<BR>　　RPC和基于消息的SOAP服务提供者。<BR>　　<BR>　　从部署好的服务自动生成WSDL。<BR>　　<BR>　　WSDL2Java工具可以从WSDL描述文件中产生相应的客户和服务器端SOAP操作框架。<BR>　　<BR>　　初步提供安全扩展，能够与Servlet2.2安全集成。<BR>　　<BR>　　通过HTTP Cookie和与传输无关的SOAP头信息提供会话跟踪。<BR>　　<BR>　　初步支持带附件的SOAP消息。<BR>　　<BR>　　在EJB方面提供把EJB作为Web服务的访问途经。<BR>　　<BR>　　基于Servlet的HTTP传输。<BR>　　<BR>　　基于JMS的传输。<BR>　　<BR>　　独立的服务器（但需要HTTP 服务器和Servlet容器支持）。<BR>　　<BR>　　提供客户端、服务器端相关应用程序的样例。<BR>　　<BR>　　Axis的运行需要如下组件包<BR>　　<BR>　　axis.jar<BR>　　<BR>　　jaxrpc.jar<BR>　　<BR>　　saaj.jar<BR>　　<BR>　　commons-logging.jar<BR>　　<BR>　　commons-discovery.jar<BR>　　<BR>　　wsdl4j.jar<BR>　　<BR>　　符合JAXP-1.1的XML处理器。<BR>　　<BR>　　一步一步开始用Axis进行Web Services操作<BR>　　<BR>　　下面给出一段简单的调用Web Services方法的客户端代码（由于原文档中直接用导入包的方式初学者不易了解那个类在那个包中，所以下面我做了一些简单的修改，希望能给学习者清晰的思路）：<BR>　　<BR>　　public class TestClient {<BR>　　<BR>　　public static void main(String[] args) {<BR>　　<BR>　　try{<BR>　　<BR>　　String endpoint="http://localhost:8080/axis/SayHello.jws?wsdl";// 调用的web服务的url地址，这里是一个http请求，希望得到的结果是wsdl文档。<BR>　　<BR>　　org.apache.axis.client.Service service=new org.apache.axis.client.Service();//建立请求服务框架实例。<BR>　　<BR>　　/*<BR>　　<BR>　　* org.apache.axis.client.Service实现JAX-RPC's javax.xml.rpc.Services接口<BR>　　<BR>　　* 该接口充当产生下面提到的org.apache.axis.client.Call实例<BR>　　<BR>　　* 的角色。<BR>　　<BR>　　*/<BR>　　<BR>　　org.apache.axis.client.Call call=(org.apache.axis.client.Call)service.createCall();//从框架中生成一个维护调用的实例。<BR>　　<BR>　　/*<BR>　　<BR>　　* org.apache.axis.client.Call实现了JAX-RPC's javax.xml.rpc.Call接口。<BR>　　<BR>　　*/<BR>　　<BR>　　call.setTargetEndpointAddress(new java.net.URL(endpoint));<BR>　　<BR>　　call.setOperationName(new javax.xml.namespace.QName("http://www.edu-edu.com.cn/luopc/ws","echoString"));//设置需要调用的函数名称<BR>　　<BR>　　String result=(String)call.invoke(new Object[]{"hello!"});<BR>　　<BR>　　System.out.println(result);<BR>　　<BR>　　}catch(Exception e){<BR>　　<BR>　　System.err.println(e.toString());<BR>　　<BR>　　}<BR>　　<BR>　　}<BR>　　<BR>　　}<BR>　　<BR>　　上面的代码可能和原文档中不同，并且在名称空间、函数多态上会给用户造成糊涂。不过别急，我在翻译手册的同时会加入很多解释的代码，如果哪位纯粹看不懂可以通过邮件获取帮助：luopc@edu-edu.com.cn ，邮件主题必须是我提供的文档名称。<BR>　　<BR>　　通过上面的调用代码，最终生成向服务器请求SOAP信息包，具体XML内容如下：<BR>　　<BR>　　&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"　　　 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"　　　 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;　&lt;SOAP-ENV:Body&gt; &lt;ns1:echoString xmlns:ns1="http://www.edu-edu.com.cn/luopc/ws"&gt;　 &lt;arg0 xsi:type="xsd:string"&gt;Hello!&lt;/arg0&gt; &lt;/ns1:echoString&gt;　&lt;/SOAP-ENV:Body&gt;&lt;/SOAP-ENV:Envelope&gt;<BR>　　<BR>　　这里我不再多少，细心的朋友请从代码中找相应的对应信息来进行自己的逻辑理解。至于SOAP协议在我以后的翻译文档中会加入进去。<BR>　　<BR>　　从上面的代码中我们在调用的时候输入了参数new Object[]{“hello!”}。然后从生成的SOAP请求包中可以看到自动序列化成&lt;arg0 xsi:type="xsd:string"&gt;Hello!&lt;/arg0&gt;。你可以看到参数名称为arg0，类型为xsd:string。其实在Axis客户端我们可以直接通过具体的方法来设置每一个参数名称、类型以及返回值类型。如下代码：<BR>　　<BR>　　call.addParameter("testParam",　　org.apache.axis.Constants.XSD_STRING,　 javax.xml.rpc.ParameterMode.IN);call.setReturnType(org.apache.axis.Constants.XSD_STRING);<BR>　　<BR>　　加入上面的代码之后生成如下的SOAP信息：<BR>　　<BR>　　&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"　　　 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"　　　 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;　&lt;SOAP-ENV:Body&gt; &lt;ns1:echoString xmlns:ns1="http://www.edu-edu.com.cn/luopc/ws"&gt;　 &lt;testParam xsi:type="xsd:string"&gt;Hello!&lt;/testParam&gt; &lt;/ns1:echoString&gt;　&lt;/SOAP-ENV:Body&gt;&lt;/SOAP-ENV:Envelope&gt;<BR>　　<BR>　　可以作简单的对比。<BR>　　<BR>　　也许你会疑惑设置参数名称和不设置参数名称有什么区别的疑问。这里作简单的解释：<BR>　　<BR>　　1. 为什么要call.setReturnType(org.apache.axis.Constants.XSD_STRING)？<BR>　　<BR>　　上面你可以调用或者可以不调用，但当返回结果中没有标明数据类型时Axis就不知道如何进行数据类型转换。当然如果返回类型你很清楚并且返回应答SOAP的结果中表明了相应的数据类型你便可以不进行上面的函数调用。<BR>　　<BR>　　2. 为什么要设置参数名称和类型？<BR>　　<BR>　　好了，下在你知道了如何调用Web Services了，下面告诉你如何写作和发布Web Services。<BR>　　<BR>　　通过Axis发布Web Services<BR>　　<BR>　　这里写作一个简单的类，然后一步一步进行发布。希望用户能够从中理出一些思路来。我在其他的关于Web Services的文章中会专门针对Web Services的通用发布方法。虽然Web Services牵涉到很多复杂的知识，但请大家不要感觉到这些操作简单，也许你已经有很多疑问，没关系，记下你的疑问，不断的投试。<BR>　　<BR>　　public class SayHello {　　public String echoString(String hello){　　　　return hello;　　}}<BR>　　<BR>　　哈哈，这个类是不是太简单了。<BR>　　<BR>　　一步一步来。<BR>　　<BR>　　Axis提供两种将Java类发布成Web Services的途径，即即时快速自动发布和通过配置文件进行发布。我们首先从最容易部署的入手。<BR>　　<BR>　　JWS----即时部署<BR>　　<BR>　　简单说就是将自己写的Java类源文件按一定的规则Copy到特定的目录下便可自行被Axis部署。具体步骤如下：<BR>　　<BR>　　将上面写的SayHello.java复制到axis目录下。<BR>　　<BR>　　改名为SayHello.jws。<BR>　　<BR>　　注意：在你写的类中不能有具体包的信息，因为这正是Axis即时部署不支持的。<BR>　　<BR>　　运行我们前面写的客户端进行测试，运行结果是hello!。<BR>　<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;目前你是否有如下的问题？<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果类中用多态的函数将如何处理？<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其实很简单，我们知道在每次发出调用请求之前代理程序在后台会直接请求你给的URL，这里是http://localhost:8080/axis/SayHello.jws?wsdl，其实这一请求返回来的是WSDL描述文件，通过具体的描述文件的内容和你输入的参数的类型比较，最终确定发送什么请求。细节上的解释需要用户阅读SOAP的具体内容。我也会提供相应的权威文当翻译的。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Axis的客户端默认就是通过HTTP协议传输吗？<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如何将自己定义的类型进行映射？<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过WSDD自定义部署<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上面的自动部署相当简单，但当你需要<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;映射自己的类型时<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不需要暴露源代码时<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;需要自己的路径和包管理时<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对用户操作Web Services的事件进行相应时<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;就需要通过WSDD来自定义部署。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;前面新特性中提到过，Axis是一个很灵活的可配置系统，但在配置之前你得懂得Axis Web Services描述文档（WSDD）的格式和意义。这里有一个简单的例子（deploy.wsdd）：<BR>&nbsp;&nbsp;&nbsp;&nbsp;<PRE class=overflow>&nbsp;&nbsp;&nbsp;&lt;deployment xmlns="http://xml.apache.org/axis/wsdd/"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &lt;service name="SayHello2" provider="java:RPC"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;parameter name="className" value="luopc.ws.SayHello"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;parameter name="allowedMethods" value="*"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &lt;/service&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/deployment&gt;</PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;很简短的描述就会自定义对特定类以Web Services的形式发布。上面的每一个service项都会意味着开通一个相应的可被WSDL文件引用的服务。其内部描述信息将会描述从请求-处理请求-应答需要的所有核心信息。这里provider=”java:RPC”对应着相应的服务类为org.apache.axis.providers.java.RPCProvider。其实你可以通过多种方式提供相应的服务。在关于Axis的架构文章中将会详细解释这些内容。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上面的各个参数我不再解释，我想大家一看就明白。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面让我们在上面的简单配置上开始一步一步的进行各种高级配置：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;服务存活范围<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Axis提供Session、Request和Application三种可选范围配置。具体配置标记为：<BR><PRE class=overflow>&lt;service name="MyService"...&gt;<BR>&nbsp;&nbsp;&lt;parameter name="scope" value="value"/&gt;<BR>&nbsp;&nbsp;...<BR>&lt;/service&gt;</PRE><BR>一旦你完成上面的文件。可以写一个脚本批处理文件来完成部署。批处理文件如下：<BR><PRE class=overflow>java -classpath F:\resource\tools\axis-1_1\lib\axis.jar;F:\resource\tools\axis-1_1\lib\commons-discovery.jar;F:\resource\tools\axis-1_1\lib\jaxrpc.jar;F:\resource\tools\axis-1_1\lib\commons-logging.jar;F:\resource\tools\axis-1_1\lib\log4j-1.2.8.jar;F:\resource\tools\axis-1_1\lib\wsdl4j.jar;F:\resource\tools\axis-1_1\lib\j2ee.jar org.apache.axis.client.AdminClient sayHelloD.wsdd。</PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上面的一些jar文件都是Axis运行需要的组件，所以必须添加到环境中。上面的目录是我的机器里的目录，你可以按自己的目录进行。<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果部署成功，会输出&lt;Admin&gt;Done processing&lt;/Admin&gt;信息。<BR>但本人这里再强调几个：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;你首先要将你编译好的类放到axis/web-inf/classes/下面。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可以通过<A href="http://localhost:8080/axis/services/SayHello2">http://localhost:8080/axis/services/SayHello2</A>来调用。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;你可以从我的配置文件中发现了包的概念。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可以用相应的xml文件进行卸载已部署的服务。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;卸载方法如下：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编写如下XML文档<BR><PRE class=overflow>&lt;undeployment xmlns="http://xml.apache.org/axis/wsdd/"&gt;<BR> &lt;service name="MyService"/&gt;<BR>&lt;/undeployment&gt;</PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;把上面的批处理文件中的sayHelloD.wsdd换成该文件便可。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;继续关注高级部署<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果你想知道自己的某个Web Services被调用多少次，你应该怎么做呢？<BR>Axis提供了相应的跟踪机制。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先你应该编写一个满足一定接口的事件处理类。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在配置文件中添加事件处理器信息。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们先看看配置文件中的信息：<BR><PRE class=overflow>&lt;deployment xmlns="http://xml.apache.org/axis/wsdd/"<BR>&nbsp;&nbsp; xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;<BR>&nbsp;&nbsp;&lt;!-- define the logging handler configuration --&gt;<BR> &lt;handler name="track" type="java:samples.userguide.example4.LogHandler"&gt;<BR>&nbsp;&nbsp;&lt;parameter name="parameter1" value="访问该services"/&gt;<BR> &lt;/handler&gt;<BR> &lt;!-- define the service, using the log handler we just defined --&gt;<BR> &lt;service name="SayHello2" provider="java:RPC"&gt;<BR>&nbsp;&nbsp;&lt;requestFlow&gt;<BR>&nbsp;&nbsp; &lt;handler type="track"/&gt;<BR>&nbsp;&nbsp;&lt;/requestFlow&gt;<BR>&nbsp;&nbsp;&lt;parameter name="className" value="luopc.ws.SayHello"/&gt;<BR>&nbsp;&nbsp;&lt;parameter name="allowedMethods" value="*"/&gt;<BR> &lt;/service&gt;<BR>&lt;/deployment&gt;</PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上面的绿色部分起到核心的配置信息提供。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面提供一个事件处理类，同样来自原文档，但为了更清晰我同样将所有的类前面加上了包名称。<BR>package luopc.ws;<BR><BR>/**<BR>* @author luopc<BR>*/<BR>public class EventHandler extends org.apache.axis.handlers.BasicHandler{<BR>&nbsp;&nbsp;&nbsp;&nbsp;public void invoke(org.apache.axis.MessageContext mtxt){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String param=(String)getOption("parameter1");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(param);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] args) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;就这样，我们对请求跟踪了。嘻嘻。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可以远程进行管理（不推荐）<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;前面就提到服务类型的问题，在Axis有四种类型的服务，分别为RPC、Document、Wrapped和Message。 <BR>　　</TD></TR></TBODY></TABLE><STRONG><FONT color=#0000ff>Axis下 WebService 的调用问题<BR>
<TABLE class=zhi14 style="WIDTH: 620px; HEIGHT: 38px" height=38 cellSpacing=0 cellPadding=0 width=620 align=center border=0>
<TBODY>
<TR>
<TD width=648 height=20>　　本人按照网上例子制作一个Sample，遇到一个问题，当用JAVA编写的客户端调用返回值类型是int的函数时能正确得到返回值，但是调用返回值类型是String的函数时，不能正确得到返回值。以下为服务器端程序源代码：<BR>　　<BR>　　/**<BR>　　* 此处插入类型描述。<BR>　　* 创建日期：(2005-10-27 10:32:48)<BR>　　* @author：Administrator<BR>　　*/<BR>　　import java.util.*;<BR>　　<BR>　　public class ZxjTest {<BR>　　protected String name="gaga";<BR>　　protected int age=20;<BR>　　protected int sex=22;<BR>　　protected List items=new ArrayList();<BR>　　/**<BR>　　* ZxjTest 构造子注解。<BR>　　*/<BR>　　public ZxjTest() {<BR>　　super();<BR>　　}<BR>　　public String getName()<BR>　　{<BR>　　return name;<BR>　　}<BR>　　public int getAge()<BR>　　{<BR>　　return age;<BR>　　}<BR>　　public int getSex()<BR>　　{<BR>　　return sex;<BR>　　}<BR>　　public List getItems()<BR>　　{<BR>　　return items;<BR>　　}<BR>　　}<BR>　　<BR>　　客户端调用的源代码：<BR>　　String endpoint = "http://myserver:7001/ZxjTest.jws";<BR>　　Service service = new Service();<BR>　　Call call = (Call) service.createCall();<BR>　　call.setTargetEndpointAddress(new java.net.URL(endpoint));<BR>　　call.setOperationName("getName");<BR>　　String ret = (String) call.invoke(new Object[] {});<BR>　　<BR>　　出错的就是最后一句。如果这一句改成调用返回值是Int的函数，就不会出错。请问，这是Axis的配置的问题吗？如果是，该如何改？<BR>　　<BR>　　应该不大可能是Axis的配置的问题，你调用的是<BR>　　<BR>　　public String getName()<BR>　　{<BR>　　return name;<BR>　　}<BR>　　<BR>　　因此返回的是String，这个是没有错误的！<BR>　　<BR>　　你的程序我在自己机器上运行的很好！不管调用哪个方法，都一样输出。你可以把String ret = (String) call.invoke(new Object[] {});改成Object ret = (Object)call.invoke(new Object[] {});这样的话你就不用去类型转换了！<BR>　　<BR>　　或者如果你要类型转换的话，也可以这样做：<BR>　　<BR>　　1，如果调用返回类型是string的方法 那么最后一句应该为<BR>　　<BR>　　String ret = (String) call.invoke(new Object[] {});<BR>　　<BR>　　2，如果调用返回类型是int的方法，那么最后一句应该为<BR>　　<BR>　　Integer ret = (Integer)call.invoke(new Object[] {});<BR>　　<BR>　　还有要注意的是在利用客户端进行测试的时候，确保服务器已经启动，否则会出错。如果你是采用http://myserver:7001/ZxjTest.jws的话，你的web-inf下确保没有<BR>　　<BR>　　server-config.wsdd，否则也会出错。<BR>　　<BR>　　还有一个很简单的错误，可能仅仅只是WebLogic配置的问题。最好重建一个应用并重新配置。</TD></TR>
<TR>
<TD style="WORD-BREAK: break-all" vAlign=top width=648 height=18></TD></TR></TBODY></TABLE></FONT></STRONG></P><img src ="http://www.blogjava.net/gf7/aggbug/29538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2006-02-04 17:49 <a href="http://www.blogjava.net/gf7/archive/2006/02/04/29538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简介 Google 开放式 WebServices 查询接口</title><link>http://www.blogjava.net/gf7/archive/2006/01/30/29370.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Mon, 30 Jan 2006 05:46:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2006/01/30/29370.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/29370.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2006/01/30/29370.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/29370.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/29370.html</trackback:ping><description><![CDATA[查找引擎之王&nbsp;google&nbsp;于&nbsp;4/11&nbsp;开放了它的查询接口，可以让全世界各地的&nbsp;Java&nbsp;以及&nbsp;.NET&nbsp;程序员，免费地以&nbsp;WebServices&nbsp;的方式，对&nbsp;google&nbsp;下查找指令，并且可以将结果使用于自己的程序或网页中。不过使用上也有限制，它一天只允许未付费的程序员查找&nbsp;1000&nbsp;次。要使用前，必须先向&nbsp;google&nbsp;注册帐号，取得一个&nbsp;32&nbsp;位长度的&nbsp;license&nbsp;key&nbsp;，每次呼叫查询时，必须带入这个&nbsp;license&nbsp;key&nbsp;即可使用。因为&nbsp;WebServices&nbsp;以&nbsp;WSDL&nbsp;(Web&nbsp;Service&nbsp;Definition&nbsp;Language)&nbsp;的方式描述所开放的接口，走的通讯协定是&nbsp;SOAP&nbsp;on&nbsp;HTTP&nbsp;，所以理论上可以穿越防火墙。&nbsp;Java&nbsp;范例程序如下∶&nbsp;<BR><BR>import&nbsp;java.io.*;<BR>import&nbsp;com.google.soap.search.*;&nbsp;//&nbsp;这是&nbsp;googleapi.jar&nbsp;，由&nbsp;google&nbsp;所提供&nbsp;<BR><BR>public&nbsp;class&nbsp;SearchGoogle&nbsp;{<BR><BR>&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(args.length&nbsp;!=&nbsp;2)&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.err.println("Usage:&nbsp;java&nbsp;SearchGoogle&nbsp;LicenseKey&nbsp;查询字符串&nbsp;");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.exit(1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;clientKey&nbsp;=&nbsp;args[0];<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;args[1];<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;查询字符串&nbsp;=&nbsp;"&nbsp;+&nbsp;queryString);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;产生查找对象，设定输出编码&nbsp;(big5)<BR>&nbsp;&nbsp;&nbsp;&nbsp;GoogleSearch&nbsp;s&nbsp;=&nbsp;new&nbsp;GoogleSearch();<BR>&nbsp;&nbsp;&nbsp;&nbsp;s.setKey(clientKey);<BR>&nbsp;&nbsp;&nbsp;&nbsp;s.setOutputEncoding("big5");<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.setQueryString(qyeryString);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GoogleSearchResult&nbsp;r&nbsp;=&nbsp;s.doSearch();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;查找结果&nbsp;:");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("======================");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(r.toString());<BR>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(GoogleSearchFault&nbsp;e)&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;查找失败&nbsp;");<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}<BR>}<BR><BR>&nbsp;<BR><BR>使用方法以及查询结果（执行环境∶&nbsp;Linux&nbsp;+&nbsp;JDK&nbsp;1.3.1_01&nbsp;，主机位于防火墙后端）∶&nbsp;<BR><BR><BR>java&nbsp;-classpath&nbsp;.:../lib/googleapi.jar&nbsp;<BR>SearchGoogle&nbsp;xxxxxxxxx-&nbsp;我的&nbsp;LicenseKey-xxxxxxxxx&nbsp;LinuxFab<BR><BR>查询字符串&nbsp;=&nbsp;LinuxFab<BR>查找结果&nbsp;:<BR>======================<BR>{<BR>TM&nbsp;=&nbsp;0.048257<BR>Q&nbsp;=&nbsp;"LinuxFab"<BR>CT&nbsp;=&nbsp;""<BR>TT&nbsp;=&nbsp;""<BR>CATs&nbsp;=<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;{SE="Big5",&nbsp;FVN="Top/World/Chinese_Traditional/&nbsp;计算机&nbsp;/Operating_Systems/Unix/Linux"}<BR>&nbsp;&nbsp;}<BR>Start&nbsp;Index&nbsp;=&nbsp;1<BR>End&nbsp;Index&nbsp;=&nbsp;10<BR>Estimated&nbsp;Total&nbsp;Results&nbsp;Number&nbsp;=&nbsp;11500<BR>Document&nbsp;Filtering&nbsp;=&nbsp;true<BR>Estimate&nbsp;Correct&nbsp;=&nbsp;false<BR>Rs&nbsp;=<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;[<BR>&nbsp;&nbsp;URL&nbsp;=&nbsp;"http://bbs.ee.ntu.edu.tw/boards/Linux/21/"<BR>&nbsp;&nbsp;Title&nbsp;=&nbsp;"&nbsp;◆&nbsp;【&nbsp;LinuxFab&nbsp;早报】&nbsp;"<BR>&nbsp;&nbsp;Snippet&nbsp;=&nbsp;"&nbsp;◆&nbsp;【&nbsp;LinuxFab&nbsp;早报】&nbsp;.&nbsp;...&nbsp;5,&nbsp;◇&nbsp;【&nbsp;LinuxFab&nbsp;本周专栏】&nbsp;如何制作简易&nbsp;Floppy&nbsp;Liunx,&nbsp;linuxfab.&nbsp;07/13/01.&nbsp;...&nbsp;"<BR>&nbsp;&nbsp;Directory&nbsp;Category&nbsp;=&nbsp;{SE="",&nbsp;FVN=""}<BR>&nbsp;&nbsp;Directory&nbsp;Title&nbsp;=&nbsp;""<BR>&nbsp;&nbsp;Summary&nbsp;=&nbsp;""<BR>&nbsp;&nbsp;Cached&nbsp;Size&nbsp;=&nbsp;"11k"<BR>&nbsp;&nbsp;Related&nbsp;information&nbsp;present&nbsp;=&nbsp;true<BR>&nbsp;&nbsp;Host&nbsp;Name&nbsp;=&nbsp;""<BR>&nbsp;&nbsp;],<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;[<BR>&nbsp;&nbsp;URL&nbsp;=&nbsp;"http://bbs.ee.ntu.edu.tw/boards/Linux/21/73.html"<BR>&nbsp;&nbsp;Title&nbsp;=&nbsp;"&nbsp;◇&nbsp;【&nbsp;LinuxFab&nbsp;早报】&nbsp;-&nbsp;Linux&nbsp;2.4.10&nbsp;内核中剽窃了&nbsp;┅&nbsp;"<BR>&nbsp;&nbsp;Snippet&nbsp;=&nbsp;"&nbsp;◇&nbsp;【&nbsp;LinuxFab&nbsp;早报】&nbsp;-&nbsp;Linux&nbsp;2.4.10&nbsp;内核中&nbsp;剽窃了&nbsp;┅&nbsp;.&nbsp;发信人&nbsp;:&nbsp;linuxfab.bbs&nbsp;...&nbsp;"<BR>&nbsp;&nbsp;Directory&nbsp;Category&nbsp;=&nbsp;{SE="",&nbsp;FVN=""}<BR>&nbsp;&nbsp;Directory&nbsp;Title&nbsp;=&nbsp;""<BR>&nbsp;&nbsp;Summary&nbsp;=&nbsp;""<BR>&nbsp;&nbsp;Cached&nbsp;Size&nbsp;=&nbsp;"10k"<BR>&nbsp;&nbsp;Related&nbsp;information&nbsp;present&nbsp;=&nbsp;true<BR>&nbsp;&nbsp;Host&nbsp;Name&nbsp;=&nbsp;"bbs.ee.ntu.edu.tw"<BR>&nbsp;&nbsp;],<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;[<BR>&nbsp;&nbsp;URL&nbsp;=&nbsp;"http://www.lslnet.com/linux/docs/linux-3033.htm"<BR>&nbsp;&nbsp;Title&nbsp;=&nbsp;"LinuxFab:&nbsp;Red&nbsp;Hat7.0&nbsp;?&nbsp;新特色&nbsp;-&nbsp;[?&nbsp;森林&nbsp;-&nbsp;自由&nbsp;?&nbsp;件&nbsp;]"<BR>&nbsp;&nbsp;Snippet&nbsp;=&nbsp;"&nbsp;...&nbsp;LinuxFab:&nbsp;Red&nbsp;Hat7.0&nbsp;?&nbsp;新特色&nbsp;?&nbsp;森林&nbsp;http://www.lslnet.com&nbsp;2000&nbsp;年&nbsp;9&nbsp;月&nbsp;24&nbsp;日&nbsp;09:59&nbsp;...&nbsp;摘自∶&nbsp;http:linuxfab.cx&nbsp;[&nbsp;??&nbsp;窗口&nbsp;].&nbsp;...&nbsp;"<BR>&nbsp;&nbsp;Directory&nbsp;Category&nbsp;=&nbsp;{SE="",&nbsp;FVN=""}<BR>&nbsp;&nbsp;Directory&nbsp;Title&nbsp;=&nbsp;""<BR>&nbsp;&nbsp;Summary&nbsp;=&nbsp;""<BR>&nbsp;&nbsp;Cached&nbsp;Size&nbsp;=&nbsp;"5k"<BR>&nbsp;&nbsp;Related&nbsp;information&nbsp;present&nbsp;=&nbsp;true<BR>&nbsp;&nbsp;Host&nbsp;Name&nbsp;=&nbsp;""<BR>&nbsp;&nbsp;],<BR>&nbsp;下略&nbsp;<BR>&nbsp;<BR><BR>当然，输出结果不是这么杂乱，&nbsp;google&nbsp;所提供的&nbsp;api&nbsp;有各种查找设定方法，例如从第几笔开始查找、设定传回笔数、偏好查找（避免查找&nbsp;java&nbsp;时传回&nbsp;咖啡&nbsp;的结果）&nbsp;...&nbsp;等等，各位可以好好玩一玩。&nbsp;<BR><BR>如果您不想使用&nbsp;google&nbsp;的&nbsp;library&nbsp;，您也可以利用手边的&nbsp;WebServices&nbsp;工具程序，自动抓取&nbsp;google&nbsp;所提供的&nbsp;WSDL&nbsp;文档（位于∶&nbsp;http://api.google.com/GoogleSearch.wsdl&nbsp;），并且产生相关的&nbsp;java&nbsp;对象。以下以&nbsp;GLUE&nbsp;这套&nbsp;Java&nbsp;WebServices&nbsp;软体包做范例∶&nbsp;<BR><BR><BR>$&nbsp;wsdl2java&nbsp;http://api.google.com/GoogleSearch.wsdl&nbsp;-p&nbsp;example&nbsp;-d&nbsp;example/<BR><BR>write&nbsp;file&nbsp;example/IGoogleSearchPort.java<BR>write&nbsp;file&nbsp;example/GoogleSearchServiceHelper.java<BR>write&nbsp;file&nbsp;example/ResultElement.java<BR>write&nbsp;file&nbsp;example/DirectoryCategory.java<BR>write&nbsp;file&nbsp;example/GoogleSearchResult.java<BR>write&nbsp;file&nbsp;GoogleSearchService.map<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;<BR><BR>GLUE&nbsp;的强处在于它自动为您处理所有&nbsp;XML&nbsp;&lt;-&gt;&nbsp;Java&nbsp;Object&nbsp;Mapping&nbsp;以及&nbsp;SOAP&nbsp;传输的问题，您甚至不需要看懂&nbsp;WSDL&nbsp;便可直接使用&nbsp;WebServices&nbsp;！我们现在已经将&nbsp;WSDL&nbsp;转换成&nbsp;Java&nbsp;对象，&nbsp;package&nbsp;名为&nbsp;example&nbsp;，接下来便是撰写&nbsp;Client&nbsp;去连接&nbsp;google&nbsp;∶&nbsp;<BR><BR>import&nbsp;java.io.*;<BR>import&nbsp;electric.registry.Registry;&nbsp;//&nbsp;包含于&nbsp;GLUE-STD.jar&nbsp;，为&nbsp;GLUE&nbsp;标准版的&nbsp;library<BR>import&nbsp;example.*;&nbsp;//GLUE&nbsp;自动为您由&nbsp;WSDL&nbsp;产生出来的&nbsp;Java&nbsp;对象&nbsp;<BR><BR>public&nbsp;class&nbsp;SearchGoogle2&nbsp;{<BR><BR>&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(args.length&nbsp;!=&nbsp;2)&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.err.println("Usage:&nbsp;java&nbsp;SearchGoogle&nbsp;LicenseKey&nbsp;查询字符串&nbsp;");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.exit(1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;clientKey&nbsp;=&nbsp;args[0];<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;queryString&nbsp;=&nbsp;args[1];<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;查询字符串&nbsp;=&nbsp;"&nbsp;+&nbsp;queryString&nbsp;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;url&nbsp;=&nbsp;"http://api.google.com/GoogleSearch.wsdl";<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;try<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;利用&nbsp;GLUE&nbsp;产生的接口，去&nbsp;bind&nbsp;google&nbsp;的&nbsp;WSDL<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IGoogleSearchPort&nbsp;searcher&nbsp;=&nbsp;(IGoogleSearchPort)&nbsp;Registry.bind(url&nbsp;,&nbsp;IGoogleSearchPort.class);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;查询<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GoogleSearchResult&nbsp;result&nbsp;=&nbsp;searcher.doGoogleSearch<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;clientKey&nbsp;,&nbsp;queryString&nbsp;,&nbsp;0&nbsp;,&nbsp;1&nbsp;,&nbsp;false&nbsp;,&nbsp;""&nbsp;,&nbsp;false&nbsp;,&nbsp;""&nbsp;,&nbsp;"Big5"&nbsp;,&nbsp;"Big5"&nbsp;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;查找结果&nbsp;:");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("======================");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;回应数量∶&nbsp;"&nbsp;+&nbsp;result.resultElements.length&nbsp;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;第一笔结果∶&nbsp;");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;简介∶&nbsp;"&nbsp;+&nbsp;result.resultElements[0].summary&nbsp;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("URL&nbsp;∶&nbsp;"&nbsp;+&nbsp;result.resultElements[0].URL&nbsp;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;片段∶&nbsp;"&nbsp;+&nbsp;result.resultElements[0].snippet&nbsp;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;标头∶&nbsp;"&nbsp;+&nbsp;result.resultElements[0].title&nbsp;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;主机∶&nbsp;"&nbsp;+&nbsp;result.resultElements[0].hostName&nbsp;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;目录∶&nbsp;"&nbsp;+&nbsp;result.resultElements[0].directoryTitle&nbsp;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(electric.registry.RegistryException&nbsp;e)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("&nbsp;错误∶&nbsp;"&nbsp;+&nbsp;e.getMessage());<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}&nbsp;<BR>}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;<BR><BR>执行结果指令如下∶&nbsp;<BR><BR>$&nbsp;java&nbsp;-classpath&nbsp;.:../lib/GLUE-STD.jar:../lib/j2ee.jar:../lib/jnet.jar&nbsp;<BR>SearchGoogle2&nbsp;xxxxxxxxx-&nbsp;我的&nbsp;LicenseKey-xxxxxxxxx&nbsp;LinuxFab<BR>查询字符串&nbsp;=&nbsp;LinuxFab<BR>查找结果&nbsp;:<BR>======================<BR>回应数量∶&nbsp;1<BR>第一笔结果∶<BR>简介∶<BR>URL&nbsp;∶&nbsp;http://bbs.ee.ntu.edu.tw/boards/Linux/21/<BR>片段∶◆&nbsp;【&nbsp;LinuxFab&nbsp;早报】&nbsp;.&nbsp;...&nbsp;5,&nbsp;◇&nbsp;【&nbsp;LinuxFab&nbsp;本周专栏】&nbsp;如何制作简易&nbsp;Floppy&nbsp;Liunx,&nbsp;linuxfab.&nbsp;07/13/01.&nbsp;...<BR>标头∶◆&nbsp;【&nbsp;LinuxFab&nbsp;早报】<BR>主机∶<BR>目录∶<BR><BR>&nbsp;<BR><BR>要注意的是，这只是&nbsp;google&nbsp;beta2&nbsp;版本的&nbsp;WSDL&nbsp;，未来接口一定会有所更动，而且远端主机&nbsp;(api.google.com)&nbsp;仍然不太稳定，有时候会连不过去，有时又会出现&nbsp;Internal&nbsp;Server&nbsp;Error&nbsp;的错误。不过以上的介绍应该可以给大家一个简单的&nbsp;WebServices&nbsp;概念了吧？目前几乎所有的程序语言都有&nbsp;WebServices&nbsp;的相关软体包，不论您是&nbsp;PHP&nbsp;网页制作者，或是&nbsp;VB&nbsp;窗口程序员，应该都找到相关的软体包，直接在您的网页&nbsp;/&nbsp;程序上面撰写&nbsp;WebServices&nbsp;的&nbsp;Client&nbsp;以及&nbsp;Server&nbsp;。&nbsp;<BR><BR>截稿前消息∶全球最大的网络书店&nbsp;Amazon&nbsp;，也开始提供&nbsp;WebServices&nbsp;接口给代销商（&nbsp;associates&nbsp;，可以在个人网页上放置连往&nbsp;Amazon&nbsp;的&nbsp;icon&nbsp;或连结，藉此赚取部分成交金额）使用。代销商现在可以利用&nbsp;Amazon&nbsp;提供的&nbsp;WebServices&nbsp;撰写&nbsp;Web/Desktop&nbsp;应用程序了！看来类似的&nbsp;WebServices&nbsp;将会逐渐在许多大站点中陆续被采用，或许&nbsp;LinuxFab/SourceFab&nbsp;可以考虑引进此技术，使本站成为华人&nbsp;Open&nbsp;Source&nbsp;界的网络运算中心。 <img src ="http://www.blogjava.net/gf7/aggbug/29370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2006-01-30 13:46 <a href="http://www.blogjava.net/gf7/archive/2006/01/30/29370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有选择的安装ＩＢＭ随机软件</title><link>http://www.blogjava.net/gf7/archive/2006/01/28/29338.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sat, 28 Jan 2006 05:04:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2006/01/28/29338.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/29338.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2006/01/28/29338.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/29338.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/29338.html</trackback:ping><description><![CDATA[用IBM的笔记本的朋友非常的多,大多数人都喜欢删除原带的系统,自己来按装新的操作系统,可是重装系统后对于IBM随机带的软件可以说是一头雾水,因为软件大多都为英文,而且数量又多,没办法许多朋友就用全部按装法,把只要是随机带的全部装到机器上,可是有一部分是完全没有必要装的,或者说可以选择性的按装,本文的目的是为了让大家了解大多数随机软件的用途,让大家按自己的用途来按装,从而结省了有限的内存空间,<BR>注: 其中大部分软件只能使用在T2x,X2x,R系列,A2x以后的机型,对于570这种老机器好多软件是无法安装的,系统为Windows XP<BR>1. Battery MaxiMiser Wizard&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;按装性:必装~<BR>这个软件按字面来看是”电池最大化向导”,它是通过电池中的一块芯片来查看电池的健康情况以及电池的充电次数和剩余电量等等一些相关参数的.它还可以自己定义电源管理模式,比如用电池时屏幕是4格亮度,CPU按最小的频率使用等.,<BR>2. IBM PM驱动&nbsp;&nbsp;&nbsp;&nbsp;按装性:必装<BR>PM的意为Power Management Driver,也就是电源管理驱动,它是十分重要的一个软件,它可以来控制当本本在市电与电池之间切换时,CPU与主板PCI总线频率的控制,也就是我们所说的CPU降频使用,当然您的CPU必须支持Speed Step技术,此软件也与上面的软件配合使用<BR>3.HotKey 驱动&nbsp;&nbsp;&nbsp;&nbsp; 按装性:必装<BR>IBM的热键驱动,它的功能有当用户调整音量与屏幕亮度时,在屏幕下方显示当前音量和亮度的等级,以图形方式显示.还包括打开键盘灯和屏幕放大的提示.等.<BR>4. ThinkPad Configuration&nbsp;&nbsp;&nbsp;&nbsp;按装性:必装<BR>这个软件相当于您系统中的设备管理器,它的功能可以说是相当强大,它可以管理IBM ThinkPad笔记本电脑中的所有硬件,以及内置的安全芯片,查看系统信息等等,它可以打开和屏蔽笔记本中的各种接口,如PCMCIA,红外端口等.<BR>5. Presentation Director&nbsp;&nbsp;&nbsp;&nbsp; 按装性:可选<BR>它叫演示向导,一个非常实用的驱动,它非常适合那些经常外出接投影仪和大屏幕显示设备的商务人士,它的组合键是FN+F7,按下后会出现一个选择分辩率的列表,当用户外接一个显示设备时可选择一个适合的分辩率,演示后还可以直接切换回来,就不用来回的调整屏幕的分辩率了,如果去多个地方又要用到不同的分辩率和显示设备,那么可以手动设置不同的分辩率和屏幕的显示方式,方便快速,节约时间,从而提高的工作效率.<BR>6. Keyboard Customizer Utility&nbsp;&nbsp; 按装性:可选<BR>用过ThinkPad本本的朋友都知道IBM的键盘没有视窗键,这个软件就可以让你用其它的键来代替视窗键.当然它的功能不止这些,它还可以让用户按照自己的喜好把键盘上的一些组合健定义成快捷键,比如笔者就把Shift+右方向键,定义成为了光驱打开.它还可以当您外接键盘时可以用重新定义功能键,有兴趣的朋友不仿自己试试.<BR>7. EasyEject Utility&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;按装性:可选<BR>它的功能等同于系统中安全移除硬件向导,组合键为FN+F9,它的优点是界面十分直观,当用户要停用移动设备时,它可以以帮助您安全的移除您连接的设备,包括用户接的扩展坞<BR>8. IBM Active Protection System&nbsp;&nbsp;&nbsp;&nbsp;按装性:必装<BR>APS驱动,这个驱动只支持T41以后的本本,当然还包括R51等支持这个硬盘保护功能笔记本,APS是一种主动的硬盘保护系统,它的作用是当用户在使用笔记本过程中,电脑意外下落,这个系统会在非常快的时间内做出反应,停止硬盘工作,保护用户的数据,把损失降到最小,笔者建议有这个功能的本本用户最好还是装上,不在乎那几M的内存,安全才是最重要的.<BR>9. IBM Access Connections&nbsp;&nbsp; 按装性:可选<BR>笔都最喜欢用的一个软件,个人认为是IBM随机软件中最最经典的一个,没有一个共享软件比的上它,说它经典是因为它非常试合网络管理员来使用,也非常适合天天带着本本在不同的网络间漫游的人(不管有线网络,无线网络,ADSL,还是企业内网),有了它网管就不用来回更改本本的IP地址了,不用建立一大堆的连接方式,不用用脑子记住不同的DNS,不同的网关,它的方便之处只有你用了才可以深深的明白,呵呵,说多了有点.具体的说,它可以让用户分别定义不同的网络配置文件,这件配置文件中包括不同的网络连接方式,不同的IP地址,网关,DNS等等,当用户从一个网络中切换到另一个网络中,不需要重新更改本机的IP地址,只要按一下FN+F5组合键,从定义好的列表中选择一种适合的配置文件即可,真是太方便了.它的优点和细节功能真是一句两句说不清楚,总之呢希望朋友们好好的利用它节省我们的时间,提高我们的工作效率<BR>10. UltraNav Wizard&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;按装性:可选<BR>这个驱动只适合那些有触模板的ThinkPad计算机,包括T30.T4x,R51等等,它的功能也很多,它可以调整触模板的一些细节设置,比如可以把触模板左右键设成快捷健,打开用户的程序.还可以把触模板的一边设成滚轮来浏览网页等等.<BR>11.Access IBM&nbsp;&nbsp;&nbsp;&nbsp; 按装性:可选)<BR>就是按下本本右上角那个蓝色的按钮出来的东东,它包括帮助文件,还有恢复系统等等,笔者没有按装,个人感觉它是一个花瓶,所以我把那个蓝色按钮改成快捷键了.如果朋友们喜欢那个蓝色按钮打开时的界面,我想还是装上去吧.对于那些对ThinkPad了解深入的朋友就没有必要按装了<BR><BR>12. Access IBM Message Center&nbsp;&nbsp; 按装性:可选<BR>IBM的消息中心,我想它是给像我这样的懒人准备的,我一般很少去IBM的官方网站去看看出个什么新驱动没有,装上它就方便多了,有什么新驱动和关于您本本的新消息,它会马上通知您下载和按装,比较方便的<BR>13. Software Installer&nbsp;&nbsp;&nbsp;&nbsp; 按装性: 必装&nbsp;&nbsp;&nbsp;&nbsp;适用机型：全部<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp; 意为“软件安装者”当初在第一篇文章中，没把它加入是我的失误，现在隆重介绍此软件，经常在Windows软件区看到不少XD，求这个驱动，那个驱动的，其实只要装了Software Installer您就不用在上IBM官方网站找驱动了，SI可以帮助你找到你的计算机所需要的最新驱动程序，当然前提是小黑必须连接入互联网，它会自己搜索针对本机的驱动程序，让用户有选择性的下载，速度还不错。没用过的XD快快装上吧。<BR><BR>14.System Migration Assistant&nbsp;&nbsp;&nbsp;&nbsp; 按装性: 建议安装&nbsp;&nbsp; 适用机型：全部<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;英文意为“IBM 系统迁移辅助程序”，我想大多数的兄弟都不太喜欢重装系统，因为有一些个人设置（如桌面、图标、网络设置、窗口大小、等一些小细节、甚至还包括声音）都要重新来过，有时还会忘记一些重要设置，有了IBM 系统迁移辅助程序，就太方便了，它可以把用户的个人设置，全部导出为扩展名为*.sma的备份文件，重装系统后，再导入到新装的系统中就可以完全1：1的回到您重装系统之前，速度快不说、最重要是它备份文件的完整性、和可选择性，它可以选择您想备份的，去掉不想备份。全中文界面，就好比选择性的克隆一样<BR>经我试用，SMA居然还可以把你在原系统中的共享文件夹也给备份了，当然包括用户信息如：Administrator的设置等等，总之SMA带给你的只有方便和简单加上快速。<BR><BR>15. IBM Client Security Software&nbsp;&nbsp;&nbsp;&nbsp;按装性: 可选&nbsp;&nbsp;&nbsp;&nbsp;适用机型：T2x\T4x\R5x\等<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;IBM 客户端安全软件,也就是IBM广告中经常提到的CSS 1.0 2.0，CSS不光应用于小黑，也应用于ThinkCentre台式电脑，CSS通过嵌入式安全子系统，也就是安全芯片，对用户的重要数据进行加密，和保护，当然还包括管理用户的常用密码，如果有CSS的XD可以不防一试，想加密文件时，就不必在按装第三方加密软件了。<BR><BR>16. IBM File and Folder Encryption&nbsp;&nbsp;按装性：可选<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;意为IBM 文件和文件夹加密，是和CSS客户端配合使用的一个程序，简称为IBM FFE，它的名气没有CCS那么大，FFE只能加密C盘的文件，对于其它驱动器，FFE是无法加密的。个人认为用CSS就可以了。FFE没有必要安装。<BR><BR>17. IBM Rescue and Recovery&nbsp;&nbsp;&nbsp;&nbsp; 按装性：建议安装<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;大名鼎鼎的IBM 营救和恢复程序，简称R&amp;R，虽然我很少使用它，因为它太大了。4××MB，不过为了这个文章装一下研究，事先说明R&amp;R只支持Win2000和XP，R&amp;R是一个超级强大的备份压缩工具，个人认为R&amp;R可以代替HPA了，R&amp;R可以备份全部的系统文件到硬盘中，或者到其它的移动介质，它可以备份所有分区，或者单独的分区，备份过程是在Windows下进行的，如果您想恢复您备份的系统，重装启动，按下F11键，一个很漂亮又熟悉的介面就会出现在你在眼前，他可以代替世面上所以的备份恢复软件,大家不防一试。R&amp;R太强大了，光*我的一个介绍难于让大家直观了解，大家可以装上看看<BR><img src ="http://www.blogjava.net/gf7/aggbug/29338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2006-01-28 13:04 <a href="http://www.blogjava.net/gf7/archive/2006/01/28/29338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MyEclipse+struts+Hibernate配置开发手册</title><link>http://www.blogjava.net/gf7/archive/2005/12/23/25255.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Fri, 23 Dec 2005 10:56:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/12/23/25255.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/25255.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/12/23/25255.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/25255.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/25255.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: MyEclipse+struts+Hibernate配置开发手册&nbsp;说明：&nbsp;这个手册只是为初学者制作的环境配置和快速开发的一些基本方法，为的是广大爱好者能快速上手，少走我走过的弯路，里面没有任何关于java模式和其他相关的说明。本人水平有限，也没有能力去讨论关于模式设计和开发细节的一些内容。&nbsp...&nbsp;&nbsp;<a href='http://www.blogjava.net/gf7/archive/2005/12/23/25255.html'>阅读全文</a><img src ="http://www.blogjava.net/gf7/aggbug/25255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-12-23 18:56 <a href="http://www.blogjava.net/gf7/archive/2005/12/23/25255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>运用Jsp技术生成彩色汉字验证码</title><link>http://www.blogjava.net/gf7/archive/2005/12/23/25254.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Fri, 23 Dec 2005 10:52:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/12/23/25254.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/25254.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/12/23/25254.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/25254.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/25254.html</trackback:ping><description><![CDATA[<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD vAlign=top height=63>
<TABLE class=zhi12 cellSpacing=0 cellPadding=0 width="96%" align=center border=0>
<TBODY>
<TR>
<TD style="FONT-WEIGHT: normal; FONT-SIZE: 16pt; LINE-HEIGHT: normal; FONT-STYLE: normal; FONT-VARIANT: normal" height=49>
<DIV align=center><B><FONT color=#003399>
<P align=center>运用Jsp技术生成彩色汉字验证码</P></FONT></B></DIV></TD></TR>
<TR>
<TD height=28>
<DIV align=center>&nbsp;</DIV></TD></TR></TBODY></TABLE>
<TABLE style="WIDTH: 85%" cellSpacing=0 cellPadding=0 width="85%" align=center border=0>
<TBODY>
<TR>
<TD>
<HR>
</TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD vAlign=top>
<TABLE class=zhi14 style="WIDTH: 620px; HEIGHT: 38px" height=38 cellSpacing=0 cellPadding=0 width=620 align=center border=0>
<TBODY>
<TR>
<TD width=648 height=20><BR>　　一些网站采用了字母和数字的验证码，数字和字母加起来一共30多个，如果有心，还是能够通过方法识别出来。<BR>　　<BR>　　我在网上看到一篇文章"jsp彩色验证码"，我进行了加强，生成的验证码内容为汉字，可以方便应用在面向汉语网民的网站认证上。<BR>　　<BR>　　当然，我还看到别人考虑的几种方法：<BR>　　<BR>　　1.生成计算题，比如20+34*(23-12)=?，用户必须输入正确的答案才能通过验证，这个想法挺好，但是用户必须打开计算器进行计算，增加了用户的难度<BR>　　<BR>　　2.问一些常见的问题，比如“人”这个字由几笔组成。这也是不错的想法，关键是必须有上万条的题库，而且题库的答案必须是明确的，简单易比较的，这个难度也较大。<BR>　　<BR>　　下面是彩色汉字验证码的代码。<BR>　　<BR>　　&lt;%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" %&gt;<BR>　　&lt;%!<BR>　　//create by smallnest<BR>　　//email: smallnest@gmail.com<BR>　　//website:www.kuaff.com<BR>　　<BR>　　//生成随机颜色<BR>　　Color getRandColor(Random random,int fc,int bc)<BR>　　{<BR>　　if(fc&gt;255) fc=255;<BR>　　if(bc&gt;255) bc=255;<BR>　　int r=fc+random.nextInt(bc-fc);<BR>　　int g=fc+random.nextInt(bc-fc);<BR>　　int b=fc+random.nextInt(bc-fc);<BR>　　return new Color(r,g,b);<BR>　　}<BR>　　%&gt;<BR>　　&lt;%<BR>　　//设置页面不缓存<BR>　　response.setHeader("Pragma","No-cache");<BR>　　response.setHeader("Cache-Control","no-cache");<BR>　　response.setDateHeader("Expires", 0);<BR>　　<BR>　　// 设置图片的长宽<BR>　　int width=176, height=30;<BR>　　//设置备选汉字，剔除一些不雅的汉字<BR>　　String base = "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6";<BR>　　//备选汉字的长度<BR>　　int length = base.length();<BR>　　<BR>　　//创建内存图像<BR>　　BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);<BR>　　// 获取图形上下文<BR>　　Graphics g = image.getGraphics();<BR>　　<BR>　　//创建随机类的实例<BR>　　Random random = new Random();<BR>　　<BR>　　// 设定图像背景色(因为是做背景，所以偏淡)<BR>　　g.setColor(getRandColor(random,200,250));<BR>　　g.fillRect(0, 0, width, height);<BR>　　<BR>　　//备选字体<BR>　　String[] fontTypes = {"\u5b8b\u4f53","\u65b0\u5b8b\u4f53","\u9ed1\u4f53","\u6977\u4f53","\u96b6\u4e66"};<BR>　　int fontTypesLength = fontTypes.length;<BR>　　<BR>　　//在图片背景上增加噪点<BR>　　g.setColor(getRandColor(random,160,200));<BR>　　g.setFont(new Font("Times New Roman",Font.PLAIN,14));<BR>　　for (int i=0;i&lt;6;i++)<BR>　　{<BR>　　g.drawString("*********************************************",0,5*(i+2));<BR>　　}<BR>　　<BR>　　//取随机产生的认证码(6个汉字)<BR>　　<BR>　　//保存生成的汉字字符串<BR>　　String sRand="";<BR>　　for (int i=0;i&lt;6;i++)<BR>　　{<BR>　　int start = random.nextInt(length);<BR>　　String rand=base.substring(start,start+1);<BR>　　sRand+=rand;<BR>　　<BR>　　//设置字体的颜色<BR>　　g.setColor(getRandColor(random,10,150));<BR>　　//设置字体<BR>　　g.setFont(new Font(fontTypes[random.nextInt(fontTypesLength)],Font.BOLD,18 + random.nextInt(6)));<BR>　　//将此汉字画到图片上<BR>　　g.drawString(rand,24*i+ 10 + random.nextInt(8),24);<BR>　　}<BR>　　<BR>　　//将认证码存入session<BR>　　session.setAttribute("rand",sRand);<BR>　　<BR>　　g.dispose();<BR>　　<BR>　　//输出图象到页面<BR>　　ImageIO.write(image, "JPEG", response.getOutputStream());<BR>　　<BR>　　%&gt;</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/gf7/aggbug/25254.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-12-23 18:52 <a href="http://www.blogjava.net/gf7/archive/2005/12/23/25254.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字符的全角和半角转换</title><link>http://www.blogjava.net/gf7/archive/2005/12/21/24956.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Wed, 21 Dec 2005 07:40:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/12/21/24956.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/24956.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/12/21/24956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/24956.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/24956.html</trackback:ping><description><![CDATA[<P>在web应用中，开发者经常会面临字符的全角和半角转换问题。那么什么是全角？什么是半角呢？简单说就是中文系统用双字节显示汉字造成的与世界标准（由美国制订的）不一的问题。<BR>举一个简单的例子，中文逗号“，”就是全角的，相对的西文逗号“,”就是半角的。这样的例子很多，比如“～”与“~”、“＋”与“+”等等。</P>
<P>那么，字符的全角和半角转换有什么用处呢？一般说来，我们做的网页都是中文的，要求用户填入的信息也多是汉字，那么很多特殊字符都是全角的，比如说填写多条信息，用逗号分隔，这里的逗号多半都是全角的。而提交到后台（服务器端）处理，或者是查询（构建select语句）或者是入库（提交给DBMS），都是基于西文体系的，因此必须将这些字符转换成对应的半角字符。<BR>下面举一个JavaScript的通用代码例子，详细介绍一下如何将这些全角字符转换成半角字符。<BR>function SD(sbc, dbc)<BR>{<BR>&nbsp;this.sbc = sbc;<BR>&nbsp;this.dbc = dbc;<BR>}</P>
<P>var sdArray = new Array();<BR>var sdCount;<BR>var i = 0;</P>
<P>sdArray[i++] = new SD("０", "0");<BR>sdArray[i++] = new SD("１", "1");<BR>sdArray[i++] = new SD("２", "2");<BR>sdArray[i++] = new SD("３", "3");<BR>sdArray[i++] = new SD("４", "4");<BR>sdArray[i++] = new SD("５", "5");<BR>sdArray[i++] = new SD("６", "6");<BR>sdArray[i++] = new SD("７", "7");<BR>sdArray[i++] = new SD("８", "8");<BR>sdArray[i++] = new SD("９", "9");<BR>sdArray[i++] = new SD("ａ", "a");<BR>sdArray[i++] = new SD("ｂ", "b");<BR>sdArray[i++] = new SD("ｃ", "i");<BR>sdArray[i++] = new SD("ｄ", "d");<BR>sdArray[i++] = new SD("ｅ", "e");<BR>sdArray[i++] = new SD("ｆ", "f");<BR>sdArray[i++] = new SD("ｇ", "g");<BR>sdArray[i++] = new SD("ｈ", "h");<BR>sdArray[i++] = new SD("ｉ", "i");<BR>sdArray[i++] = new SD("ｊ", "j");<BR>sdArray[i++] = new SD("ｋ", "k");<BR>sdArray[i++] = new SD("ｌ", "l");<BR>sdArray[i++] = new SD("ｍ", "m");<BR>sdArray[i++] = new SD("ｎ", "n");<BR>sdArray[i++] = new SD("ｏ", "o");<BR>sdArray[i++] = new SD("ｐ", "p");<BR>sdArray[i++] = new SD("ｑ", "q");<BR>sdArray[i++] = new SD("ｒ", "r");<BR>sdArray[i++] = new SD("ｓ", "s");<BR>sdArray[i++] = new SD("ｔ", "t");<BR>sdArray[i++] = new SD("ｕ", "u");<BR>sdArray[i++] = new SD("ｖ", "v");<BR>sdArray[i++] = new SD("ｗ", "w");<BR>sdArray[i++] = new SD("ｘ", "x");<BR>sdArray[i++] = new SD("ｙ", "y");<BR>sdArray[i++] = new SD("ｚ", "z");<BR>sdArray[i++] = new SD("Ａ", "A");<BR>sdArray[i++] = new SD("Ｂ", "B");<BR>sdArray[i++] = new SD("Ｃ", "C");<BR>sdArray[i++] = new SD("Ｄ", "D");<BR>sdArray[i++] = new SD("Ｅ", "E");<BR>sdArray[i++] = new SD("Ｆ", "F");<BR>sdArray[i++] = new SD("Ｇ", "G");<BR>sdArray[i++] = new SD("Ｈ", "H");<BR>sdArray[i++] = new SD("Ｉ", "I");<BR>sdArray[i++] = new SD("Ｊ", "J");<BR>sdArray[i++] = new SD("Ｋ", "K");<BR>sdArray[i++] = new SD("Ｌ", "L");<BR>sdArray[i++] = new SD("Ｍ", "M");<BR>sdArray[i++] = new SD("Ｎ", "N");<BR>sdArray[i++] = new SD("Ｏ", "O");<BR>sdArray[i++] = new SD("Ｐ", "P");<BR>sdArray[i++] = new SD("Ｑ", "Q");<BR>sdArray[i++] = new SD("Ｒ", "R");<BR>sdArray[i++] = new SD("Ｓ", "S");<BR>sdArray[i++] = new SD("Ｔ", "T");<BR>sdArray[i++] = new SD("Ｕ", "U");<BR>sdArray[i++] = new SD("Ｖ", "V");<BR>sdArray[i++] = new SD("Ｗ", "W");<BR>sdArray[i++] = new SD("Ｘ", "X");<BR>sdArray[i++] = new SD("Ｙ", "Y");<BR>sdArray[i++] = new SD("Ｚ", "Z");<BR>sdArray[i++] = new SD("．", ".");<BR>sdArray[i++] = new SD("　", " ");<BR>sdArray[i++] = new SD("（", "(");<BR>sdArray[i++] = new SD("）", ")");<BR>sdArray[i++] = new SD("｛", "{");<BR>sdArray[i++] = new SD("｝", "}");<BR>sdArray[i++] = new SD("［", "[");<BR>sdArray[i++] = new SD("］", "]");<BR>sdArray[i++] = new SD("＜", "&lt;");<BR>sdArray[i++] = new SD("＞", "&gt;");<BR>sdArray[i++] = new SD("「", "“");<BR>sdArray[i++] = new SD("」", "”");<BR>sdArray[i++] = new SD("｀", "`");<BR>sdArray[i++] = new SD("～", "~");<BR>sdArray[i++] = new SD("！", "!");<BR>sdArray[i++] = new SD("＠", "@");<BR>sdArray[i++] = new SD("＃", "#");<BR>sdArray[i++] = new SD("％", "%");<BR>sdArray[i++] = new SD("＾", "^");<BR>sdArray[i++] = new SD("※", "&amp;");<BR>sdArray[i++] = new SD("＊", "*");<BR>sdArray[i++] = new SD("－", "-");<BR>sdArray[i++] = new SD("＿", "_");<BR>sdArray[i++] = new SD("＋", "+");<BR>sdArray[i++] = new SD("＝", "=");<BR>sdArray[i++] = new SD("｜", "|");<BR>sdArray[i++] = new SD("＼", "\\");<BR>sdArray[i++] = new SD("■", "-");<BR>sdArray[i++] = new SD("＇", "'");<BR>sdArray[i++] = new SD("＂", "\"");<BR>sdArray[i++] = new SD("／", "/");<BR>sdArray[i++] = new SD("；", ";");<BR>sdArray[i++] = new SD("：", ":");<BR>sdArray[i++] = new SD("，", ",");<BR>sdArray[i++] = new SD("。", ".");<BR>sdArray[i++] = new SD("？", "?");</P>
<P>sdCount = i;</P>
<P><BR>function sbc2dbc(src)<BR>{<BR>&nbsp;var k;<BR>&nbsp;var i;<BR>&nbsp;var len = src.length;<BR>&nbsp;var result = "";<BR>&nbsp;<BR>&nbsp;for (k=0; k&lt;len; k++)<BR>&nbsp;{<BR>&nbsp;&nbsp;ch = src.charAt(k);<BR>&nbsp;&nbsp;for (i=0; i&lt;sdCount; i++)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;if (sdArray[i].sbc == ch)<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;result += sdArray[i].dbc;<BR>&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;if (i == sdCount)&nbsp;//没有查到对应的全角字符<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;result += ch;<BR>&nbsp;&nbsp;}<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;return result;<BR>}<BR>代码的原理就不详细介绍了， src参数就是需要转换的字符串，直接调用sbc2dbc函数就可以把src里面所有的全角字符转换成半角字符。<BR>为什么没有半角字符转换成全角字符的函数？呵呵，因为没有想到那里会用到，如果你在开发中真有此需求，相信根据上面的源码，你也可以写出对应的转换函数。祝你顺利。</P>
<P>&nbsp;</P><img src ="http://www.blogjava.net/gf7/aggbug/24956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-12-21 15:40 <a href="http://www.blogjava.net/gf7/archive/2005/12/21/24956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在JSP中执行dos命令 </title><link>http://www.blogjava.net/gf7/archive/2005/10/18/15856.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Tue, 18 Oct 2005 15:33:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/10/18/15856.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/15856.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/10/18/15856.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/15856.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/15856.html</trackback:ping><description><![CDATA[<H4>
<P><FONT face=Verdana color=#000000 size=2>&nbsp;&nbsp;&nbsp;&nbsp; 在JSP中我们经常要调用服务器端的一些dos命令，已达到一些特殊的效果，但同时调用服务器端的dos命令也存在着一些安全隐患，因此需要慎重使用。</FONT></P>
<P><FONT face=Verdana color=#000000 size=2>&nbsp;&nbsp;&nbsp;&nbsp; 以下以一个例子来说明用jsp执行dos的过程，比如在服务器端每天都会自动生成一个目录（目录名称为当天的日期），再此目录下会生成一些当天的新闻文件，管理员会把这些文件几个月作一次备份，备份完后在把这些文件删除。</FONT></P>
<P><FONT face=Verdana color=#000000 size=2>&nbsp;&nbsp;&nbsp;&nbsp; 如果在服务器上，我们可以在dos下直接执行c:\j2sdk\jar cf d:\bak\200502.jar d:\news\20050101&nbsp;命令， 然后再把20050101目录删除即可。</FONT></P>
<P><FONT face=Verdana color=#000000 size=2>&nbsp;&nbsp;&nbsp;&nbsp; 在JSP中我们应当这么来写</FONT></P>
<P><FONT face=Verdana color=#000000 size=2>&lt;%<BR>//执行dos命令<BR>String commandstr = "c:/j2sdk/jar cf d:/bak/200502.jar d:/news/20050101";<BR>Process p ;<BR>try {<BR>&nbsp;&nbsp;&nbsp;p = Runtime.getRuntime().exec(commandstr);<BR>//等待刚刚执行的命令的结束&nbsp;&nbsp; <BR>while (true){&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;if(p.waitFor() == 0)&nbsp;&nbsp;&nbsp;break;<BR>&nbsp; &nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;<BR>} catch (Exception e) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;out.println(e.toString());<BR>&nbsp;&nbsp;&nbsp;}</FONT></P>
<P><FONT face=Verdana color=#000000 size=2>//删除已经打包的文件及其目录<BR>File f = new File("d:/news/20020101");<BR>String[] allFiles = f.list();<BR>for (int i = 0; i &lt; allFiles.length; i++) {<BR>&nbsp;&nbsp; File delF = new File("d:/news/20050101/"+allFiles[i]);<BR>&nbsp;&nbsp; delF.delete();<BR>}<BR>File delD = new File("d:/news/20050101");<BR>delD.delete();<BR>%&gt;</FONT></P>
<P><FONT face=Verdana color=#000000 size=2>&nbsp;&nbsp;&nbsp;&nbsp; 在jsp中以下代码必须执行，如果没有该代码，则由于删除文件的速度快于打包的速度，因此当压缩包还没有打包完成，一些文件已经被删除，加入下面的代码，会在此一直做循环，一直p.waitFor()（这个方法的说明是：等待子进程的结束，如果已经结束，一般返回0）返回0为止才会接着执行后面的代码<BR>while (true){&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;if(p.waitFor() == 0)&nbsp;&nbsp;&nbsp;break;<BR>&nbsp; &nbsp;}&nbsp;</FONT></P></H4><img src ="http://www.blogjava.net/gf7/aggbug/15856.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-10-18 23:33 <a href="http://www.blogjava.net/gf7/archive/2005/10/18/15856.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javamail总结经验（二）</title><link>http://www.blogjava.net/gf7/archive/2005/10/15/15596.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sat, 15 Oct 2005 12:24:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/10/15/15596.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/15596.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/10/15/15596.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/15596.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/15596.html</trackback:ping><description><![CDATA[先还是看一段程序后，再一一讲解其内容吧<BR>public&nbsp;class&nbsp;ReadMail<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;//初始化主机<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;host=”smtp.163.com”;<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;nuserName=”邮箱的用户名”;<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;&nbsp;pwd=”用户密码”;<BR>&nbsp;&nbsp;&nbsp;&nbsp;Session&nbsp;session;<BR>&nbsp;&nbsp;&nbsp;&nbsp;Public&nbsp;void&nbsp;readMail()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;Properties&nbsp;props=new&nbsp;Properties();<BR>&nbsp;&nbsp;&nbsp;&nbsp;props.put(“mail.transport.protocol”,”smtp”);<BR>&nbsp;&nbsp;&nbsp;&nbsp;props.put(“mail.smtp.host”,””+host+””);<BR>&nbsp;&nbsp;&nbsp;&nbsp;props.put(“mail.smtp.port”,”25”);<BR>&nbsp;&nbsp;&nbsp;&nbsp;session=Session.getDefaultInstance(props);<BR>&nbsp;&nbsp;&nbsp;&nbsp;//获取Store对象，使用pop3协议也可以使用IMAP<BR>&nbsp;&nbsp;&nbsp;&nbsp;Stroe&nbsp;store=session.getStore(“pop3”);<BR>&nbsp;&nbsp;&nbsp;&nbsp;//连接到邮件服务器<BR>store.connect(host,username,password);<BR>//获取该用Floder对，并以只读方式打开<BR>Folder&nbsp;folder=store.getFolder(“INBOX”);<BR>Folder.open(Folder.READ_ONLY);<BR>//检索所有邮件，按需填充<BR>Message&nbsp;msg[]=folder.getMessage();<BR>//遍历每一个邮件<BR>BufferedReader&nbsp;reader=new&nbsp;BufferedReader(new&nbsp;InputStreamReader(System.in));<BR>For(int&nbsp;i=0,n=msg.length;I&lt;n;I++)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//打印每个邮件的发件人和主题<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(I+”:”+msg[i].getFrom()[0]+”\t”+msg[i].getSubject());<BR>//显示消息内容<BR>msg[i].writeTo(System.out);<BR>}<BR>floder.close(false);<BR>store.close();<BR>}<BR>}<BR>现在对程序一一讲解吧！<BR>Store是一个抽象类，它模拟了消息存储器（或称为消息数据库）及其内部目录（Folder）访问协议，以存储和读取消息，由其子类提供具体实现。客户程序可以通过获取一个Store对象来访问消息存储器，以绝大多数的存储器要求用户在访问前提供认证信息，connect方法执行了该认证过程。与Transport类似，也可以指定Store使用协议。邮件是读取邮件所以用pop3协议来读取。<BR>具体如：Store&nbsp;store=new&nbsp;Store(“pop3”);<BR>&nbsp;&nbsp;&nbsp;&nbsp;然后认证:store.connect(host,username,pwd)<BR>javax.mail.Folder类，它是一个抽象类，用于分级组织邮件，其子类提供针对具本协议的实现。存储在目录内的消息被顺序计数（从1开始到消息总数），该顺序被称为邮箱顺序，邮件顺序的改变消息的序列号，这种情况仅发生在客户程序调用Expunge方法擦除目录内设置了Flags.Flag.DELETED标志位的消息时。执行擦除操作后，目录内消息将重新编号。客户程序可以通过消息序列号和直接通过相应的Message对象引用目录中的对象，由于消息序列号会在会话中很可能会改变，因此应尽可能保存Message对象来引用对象。<BR>连接stroe之后，接一来就可以获取一个文件夹（Folder）。该文件夹必须先使用open()方法打开，然后才能读取里面的消息。<BR>Folder&nbsp;folder=store.getDefaultFolder();<BR>//或Folder&nbsp;folder=store.getFolder(“inbox”);<BR>folder.open(Folder.READ_WRITE);<BR>Message&nbsp;message[]=folder.getMessages();<BR>Open()方法指定了要打开的文件及打开方试（如Folder.READ_WRITE）。Inbox是pop3惟一可以使用的文件夹。如果使用IMAP，还可以使用其它的文件夹。读取了Message之后，就可以用getContent()获得内容，或者用writeTo()将内容写入输出流。GetContent()方法只能得到消息内容，而writeTo()输出却包含消息头.<BR>如下两种方试<BR>System.out.println(((MimeMessage)msg).getContent());<BR>Msg.writeTo(System.out);<BR>读完邮件后要关闭与Folder和Store的连接<BR>folder.close(false);<BR>stroe.close();<BR><BR><img src ="http://www.blogjava.net/gf7/aggbug/15596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-10-15 20:24 <a href="http://www.blogjava.net/gf7/archive/2005/10/15/15596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javamail总结经验（一）</title><link>http://www.blogjava.net/gf7/archive/2005/10/15/15569.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sat, 15 Oct 2005 05:57:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/10/15/15569.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/15569.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/10/15/15569.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/15569.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/15569.html</trackback:ping><description><![CDATA[环境配置。为了运行javamail。我们需要在classpath里导入两个包：mail.jar和activation.jar，这是在纯DOS里或者其它简单工具使用时才需要这个classpath。如果使用像eclipes这样的工具就不需要配置。因为myeclipes已经帮你做好了。<BR>为了要发送邮件和接收邮件，我们必须要遵守smtp和pop3协议，不过还有其它协议也可执行(如IMAP)。如果把本机当作服务器来发送邮件请在<A href="http://jakrata.apache.org/">http://jakrata.apache.org</A>网站里下载james邮件服务器，然后解压在本机上。运行james/bin里的run.bat就可以启动了服务器。<BR>运行后在DOS里登录邮件服务器。具体命令如下：<BR>系统管理员：root<BR>密码：root<BR>telnet&nbsp;localhost&nbsp;4555<BR>然后就可以增加邮箱用户名了。命令如下：<BR>adduser&nbsp;用户名&nbsp;密码<BR>例：adduser&nbsp;test&nbsp;test<BR>这样就建立了这样一个邮箱test@localhost&nbsp;密码为：test&nbsp;<BR>如果想要更多功能用help命令<BR>注意：如果在本机装了邮件服务器的话，只能在本机局域网里申请邮箱，发送和接收。不能发送到外部的邮箱里去。如果用外部的邮件服务器像比如163和126的服务器等就可以随心所欲的发邮件了。哈哈是不是很爽呢？<BR>先看看用james邮件服务器在本机上发邮件吧。先简单看一个例子。<BR>import&nbsp;javax.mail.*;<BR>import&nbsp;java.util.*;<BR>import&nbsp;javax.mail.internet.*;<BR>public&nbsp;class&nbsp;MyFirstMail&nbsp;<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;Session&nbsp;mailSession;<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;MyFirstMail()throws&nbsp;Exception<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init();<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;MyFirstMail().sendMail();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print("邮件已发");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch(Exception&nbsp;e)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>//初始化服务器环境<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;init()throws&nbsp;Exception<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Properties&nbsp;props=new&nbsp;Properties();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.put("mail.transport.protocol","smtp");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.put("mail.smtp.host","localhost");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.put("mail.smtp.port","25");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mailSession=Session.getDefaultInstance(props,&nbsp;null);;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;sendMail()throws&nbsp;Exception<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>//从哪里发的邮件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>msg.setFrom(new&nbsp;InternetAddress("test@localhost"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;//发送到目标邮件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.setRecipients(Message.RecipientType.TO,InternetAddress.parse("wang@localhost"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;//抄送的接收者&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.setRecipients(Message.RecipientType.CC,InternetAddress.parse("wang@localhost"));<BR>//暗送的接收者<BR>msg.setRecipients(Message.RecipientType.BCC,InternetAddress.parse("wang@localhost"));<BR>//设置发送时间<BR>msg.setSentDate(new&nbsp;java.util.Date());<BR>//设置邮件标题<BR>msg.setSubject("a&nbsp;test&nbsp;mail");<BR>//设置邮件内容<BR>msg.setText("this&nbsp;is&nbsp;the&nbsp;email&nbsp;content");<BR>//指定协议发送消息的对像<BR>Transport&nbsp;transport=mailSession.getTransport("smtp");<BR>//发送消息<BR>Transport.send(msg);<BR>}<BR>catch(Exception&nbsp;e)<BR>{<BR>throw&nbsp;e;<BR>}<BR>}<BR>发送完后想要看邮件就要到james-&gt;apps-&gt;james-&gt;var-&gt;mail-&gt;inboxes就可以看见每个邮箱里的邮件数了。由于发过来的是字节流，邮件包括一个邮件属性和消息，所以每一封邮件是由二个文件组成的。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>也许没有学过的javamail的人看上去会一头雾水。不要紧，现在一一详解。先说初始化的内容的吧！<BR>1、&nbsp;&nbsp;&nbsp;&nbsp;mail.transport.protocol=smtp&nbsp;这里主要说明的是邮件传输协议。<BR>2、&nbsp;&nbsp;&nbsp;&nbsp;mail.smtp.host=localhost&nbsp;发送邮件的主机如果用外部邮件服务器的话，可以这样写<BR>mail.smtp.host=smtp.163.com这样就以163.为服务器了。<BR>3、mail.smtp.prot=25&nbsp;&nbsp;&nbsp;&nbsp;smtp端口可以省略，缺省为25<BR><BR>javax.mail.session<BR>session类定义了与远程邮件系统通信的邮件会话。需要注意的是这个session不同servlet中的会话。Servlet中的会话需要共享一些信息，而mail里的session里没有这个功能，它只是用于存储与服务器建立连接会话相关信息和逻辑。Session类是javamail&nbsp;api最高层入口类，所有其它类都必须经由session对象生效。Session对象它管理配置选项和用于与邮件系统交互的用认证信息息。它通过使用java.util.properties对象配置邮件会话的属性如邮件服务器，用户名，密码，及整个应用程序中共享的其它信息。<BR>Session并不处现任何授权操作，它只是存储这些授权信息。Session类的构造器是私有的，它不能被继承，也不能用new语名创建实例。但它提供了两个静态方法getInstance&nbsp;和getDefaultInstance来获取session实例，在创建session实例时需要提供一些属性。具体实现如下：<BR>&nbsp;&nbsp;&nbsp;&nbsp;Properties&nbsp;props=new&nbsp;Properties()<BR>&nbsp;&nbsp;&nbsp;&nbsp;Props.put(“mail.transport.protocol”,”smtp”)<BR>&nbsp;&nbsp;&nbsp;&nbsp;Props.put(“mail.smtp.host”,”localhost”);<BR>&nbsp;&nbsp;Props.put(“mail.smtp.prot”,”25”)<BR>//不加以认证也可以这样写<BR>//Session&nbsp;session=Session.getDefaultInstance(props,null)<BR>//如果认证传入null那么它和不使用认证调用方式一样&nbsp;<BR>&nbsp;Session&nbsp;session=Session.getDefaultInstance(props)<BR>Javax.mail.&nbsp;Message<BR>经过session配置后就可以进行发送消息任务了。这由Message类来完成。Message实现了Part接口，它表示一个邮件消息，包含一系列的属性和一个消息内容。消息属性包括了消息址址消息，定义了消息内容的结构（包括内容类型），消息内容使用DataHandler对象包装实际数据。当邮件消息位于目录(folder)中时，系统还使用了一个标志位集合来描述它的状态。<BR>Message是抽象类，实际使用时必须用一个子类代替以表示具体的邮件格式。比如说javamail&nbsp;api提供了MimeMessage类，该类扩展了Message，实现了RFC822和MIME标准。有两个构造方法：<BR>//一般使用第一种<BR>&nbsp;&nbsp;&nbsp;&nbsp;Message&nbsp;msg=new&nbsp;MimeMessage(Session&nbsp;session)<BR>Message&nbsp;msg=new&nbsp;MimeMessage(MimeMessage&nbsp;msg)<BR>获得消息后，就可以设置消息各个部份了。在设置之前因为要涉及地址。所以讲一下地址类<BR>javax.mail.Address<BR>Address类表示电子邮件类，它是一个抽象类，它的子类InternetAddress提供具体实现且通常可串行化。若创建的地址只包含电子邮件，只要传递电子邮件到构造器即可如<BR>InternetAddress&nbsp;addr=new&nbsp;InternetAddress();<BR>addr.setAddress(“wang@126.com”)<BR>或者是：InterntAddress&nbsp;addr=new&nbsp;InternetAddress(“wang@126.com”)<BR>另外，InternetAddress类还提供了地址解析方法如<BR>Address[]&nbsp;addrs=InternetAddress.parse(“wang@163.com,f@126.com,zuo@126.com”);<BR>地址之后就可以发送消息了。<BR>//设置发送者<BR>Msg.setFrom(new&nbsp;InternetAddress(“test@126.com”));<BR>//设置接收者,并还具有解析功能<BR>Msg.setRecipients(Message.RecipientType.To,InternetAddress.parse(“zuolin0806@163.com”));<BR>//抄送的接收者<BR>Msg.setRecipients(Message.RecipientType.CC,InternetAddress.parse(“zuolin0806@163.com”));<BR>//暗送的接收者<BR>Msg.setRecipients(Message.RecipientType.CC,InternetAddress.parse(“zuolin0806@163.com”));<BR>//设置消息主题<BR>&nbsp;msg.setSubject(“我的爱”)<BR>//设置内容的基本机制，其参数Mime类型<BR>&nbsp;msg.setContent(“这是我的内容”,”text/html;charset=gb2312”)<BR>其中的text/html表示消息内容采用的是HTML格式。如果消息格式是(text/plain)，而且使用的是MimeMessage,那么setText()方法设置邮件内容的参数（Mime类型默认为text/plain）<BR>//设置邮件内容<BR>msg.setText();<BR>//设置发送时间<BR>msg.setSentDate(new&nbsp;java.util.Date());<BR>最后一步是就是发送了<BR>javax.mail.Transport<BR>该类也是抽象类，它可通过静态方法和实便方法发送消息。Transport断承service类。所以它提供了通用方法，如命名传输，连接服务器和监听传输事件等。<BR>//默认<BR>Transport.send(msg);<BR><BR>最后看一下使用外部邮件服务器的使用方法。先看程序再讲解，注意在使用外部邮件服务器时一定要有一个类来认证。到时在讲。<BR>public&nbsp;class&nbsp;MySecondMail<BR>{<BR>protected&nbsp;Session&nbsp;session&nbsp;=&nbsp;null;<BR>//邮件用户名<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;mailUser&nbsp;=&nbsp;"zuolin0806";<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;host&nbsp;=&nbsp;"smtp.163.com";<BR>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;pwd&nbsp;=&nbsp;"用户名的密码";<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;MySecondMail()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init();<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;init()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Properties&nbsp;props&nbsp;=&nbsp;new&nbsp;Properties();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.put("mail.transpost.protocol",&nbsp;"smtp");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.put("mail.smtp.host",&nbsp;"smtp.163.com");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//必须要有一个类来认证<BR>props.put("mail.smtp.auth",&nbsp;"true");<BR>props.put("mail.smpt.port",&nbsp;"25")<BR>Email_Autherticatorbean&nbsp;auth&nbsp;=&nbsp;&nbsp;new&nbsp;Email_Autherticatorbean(mailUser,pwd);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//session认证<BR>session&nbsp;=&nbsp;Session.getInstance(props,auth);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//这个是跟踪后台消息。打印在控制台<BR>session.setDebug(true);<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;MySecondMail().sendMails();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("send&nbsp;mail&nbsp;success!");<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;sendMails()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Message&nbsp;msg&nbsp;=&nbsp;new&nbsp;MimeMessage(session);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.setFrom(new&nbsp;InternetAddress("zuolin0806@163.com"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.setRecipients(Message.RecipientType.TO,&nbsp;InternetAddress.parse("javaboy@126.com"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.setRecipients(Message.RecipientType.BCC,&nbsp;InternetAddress.parse("javaboy@126.com"));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.setSentDate(new&nbsp;Date());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.setSubject("this&nbsp;is&nbsp;my&nbsp;Threee&nbsp;mail");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.setContent("this&nbsp;is&nbsp;my&nbsp;mail","text/html");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.setText("我成功了。哈哈");<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transport&nbsp;transport&nbsp;=&nbsp;session.getTransport("smtp");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;与发送者的邮箱相连<BR>transport.connect(host,mailUser,pwd);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transport.send(msg);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(SendFailedException&nbsp;e)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch&nbsp;(Exception&nbsp;ee)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ee.printStackTrace();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR><BR>认证类必须继承Authenticator&nbsp;&nbsp;例子如下:<BR>import&nbsp;javax.mail.*;<BR>public&nbsp;class&nbsp;Email_Autherticatorbean&nbsp;extends&nbsp;Authenticator<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;m_username&nbsp;=&nbsp;null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;m_userpass&nbsp;=&nbsp;null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setUsername(String&nbsp;username)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_username&nbsp;=&nbsp;username;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setUserpass(String&nbsp;userpass)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_userpass&nbsp;=&nbsp;userpass;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Email_Autherticatorbean(String&nbsp;username,&nbsp;String&nbsp;userpass)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setUsername(username);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setUserpass(userpass);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;PasswordAuthentication&nbsp;getPasswordAuthentication()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;PasswordAuthentication(m_username,m_userpass);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR>经过成功发送邮件后是不是有点成就感呢！但还有很多疑问比如怎么读邮件呢？看了下面章节你就会知道了<BR><img src ="http://www.blogjava.net/gf7/aggbug/15569.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-10-15 13:57 <a href="http://www.blogjava.net/gf7/archive/2005/10/15/15569.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>小组开发环境搭建:dhcp+apache+ftp+cvs+samba(经典)</title><link>http://www.blogjava.net/gf7/archive/2005/10/09/15094.html</link><dc:creator>风</dc:creator><author>风</author><pubDate>Sun, 09 Oct 2005 15:07:00 GMT</pubDate><guid>http://www.blogjava.net/gf7/archive/2005/10/09/15094.html</guid><wfw:comment>http://www.blogjava.net/gf7/comments/15094.html</wfw:comment><comments>http://www.blogjava.net/gf7/archive/2005/10/09/15094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gf7/comments/commentRss/15094.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gf7/services/trackbacks/15094.html</trackback:ping><description><![CDATA[<STRONG><FONT face=Verdana color=#0000ff size=2>小组开发环境搭建:dhcp+apache+ftp+cvs+samba<BR></FONT></STRONG><FONT size=1><FONT face=Verdana><FONT class=smallfont color=#ff9900>2004-04-23 15:18 pm</FONT><BR></FONT></FONT><FONT class=normalfont><FONT face=Verdana size=2>作者：车东 chedong@bigfoot.com<BR>来自：Linux知识宝库<BR>现载：</FONT><A href="http://www.douzhe.com/linuxtips/1196.html"><FONT face=Verdana color=#666666 size=2>http://www.douzhe.com/linuxtips/1196.html</FONT></A><BR><FONT face=Verdana size=2>地址：无名<BR><BR>　　本文主要介绍一些小组开发环境搭建中经常会遇到一些服务器服务设置，这些服务很多都是鉴于大部分的开发客户端仍然是Windows设置的，每个服务都提供了简单的基本配置示范。(2003-01-10 09:22:08) By 风过留枫, 出处：作者： 车东 chedong@bigfoot.com<BR><BR>　　作者： 车东 chedong@bigfoot.com<BR><BR>　　最后更新：2003-01-08 09:51:53<BR><BR>　　版权声明：可以任意转载，转载时请务必标明原始出处和作者信息<BR><BR>　　关键词：linux develop environment cvs version contral gnats bug tracking samba dhcpd wget<BR><BR>　　内容摘要：本文主要介绍一些小组开发环境搭建中经常会遇到一些服务器服务设置，这些服务很多都是鉴于大部分的开发客户端仍然是Windows设置的，每个服务都提供了简单的基本配置示范。包括：<BR><BR>　　IP管理（DHCP）：服务器IP地址的管理和解析（结合SAMBA的WINS服务），开发客户端的IP管理； WEB服务（APACHE）：文档共享，CVS的WEB界面浏览，论坛工具等；<BR><BR>　　FTP服务（FTP）：用于文件下载/共享；<BR><BR>　　版本控制（CVS）：程序源代码和文档的版本控制；<BR><BR>　　文件共享（SAMBA）：基于NETBIOS的文件共享，方便WINDOWS客户端的访问（比如一些工具的安装等）； 数据库服务器（MYSQL）：一些应用的后台数据库服务； 备份机制（wget + rsync）：备份<BR><BR>　　很多设置是缺省按照在bash环境中，在tcsh环境中，有一些设置不太一直。<BR><BR>　　服务器规划如下：<BR><BR><BR>主服务器 (Main) 备份服务器(Backup)<BR>__________________ _______________<BR>|APACHE WEB SERVER | | File Backup | <BR>|SAMBA SHARE | | |<BR>|DHCP SERVER | | DHCP Backup |<BR>|CVS SERVER | | MySQL server |<BR>|GNATS SERVER | | |<BR>|PHORUM SERVER | | |<BR>|Database backup | | |<BR>------------------ ---------------　<BR><BR>　　硬件准备：至少要2台服务器<BR><BR>　　从理论上说，任何系统的崩溃只是时间问题，而且谁也不能保证开发者不犯错误<BR><BR>　　解决的办法只有：备份，备份，备份……<BR><BR>　　操作系统准备<BR><BR>　　FreeBSD或GNU/Liunx，系统安装时，本文的配置主要以在RedHat 8上运行为例。注意：安装时要将“开发工具”大类选上，后面的很多工具都需要使用GCC进行编译，有的应用脚本运行用到了PERL。2台主服务器分别使用IP地址192.168.0.200和192.168.0.201。<BR><BR>　　2台机器上都安装的服务：SSH FTP DHCP服务<BR><BR>　　SSH: 基本的登陆服务，对于内部分开发来说一般用缺省的就可以了，但是建议将/etc/ssh/sshd_config中的：<BR><BR>　　PermitRootLogin yes改成PermitRootLogin no<BR><BR>　　FTP:如果是FREEBSD建议用PROFTPD代替：http://www.proftpd.org/<BR><BR>　　安装：<BR><BR><BR>　　tar zxf proftpd-version.tar.gz<BR>　　cd proftpd-version/<BR>　　 ./configure<BR>　　 make<BR>　　 make install<BR><BR>　　缺省配置/usr/local/etc/proftpd.conf<BR><BR><BR>　　ServerName "ProFTPD"<BR>　　ServerType standalone<BR>　　DefaultServer on<BR>　　AllowOverwrite on<BR>　　Port 21<BR>　　Umask 022<BR>　　#不反相解析登陆机器的域名<BR>　　UseReverseDNS off<BR>　　MaxInstances 30<BR>　　User nobody<BR>　　Group nogroup<BR><BR>　　DHCP服务：为了更方便的管理在同一个局域网中开发者的IP地址和服务器的IP地址，最好将服务器安排在一定范围内的静态IP内（比如192.168.0.200以上），将(192.168.0.10-200)范围内为开发机客户端提供动态IP。假设我们的主服务器(192.168.0.200)和辅助开发服务器(192.168.0.201)使用静态IP，同时为网段内提供192.168.0.10-200动态IP分配服务。DHCP服务在2台服务器上都安装，一个做主DHCP服务，用于给子网IP池提供70%的IP，另外一台做备份，拥有IP池的30%。在例子中：200负责10-100，201负责110-150。缺省dhcpd没有安装的话，从安装盘上找到DHCP软件包安装或者从http://www.isc.org下载源文件编译即可（安装位置和配置文件可能有所不同）。<BR><BR>　　缺省配置：主服务器上<BR><BR><BR>　　ddns-update-style none;<BR>　　default-lease-time 120000; <BR>　　max-lease-time 920000; <BR>　　option subnet-mask 255.255.255.0; <BR>　　option broadcast-address 192.168.0.255; <BR>　　option netbios-name-servers 192.168.0.200;<BR>　　option routers 192.168.0.1; <BR>　　option domain-name-servers 202.106.196.115,202.96.199.133; <BR>　　option domain-name "example.com"; <BR><BR>　　subnet 192.168.0.0 netmask 255.255.255.0{<BR>　　range 192.168.0.10 192.168.0.100; <BR>　　}<BR><BR>　　说明：<BR><BR>　　缺省每个IP租期2天: default-lease-time 120000;<BR><BR>　　最长租期: max-lease-time 920000;<BR><BR>　　缺省子网掩码：option subnet-mask 255.255.255.0;<BR><BR>　　缺省广播地址：option broadcast-address 192.168.0.255;<BR><BR>　　让192.168.0.200上的samba服务启用WINS服务：用于内部域名解析:option netbios-name-servers 192.168.0.200;<BR><BR>　　缺省网关 option routers 192.168.0.1;<BR><BR>　　缺省域名服务器 option domain-name-servers 202.106.196.115,202.96.199.133;<BR><BR>　　缺省域名 option domain-name "example.com";<BR><BR><BR>　　#一个缺省的子网设置：<BR>　　subnet 192.168.0.0 netmask 255.255.255.0{<BR>#为子网动态分配0.10－100的IP<BR>　　range 192.168.0.10 192.168.0.100; <BR>　　} <BR><BR>　　辅DHCP服务器上唯一不同的地方是：为子网动态分配0.110－150的IP，主DHCP和附DHCP服务器的IP池不能相互重叠<BR><BR><BR>　　subnet 192.168.0.0 netmask 255.255.255.0{ <BR>　　range 192.168.0.110 192.168.0.150; <BR>　　}<BR><BR>　　主服务器上的应用安装:<BR><BR>　　SAMBA服务：用于文件的共享和内部WINS解析<BR><BR>　　这里只做一个只读共享的简单配置，<BR><BR><BR>　　[global]<BR>　　 #别人会通过"网上邻居"看到WORKGROUP组里的<BR>　　　　linux机器，注释是：My Samba Server<BR>　　 workgroup = WORKGROUP<BR>　　netbios name = linux<BR>　　 server string = My Samba Server<BR><BR>　　 #日志设置<BR>　　 log file = /var/log/samba/%m.log<BR>　　 max log size = 50<BR><BR>　　 #安全设置<BR>　　 security = share<BR><BR>　　 #用SAMBA的WINS服务支持，并且用/etc/hosts做内部域名解析<BR>　　 wins support = yes<BR>　　 name resolve order = hosts lmhosts wins bcast<BR>　　 dns proxy = yes<BR><BR>　[public]<BR>　　 #一个共享设置<BR>　　 comment = Public Stuff <BR>　　 path = /home/share<BR>　　 public = yes<BR>　　 guest ok = yes<BR>　　 read only = yes<BR>　　 writable = no<BR>　　 printable = no<BR><BR>　　在这里为了让大家能够在内部使用dev.example.com访问主服务器（192.168.0.200），我用DHCP设置主服务器（192.168.0.200）同时也是是内部的WINS服务器，而在200的SAMBA服务中，启用了WINS支持，并设置WINS用可以利用DNS做NETBIOS名称解析。这样如果DNS读取的是/etc/hosts文件中的设置的话，hosts文件就可以当作WINS域名配置文件了，在/etc/hosts里设置了：<BR><BR><BR>　　192.168.0.200 dev.example.com bbs.example.com dev bbs<BR>　　192.168.0.201 bak.example.com backup<BR><BR>　　后，通过DHCP获得IP的内网客户端就可以直接通过: dev.example.com访问开发服务器了。<BR><BR>　　所有的机器名前缀我都使用了缩写：dev, bbs bak之类的，原因是samba的NMBD实际上是NETBIOS名称的解析，名称长度是16个字符（实际是15个）有限制的。因此，虽然192.168.0.202 username.example.com虽然是一个合法的DNS名称解析，但由于username.example.com长度超过了16个字符，所以通过SAMBA的WINS服务解析仍然无法找到。dev.chedong.com相当于dev.chedong.com这样的一台机器。当初用SAMBA的WINS解析在客户端总是ping不通testing.chedong.com这个问题困扰了我好一阵。<BR><BR>　　WEB服务：APACHE<BR><BR>　　主要用作文件的WEB共享和一些应用的前端浏览（CVSWEB GNATSWEB PHPMYADMIN等），Apache，这里仍然使用了1.3，因为很多应用，比如PHP在2.0上运行还不是完整。<BR><BR>　　安装： http://httpd.apache.org下载最新版本：<BR><BR>　　编译选项：这样可以让所有的模块都通过配置文件动态加载，方便后面其他应用模块的添加删除： ./configure --prefix=/home/apache --enable-shared=max --enable-module=most 更多安装说明可以参考: APACHE安装笔记<BR><BR>　　文档共享技巧：<BR><BR>　　1 对于文档的共享来说，autoindex模块非常有用，让APACHE自动索引目录缺省是按文件/目录名排序的，而且文件名40个字符以上部分是被截断的，为了能显示完整的文件名，并且像资源管理器那样将目录排在前面，文件排在后面：<BR><BR>　　在模块设置中：<BR><BR><BR>#增加NameWidth选项，并且文件名长度是*(自动适<BR>　　 #应当前目录下最长文件名)<BR>#增加FoldersFirst选项，让目录列在前面（类似于资源管理器）<BR>#增加了ScanHTMLTitles用HTML文件的TITLE做文件<BR>　　 #的描述，并设置描述长度是*（自适应最长）<BR>IndexOptions FancyIndexing +NameWidth=* <BR>　　　FoldersFirst ScanHTMLTitles +DescriptionWidth=*<BR><BR>　　2 如果是CGI开发，如何让用户在自己的目录下能够发布CGI程序，比如：http://192.168.0.200/~chedong/cgi-bin/my_cgi：在 模块设置中，添加正则表达式： ScriptAliasMatch ~([a-z]+)/cgi-bin/(.*) /home/$1/cgi-bin/$2<BR><BR>　　意思是匹配~user_name/cgi-bin/cgi_name自动映射到/home/user_name/cgi-bin/cgi-name脚本<BR><BR>　　版本控制：CVS<BR><BR>　　CVS缺省在服务器上几乎都安装好了，只要按照以下步骤初始化即可：<BR><BR>　　在/etc/profile里：<BR><BR>　　CVS库所在的主服务器设置：<BR><BR><BR>　　export CVSROOT=/home/cvsroot<BR><BR>　　在其他开发服务器里设置：<BR><BR><BR>　　export CVSROOT=:ext:$USER@192.168.0.200:/home/cvsroot<BR>　　export CVS_RSH=ssh<BR><BR>　　然后在主服务器上cvs init初始化：<BR><BR>　　关于CVSWEB的设置，重复以下CVS常用命令手册中CVSWEB的内容：<BR><BR>　　CVSWEB的下载：CVSWEB从最初的版本已经演化出很多功能界面更丰富的版本，这个是个人感觉安装设置比较方便的： http://www.spaghetti-code.de/software/linux/cvsweb/<BR><BR>　　下载解包：<BR><BR><BR>　　tar zxf cvsweb.tgz<BR><BR>　　把配置文件cvsweb.conf放到安全的地方（比如和apache的配置放在同一个目录下），<BR><BR>　　修改：cvsweb.cgi让CGI找到配置文件：<BR><BR><BR>　　$config = $ENV{'CVSWEB_CONFIG'}' <BR>　　　　''/path/to/apache/conf/cvsweb.conf';<BR><BR>　　转到/path/to/apache/conf下并修改cvsweb.conf：<BR><BR>　　修改CVSROOT路径设置：<BR><BR><BR>　　%CVSROOT = (<BR>'Development' =&gt; '/path/to/cvsroot', <BR>　　#&lt;==修改指向本地的CVSROOT<BR>　　); <BR><BR>　　缺省不显示已经删除的文档：<BR><BR>　　"hideattic" =&gt; "1",#&lt;==缺省不显示已经删除的文档<BR><BR>　　在配置文件cvsweb.conf中还可以定制页头的描述信息，你可以修改$long_intro成你需要的文字<BR><BR>　　首先可以CVS进库里的就是以上系统的安装文档。<BR><BR>　　更多的关于CVS的扩展应用可以参考CVS常用命令手册CVSTRAC部分。<BR><BR>　　多个服务之间的资源共享<BR><BR>　　一般可以通过链接解决，比如：<BR><BR>　　我希望匿名ftp共享的内容（比如在/var/ftp/pub目录下）都可以WEB发布，<BR><BR><BR>　　ln -s /var/ftp/pub /home/apache/htdocs/pub<BR><BR>　　我希望/usr/share/doc里的文档大家可以通过WEB浏览：<BR><BR><BR>　　ln -s /usr/share/doc /home/apache/htdocs/doc<BR><BR>　　我希望WEB发布的内容大家通过WINDOWS网络邻居也可以访问：假设/home/share是samba发布的只读共享路径<BR><BR><BR>　　ln -s /home/apache/htdocs /home/share<BR><BR>　　服务的自动启动：<BR><BR>　　系统已经安装的服务一般可以通过setup的服务配置是否自动启动，否则就在/etc/rc.local里加一些启动脚本即可。<BR><BR>　　比如：<BR><BR>　　备份和日志统计<BR><BR>　　可以将以下脚本写在主服务器的ROOT的CRON里：<BR><BR><BR>　　#time sync<BR>　　0 5 * * 1 (/usr/bin/rdate -s YOUR_DATE_TIME_SERVER)<BR><BR>　　#backup gnats <BR>　　 6 3 * * * (cd /home; tar cf<BR>　　　　 /home/backup/gnats.`date +\%w`.tar gnats)<BR><BR>　　#backup cvsroot<BR>　　5 3 * * * (cd /home; tar cf<BR>　　　 /home/backup/cvsroot.`date +\%w`.tar cvsroot)<BR><BR>　　#backup apache<BR>　　8 3 * * * (cd /home; tar cf <BR>　　　　/home/backup/apache.`date +\%w`.tar apache)<BR><BR>　　#gzip all backup<BR>　　50 3 * * * (gzip -f /home/backup/*.tar)<BR><BR>　　#webalizer demo<BR>　　3 5 * * * (/usr/local/bin/webalizer -c /home/apache/conf/webalizer.conf <BR>　　　　/home/apache/logs/`date -d yesterday +<BR>%w`/access_log)<BR><BR>　　#remove last week log<BR>　　3 4 * * * (find /home/apache/logs/ -name <BR>　　　　access_log -mtime +6 -exec rm -f {};)<BR><BR>　　这样，在/home/backup目录下会有按星期轮训的7个备份。然后通过在辅助服务器上设置CRON用wget的-m选项镜像主服务器上的/home/backup目录或者用rsync做同步就可以了。后面的2条是关于使用webalzier做服务器的日志统计，APACHE的日志通过cronolog进行了轮循。具体设置请参考：</FONT><BR></FONT><img src ="http://www.blogjava.net/gf7/aggbug/15094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gf7/" target="_blank">风</a> 2005-10-09 23:07 <a href="http://www.blogjava.net/gf7/archive/2005/10/09/15094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>