﻿<?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-weibogao-随笔分类-software development</title><link>http://www.blogjava.net/weibogao/category/10168.html</link><description>my second lifespace</description><language>zh-cn</language><lastBuildDate>Thu, 04 Mar 2010 18:38:07 GMT</lastBuildDate><pubDate>Thu, 04 Mar 2010 18:38:07 GMT</pubDate><ttl>60</ttl><item><title>常用的算法网站汇总</title><link>http://www.blogjava.net/weibogao/archive/2010/03/04/314514.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Thu, 04 Mar 2010 06:21:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2010/03/04/314514.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/314514.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2010/03/04/314514.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/314514.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/314514.html</trackback:ping><description><![CDATA[1.http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/AlgorithmGossip.htm（包括c，java等的不同实现，基础练习很有用）<br />
2.http://www.javaeye.com/forums/tag/algorithm（专业java网站上的论坛，很不错）<br />
3.待续。。。。。。<br />
<img src ="http://www.blogjava.net/weibogao/aggbug/314514.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2010-03-04 14:21 <a href="http://www.blogjava.net/weibogao/archive/2010/03/04/314514.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate批量处理的性能优化问题</title><link>http://www.blogjava.net/weibogao/archive/2006/12/27/90245.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Wed, 27 Dec 2006 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/12/27/90245.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/90245.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/12/27/90245.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/90245.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/90245.html</trackback:ping><description><![CDATA[
		<p>
				<br />Hibernate批量处理:</p>
		<p>Hibernate批量处理其实从性能上考虑，它是很不可取的，浪费了很大的内存。从它的机制上讲，Hibernate它是先把符合条件的数据查出来，放到内存当中，然后再进行操作。实际使用下来性能非常不理想,在笔者的实际<br />使用中采用下面的第三种优化方案的数据是:100000条数据插入数据库,主流台式机的配置,需要约30分钟,呵呵,晕倒.</p>
		<p>总结下来有三种来处理以解决性能问题：</p>
		<p>1：绕过Hibernate API ，直接通过 JDBC API 来做，这个方法性能上是比较好的。也是最快的.</p>
		<p>2：运用存储过程。</p>
		<p>3：还是用Hibernate API 来进行常规的批量处理，可以也有变，变就变在，我们可以在查找出一定的量的时候，及时的将这些数据做完操作就</p>
		<p>删掉，session.flush();session.evict(XX对象集); 这样也可以挽救一点性能损失。这个“一定的量”要就要根据实际情况做定量参考了。一般为30-60左右,但效果仍然不理想.</p>
		<p> </p>
		<p> </p>
		<p>1：绕过Hibernate API ，直接通过 JDBC API 来做，这个方法性能上是比较好的，也是最快的。(实例为 更新操作)</p>
		<p> </p>
		<p>Transaction tx=session.beginTransaction(); //注意用的是hibernate事务处理边界</p>
		<p>Connection conn=session.connection(); </p>
		<p>PreparedStatement stmt=conn.preparedStatement("update CUSTOMER as C set C.sarlary=c.sarlary+1 where c.sarlary&gt;1000");</p>
		<p>stmt.excuteUpdate();</p>
		<p>tx.commit(); //注意用的是hibernate事务处理边界 </p>
		<p>这小程序中，采用的是直接调用JDBC 的API 来访问数据库，效率很高。避免了Hibernate 先查询出来加载到内存，再进行操作引发的性能问题</p>
		<p>。 </p>
		<p>2：运用存储过程。但这种方式考虑到易植和程序部署的方便性,不建议使用.(实例为 更新操作)</p>
		<p>如果底层数据库（如Oracle）支持存储过程，也可以通过存储过程来执行批量更新。存储过程直接在数据库中运行，速度更加快。在Oracle数</p>
		<p>据库中可以定义一个名为batchUpdateCustomer()的存储过程，代码如下： </p>
		<p>
				<br />代码内容<br />create or replace procedure batchUpdateCustomer(p_age in number) as <br />begin <br />update CUSTOMERS set AGE=AGE+1 where AGE&gt;p_age; <br />end;  </p>
		<p>
				<br />以上存储过程有一个参数p_age，代表客户的年龄，应用程序可按照以下方式调用存储过程： </p>
		<p>代码内容<br />tx = session.beginTransaction(); <br />Connection con=session.connection(); <br />String procedure = "{call batchUpdateCustomer(?) }"; <br />CallableStatement cstmt = con.prepareCall(procedure); <br />cstmt.setInt(1,0); //把年龄参数设为0 <br />cstmt.executeUpdate(); <br />tx.commit();  </p>
		<p>
				<br />从上面程序看出，应用程序也必须绕过Hibernate API，直接通过JDBC API来调用存储过程。 </p>
		<p>3：还是用Hibernate API 来进行常规的批量处理，可以也有变，变就变在，我们可以在查找出一定的量的时候，及时的将这些数据做完操作就</p>
		<p>删掉，session.flush();session.evict(XX对象集); 这样也可以挽救一点性能损失。这个“一定的量”要就要根据实际情况做定量参考了。。</p>
		<p>(实例为 保存操作)</p>
		<p>业务逻辑为：我们要想数据库插入10 0000 条数据</p>
		<p>tx=session.beginTransaction();</p>
		<p>for(int i=0;i&lt;100000;i++)</p>
		<p>{</p>
		<p>Customer custom=new Customer();</p>
		<p>custom.setName("user"+i);</p>
		<p>session.save(custom);</p>
		<p>if(i%50==0) // 以每50个数据作为一个处理单元，也就是我上面说的“一定的量”，这个量是要酌情考虑的</p>
		<p>{</p>
		<p>session.flush(); </p>
		<p>session.clear();</p>
		<p>}</p>
		<p>}</p>
		<p>这样可以把系统维持在一个稳定的范围....<br /></p>
<img src ="http://www.blogjava.net/weibogao/aggbug/90245.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-12-27 11:16 <a href="http://www.blogjava.net/weibogao/archive/2006/12/27/90245.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模式对话框的详细使用说明</title><link>http://www.blogjava.net/weibogao/archive/2006/09/20/70715.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Wed, 20 Sep 2006 02:27:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/09/20/70715.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/70715.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/09/20/70715.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/70715.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/70715.html</trackback:ping><description><![CDATA[
		<p>javascript有许多内建的方法来产生对话框，如：window.alert(), window.confirm(),window.prompt().等。 然而IE提供更多的方法支持对话框。如： <br /><br />　　showModalDialog() (IE 4+ 支持) <br />　　showModelessDialog() (IE 5+ 支持) <br /><br /><br />window.showModalDialog()方法用来创建一个显示HTML内容的模态对话框，由于是对话框，因此它并没有一般用window.open()打开的窗口的所有属性。 <br />window.showModelessDialog()方法用来创建一个显示HTML内容的非模态对话框。 <br /><br />当我们用showModelessDialog()打开窗口时，不必用window.close()去关闭它，当以非模态方式［IE5］打开时， 打开对话框的窗口仍可以进行其他的操作，即对话框不总是最上面的焦点，当打开它的窗口ＵＲＬ改变时，它自动关闭。而模态［ＩＥ４］方式的对话框始终有焦点（焦点不可移走，直到它关闭）。模态对话框和打开它的窗口相联系，因此我们打开另外的窗口时，他们的链接关系依然保存，并且隐藏在活动窗口的下面。 <br /><br />使用方法如下： <br />vReturnvalue = window.showModalDialog(sURL [, vArguments] [, sFeatures]) <br />vReturnvalue = window.showModelessDialog(sURL [, vArguments] [, sFeatures]) <br />参数说明： <br />sURL <br />必选参数，类型：字符串。用来指定对话框要显示的文档的URL。 <br />vArguments <br />可选参数，类型：变体。用来向对话框传递参数。传递的参数类型不限，包括数组等。对话框通过window.dialogArguments来取得传递进来的参数。 <br />sFeatures <br />可选参数，类型：字符串。用来描述对话框的外观等信息，可以使用以下的一个或几个，用分号“;”隔开。 <br />  dialogHeight 对话框高度，不小于１００px，ＩＥ４中dialogHeight 和 dialogWidth 默认的单位是em，而ＩＥ５中是px，为方便其见，在定义modal方式的对话框时，用px做单位。 <br />　　dialogWidth: 对话框宽度。 <br />　　dialogLeft: 距离桌面左的距离。 <br />　　dialogTop: 离桌面上的距离。 <br />　　center: {yes | no | 1 | 0 }：窗口是否居中，默认yes，但仍可以指定高度和宽度。 <br />　　help: {yes | no | 1 | 0 }：是否显示帮助按钮，默认yes。 <br />　　resizable: {yes | no | 1 | 0 } ［ＩＥ５＋］：是否可被改变大小。默认no。 <br />　　status: {yes | no | 1 | 0 } ［IE5+］：是否显示状态栏。默认为yes[ Modeless]或no[Modal]。 <br />  scroll:{ yes | no | 1 | 0 | on | off }：指明对话框是否显示滚动条。默认为yes。 <br /><br />  还有几个属性是用在HTA中的，在一般的网页中一般不使用。 <br />  dialogHide:{ yes | no | 1 | 0 | on | off }：在打印或者打印预览时对话框是否隐藏。默认为no。 <br />  edge:{ sunken | raised }：指明对话框的边框样式。默认为raised。 <br />  unadorned:{ yes | no | 1 | 0 | on | off }：默认为no。 <br /><br />传入参数： <br />要想对话框传递参数，是通过vArguments来进行传递的。类型不限制，对于字符串类型，最大为4096个字符。也可以传递对象，例如： <br /><br />test1.htm <br />==================== <br />&lt;script&gt; <br />  var mxh1 = new Array("mxh","net_lover","孟子E章") <br />  var mxh2 = window.open("about:blank","window_mxh") <br />  // 向对话框传递数组 <br />  window.showModalDialog("test2.htm",mxh1) <br />  // 向对话框传递window对象 <br />  window.showModalDialog("test3.htm",mxh2) <br />&lt;/script&gt; <br /><br />test2.htm <br />==================== <br />&lt;script&gt; <br />  var a = window.dialogArguments <br />  alert("您传递的参数为：" + a) <br />&lt;/script&gt; <br /><br />test3.htm <br />==================== <br />&lt;script&gt; <br />  var a = window.dialogArguments <br />  alert("您传递的参数为window对象，名称：" + a.name) <br />&lt;/script&gt; <br /><br />可以通过window.returnvalue向打开对话框的窗口返回信息，当然也可以是对象。例如： <br /><br />test4.htm <br />=================== <br />&lt;script&gt; <br />  var a = window.showModalDialog("test5.htm") <br />  for(i=0;i&lt;a.length;i++) alert(a[i]) <br />&lt;/script&gt; <br /><br />test5.htm <br />=================== <br />&lt;script&gt; <br />function sendTo() <br />{ <br />  var a=new Array("a","b") <br />  window.returnvalue = a <br />  window.close() <br />} <br />&lt;/script&gt; <br />&lt;body&gt; <br />&lt;form&gt; <br />  &lt;input value="返回" type=button onclick="sendTo()"&gt; <br />&lt;/form&gt; <br /><br />常见问题： <br />1，如何在模态对话框中进行提交而不新开窗口？ <br />如果你 的 浏览器是IE5.5+,可以在对话框中使用带name属性的iframe，提交时可以制定target为该iframe的name。对于IE4+，你可以用高度为0的frame来作：例子， <br /><br />test6.htm <br />=================== <br />&lt;script&gt; <br />  window.showModalDialog("test7.htm") <br />&lt;/script&gt; <br /><br />test7.htm <br />=================== <br />if(window.location.search) alert(window.location.search) <br />&lt;frameset rows="0,*"&gt; <br />  &lt;frame src="about:blank"&gt; <br />  &lt;frame src="test8.htm"&gt; <br />&lt;/frameset&gt; <br /><br />test8.htm <br />=================== <br />&lt;form target="_self" method="get"&gt; <br />&lt;input name=txt value="test"&gt; <br />&lt;input type=submit&gt; <br />&lt;/form&gt; <br />&lt;script&gt; <br />if(window.location.search) alert(window.location.search) <br />&lt;/script&gt; <br />2,可以通过http://servername/virtualdirname/test.htm?name=mxh方式直接向对话框传递参数吗？ <br />答案是不能。但在frame里是可以的。 <br /><br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－ <br />另外： <br /><a href="http://www.csdn.net/" target="_blank">http://www.csdn.net/</a><br />本人整理 <br /><br />问： <br />1.模态窗口的打开 <br />2.模态窗口的关闭 <br />3.模态窗口的传递参数。 <br />4.其他。。。。 <br /><br />hgknight(江雨.net)答： <br />1.window.showModalDialog("DialogPage.aspx","newwin","dialogHeight: 200px; dialogWidth: 150px; dialogTop: 458px; dialogLeft: 166px; edge: Raised; center: Yes; help: Yes; resizable: Yes; status: Yes;"); <br /><br />2.window.close(); <br /><br />3.传值 <br />ParentPage.aspx: <br />window.showModalDialog("DialogPage.aspx?para1=aaa¶2=bbb"); <br /><br />DialogPage.aspx: <br />string str1=Request.QueryString["para1"].toString(); <br />string str2=Request.QueryString["para2"].toString(); <br /><br />返回值 <br />DialogPage.aspx: <br />window.returnvalue="aaa"; <br /><br />ParentPage.aspx: <br />var str=window.showModalDialog("DialogPage.aspx"); <br /><br />4. <br />aspx页面在showmodeldialog情况下为什么一提交就重新打开一个页面? <br />showmodaldialog打开的页面中在&lt;head&gt;&lt;/head&gt;之间加入一行：&lt;base target="_self"&gt; <br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－ <br />snowjin78(方圆) <br />以前，我也问过此类问题，现把收获贴如下（当然好多东西都是别人告诉我的）： <br />最好不要用Response.Write(  "  &lt;script....  &lt;/script  &gt;  ")这样的方法注册客户端脚本，而应该用Page.RegisterStartupScript或Page.RegisterClientScriptBlock方法来注册. <br />Page.RegisterClientScriptBlock：   <br />在  Page  对象的    &lt;form  runat=  server  &gt;  元素的开始标记后立即发出客户端脚本   <br />Page.RegisterStartupScript:   <br />该方法在  Page  对象的    &lt;form  runat=  server  &gt;  元素的结束标记之前发出该脚本 <br /><br />客户端代码有两个问题，第一是把window写成了Window，javascript是严格区分大小写的，用Window是肯定会出错的；第二个问题是设置对话框的宽度用dialogWidth，高度用dialogHeight，而不是height和width。！</p>
<img src ="http://www.blogjava.net/weibogao/aggbug/70715.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-09-20 10:27 <a href="http://www.blogjava.net/weibogao/archive/2006/09/20/70715.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>web页面打印的相关脚本</title><link>http://www.blogjava.net/weibogao/archive/2006/07/13/57929.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Thu, 13 Jul 2006 03:25:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/07/13/57929.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/57929.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/07/13/57929.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/57929.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/57929.html</trackback:ping><description><![CDATA[
		<p style="LINE-HEIGHT: 150%">
				<font class="f14" id="zoom" style="FONT-SIZE: 14px">1、控制"纵打"、 横打”和“页面的边距。 <br />（1）&lt;script defer&gt; <br />function SetPrintSettings() { <br />　// -- advanced features <br />　factory.printing.SetMarginMeasure(2) // measure margins in inches <br />　factory.SetPageRange(false, 1, 3) // need pages from 1 to 3 <br />　factory.printing.printer = "HP DeskJet 870C" <br />　factory.printing.copies = 2 <br />　factory.printing.collate = true <br />　factory.printing.paperSize = "A4" <br />　factory.printing.paperSource = "Manual feed" <br /><br />　// -- basic features <br />　factory.printing.header = "This is MeadCo" <br />　factory.printing.footer = "Advanced Printing by ScriptX" <br />　factory.printing.portrait = false <br />　factory.printing.leftMargin = 1.0 <br />　factory.printing.topMargin = 1.0 <br />　factory.printing.rightMargin = 1.0 <br />　factory.printing.bottomMargin = 1.0 <br />} <br />&lt;/script&gt; <br /><br />（2） <br />&lt;script language="javascript"&gt; <br />　　function printsetup(){ <br />　　// 打印页面设置 <br />　　wb.execwb(8,1); <br />　　} <br />　　function printpreview(){ <br />　　// 打印页面预览 <br />　　　　 <br />　　wb.execwb(7,1); <br />　　　　　 <br />　　　　 <br />　　} <br /><br />　　function printit() <br />　　{ <br />　　if (confirm('确定打印吗？')) { <br />　　wb.execwb(6,6) <br />　　} <br />　　} <br />　　&lt;/script&gt; <br />&lt;/head&gt; <br />&lt;body&gt; <br />&lt;OBJECT classid="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2" <br /><br />height=0 id=wb name=wb width=0&gt;&lt;/OBJECT&gt; <br />&lt;input type=button name=button_print value="打印" <br /><br />onclick="javascript:printit()"&gt; <br />&lt;input type=button　name=button_setup value="打印页面设置" <br /><br />onclick="javascript:printsetup();"&gt; <br />&lt;input type=button　name=button_show value="打印预览" <br /><br />onclick="javascript:printpreview();"&gt; <br />&lt;input type=button name=button_fh value="关闭" <br /><br />onclick="javascript:window.close();"&gt; <br /><br />------------------------------------------------ <br />关于这个组件还有其他的用法，列举如下： <br />WebBrowser.ExecWB(1,1) 打开 <br />Web.ExecWB(2,1) 关闭现在所有的IE窗口，并打开一个新窗口 <br />Web.ExecWB(4,1) 保存网页 <br />Web.ExecWB(6,1) 打印 <br />Web.ExecWB(7,1) 打印预览 <br />Web.ExecWB(8,1) 打印页面设置 <br />Web.ExecWB(10,1) 查看页面属性 <br />Web.ExecWB(15,1) 好像是撤销，有待确认 <br />Web.ExecWB(17,1) 全选 <br />Web.ExecWB(22,1) 刷新 <br />Web.ExecWB(45,1) 关闭窗体无提示 <br /><br />2、分页打印 <br />&lt;HTML&gt; <br />&lt;HEAD&gt; <br />&lt;STYLE&gt;　　 <br />　　P {page-break-after: always} <br />&lt;/STYLE&gt; <br />&lt;/HEAD&gt; <br />&lt;BODY&gt; <br />&lt;%while not rs.eof%&gt; <br />&lt;P&gt;&lt;%=rs(0)%&gt;&lt;/P&gt; <br />&lt;%rs.movenext%&gt; <br />&lt;%wend%&gt; <br />&lt;/BODY&gt; <br />&lt;/HTML&gt; <br /><br />3、ASP页面打印时如何去掉页面底部的路径和顶端的页码编号 <br />（1）ie的文件-〉页面设置-〉讲里面的页眉和页脚里面的东西都去掉，打印就不出来了。 <br />（2）&lt;HTML&gt; <br />&lt;HEAD&gt; <br />&lt;TITLE&gt; New Document &lt;/TITLE&gt; <br />&lt;META NAME="Generator" CONTENT="EditPlus"&gt; <br />&lt;META NAME="Author" CONTENT="YC"&gt; <br />&lt;script language="VBScript"&gt; <br />dim hkey_root,hkey_path,hkey_key <br />hkey_root="HKEY_CURRENT_USER" <br />hkey_path="\Software\Microsoft\Internet Explorer\PageSetup" <br />'//设置网页打印的页眉页脚为空 <br />function pagesetup_null() <br />　　on error resume next <br />　　Set RegWsh = CreateObject("WScript.Shell") <br />　　hkey_key="\header"　　 <br />　　RegWsh.RegWrite hkey_root+hkey_path+hkey_key,"" <br />　　hkey_key="\footer" <br />　　RegWsh.RegWrite hkey_root+hkey_path+hkey_key,"" <br />end function <br />'//设置网页打印的页眉页脚为默认值 <br />function pagesetup_default() <br />　　on error resume next <br />　　Set RegWsh = CreateObject("WScript.Shell") <br />　　hkey_key="\header"　　 <br />　　RegWsh.RegWrite hkey_root+hkey_path+hkey_key,"&amp;w&amp;b页码，&amp;p/&amp;P" <br />　　hkey_key="\footer" <br />　　RegWsh.RegWrite hkey_root+hkey_path+hkey_key,"&amp;u&amp;b&amp;d" <br />end function <br />&lt;/script&gt; <br />&lt;/HEAD&gt; <br /><br />&lt;BODY&gt; <br />&lt;br/&gt; <br />&lt;br/&gt; <br />&lt;br/&gt; <br />&lt;br/&gt; <br />&lt;br/&gt; <br />&lt;br/&gt;&lt;p align=center&gt; <br />&lt;input type="button" value="清空页码" onclick=pagesetup_null()&gt; &lt;input type="button" value="恢复页吗" onclick=pagesetup_default()&gt;&lt;br/&gt; <br /><br />&lt;/p&gt; <br />&lt;/BODY&gt; <br />&lt;/HTML&gt; <br />4、浮动帧打印 <br />&lt;SCRIPT LANGUAGE=javascript&gt; <br />function button1_onclick() { <br />　　var odoc=window.iframe1.document; <br />　　var r=odoc.body.createTextRange(); <br />　　var stxt=r.htmlText; <br />　　alert(stxt) <br />　　var pwin=window.open("","print"); <br />　　pwin.document.write(stxt); <br />　　pwin.print(); <br />} <br />&lt;/SCRIPT&gt; <br />4、用FileSystem组件实现WEB应用中的本地特定打印 <br />&lt;script Language=VBScript&gt; <br />function print_onclick //打印函数 <br />dim label <br />label=document.printinfo.label.value //获得HTML页面的数据 <br />set objfs=CreateObject("Scripting.FileSystemObject") //创建FileSystem组件对象的实例 <br />set objprinter=objfs.CreateTextFile ("LPT1:",true) //建立与打印机的连接 <br />objprinter.Writeline("__________________________________") //输出打印的内容 <br />objprinter.Writeline("| |") <br />objprinter.Writeline("| 您打印的数据是："&amp;label&amp; " |”) <br />objprinter.Writeline("| |") <br />objprinter.Writeline("|_________________________________|") <br />objprinter.close //断开与打印机的连接 <br />set objprinter=nothing <br />set objfs=nothing // 关闭FileSystem组件对象 <br />end function <br />&lt;/script&gt; <br />服务器端脚本： <br />&lt;%……… <br />set conn=server.CreateObject ("adodb.connection") <br />conn.Open "DSN=name;UID=XXXX;PWD=XXXX;" <br />set rs=server.CreateObject("adodb.recordset") <br />rs.Open(“select ……”),conn,1,1 <br />……….%&gt; //与数据库进行交互 <br />HTML页面编码： <br />&lt;HTML&gt; <br />……… <br />&lt;FORM ID=printinfo NAME="printinfo" &gt; <br />&lt;INPUT type="button" value="打印&gt;&gt;" id=print name=print &gt; //调用打印函数 <br />&lt;INPUT type=hidden id=text1 name=label value=&lt;%=………%&gt;&gt; //保存服务器端传来的数据 <br />……… <br />&lt;/HTML&gt;</font>
		</p>
<img src ="http://www.blogjava.net/weibogao/aggbug/57929.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-07-13 11:25 <a href="http://www.blogjava.net/weibogao/archive/2006/07/13/57929.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jfreechart使用总结</title><link>http://www.blogjava.net/weibogao/archive/2006/07/11/57622.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Tue, 11 Jul 2006 03:31:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/07/11/57622.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/57622.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/07/11/57622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/57622.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/57622.html</trackback:ping><description><![CDATA[
		<p>
				<br />
				<br />这里分三部分来介绍 jFreeChart 。第一部分介绍jFreeChart产生<br />图形的流程及相关的重要的类；第二部分介绍四种常用的报表图（饼图、柱状图、折线图、时间序列图）；第三部分<br />介绍在图形中增加Item Lable 。 <br />jFreeChart 的版本是jfreechart-1.0.0-pre2(1)<br /><br /></p>
		<p>[b]一、jFreeChart产生图形的流程[/b]<br />   创建一个数据源（dataset）来包含将要在图形中显示的数据,创建一个 JFreeChart 对象来代表要显示的图形<br />   把图形输出<br />   重要的类和接口：<br />   org.jfree.data.general.Dataset  所有数据源类都要实现的接口<br />   org.jfree.chart.ChartFactory    由它来产生 JFreeChart 对象<br />   org.jfree.chart.JFreeChart    所有对图形的调整都是通过它噢！！<br />   org.jfree.chart.plot.Plot    通过JFreeChart 对象获得它，然后再通过它对图形外部部分（例：坐标轴）调整<br />                                注意：它有很多子类，一般都下嗍造型到它的子类！<br />   org.jfree.chart.renderer.AbstractRenderer     通过JFreeChart 对象获得它，然后再通过它对图形内部部分<br />                                                （例：折线的类型）调整。同样，针对不同类型的报表图，它有<br />                                                着不同的子类实现！在下面我们简称它为 Renderer<br />   下面我们结合不同类型的图形来具体分析这个流程。<br />   <br />[b]二、饼图[/b]<br />   饼图的dataset 一般是用PieDataset 接口，具体实现类是 DefaultPieDataset<br />   1、创建一个数据源（dataset）：<br />    private static PieDataset createDataset()<br />    {<br />        DefaultPieDataset defaultpiedataset = new DefaultPieDataset(); //注意是DefaultPieDataset！！<br />        defaultpiedataset.setValue("One", new Double(43.200000000000003D));<br />        defaultpiedataset.setValue("Two", new Double(10D));<br />        defaultpiedataset.setValue("Three", new Double(27.5D));<br />        defaultpiedataset.setValue("Four", new Double(17.5D));<br />        return defaultpiedataset;<br />    } <br />   2、由ChartFactory  产生 JFreeChart 对象<br />    private static JFreeChart createChart(PieDataset piedataset)<br />    {<br />        JFreeChart jfreechart = ChartFactory.createPieChart("Pie Chart Demo 1",  //图形标题名称<br />                                                              piedataset,   // dataset<br />                                                              true,      // legend?<br />                                                              true,     // tooltips?<br />                                                              false);  //URLs?<br />        PiePlot pieplot = (PiePlot)jfreechart.getPlot();  //通过JFreeChart 对象获得 plot：PiePlot！！<br />        pieplot.setNoDataMessage("No data available");    // 没有数据的时候显示的内容<br />        return jfreechart;<br />    } <br />    一些重要的方法：<br />    pieplot.setExplodePercent(0,0.3D) //把Lable 为"One" 的那一块”挖“出来30%    <br />   3、输出略  <br />   <br />[b]三、柱状图[/b]<br />   柱状图的dataset 一般是用CatagoryDataset接口(具体实现类是DefaultCategoryDataset),也会用 IntervalXYDataset <br />   接口<br />   1、创建一个数据源（dataset）：<br />    private static CategoryDataset createDataset()<br />    {<br />        String series1 = "First";<br />        String series2 = "Second";<br />        String series3 = "Third";<br />        String category1 = "Category 1";<br />        String category2 = "Category 2";<br />        String category3 = "Category 3";<br />        String category4 = "Category 4";<br />        String category5 = "Category 5";<br />        DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();<br />        defaultcategorydataset.addValue(1.0D, series1, category1);<br />        defaultcategorydataset.addValue(4D, series1, category2);<br />        defaultcategorydataset.addValue(3D, series1, category3);<br />        defaultcategorydataset.addValue(5D, series1, category4);<br />        defaultcategorydataset.addValue(5D, series1, category5);<br />        <br />        defaultcategorydataset.addValue(5D, series2, category1);<br />        defaultcategorydataset.addValue(7D, series2, category2);<br />        defaultcategorydataset.addValue(6D, series2, category3);<br />        defaultcategorydataset.addValue(8D, series2, category4);<br />        defaultcategorydataset.addValue(4D, series2, category5);<br />        <br />        defaultcategorydataset.addValue(4D, series3, category1);<br />        defaultcategorydataset.addValue(3D, series3, category2);<br />        defaultcategorydataset.addValue(2D, series3, category3);<br />        defaultcategorydataset.addValue(3D, series3, category4);<br />        defaultcategorydataset.addValue(6D, series3, category5);<br />        return defaultcategorydataset;<br />    }<br />   2、由ChartFactory  产生 JFreeChart 对象    <br />    private static JFreeChart createChart(CategoryDataset categorydataset)<br />    {<br />        JFreeChart jfreechart = ChartFactory.createBarChart("Bar Chart Demo", //图形标题名称<br />                                                            "Category",//domain 轴 Lable <br />                                                                         这里先简单理解为横坐标Lable好了<br />                                                            "Value", //range 轴 Lable<br />                                                                       这里也先简单理解为纵坐标Lable好了<br />                                                            categorydataset, //  dataset<br />                                                            PlotOrientation.VERTICAL, //垂直显示<br />                                                            true, // legend?<br />                                                            true,  // tooltips?<br />                                                            false); //URLs?<br />        jfreechart.setBackgroundPaint(Color.white);   //设定背景色为白色<br />        CategoryPlot categoryplot = jfreechart.getCategoryPlot(); //获得 plot：CategoryPlot！！<br />        categoryplot.setBackgroundPaint(Color.lightGray); //设定图表数据显示部分背景色<br />        categoryplot.setDomainGridlinePaint(Color.white); //横坐标网格线白色<br />        categoryplot.setDomainGridlinesVisible(true); //可见<br />        categoryplot.setRangeGridlinePaint(Color.white); //纵坐标网格线白色<br />        //下面两行使纵坐标的最小单位格为整数<br />        NumberAxis numberaxis = (NumberAxis)categoryplot.getRangeAxis();<br />        numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());<br />        BarRenderer barrenderer = (BarRenderer)categoryplot.getRenderer(); //获得renderer 注意这里是下嗍造型<br />                                                                             到BarRenderer！！<br />        barrenderer.setDrawBarOutline(false); // Bar的外轮廓线不画<br />        GradientPaint gradientpaint = new GradientPaint(0.0F, 0.0F, Color.blue, <br />        0.0F, 0.0F, new Color(0, 0, 64));   //设定特定颜色<br />        GradientPaint gradientpaint1 = new GradientPaint(0.0F, 0.0F, Color.green, <br />        0.0F, 0.0F, new Color(0, 64, 0));<br />        GradientPaint gradientpaint2 = new GradientPaint(0.0F, 0.0F, Color.red,<br />        0.0F, 0.0F, new Color(64, 0, 0));<br />        barrenderer.setSeriesPaint(0, gradientpaint); //给series1 Bar设定上面定义的颜色<br />        barrenderer.setSeriesPaint(1, gradientpaint1); //给series2 Bar 设定上面定义的颜色<br />        barrenderer.setSeriesPaint(2, gradientpaint2); //给series3 Bar 设定上面定义的颜色<br />        CategoryAxis categoryaxis = categoryplot.getDomainAxis();  //横轴上的 Lable 45度倾斜<br />        categoryaxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);        <br />        return jfreechart;<br />    }  <br />    一些重要的方法：（增加一块标记）<br />        IntervalMarker intervalmarker = new IntervalMarker(4.5D, 7.5D);<br />        intervalmarker.setLabel("Target Range");<br />        intervalmarker.setLabelFont(new Font("SansSerif", 2, 11));<br />        intervalmarker.setLabelAnchor(RectangleAnchor.LEFT);<br />        intervalmarker.setLabelTextAnchor(TextAnchor.CENTER_LEFT);<br />        intervalmarker.setPaint(new Color(222, 222, 255, 128));<br />        categoryplot.addRangeMarker(intervalmarker, Layer.BACKGROUND);    <br />        <br />[b]四、折线图[/b]<br />   折线图的dataset 两种CatagoryDataset接口(具体实现类是DefaultCategoryDataset),XYDataset 接口 <br />   1、CatagoryDataset接口：         <br />   A、创建一个数据源（dataset）： <br />    private static CategoryDataset createDataset()<br />    {<br />        String series1 = "First";<br />        String series2 = "Second";<br />        String series3 = "Third";<br />        String type1 = "Type 1";<br />        String type2 = "Type 2";<br />        String type3 = "Type 3";<br />        String type4 = "Type 4";<br />        String type5 = "Type 5";<br />        String type6 = "Type 6";<br />        String type7 = "Type 7";<br />        String type8 = "Type 8";<br />        DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();<br />        defaultcategorydataset.addValue(1.0D, series1, type1);<br />        defaultcategorydataset.addValue(4D, series1, type2);<br />        defaultcategorydataset.addValue(3D, series1, type3);<br />        defaultcategorydataset.addValue(5D, series1, type4);<br />        defaultcategorydataset.addValue(5D, series1, type5);<br />        defaultcategorydataset.addValue(7D, series1, type6);<br />        defaultcategorydataset.addValue(7D, series1, type7);<br />        defaultcategorydataset.addValue(8D, series1, type8);<br />        <br />        defaultcategorydataset.addValue(5D, series2, type1);<br />        defaultcategorydataset.addValue(7D, series2, type2);<br />        defaultcategorydataset.addValue(6D, series2, type3);<br />        defaultcategorydataset.addValue(8D, series2, type4);<br />        defaultcategorydataset.addValue(4D, series2, type5);<br />        defaultcategorydataset.addValue(4D, series2, type6);<br />        defaultcategorydataset.addValue(2D, series2, type7);<br />        defaultcategorydataset.addValue(1.0D, series2, type8);<br />        <br />        defaultcategorydataset.addValue(4D, series3, type1);<br />        defaultcategorydataset.addValue(3D, series3, type2);<br />        defaultcategorydataset.addValue(2D, series3, type3);<br />        defaultcategorydataset.addValue(3D, series3, type4);<br />        defaultcategorydataset.addValue(6D, series3, type5);<br />        defaultcategorydataset.addValue(3D, series3, type6);<br />        defaultcategorydataset.addValue(4D, series3, type7);<br />        defaultcategorydataset.addValue(3D, series3, type8);<br />        return defaultcategorydataset;<br />    } <br />   B、由ChartFactory  产生 JFreeChart 对象     (与上面重复的部分就不再注释）<br />    private static JFreeChart createChart(CategoryDataset categorydataset)<br />    {<br />        JFreeChart jfreechart = ChartFactory.createLineChart("Line Chart Demo 1", <br />                                                             "Type", <br />                                                             "Value", <br />                                                             categorydataset, <br />                                                             PlotOrientation.VERTICAL, <br />                                                             true, <br />                                                             true, <br />                                                             false);<br />        jfreechart.setBackgroundPaint(Color.white);<br />        CategoryPlot categoryplot = (CategoryPlot)jfreechart.getPlot();<br />        categoryplot.setBackgroundPaint(Color.lightGray);<br />        categoryplot.setRangeGridlinePaint(Color.white);<br />        NumberAxis numberaxis = (NumberAxis)categoryplot.getRangeAxis();<br />        numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());<br />        numberaxis.setAutoRangeIncludesZero(true);<br />        //获得renderer 注意这里是下嗍造型到lineandshaperenderer！！<br />        LineAndShapeRenderer lineandshaperenderer = (LineAndShapeRenderer)categoryplot.getRenderer();<br />        lineandshaperenderer.setShapesVisible(true); //series 点（即数据点）可见<br />        lineandshaperenderer.setSeriesStroke(0, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {<br />            10F, 6F<br />        }, 0.0F)); //定义series为"First"的（即series1）点之间的连线 ，这里是虚线，默认是直线<br />        lineandshaperenderer.setSeriesStroke(1, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {<br />            6F, 6F<br />        }, 0.0F)); //定义series为"Second"的（即series2）点之间的连线<br />        lineandshaperenderer.setSeriesStroke(2, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {<br />            2.0F, 6F<br />        }, 0.0F)); //定义series为"Third"的（即series3）点之间的连线<br />        return jfreechart;<br />    } <br />        一些重要的方法：<br />        lineandshaperenderer.setLineVisible(true)  //series 点（即数据点）间有连线可见<br />   2、XYDataset 接口：<br />   A、创建一个数据源（dataset）：<br />    private static XYDataset createDataset()<br />    {<br />        XYSeries xyseries = new XYSeries("First"); //先产生XYSeries 对象<br />        xyseries.add(1.0D, 1.0D);<br />        xyseries.add(2D, 4D);<br />        xyseries.add(3D, 3D);<br />        xyseries.add(4D, 5D);<br />        xyseries.add(5D, 5D);<br />        xyseries.add(6D, 7D);<br />        xyseries.add(7D, 7D);<br />        xyseries.add(8D, 8D);<br />        <br />        XYSeries xyseries1 = new XYSeries("Second");<br />        xyseries1.add(1.0D, 5D);<br />        xyseries1.add(2D, 7D);<br />        xyseries1.add(3D, 6D);<br />        xyseries1.add(4D, 8D);<br />        xyseries1.add(5D, 4D);<br />        xyseries1.add(6D, 4D);<br />        xyseries1.add(7D, 2D);<br />        xyseries1.add(8D, 1.0D);<br />        <br />        XYSeries xyseries2 = new XYSeries("Third");<br />        xyseries2.add(3D, 4D);<br />        xyseries2.add(4D, 3D);<br />        xyseries2.add(5D, 2D);<br />        xyseries2.add(6D, 3D);<br />        xyseries2.add(7D, 6D);<br />        xyseries2.add(8D, 3D);<br />        xyseries2.add(9D, 4D);<br />        xyseries2.add(10D, 3D);<br />        <br />        XYSeriesCollection xyseriescollection = new XYSeriesCollection(); //再用XYSeriesCollection添加入XYSeries 对象<br />        xyseriescollection.addSeries(xyseries);<br />        xyseriescollection.addSeries(xyseries1);<br />        xyseriescollection.addSeries(xyseries2);<br />        return xyseriescollection;<br />    }<br />   B、由ChartFactory  产生 JFreeChart 对象 <br />    private static JFreeChart createChart(XYDataset xydataset)<br />    {<br />        JFreeChart jfreechart = ChartFactory.createXYLineChart("Line Chart Demo 2", <br />                                                               "X", <br />                                                               "Y", <br />                                                               xydataset, <br />                                                               PlotOrientation.VERTICAL, <br />                                                               true, <br />                                                               true, <br />                                                               false);<br />        jfreechart.setBackgroundPaint(Color.white);<br />        XYPlot xyplot = (XYPlot)jfreechart.getPlot(); //获得 plot：XYPlot！！<br />        xyplot.setBackgroundPaint(Color.lightGray); //设定图表数据显示部分背景色<br />        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D)); //设定坐标轴与图表数据显示部分距离<br />        xyplot.setDomainGridlinePaint(Color.white); //网格线颜色<br />        xyplot.setRangeGridlinePaint(Color.white);<br />        //获得 renderer 注意这里是XYLineAndShapeRenderer ！！<br />        XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyplot.getRenderer();<br />        xylineandshaperenderer.setShapesVisible(true); //数据点可见<br />        xylineandshaperenderer.setShapesFilled(true); //数据点被填充即不是空心点<br />        NumberAxis numberaxis = (NumberAxis)xyplot.getRangeAxis();<br />        numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());<br />        return jfreechart;<br />    }                      <br />   一些重要的方法：<br />        XYLineAndShapeRenderer xylineandshaperenderer = new XYLineAndShapeRenderer();<br />        xylineandshaperenderer.setSeriesLinesVisible(0, false); //第一个XYSeries数据点间连线不可见<br />        xylineandshaperenderer.setSeriesShapesVisible(1, false); //第二个XYSeries数据点不可见<br />        xyplot.setRenderer(xylineandshaperenderer);   <br />        <br />[b]五、时间序列图[/b]<br />    时间序列图和折线图很相似，不同的是它在 domain轴的数据是时间而不是数字。 时间序列图的dataset 是<br />    XYDataset 接口，具体实现类是TimeSeriesCollection ，和上面类似，有TimeSeries 对象，它被添加入<br />    TimeSeriesCollection 。                                                                               <br />  1、创建一个数据源（dataset）：<br />    private static XYDataset createDataset()<br />    {<br />        TimeSeries timeseries = new TimeSeries("L&amp;G European Index Trust",Month.class);<br />        timeseries.add(new Month(2, 2001), 181.8D);//这里用的是Month.class，同样还有Day.class Year.class 等等<br />        timeseries.add(new Month(3, 2001), 167.3D);<br />        timeseries.add(new Month(4, 2001), 153.8D);<br />        timeseries.add(new Month(5, 2001), 167.6D);<br />        timeseries.add(new Month(6, 2001), 158.8D);<br />        timeseries.add(new Month(7, 2001), 148.3D);<br />        timeseries.add(new Month(8, 2001), 153.9D);<br />        timeseries.add(new Month(9, 2001), 142.7D);<br />        timeseries.add(new Month(10, 2001), 123.2D);<br />        timeseries.add(new Month(11, 2001), 131.8D);<br />        timeseries.add(new Month(12, 2001), 139.6D);<br />        timeseries.add(new Month(1, 2002), 142.9D);<br />        timeseries.add(new Month(2, 2002), 138.7D);<br />        timeseries.add(new Month(3, 2002), 137.3D);<br />        timeseries.add(new Month(4, 2002), 143.9D);<br />        timeseries.add(new Month(5, 2002), 139.8D);<br />        timeseries.add(new Month(6, 2002), 137D);<br />        timeseries.add(new Month(7, 2002), 132.8D);<br />        <br />        TimeSeries timeseries1 = new TimeSeries("L&amp;G UK Index Trust",Month.class);<br />        timeseries1.add(new Month(2, 2001), 129.6D);<br />        timeseries1.add(new Month(3, 2001), 123.2D);<br />        timeseries1.add(new Month(4, 2001), 117.2D);<br />        timeseries1.add(new Month(5, 2001), 124.1D);<br />        timeseries1.add(new Month(6, 2001), 122.6D);<br />        timeseries1.add(new Month(7, 2001), 119.2D);<br />        timeseries1.add(new Month(8, 2001), 116.5D);<br />        timeseries1.add(new Month(9, 2001), 112.7D);<br />        timeseries1.add(new Month(10, 2001), 101.5D);<br />        timeseries1.add(new Month(11, 2001), 106.1D);<br />        timeseries1.add(new Month(12, 2001), 110.3D);<br />        timeseries1.add(new Month(1, 2002), 111.7D);<br />        timeseries1.add(new Month(2, 2002), 111D);<br />        timeseries1.add(new Month(3, 2002), 109.6D);<br />        timeseries1.add(new Month(4, 2002), 113.2D);<br />        timeseries1.add(new Month(5, 2002), 111.6D);<br />        timeseries1.add(new Month(6, 2002), 108.8D);<br />        timeseries1.add(new Month(7, 2002), 101.6D);<br />        TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();<br />        timeseriescollection.addSeries(timeseries);<br />        timeseriescollection.addSeries(timeseries1);<br />        timeseriescollection.setDomainIsPointsInTime(true); //domain轴上的刻度点代表的是时间点而不是时间段<br />        return timeseriescollection;<br />    }<br />   2、由ChartFactory  产生 JFreeChart 对象 <br />    private static JFreeChart createChart(XYDataset xydataset)<br />    {<br />        JFreeChart jfreechart = ChartFactory.createTimeSeriesChart("Legal &amp; General Unit Trust Prices", <br />                                                                   "Date", <br />                                                                   "Price Per Unit", <br />                                                                   xydataset, <br />                                                                   true, <br />                                                                   true, <br />                                                                   false);<br />        jfreechart.setBackgroundPaint(Color.white);<br />        XYPlot xyplot = (XYPlot)jfreechart.getPlot(); //获得 plot : XYPlot!!<br />        xyplot.setBackgroundPaint(Color.lightGray);<br />        xyplot.setDomainGridlinePaint(Color.white);<br />        xyplot.setRangeGridlinePaint(Color.white);<br />        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));<br />        xyplot.setDomainCrosshairVisible(true);<br />        xyplot.setRangeCrosshairVisible(true);<br />        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();<br />        if(xyitemrenderer instanceof XYLineAndShapeRenderer)<br />        {<br />            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyitemrenderer;<br />            xylineandshaperenderer.setDefaultShapesVisible(true); //数据点可见<br />            xylineandshaperenderer.setDefaultShapesFilled(true);  //数据点是实心点<br />        }<br />        DateAxis dateaxis = (DateAxis)xyplot.getDomainAxis(); //对domain 轴上日期显示格式定义<br />        dateaxis.setDateFormatOverride(new SimpleDateFormat("MMM-yyyy"));<br />        return jfreechart;<br />    }  <br />       一些重要的方法：<br />     A、增加标记线： <br />        xyplot.addRangeMarker(new ValueMarker(550D)); //数值轴<br />        Quarter quarter = new Quarter(2, 2002);<br />        xyplot.addDomainMarker(new ValueMarker(quarter.getMiddleMillisecond()));  //时间轴<br />     B、数据点的调整<br />        XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyplot.getRenderer();<br />        xylineandshaperenderer.setDefaultShapesVisible(true);  //数据点可见<br />        xylineandshaperenderer.setSeriesFillPaint(0, Color.red);  //数据点填充为红色<br />        xylineandshaperenderer.setSeriesFillPaint(1, Color.white);  //数据点填充为白色<br />        xylineandshaperenderer.setUseFillPaint(true);    //应用<br />     C、平均值曲线 <br />       这个曲线有什么用呢？很简单的例子，这里有一个以半年每天为单位的数据绘制的曲线，我们想看看以月为单位数据<br />       的变化，这时就可以用到它了。 <br />        TimeSeries timeseries = createEURTimeSeries();  //就是以半年每天为单位的数据<br />        TimeSeries timeseries1 = MovingAverage.createMovingAverage(timeseries, <br />                                                                   "30 day moving average", <br />                                                                   30, //30天为一个周期<br />                                                                   30); //最开始的30天跳过<br />        TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();<br />        timeseriescollection.addSeries(timeseries);<br />        timeseriescollection.addSeries(timeseries1);<br />        return timeseriescollection; <br />     <br />[b]六、总结一下[/b]<br />                           dataset                          plot                    renderer                       <br />  饼图           PieDataset（DefaultPieDataset）           PiePlot                    ------<br />  柱状图    CatagoryDataset（DefaultCategoryDataset）    CategoryPlot                BarRenderer<br />  折线图    CatagoryDataset（DefaultCategoryDataset）    CategoryPlot              LineAndShapeRenderer<br />                  XYDataset（XYSeriesCollection）           XYPlot                XYLineAndShapeRenderer<br />  时间序列图     XYDataset （TimeSeriesCollection）         XYPlot                XYLineAndShapeRenderer<br />  这里只是一些常用的方法，具体还是看API ,主要的类总结如下：<br />JFreeChart:生成图表的中间存放类。</p>
		<div>CategoryDataSet:图表的数据，主要包含行数据（String[] 类型），列数据(String[] 类型）和主数据                    (double[][]类型）。一般来说简单的图表主数据都是double[1][]类型的。</div>
		<div>ChartFactory: 工厂类，提供多种方法生成多达30多种图表，用得比较多的是BarChart(柱状图),LineChart             （折线图），PieChart（饼状图）。工厂方法看起来比较统一：creatXXXChart(图表标题，              行标题，列标题，主数据（CategoryDataSet）)</div>
		<div>ChartUtities: 公用类，提供各种持久保存图表数据的方法，比如saveChartAsJPEG(File，                             JFreeChart,width,height)</div>
		<div>其他还有一些渲染类，主要是用来美化图表界面，调整和优化显示风格等。</div>
		<div>总的来说还不错，比jasperReport要简单，上手很快，图表效果也还不错，用来做普通数据图表足够了</div>
		<p>
				<br />
				<br />[b]七、Item Lable[/b] <br />   这里以柱状图为例说明，具体来说就是在每个柱状上显示它的数据，具体有下面内容：<br />   A、使 Item Lable 可见<br />   B、调整 Item Lable 的颜色、字体等<br />   C、调整 Item Lable 的位置<br />   D、定制 Item Lable 的内容<br />   1、分配一个 Lable Generator 给 renderer<br />      BarRenderer barrenderer = (BarRenderer)categoryplot.getRenderer();<br />      GategoryLableGenerator generator =new StandardGategoryLableGenerator(<br />           "{2}", new DecimalFormat("0.00")    //调整显示的数字和字符格式<br />      );<br />      barrenderer.setLableGenerator(generator);<br />   2、使 Item Lable 可见<br />      barrenderer.setItemLableVisible(true);<br />   3、调整 Item Lable 的颜色、字体等<br />      barrenderer.setItemLablePaint(Color.red);<br />      barrenderer.setItemLableFont(new Font("SansSerif",Font.PLAIN,10));<br />   4、调整 Item Lable 的位置<br />      这里涉及到一个新的对象 ItemLablePosition , ItemLablePosition的构造函数有两个或四个参数<br />      public ItemLabelPosition(ItemLabelAnchor itemLabelAnchor,<br />                         org.jfree.ui.TextAnchor textAnchor,<br />                         org.jfree.ui.TextAnchor rotationAnchor,<br />                         double angle)<br />      itemLabelAnchor - Item Lable 的位置 （最重要的！！）<br />      textAnchor - Item Lable里包含的正文相对于Item Lable 的位置<br />      rotationAnchor - Item Lable里包含的正文旋转的位置<br />      angle - 旋转的角度<br />      ItemLabelPosition itemlabelposition = new ItemLabelPosition(ItemLabelAnchor.INSIDE12, <br />                                                      TextAnchor.CENTER_RIGHT, <br />                                                      TextAnchor.CENTER_RIGHT, <br />                                                      -1.57D);<br />      barrenderer.setPositiveItemLabelPosition(itemlabelposition); <br />   这样就可以每个柱状上显示它的数据了，当然可以定制 Item Lable 的内容，比如 Item Lable text 超过100的才<br />   显示，这样就需要定制自己的类，它要实现GategoryLableGenerator 接口，实现generateItemLable()方法。</p>
<img src ="http://www.blogjava.net/weibogao/aggbug/57622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-07-11 11:31 <a href="http://www.blogjava.net/weibogao/archive/2006/07/11/57622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jsp标签小结</title><link>http://www.blogjava.net/weibogao/archive/2006/07/06/56954.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Thu, 06 Jul 2006 07:05:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/07/06/56954.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/56954.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/07/06/56954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/56954.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/56954.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JSP自定义标签试验原文：兔八哥笔记3:JSP自定义标签试验  一、概述       JSP中有一块重要的技术：自定义标签（Custom Tag），最近这几天在学习Struts的时候发现Struts中使用了很多自定义标签，如html、bean等。所以我就做了个简单的试验，学习一下这种技术。       首先介绍一下这种技术吧！1．优点：取代了JSP中的Java程序，并且可以重复使用，方便不熟悉...&nbsp;&nbsp;<a href='http://www.blogjava.net/weibogao/archive/2006/07/06/56954.html'>阅读全文</a><img src ="http://www.blogjava.net/weibogao/aggbug/56954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-07-06 15:05 <a href="http://www.blogjava.net/weibogao/archive/2006/07/06/56954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate中的投影查询</title><link>http://www.blogjava.net/weibogao/archive/2006/07/05/56749.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Wed, 05 Jul 2006 06:44:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/07/05/56749.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/56749.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/07/05/56749.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/56749.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/56749.html</trackback:ping><description><![CDATA[投影(Projections)、聚合（aggregation）和分组（grouping） 
<div></div><p><tt class="literal">org.hibernate.criterion.Projections</tt>是 <tt class="literal">Projection</tt> 的实例工厂。我们通过调用 <tt class="literal">setProjection()</tt>应用投影到一个查询。 </p><pre class="programlisting">List results = session.createCriteria(Cat.class)
    .setProjection( Projections.rowCount() )
    .add( Restrictions.eq("color", Color.BLACK) )
    .list();</pre><pre class="programlisting">List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount() )
        .add( Projections.avg("weight") )
        .add( Projections.max("weight") )
        .add( Projections.groupProperty("color") )
    )
    .list();</pre><p>在一个条件查询中没有必要显式的使用 "group by" 。某些投影类型就是被定义为<span class="emphasis"><em> 分组投影</em></span>，他们也出现在SQL的<tt class="literal">group by</tt>子句中。 </p><p>你可以选择把一个别名指派给一个投影，这样可以使投影值被约束或排序所引用。下面是两种不同的实现方式： </p><pre class="programlisting">List results = session.createCriteria(Cat.class)
    .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
    .addOrder( Order.asc("colr") )
    .list();</pre><pre class="programlisting">List results = session.createCriteria(Cat.class)
    .setProjection( Projections.groupProperty("color").as("colr") )
    .addOrder( Order.asc("colr") )
    .list();</pre><p><tt class="literal">alias()</tt>和<tt class="literal">as()</tt>方法简便的将一个投影实例包装到另外一个 别名的<tt class="literal">Projection</tt>实例中。简而言之，当你添加一个投影到一个投影列表中时 你可以为它指定一个别名： </p><pre class="programlisting">List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount(), "catCountByColor" )
        .add( Projections.avg("weight"), "avgWeight" )
        .add( Projections.max("weight"), "maxWeight" )
        .add( Projections.groupProperty("color"), "color" )
    )
    .addOrder( Order.desc("catCountByColor") )
    .addOrder( Order.desc("avgWeight") )
    .list();</pre><pre class="programlisting">List results = session.createCriteria(Domestic.class, "cat")
    .createAlias("kittens", "kit")
    .setProjection( Projections.projectionList()
        .add( Projections.property("cat.name"), "catName" )
        .add( Projections.property("kit.name"), "kitName" )
    )
    .addOrder( Order.asc("catName") )
    .addOrder( Order.asc("kitName") )
    .list();</pre><p>你也可以使用<tt class="literal">Property.forName()</tt>来表示投影： </p><pre class="programlisting">List results = session.createCriteria(Cat.class)
    .setProjection( Property.forName("name") )
    .add( Property.forName("color").eq(Color.BLACK) )
    .list();</pre><pre class="programlisting">List results = session.createCriteria(Cat.class)
    .setProjection( Projections.projectionList()
        .add( Projections.rowCount().as("catCountByColor") )
        .add( Property.forName("weight").avg().as("avgWeight") )
        .add( Property.forName("weight").max().as("maxWeight") )
        .add( Property.forName("color").group().as("color" )
    )
    .addOrder( Order.desc("catCountByColor") )
    .addOrder( Order.desc("avgWeight") )
    .list();</pre><img src ="http://www.blogjava.net/weibogao/aggbug/56749.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-07-05 14:44 <a href="http://www.blogjava.net/weibogao/archive/2006/07/05/56749.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate中多对多的两种保存方式</title><link>http://www.blogjava.net/weibogao/archive/2006/07/05/56740.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Wed, 05 Jul 2006 06:31:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/07/05/56740.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/56740.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/07/05/56740.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/56740.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/56740.html</trackback:ping><description><![CDATA[1.使用关联表实现多对多的关联，在实体一端的映射文件中定义：<br />&lt;set name="unitTypes" lazy="true" table="IPMS_UNITTYPE" cascade="all"&gt;<br />   &lt;key column="UNITID"/&gt;<br />   &lt;many-to-many class="com.toone.ipms.common.dict.vo.CommDict" column="DICTID"/&gt;<br />&lt;/set&gt;<br />因为配置中cascade="all"，所以可以不使用中间表关联类来实现，而且不需要分别进行save操作<br />其中两个column都是关联表中的字段，key为本端外键，而另一个则是另一端外键 <br />2.另一种方式为生成关联表的映射文件和PO，写出关联类的基本管理类的增删改操作，实现保存时两个类的关联<img src ="http://www.blogjava.net/weibogao/aggbug/56740.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-07-05 14:31 <a href="http://www.blogjava.net/weibogao/archive/2006/07/05/56740.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DisplayTag应用(转载)</title><link>http://www.blogjava.net/weibogao/archive/2006/07/03/56309.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Mon, 03 Jul 2006 05:23:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/07/03/56309.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/56309.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/07/03/56309.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/56309.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/56309.html</trackback:ping><description><![CDATA[
		<div class="posttitle">
				<a class="singleposttitle" id="viewpost1_TitleUrl" href="/RongHao/archive/2005/12/08/22990.html">DisplayTag应用</a>
		</div>
		<p>  DisplayTag是一个非常好用的表格显示标签，适合MVC模式，其主页在<a href="http://displaytag.sourceforge.net/">http://displaytag.sourceforge.net/</a>  <br /><strong>一、最简单的情况，未使用&lt;display:column/&gt;标签<br /></strong>  &lt;%request.setAttribute( "test", new ReportList(6) );%&gt;<br />  &lt;display:table name="test" /&gt;<br />  标签遍历List里的每一个对象，并将对象里的所有属性显示出来。一般用于开发的时候检查对象数据的完整性。<br />  <br /><strong>二、使用&lt;display:column/&gt;标签的情况</strong><br />&lt;display:table name="test"&gt;<br />  &lt;display:column property="id" title="ID" /&gt;<br />  &lt;display:column property="name" /&gt;<br />  &lt;display:column property="email" /&gt;<br />  &lt;display:column property="status" /&gt;<br />  &lt;display:column property="description" title="Comments"/&gt;<br />&lt;/display:table&gt;<br />   property对应List里对象的属性（用getXXX()方法取得），title则对应表格表头里的列名。定义列有两种方式：<br />   A、&lt;display:column property="email" /&gt; <br />      使用&lt;display:column/&gt;标签里的property属性来定义<br />   B、&lt;display:column title="email"&gt;email@it.com&lt;/display:column&gt; <br />      在&lt;display:column/&gt;标签体里增加内容，可以是常量，也可以用其他标签等等<br />   两种方式比较，用property属性来定义更加快速和利于排序。<br />   <br /><strong>三、表格显示样式的定义<br /></strong>  A、在&lt;display:table/&gt;和&lt;display:column/&gt;标签里指定标准的html属性，烦琐<br />  B、修改样式表<br />&lt;display:table name="test" class="mars"&gt;<br />  &lt;display:column property="id" title="ID" class="idcol"/&gt;<br />  &lt;display:column property="name" /&gt;<br />  &lt;display:column property="email" /&gt;<br />  &lt;display:column property="status" class="tableCellError" /&gt;<br />  &lt;display:column property="description" title="Comments"/&gt;<br />&lt;/display:table&gt;<br />   通过class属性来指定所要应用的样式。可以在其默认样式表里（./css/screen.css）直接修改<br />   <br /><strong>四、标签取得数据的数据源<br /></strong>  有四种范围<br />   pageScope <br />   requestScope (默认)  &lt;display:table name="test2" &gt;<br />   sessionScope  &lt;display:table name="sessionScope.holder.list" &gt; 注意，这里要指定范围，非默认<br />   applicationScope <br />   <br /><strong>五、通过增加id属性创建隐含的对象<br /></strong>&lt;display:table name="test" id="testit"&gt;<br />    &lt;display:column property="id" title="ID" /&gt;<br />    &lt;display:column property="name" /&gt;<br />    &lt;display:column title="static value"&gt;static&lt;/display:column&gt;<br />    &lt;display:column title="row number (testit_rowNum)"&gt;&lt;%=pageContext.getAttribute("testit_rowNum")%&gt;&lt;/display:column&gt;<br />    &lt;display:column title="((ListObject)testit).getMoney()"&gt;&lt;%=((ListObject)pageContext.getAttribute("testit")).getMoney()%&gt;&lt;/display:column&gt;<br />&lt;/display:table&gt;<br />   注意到在&lt;display:table/&gt;里增加了id属性，这时就在page context里创建了一个隐含对象，指向List里的当前对象，<br />   可以通过(ListObject)pageContext.getAttribute("id")来捕获这个对象。同时还创建了一个id_rowNum对象，同样，可<br />   通过pageContext.getAttribute("testit_rowNum")来捕获，它仅仅代表当前行的行数。<br />   有了这两个隐含对象，就可以通过其他标签来访问，例如Jstl:<br />  &lt;display:table id="row" name="mylist"&gt;<br />    &lt;display:column title="row number" &gt;<br />      &lt;c:out value="${row_rowNum}"/&gt;<br />    &lt;/display:column&gt;<br />    &lt;display:column title="name" &gt;<br />      &lt;c:out value="${row.first_name}"/&gt;<br />      &lt;c:out value="${row.last_name}"/&gt;<br />    &lt;/display:column&gt;<br />  &lt;/display:table&gt;<br />  <br /><strong>六、显示部分数据</strong><br />   显示开始五条数据：通过设定length属性<br />&lt;display:table name="test" length="5"&gt;<br />  &lt;display:column property="id" title="ID" /&gt;<br />  &lt;display:column property="email" /&gt;<br />  &lt;display:column property="status" /&gt;<br />&lt;/display:table&gt;<br />   显示第三到第八条数据：通过设定offset和length属性<br />&lt;display:table name="test" offset="3" length="5"&gt;<br />  &lt;display:column property="id" title="ID" /&gt;<br />  &lt;display:column property="email" /&gt;<br />  &lt;display:column property="status" /&gt;<br />&lt;/display:table&gt;  </p>
		<p>
				<strong>七、对email和url地址的直接连接</strong>
				<br /> &lt;display:table name="test" &gt;<br />  &lt;display:column property="id" title="ID" /&gt;<br />  &lt;display:column property="email" autolink="true" /&gt;<br />  &lt;display:column property="url" autolink="true" /&gt;<br /> &lt;/display:table&gt;<br /> 如果要显示的对象里包含email和url地址，则可以在display:column里直接设定autolink="true"来直接连接<br /> <br /><strong>八、使用装饰模式转换数据显示（写自己的 decorator ）</strong><br />  A、对整个表格应用decorator<br />  &lt;display:table name="test" decorator="org.displaytag.sample.Wrapper" &gt;<br />      &lt;display:column property="id" title="ID" /&gt;<br />      &lt;display:column property="email" /&gt;<br />      &lt;display:column property="status" /&gt;<br />      &lt;display:column property="date" /&gt;<br />      &lt;display:column property="money" /&gt;<br />  &lt;/display:table&gt;<br />    org.displaytag.sample.Wrapper即自己写的decorator，它要继承TableDecorator类，看看它的一个方法：<br />        public String getMoney()<br />    {<br />        return this.moneyFormat.format(((ListObject) this.getCurrentRowObject()).getMoney());<br />    }<br />    很明显，它通过父类的getCurrentRowObject()方法获得当前对象，然后对其getMoney()方法进行‘油漆’<br />  B、对单独的column应用decorator<br />  &lt;display:table name="test"&gt;<br />     &lt;display:column property="id" title="ID" /&gt;<br />     &lt;display:column property="email" /&gt;<br />     &lt;display:column property="status" /&gt;<br />     &lt;display:column property="date" decorator="org.displaytag.sample.LongDateWrapper" /&gt;<br />  &lt;/display:table&gt;<br />    org.displaytag.sample.LongDateWrapper要实现ColumnDecorator接口，它的方法：<br />        public final String decorate(Object columnValue)<br />    {<br />        Date date = (Date) columnValue;<br />        return this.dateFormat.format(date);<br />    }<br />    显然，它获得不了当前对象（因为它实现的是接口），仅仅是获得该对象的columnValue，然后‘油漆’<br />    <br /><strong>九、创建动态连接<br /></strong>   有两种方法创建动态连接：<br />   A、在&lt;display:column/&gt;里通过增加href、paramId、paramName、paramScope、paramProperty属性<br />      href             基本的URL 地址<br />      paramId          加在URL 地址后的参数名称<br />      paramName        数据bean的名称，一般为null（即使用当前List里的对象）<br />      paramScope       数据bean的范围，一般为null<br />      paramProperty    数据bean的属性名称，用来填充URL 地址后的参数值<br />&lt;display:table name="sessionScope.details"&gt;<br />  &lt;display:column property="id" title="ID" href="details.jsp" paramId="id" /&gt;<br />  &lt;display:column property="email" href="details.jsp" paramId="action" paramName="testparam" paramScope="request" /&gt;<br />  &lt;display:column property="status" href="details.jsp" paramId="id" paramProperty="id" /&gt;<br />&lt;/display:table&gt;  <br />    这种方法简便直接，但缺点是无法产生类似details.jsp?id=xx&amp;action=xx的复合URL<br />   B、应用decorator 创建动态连接：<br />&lt;display:table name="sessionScope.details" decorator="org.displaytag.sample.Wrapper" &gt;<br />  &lt;display:column property="link1" title="ID" /&gt;<br />  &lt;display:column property="email" /&gt;<br />  &lt;display:column property="link2" title="Actions" /&gt;<br />&lt;/display:table&gt;<br />   org.displaytag.sample.Wrapper里的方法：<br /> public String getLink1()<br /> {<br />  ListObject lObject= (ListObject)getCurrentRowObject();<br />  int lIndex= getListIndex();<br />  return "&lt;a href=\"details.jsp?index=" + lIndex + "\"&gt;" + lObject.getId() + "&lt;/a&gt;";<br /> }</p>
		<p>
				<br /> public String getLink2()<br /> {<br />  ListObject lObject= (ListObject)getCurrentRowObject();<br />  int lId= lObject.getId();</p>
		<p>  return "&lt;a href=\"details.jsp?id=" + lId<br />   + "&amp;action=view\"&gt;View&lt;/a&gt; | "<br />   + "&lt;a href=\"details.jsp?id=" + lId<br />   + "&amp;action=edit\"&gt;Edit&lt;/a&gt; | "<br />   + "&lt;a href=\"details.jsp?id=" + lId<br />   + "&amp;action=delete\"&gt;Delete&lt;/a&gt;";<br /> }</p>
		<p>
				<strong>十、分页<br /></strong>   实现分页非常的简单，增加一个pagesize属性指定一次想显示的行数即可<br />&lt;display:table name="sessionScope.test" pagesize="10"&gt;<br /> &lt;display:column property="id" title="ID" /&gt;<br /> &lt;display:column property="name" /&gt;<br /> &lt;display:column property="email" /&gt;<br /> &lt;display:column property="status" /&gt;<br />&lt;/display:table&gt;</p>
		<p>
				<strong>十一、排序<br /></strong>   排序实现也是很简单，在需要排序的column里增加sortable="true"属性，headerClass="sortable"仅仅是<br />   指定显示的样式。column里的属性对象要实现Comparable接口，如果没有的话可以应用decorator<br />   defaultsort="1"              默认第一个column排序<br />   defaultorder="descending"    默认递减排序<br />&lt;display:table name="sessionScope.stest" defaultsort="1" defaultorder="descending"&gt;<br />  &lt;display:column property="id" title="ID" sortable="true" headerClass="sortable" /&gt;<br />  &lt;display:column property="name" sortable="true" headerClass="sortable"/&gt;<br />  &lt;display:column property="email" /&gt;<br />  &lt;display:column property="status" sortable="true" headerClass="sortable"/&gt;<br />&lt;/display:table&gt;<br />  注意的是，当同时存在分页时排序仅仅针对的是当前页面，而不是整个List都进行排序<br />  <br /><strong>十二、column 分组<br /></strong>   分组只是需要在column里增加group属性<br />&lt;display:table name="test" class="simple"&gt;<br />  &lt;display:column property="city" title="CITY" group="1"/&gt;<br />  &lt;display:column property="project" title="PROJECT" group="2"/&gt;<br />  &lt;display:column property="amount" title="HOURS"/&gt;<br />  &lt;display:column property="task" title="TASK"/&gt;<br />&lt;/display:table&gt;</p>
		<p>
				<strong>十三、导出数据到其他格式（页面溢出filter??）</strong>
				<br />   在&lt;display:table/&gt;里设定export="true"<br />   在&lt;display:column/&gt;里设定media="csv excel xml pdf" 决定该字段在导出到其他格式时被包不包含，不设定则都包含<br />   &lt;display:setProperty name="export.csv" value="false" /&gt;<br />   决定该种格式能不能在页面中导出<br />&lt;display:table name="test" export="true" id="currentRowObject"&gt;<br />  &lt;display:column property="id" title="ID"/&gt;<br />  &lt;display:column property="email" /&gt;<br />  &lt;display:column property="status" /&gt;<br />  &lt;display:column property="longDescription" media="csv excel xml pdf" title="Not On HTML"/&gt;<br />  &lt;display:column media="csv excel" title="URL" property="url"/&gt;<br />  &lt;display:setProperty name="export.pdf" value="true" /&gt;<br />  &lt;display:setProperty name="export.csv" value="false" /&gt;<br />&lt;/display:table&gt;</p>
		<p>
				<strong>十四、配置属性，覆盖默认<br /></strong>  两种方法：<br />  A、在程序classpath下新建displaytag.properties文件<br />  B、对于单个表格，应用&lt;display:setProperty&gt;标签<br />  具体可配置的属性：<a href="http://displaytag.sourceforge.net/configuration.html">http://displaytag.sourceforge.net/configuration.html</a><br />  <br /><strong>十五、一个完整的例子</strong><br />&lt;display:table name="test" export="true" sort="list" pagesize="8"&gt;<br />  &lt;display:column property="city" title="CITY" group="1" sortable="true"    headerClass="sortable"/&gt;<br />  &lt;display:column property="project" title="PROJECT" group="2" sortable="true" headerClass="sortable"/&gt;<br />  &lt;display:column property="amount" title="HOURS"/&gt;<br />  &lt;display:column property="task" title="TASK"/&gt;<br />&lt;/display:table&gt; <br />   sort="list" 对整个list进行排序<br />   导出数据到其他格式时，group无效</p>
<img src ="http://www.blogjava.net/weibogao/aggbug/56309.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-07-03 13:23 <a href="http://www.blogjava.net/weibogao/archive/2006/07/03/56309.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于ClassName.class.getResourceAsStream的路径问题</title><link>http://www.blogjava.net/weibogao/archive/2006/06/20/54010.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Tue, 20 Jun 2006 08:20:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/06/20/54010.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/54010.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/06/20/54010.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/54010.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/54010.html</trackback:ping><description><![CDATA[
		<h2>
				<a id="viewpost1_TitleUrl" href="http://blog.dream4ever.org/zhangye/articles/104285.drl">关于ClassName.class.getResourceAsStream的路径问题</a>
		</h2>
		<p>对ClassName.class.getResourceAsStream的路径问题比较模糊，现在把研究的结果写一下：</p>
		<p>ClassName是这个Class的名称，这里假设为MyClass，处于MyPackage.MyChildPackage包中，如果你将source.props文件放在Classes文件夹中的时候，可以这样写ClassName.class.getResourceAsStream(/source.props)</p>
		<p>如果你想把props文件放在包中的时候，假设放到MyPackage.MyChildPackage中的res文件夹，可以这样写ClassName.class.getResourceAsStream(/MyPackage/MyChildPackage/res/source.props)，/代表的是包的.</p>
<img src ="http://www.blogjava.net/weibogao/aggbug/54010.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-06-20 16:20 <a href="http://www.blogjava.net/weibogao/archive/2006/06/20/54010.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate中很少用的one-to-one配置注意事项（一对一的本质是一对多的特例）</title><link>http://www.blogjava.net/weibogao/archive/2006/06/19/53800.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Mon, 19 Jun 2006 07:43:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/06/19/53800.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/53800.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/06/19/53800.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/53800.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/53800.html</trackback:ping><description><![CDATA[
		<table class="fixedTable blogpost" cellspacing="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="ellipse">
										<span class="bvTitle" id="subjcns!B3ECA62141FF5FE0!192">
												<strong>hibernate:one-to-one注意事项</strong>
										</span>
								</td>
						</tr>
						<tr>
								<td class="bvh8">
										<strong>
										</strong>
								</td>
						</tr>
						<tr>
								<td id="msgcns!B3ECA62141FF5FE0!192">
										<div>
												<strong>one-to-one</strong>在hibernate中可以用来作为两张表之间的主键关联，这也是hibernate中主键关联的一种用法，这样在一张表中的ID，在生成另外一张表的同时回自动插入到相应的ID字段中去，相应的XML文件设置比较简单，举例如下：<br /><br />    &lt;!-- 建立一对一的到Address的映射，<font color="#ff0000">这个是写在User的XML配置文件中的</font> --&gt;<br />    &lt;!-- <font color="#ff0000">相应的User bean（PO）中也要添加属性 <strong>com.xx.Address </strong> <strong>address</strong></font>--&gt;<br />    <strong><font color="#008000">&lt;one-to-one name="address" cascade="all" class="com.xx.Address"/&gt;<br /></font></strong>   <br />   &lt;!-- cascade的属性设置不再重复了，可以查看hibernate文档 --&gt;<br /><br />    &lt;!-- 建立一对一的到User的映射，<font color="#ff0000">这个是写在Address的XML配置文件中的</font> --&gt;<br />    &lt;!-- <font color="#ff0000">相应的Address bean（PO）中也要添加属性 </font><font color="#ff0000"><strong>com.xx.</strong>User user</font>--&gt; --&gt;<br />    <strong><font color="#008000">&lt;one-to-one name="user" class="com.xx.User" constrained="true"/&gt;<br /></font></strong><br />      为了在Address中使用User中的主键ID值，我们需要设置Address中的主键生成规则，如下所示，采用foreign关键字<br /><br />   <strong><font color="#008000">&lt;id column="ID" name="id" type="long" unsaved-value="0"&gt; <br />      &lt;generator class="foreign"&gt;<br />        &lt;param name="property"&gt;user&lt;/param&gt;  <br />      &lt;/generator&gt;<br />   &lt;/id&gt;<br /></font></strong><br /><br />      <font color="#000000"><strong><em>这里需要注意的是property的属性值必须与上面到User的映射所填写的name属性值一致</em></strong></font>，这样就完成了one-to-one的映射关系。<br /><br />上面的过程都很简单，下面我来说说这里需要注意的地方：<br /><br />  1.   <strong>在设置属性ID的时候必须注意字段的长度，如笔者这样使用oracle的sequence来生成ID，其长度有14位之长，则应选择hibernate类型long，对应的实体中应选择Long，这样不会出现溢出的情况。</strong><br /><br /><br />  2.   在测试的时候必须要注意这两张表之间因为已经存在了一对一的关系，所以我们不能只写<br />         <font color="#008000">user.setAddress(address);<br /></font>         而忽略了<br />         <font color="#008000">address.setUser(user);<br /></font>         这样在做插入的时候会报出attempted to assign id from null one-to-one property: address的错误，这一点初学者会经常犯，笔者也是其中之一。<br /><br /><br /> 3.   如果不写cascade="all"或者写成cascade="none"的话，即使你写了<br />         <font color="#008000">user.setAddress(address);<br />         address.setUser(user);<br /></font>       也不会发生任何事情，只有user会被存储。</div>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/weibogao/aggbug/53800.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-06-19 15:43 <a href="http://www.blogjava.net/weibogao/archive/2006/06/19/53800.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之食堂版</title><link>http://www.blogjava.net/weibogao/archive/2006/05/29/48728.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Mon, 29 May 2006 05:09:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/05/29/48728.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/48728.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/05/29/48728.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/48728.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/48728.html</trackback:ping><description><![CDATA[
		<div class="tbox">转贴: <br /><br />设计模式是美国一位建筑大师（同时也是信息工程师，画家，机械工程师…的）克里斯蒂安.亚历山大首先提出来的，很快被软件界的技术员们所接受推广，成为软件工程里至高无上的法则之一（有兴趣的人可以找他的《建筑的永恒之道》一书看看，相信会受益非浅）。简单地说就是在面对对象的基础上，包括面对对象，把要设计的整体的各个部分模式化，层次化，细粒度化，高度复用化，可控化，人性化。其中至高无上的原则是建立在需求的基础之上，也就是说，无论做什么，人的需求要放在第一位考虑，从这个角度考虑整个系统是否足够合理。这门学问是非常有趣的，尤其在flash中，可以应用到很多很好玩的实例中去。下面我按照一些通用的设计模式，举例说明，有错误的地方，敬请高手指正：<br /><br />1．抽象工厂模式（Abstract Factory）：<br /><br />食堂里吃的东西很多，而我只想吃一样，那么食堂这个概念对我来说就是个抽象工厂，每个窗口可以看成它的一个具体实现，我要做的就是，去食堂，找到那个窗口，从窗口里买我要吃的东西。<br /><br />举例：flash前台与asp后台的交互，访问某个动态页面，从数据库里取出需要的数据，通常的做法是在后台就把数据集解析成xml字符串，再送给swf。每个业务逻辑模块，所取出的数据结构，也就是xml的结构是不一样的，我们要针对各个具体的业务逻辑，对相应的xml字符串解析，转换成可供显示的数组。也要把flash里文本输入的内容转换成 xml字符串，提交给后台也面<br /><br />AbstractFactory.as<br />//抽象工厂的接口<br />Interface AbstractFactory{<br />//生成xml解析工厂的具体实现<br />function createXmlParseFactory();<br />}<br /><br />XMLParserGetFactory.as<br />//生成解析读入的xml的对象的工厂<br />class XMLParserGetFactory implements AbstractFactory.{<br />var xmlParser;<br />function XMLParserGetFactory(str:String){<br />//生成解析器的具体实现，在后面会提到<br />}<br />function createXmlParser(){<br />return xmlParser;<br />}<br />}<br />XMLParserPostFactory.as<br />//生成解析输出的xml的对象的工厂<br />class XMLParserPostFactory implements AbstractFactory.{<br />var xmlParser;<br />function XMLParserPostFactory(str:String){<br />//生成解析器的具体实现<br />}<br />function createXmlParser(){<br />return xmlParser;<br />}<br />}<br /><br />这样，我们读入某个xml字符串时，在onLoad里面加入<br />//生成对留言板的留言列表解析的工厂<br />var xmlParser=new XMLParserGetFactory(“xmlParseGuestbookList”)<br />xmlParser= XMLParserGetFactory. createXmlParser()<br /><br />备注：抽象工厂模式是软件工程里最常用的设计模式之一，实现过程在于，需要某个类的实例时，通过某个工厂创建，而不是直接创建，坦白地说，它加大了开发工作量，但是对程序的层次性变得分明和降低耦合度有极大帮助。<br /><br /><br />2．生成器模式（builder）：<br /><br />还是那个说法，我要吃东西就去相应的食堂窗口，但我不能吃食堂窗口，窗口里的东西也许不少，我要跟师傅说，要这个，这个，还有这个。<br /><br />举例：我已经建立了 xml解析器的工厂，现在要返回解析器本身，就让工厂创建，返回给我。<br /><br />XMLParserGetFactory.as<br />//生成解析读入的xml的对象的工厂<br />class XMLParserGetFactory implements AbstractFactory.{<br />var xmlParser;<br />function XMLParserGetFactory(str:String){<br />//如果要求留言板列表解析器，就生成一个<br />if(str==” xmlParseGuestbookList”){<br />xmlParser=new xmlParserGuestbookList();<br />}<br />}<br />function createXmlParser(){<br />//返回所要求的解析器<br />return xmlParser;<br />}<br />}<br /><br />AbstractXmlParser.as<br />//抽象xml解析器<br />Interface AbstractXmlParser{<br />function ParseXml();<br />}<br />xmlParserGuestBookList.as<br />//留言板列表解析器<br />Class xmlParserGuestBookList implements AbstractXmlParser{<br />//把xml字符串里的内容解析到一堆数组里<br />function ParseXml(xml:XML,arrayID:Array,arrayTitle:Array){<br />//具体循环操作<br />}<br />}<br /><br />使用的时候：<br />var xmlParser=new XMLParserGetFactory(“xmlParseGuestbookList”)<br />xmlParser= XMLParserGetFactory. createXmlParser(xml,arrayID,arrayTitle);<br /><br />3．工厂方法模式（Factory Method）<br />我到了食堂窗口，如果师傅跟那儿抽烟，我还是吃不着东西。我说：师傅，打饭！师傅才会完成打饭这一动作。这是工厂方法模式，抽象工厂的实现通常用工厂方法模式来完成。<br /><br />举例：还是上一条，我本来想用一句话带一个参数就实现具体xml解析器的实现，无奈构造函数没有返回值，所以必须用<br />xmlParser= XMLParserGetFactory. createXmlParser(xml,arrayID,arrayTitle);<br />实现。<br /><br />备注：抽象工厂模式，生成器模式和工厂方法模式需要灵活应用。<br /><br /><br />4．单件模式（singleton）<br /><br />我前面一个人买了一条巨大的鸡腿，我说我也要一条，师傅说，就这一条<br /><br />举例：单件模式的应用是相当广泛的，它确保每个实例在全局范围内只被创建一次，我们flash里的mc大多数是单件。内核里的核心组件也只是单件，比如我的消息映射列表（见后）。<br />按照单件模式的严格定义，应该让类负责保存它的唯一实例。但是我在Flash里还想不到怎么实现这一点，或者实现它的意义所在，但另外一点我们可以做到，就是在全局范围内只提供该对象的唯一访问点。这可以由层次关系做到，把对该对象的访问具体实现全部封装在下层，只给上层提供唯一的访问点（原因是，上层不知道这个单件的具体信息，比如路径）。<br />看我内核文件的一部分：<br />Core.as<br />//内核<br />class Core {<br />var strucGlobalParam:ConfigVariables;<br />//站点信息<br />var xmlConfig:XML;<br />//站点信息的xml化对象<br />var ArrayStructureInitial:Array;<br />//用来提供给loadObject对象的数组<br />var ArrayForBtn:Array;<br />//用来初始化导航条组件的数组<br />var objInitial:loadObject;<br />//读取影片的对象<br />var objMessageMap:MessageMap;<br />//消息映射组件<br />……<br />}<br />这是我的内核类也就是全站最核心类的数据结构。里面的数据只有通过下层的BasicMovie，OriginalFunctionObject等类（见后）直接访问。<br /><br />备注，核心思想是，确保只有一个。<br /><br /><br />5．原型模式（protoType）<br /><br />到小炒窗口，看前面的哥们炒的青椒炒肉不错的样子。“师傅，我也要这样的。”<br /><br />举例：这对flash的用户来说再熟悉不过了，我们经常用duplicateMovieClip()和<br />attachMovie()这两个函数。按照一个原型复制相应的实例，各自执行自己的动作。在我的blog列表，导航条的生成。。几乎用得到多项数据的地方就要用原型模式。<br /><br />6.责任链模式，7.中介者模式，8.观察者模式：<br /><br />食堂里厨房最远的窗口没熬白菜了，要告诉厨房，快送过来。<br />责任链模式：一个窗口一个窗口地传话，一直传到食堂，食堂一看不妙，赶快做好送过去。<br />中介者模式：专门派一个人负责传话，任何窗口没菜了，就要这个人赶快去厨房催。<br />观察者模式：厨房那边派一个盯着，看哪个窗口没菜了就开始大声嚷嚷。<br /><br />举例：之所以要把这三个设计模式放在一块儿，是因为我在我的站里面结合这三者建立了一个好玩的东西，可以说是我的网站的核心所在。它解决了我的flash里面各个mc的通信问题。<br />比如，影片A放完了，要通知影片B开始播放，直接的做法是在A的最后一帧，写从A到B的相对路径或B的绝对路径，让B play()。这样做A和B的耦合性是相当高的，也就是说，相互依赖程度太高。运用设计模式的解决方案如下：<br /><br />MessageMap.as<br />//消息映射类<br />class MessageMap extends Object {<br />var Message:String;<br />var MessageWatcher:Function;<br />var Target;<br />var MessageList:Array;<br />var Num_Msg:Number;<br />function MessageMap() {<br />Num_Msg = 0;<br />MessageList = new Array();<br />Message = "HANG_UP";<br />MessageWatcher = function (prop, oldVar, newVar, Param) {<br />for (var i = 0; i<num_msg+1; i++)="" {<br="">if (newVar == MessageList[i][0]) {<br />MessageList[i][1].apply(MessageList[i][3], MessageList[i][2]);<br />if (!MessageList[i][4]) {<br />MessageList.splice(i, 1);<br />Num_Msg--;<br />i-=1;<br />}<br />}<br />}<br /><br />};<br />this.watch("Message", MessageWatcher, "test");<br />}<br />function SendMessage(Msg:String, mc:MovieClip) {<br />Message = Msg;<br />}<br />function UpdateMessageMap(Msg:String, objFunction:Function, ArrayParam:Array, objRefer,IsMultiUsed:Boolean) {<br />MessageList[Num_Msg] = new Array();<br />MessageList[Num_Msg][0] = new String();<br />MessageList[Num_Msg][0] = Msg;<br />MessageList[Num_Msg][1] = new Function();<br />MessageList[Num_Msg][1] = objFunction;<br />MessageList[Num_Msg][2] = new Array();<br />MessageList[Num_Msg][2] = ArrayParam;<br />MessageList[Num_Msg][3] = objRefer;<br />MessageList[Num_Msg][4] = IsMultiUsed;<br />Num_Msg++;<br />}<br />function DeleteMessageMap(objRefer) {<br />for (var i = 0; i<num_msg; i++)="" {<br="">if (MessageList[i][2] == objRefer) {<br />MessageList.splice(i, 1);<br />Num_Msg--;<br />}<br />}<br />}<br />}<br /><br />class SubTemplateMovie extends BaseMovie {<br />var MovieRemoveFunction:Function;<br />function SubTemplateMovie() {<br />this.stop();<br />MovieStartFunction = function () {<br />Lock();<br />this.play();<br />};<br />MovieEndFunction = function () {<br />Lock();<br />this.play();<br />};<br /><br />MovieRemoveFunction = function () {<br />this.stop();<br />SendMsg("SUB_TEMPLATE_REMOVED", this);<br />_parent.unloadMovie();<br />};<br />MovieMainFunction = function () {<br />stop();<br />SendMsg("SUB_TEMPLATE_OPEN", this);<br />};<br />UpdateMessage("LOADING_BAR_OVER", MovieStartFunction, null, this, false);<br />UpdateMessage("BACK_TO_INDEX", MovieEndFunction, null, this, false);<br />}<br />}<br /><br />大概机制就是，影片提前提交一个数据结构，声明，如果有影片提交这条消息，就执行这条函数。原理在于，发送消息，实际上是把消息映射的一个变量赋值，由于消息映射继承自object类，可以用watch方法对该变量进行监视，一旦改变，在已经提交上来的消息映射列表里检查，如果有，执行对应函数。实际上这也造成了一定程度的耦合性，但是我们已经成功地把耦合性控制在了下级类，上级子类完全不用理会这一套消息机制的实现过程。<br /><br />这个机制可以让我们对oop的真正目的有更深的看法。举例说明，影片A播放完了，就声明自己播放完了，至于我播完了你要干什么，不是我的事，我不控制你。所谓的降低耦合度是个相对概念，别忘了在计算机最底层，耦合度还是一样，cpu总是不断的直接或间接寻址，但我们需要做的是，改变系统的拓扑结构，把耦合度控制在某一个范围之内。<br /><br />整个消息映射类相当于一个中介者，内部生成一个观察器，一旦触发消息，以责任链的方式执行。<br /><br /><br />9.桥接模式（Bridge）<br /><br />菜太淡，不合有些人的胃口，所以要求食堂的师傅，专门开一个窗口，专门在做好的菜里多加些辣椒。<br /><br />我在自己的站里运用了桥接模式：所有的影片都继承自我定义的BasicMovie 类（BasicMovie继承自MovieClip类），但是在四个下级栏目的影片里，需要定义相同的方法和事件来响应消息，BasicMovie没有这些函数，不符合要求，这时候，在四个影片里都写一遍是愚蠢的，我又写了一个SubTemplateMovie类继承自BaseMovie，里面加进一些通用的方法，然后四个下级模板影片都继承它，这样大大简化了后期开发。<br /><br />BasicMovie.as<br />//基类影片<br />/所有影片的原始类，一切影片的父类都继承此类而来<br />class BaseMovie extends MovieClip {<br />var isLocked:Boolean;<br />//初始类开始影片函数<br />var MovieStartFunction:Function;<br />//初始类影片主功能函数<br />var MovieMainFunction:Function;<br />//初始类结束影片函数<br />var MovieEndFunction:Function;<br />var GlobalParam<br />//初始类构造函数<br />function BaseMovie() {<br />}<br />//<br /><br />//发送消息<br />function SendMsg(Msg:String, Mc:MovieClip) {<br />_root.objCore.objMessageMap.SendMessage(Msg, Mc);<br />}<br />//添加消息映射<br />function UpdateMessage(Msg:String, MsgMapFunction:Function, ArrayParam, obj, IsMultiUsed) {<br />_root.objCore.objMessageMap.UpdateMessageMap(Msg, MsgMapFunction, ArrayParam, obj, IsMultiUsed);<br />}<br />//删除消息映射<br />function DeleteMessage(obj) {<br />_root.objCore.objMessageMap.DeleteMessageMap(obj);<br />}<br />function GetGlobalParam() {<br />GlobalParam=_root.objCore.strucGlobalParam;<br />}<br />}<br /><br />SubTemplateMovie.as<br />//下级模板影片类<br />class SubTemplateMovie extends BaseMovie {<br />var MovieRemoveFunction:Function;<br />function SubTemplateMovie() {<br />this.stop();<br />MovieStartFunction = function () {<br />Lock();<br />this.play();<br />};<br />MovieEndFunction = function () {<br />Lock();<br />this.play();<br />};<br /><br />MovieRemoveFunction = function () {<br />this.stop();<br />SendMsg("SUB_TEMPLATE_REMOVED", this);<br />_parent.unloadMovie();<br />};<br />MovieMainFunction = function () {<br />stop();<br />SendMsg("SUB_TEMPLATE_OPEN", this);<br />};<br />UpdateMessage("LOADING_BAR_OVER", MovieStartFunction, null, this, false);<br />UpdateMessage("BACK_TO_INDEX", MovieEndFunction, null, this, false);<br />}<br />}<br />注（关于消息映射机制看 责任链模式）<br /><br /><br />10.适配器模式（Adapter）<br /><br />我要一碗汤，但是只有纸饭盒，还没勺，所以食堂的师傅给了我一次性的汤碗和勺，这叫适配器。<br /><br />适配器解决的是某一个类的对外接口不合用的问题，可能是参数或者返回值类型不符等问题造成的，这时候我们需要在工作对象和这个类之间加一层间接的层次。<br />这个模式我在底层的数据交换层用过。我说过，flash和asp.net之间交换数据全以xml为载体。返回xml在底层只有三层，数据库操作，数据操作，数据显示，由数据操作层返回给数据显示层一个xml字符串就可以了。然后我就遇到一个小问题，在另一方面，我需要提交数据到数据库，也是提交一个xml字符串，但是我需要数据库里对应的表的数据集的xml表现形式的xsd验证！（一口气说完，差点没憋死）。就是说我至少需要取出这个表里的一条记录，问题在于，我封装的类从来只返回xml，没有返回xsd的。解决办法就是适配器，新建一个项目，加了一层专用于获得xml验证格式，这样就完成了不同接口之间的转换。<br /><br />备注：适配器和桥接很象，都是在已有类不符合要求的时候，加入一层间接的元素以达到目的。不同的是适配器是解决不兼容接口之间的转换，桥接一般不涉及这个问题，只是完成一个一对多的转换。<br /><br /><br />11.外观模式（Facade）<br /><br />每天都要去食堂，每个人去不同的窗口吃不同的菜，很累，今天全寝室推举猴子去打饭：<br />你吃这个，三两饭，我吃那个，五两饭，所有人都只跟猴子一个人交涉，食堂所有的师傅也只见猴子一个人。<br /><br />举例：这个模式在程序的上下层的通信之间可以应用得十分广泛。Asp的每个模块要去不同的数据，访问数据库的不同表，就要跟不同的下层数据访问组件打交道。就是说，每个mc模块必须知道，我要去哪个具体的数据访问组件取数据。每个模块要维持自己的一个，至少是字符串。<br />如果运用外观模式。我们可以让所有的需要数据交互的mc访问同一个aspx页面，比如getStrXml.aspx。只要传送一个标示符，就可以通知这个唯一的取数据的叶面，访问哪个下层组件获取数据。下层组件不知道哪个mc要求数据，mc也不知道数据的具体来源，这样，上下层之间互相都显得不透明。这就降低了耦合度。<br /><br /><br />12.代理模式（Proxy）<br /><br />可能我们不是每个人每天都想吃饭，所以我们要求猴子每天中午必须在寝室，如果我们要吃，他就去，如果我们都不吃，他爱干嘛干嘛。<br /><br />举例：这恐怕是每个人在flash里都会无意中用到的模式。比如，一个网站，它的下级栏目不用在整个网站初始化的时候一开始就读进来，但是我们要确保，在浏览者想看并且点击导航条上的某个按钮时，能够正确地读进相应的影片文件，前提是，我们必须在内部保留一个索引，可以称作代理。通常是一个空mc<br /><br /><br />13.策略模式：（strategy）<br /><br />我每天先在食堂找座位，再打饭，再打菜，再买杯酸奶。这已经模式化。要是食堂有服务员，我也会要他这么做。<br /><br />举例，策略模式是把一系列的算法封装起来，形成一个类。这个模式几乎是随时随地都可以整合到别的模式里去的，我的那一堆xml解析器实际上就是策略模式的应用，这个模式还应用到我网站的下层，因为flash提交给aspx页面的数据也是xml字符串，下层模块也需要相应的解析算法。同样的，我把对xml的解析封装进了一个类。<br /><br />//Cs文件里的解析函数<br /><br />Class DataModel.BlogMsgs{<br />…<br />Public DataSet parseXML(string strXml){<br />DataSet ds=new DataSet(); <br />//。。把xml装载到DataSet 里<br />Return ds<br />}<br />…<br />}<br /><br /><br />14.享元模式（Flyweight）<br /><br />东西不够吃？给你摆20面镜子~<br />师傅，东西还是只有一份。。。<br /><br />关于这个模式十分抱歉，我暂时还没想到在flash显示层里面的实现。需要举例说明的是，浏览器的机制是，在有大量文字的英文文档里，相同的字母共享一个Flyweight，在内存里其实只占一份空间，然后在文档不同的地方显示，这样对于大量细粒度的效果来说，可以节省很多资源。在下层，我们可以做到的就是，对某个全局对象只在某处真正保存，任何对象想要这个全局对象，只引用它而不复制它。<br /><br />在显示层里有哪位想到了该怎么做请一定赐教。<br /><br /><br />15.访问者模式（Visitor）<br /><br />只要愿意，我随时都可以跑到哪个窗口打要吃的东西，前提是，我必须跑这一趟。<br /><br />举例：我说过，我的所有mc都继承自BasicMovie这个类，但不是我的所有mc都要从后来获取数据库数据。获取数据库数据所要访问的信息，比如ip，路径，文件保存在配置文件里，初始化的时候读入内核，并且只有内核那里有一份。在BasicMovie里加入对这些全局变量的引用是不合适的，因为只有少数mc要用到，而且由于某些原因我无法再使用桥接模式（我已经有了SubTemplateMovie，不能多继承），所以我用了访问者模式。<br /><br />BasicMovie.as<br /><br />//获取全局变量<br />function GetGlobalParam() {<br />GlobalParam=_root.objCore.strucGlobalParam;<br />}<br /><br />如果上级mc不执行这个函数，是不能获取全局变量的，如果要用，就执行。<br />也就是说，需要的时候，我去访问它。<br /><br />备注：声明一个visit操作，使得访问者可以正确访问需要的类。<br /><br /><br />16.状态模式（state）<br /><br />我今天想吃面，师傅问我：要什么料？西红柿鸡蛋，排骨还是牛肉？<br /><br />举例：状态模式是指将对象当前的某些状态局部化，当对象改变状态时，看起来好像改变了类。例子还是我的滚动条。如果要滚动的是文本框，就要引用一个TextField的Scroll,maxscroll属性，如果是mc，引用的是_y,_height属性，我用一个参数将二者区分，由一个if语句控制，让滚动条可以自由区别状态。<br />另外一个解决方案是定义ScrollBar的不同子类，这两者本质区别不大，在状态比较多时，可能要维持一个庞大的if算法，这样就用生成子类的方法比较好。<br /><br />ScrollBar.as<br />//滚动条组件<br />function BindTo(mc,type:String,intMcHeight:Number,yinitial:Number){<br />ScrollType=type;<br />if(type=="TXT"){<br />scrollTxt=mc;<br />}<br />if(type=="MC"){<br />initialY=yinitial;<br />McHeight=intMcHeight;<br />scrollMc=mc;<br />} <br />}<br />function Scroll() {<br />if(ScrollType=="TXT")<br />this.onEnterFrame = function() {<br />scrollTxt.scroll = scrollTxt.maxscroll*mcBlock._y/(BgLength-BlockLength*3/2)<br />};<br />if(ScrollType=="MC"){<br />this.onEnterFrame=function(){<br />if(scrollMc._height&gt;McHeight){<br />scrollMc._y=initialY-(scrollMc._height-McHeight)*mcBlock._y/(BgLength-BlockLength*3/2)}<br />}<br />}<br />}<br /><br />备注：这也是常见模式，在flash的逻辑控制里尤其随处可见<br /><br /><br />17.装饰模式（Decorator）<br /><br />在食堂吃饭，没筷子怎么行？我是从来不带饭盆的。师傅很人性化，每个窗口都放着一大把筷子，随用随拿。<br /><br />这个模式如果用好，有的地方可以很省力。比如，我网站里的滚动条：<br /><br />ScrollBar.as<br />//滚动条组件<br />class ScrollBar extends BaseMovie {<br />var BgLength:Number;<br />var BlockLength:Number;<br />var mcBlock:MovieClip<br />var Width:Number;<br />var ScrollType;<br />var scrollTxt:TextField;<br />var scrollMc:MovieClip;<br />var McHeight:Number<br />var initialY:Number<br />function ScrollBar() {<br />}<br />function InitialScrollBar(BgLength, BlockLength) {<br />this.BlockLength = BlockLength;<br />this.BgLength = BgLength;<br />}<br />function BindTo(mc,type:String,intMcHeight:Number,yinitial:Number){<br />ScrollType=type;<br />if(type=="TXT"){<br />scrollTxt=mc;<br />}<br />if(type=="MC"){<br />initialY=yinitial;<br />McHeight=intMcHeight;<br />scrollMc=mc;<br />} <br />}<br />function Scroll() {<br />if(ScrollType=="TXT")<br />this.onEnterFrame = function() {<br />scrollTxt.scroll = scrollTxt.maxscroll*mcBlock._y/(BgLength-BlockLength*3/2)<br />};<br />if(ScrollType=="MC"){<br />this.onEnterFrame=function(){<br />if(scrollMc._height&gt;McHeight){<br />scrollMc._y=initialY-(scrollMc._height-McHeight)*mcBlock._y/(BgLength-BlockLength*3/2)}<br />}<br />}<br />}<br />function ScrollMc() {<br /><br />}<br />function StopScroll() {<br />this.onEnterFrame=null;<br />}<br />function Reset(){<br />mcBlock._y=0;<br />}<br />}<br /><br />核心函数是BindTo（），把这个滚动条的实例绑定到某个动态文本框或者某个mc上，就可以实现滚动。<br /><br />备注：装饰模式的思想是，在不影响其他对象的情况下，以动态，透明的方式给单个对象添加职责。<br /><br /><br />18.组合模式（composite）<br /><br />我中午吃六两饭，猪肉炖粉条，辣子鸡，鱼丸，咸鸭蛋，外加两杯酸奶（猪！）<br />这些东西都是对象，他们共同组成了我的午饭。<br /><br />举例：应该说在Flash里组合模式是无处不在的，因为只要还有mc的嵌套，就有组合模式存在。几个mc装在一个mc里，这个装载用的mc称作容器。<br />但是就这么说，恐怕没人会重视这个模式，因为不管理不理解他我们都在用。他的确有很多种实现方式，我的方式之一是这样的。<br /><br />//blog.as<br />我的Blog<br />class Blog extends BaseMovie {<br />//blog第一界面，包括日记列表，日历，最近留言<br />var mcBlogList: mcBlogList;<br />//blog第二界面，包括日记全文，回复，对该日记的留言。<br />var mcBlogDairy:MovieClip;<br />var currentState:String;<br />var currentDairyID:Number;<br />function blog(){<br />} <br />}<br /><br />mcBlogList.as<br />//blog第一界面<br />class mcBlogList extends BaseMovie {<br />//最近留言<br />var recentMsgs:blogMsgsSC;<br />//日记列表<br />var blogList:BlogList;<br />//日历<br />var calendar:CalenderForBlog;<br /><br />｝<br />mcblogDairy.as<br />//blog第二界面<br />class mcBlogDairy extends BaseMovie {<br />//日记全文显示<br />var BlogDairy:BlogDairy;<br />//留言板<br />var GuestBook:BlogInputMsg;<br />//留言列表显示<br />var BlogMsgs:BlogMsgs;<br />}<br /><br />然后里面每个组件都还包含另外的组件，比如滚动条，动态文本框什么的，我想说的是，我写在as里的mc嵌套模式并不一定就符合fla文件里的具体物理嵌套模式，有很多装饰性的mc不需要包含进来，也有很多具体原因，需要改写路径。比如在BlogDairy下，滚动条的实际路径是BlogDairy.mc1.ScrollBar，不做成BlogDairy.ScrollBar可能是因为我需要mc1的动画，也可能是别的具体原因。但是我们可以在mc1的时间轴上加一句<br />_parent. ScrollBar =This.ScrollBar<br />把路径指向改写，达到我们要使用的模式，ScrollBar就是BlogDairy的直接成员。另外我没有语句初始化mc，我习惯在库里设置mc的linkage。<br /><br />备注：虽然组合模式是每个人必不可少要用的，但正因为如此，我们可以想出他更多更好更灵活的实现方式<br /><br /><br />19.备忘录模式（memento）<br /><br />～师傅，晚上的鸡腿没中午的新鲜啊。<br />～胡说！这就是中午的。<br /><br />举例：开个玩笑，上面两句话不是备忘录模式的本意，实际上我一时想不出在食堂里备忘录是什么样子。备忘录的意思是，在不破坏对象封装型的前提下，保存对象的当前状态，当需要时，恢复这个状态或提取这个状态。<br /><br />备忘录被广泛地运用到逻辑关系里，它似乎是目前我提到的唯一跟时间有关的模式，在控制论里可以涉及到因果系统。备忘录的应用非常广泛，最常见的是浏览器或网站的后退功能，返回到上一个界面，但是在我的站里没有用到，因为我的站是树状拓扑结构，每个栏目都只能唯一地从主界面进入或退回到主界面，那些网状拓扑结构的站点，每个栏目都可以通向其他的任何栏目，很可能就需要这么一个功能，其实现方法往往是维持一个堆栈型的数组。<br /><br />另外一个我想实现的东西是网站内部自动记录，由于某些原因我暂时没有把它加到网站里。很简单，就是监视浏览者的每一步操作，在哪个栏目，停了多久，做了些什么之类，如果离开了，下次访问网站时让他选择是否直接进入上次浏览的界面（比如他上次在看我写的小说而没看完）。这个可以通过sharedObject实现，差不多也就是flash内部的cookie。<br /><br />备注：备忘录的实现要求还是很高的，在提取对象状态的时候不要破坏对象的封装性。理想的备忘录作为一个对象需要两个借口，一个给管理者，它不知道备忘录里封装了什么状态，只负责地把状态移交给需要的对象，一个留给原发者，原发者只能了解并操作备忘录里封装的状态，不能做别的操作。<br /><br /><br />小结： <br /><br />小结：我会随时补充这篇文章。但是我要举的一些例子暂时已经说完了。其实设计模式远远不止这几种，经典的有２３种，我已知的有４１种，而这里只有１９种，还有命令模式，解释器模式，迭代器模式，模板方法模式我没写到。我的站还用了一些我没有提到的，自己都还没细想过的设计模式。但是一一列举其实是意义不大的，有兴趣的同志们要做的就是接触一下这些设计模式的细节和思想，然后统统忘掉，就和张无忌学太极拳，先学后忘是一样的。招式要看，要学，但是要领会其中的深意，灵活地，创造地，相互结合，融会贯通地使用招式，不能拘泥于招式，更不能为了用招而用招。设计模式作为UML的重要组成部分，能够极大程度地促进我们的开发效率，使我们养成好的书写习惯，做出更人性，更和谐，更清晰，复用性和可控性更高的作品。<br />不要说你不是程序员，就可以跟着感觉走，随心所欲，当然我们无权干涉。我也说了，as本来就是想怎么写就怎么写，但接不接触，学不学习先进的思维模式，这也是你的自由。更不要说你是搞艺术的，头脑偏重感性，不适合接触这些，我之所以要顺带拿食堂举例，是想说明，我要说的其实是就Christian Alexander先生的，建筑的永恒之道，无论是建筑本身，还是任何软件工程，或者Flash 的as，甚至Flash 的矢量绘图，美工，平面设计，一直到世界这一整体，无不是遵循一个结构化的，由模式构成的永恒之道，有着惊人的高度相通和相似性。参悟了这一点，不仅对做Flash，对整个生活都会有新的看法。区别仅仅在于，从哪里开始入手思考，在这里，可以从Flash开始。</num_msg;></num_msg+1;></div>
<img src ="http://www.blogjava.net/weibogao/aggbug/48728.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-05-29 13:09 <a href="http://www.blogjava.net/weibogao/archive/2006/05/29/48728.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java2 RMI 入门</title><link>http://www.blogjava.net/weibogao/archive/2006/05/26/48384.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Fri, 26 May 2006 09:16:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/05/26/48384.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/48384.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/05/26/48384.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/48384.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/48384.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td class="down" align="middle" height="40">
										<strong>
												<font style="FONT-SIZE: 14px">Java2 RMI 入门</font>
										</strong>
								</td>
						</tr>
						<tr>
								<td align="middle" height="22">日 期：2004-12-30 14:36:22  出 处：原创  作 者：admin  阅 读：<font color="#990000">128</font>次</td>
						</tr>
						<tr>
								<td> </td>
						</tr>
						<tr>
								<td>
										<table cellspacing="0" cellpadding="0" width="95%" align="center" border="0">
												<tbody>
														<tr>
																<td class="thin" style="FONT-SIZE: 14px">RMI从Java1.1开始，RMI使得运行于不同JVM(包括不同主机)上的Java应用程序可以彼此通话。 <br />即：一个JVM中的Java应用程序可以调用另一JVM上的对象（远程对象）所定义的方法。 <br />Java RMI有着重要的意义。RMI在Java网络编程和高级编程中都有重要的应用，如EJB, Jini等。 <br />Java2对RMI做了很多增强和改进，如安全性，动态代码下载等。 <br />本文给出了一个最简单的例子，以说明其中的一些基本原理。本文的特点是注重了实际开发和真正的运行 <br />环境相结合，模拟了RMI真正的开发和运行过程。 <br /><br />1. 实现远程接口，生成远程对象，存根（Stub）和框架(Skeleton) <br /><br />实现远程接口,远程接口告诉JVM：实现了该接口的对象可以远程调用及有哪些方法可以调用。 <br />本例子中定义了sayHello（）。由于远程调用会涉及到网络通讯，因此这些方法都要抛出RemoteException. <br />远程接口和远程对象可以由A开发，并把远程接口(Hello)d打包分给Client端开发者B。 <br /><br />建立f:\server目录，把Hello.java和HelloImpl.java拷贝到该目录中。 <br /><br />// Hello.java <br />package jdeveloper.rmi; <br /><br />import java.rmi.Remote; <br />import java.rmi.RemoteException; <br /><br />public interface Hello extends Remote { <br />String sayHello() throws RemoteException; <br />} <br /><br />生成远程对象. <br />// HelloImpl.java <br />package jdeveloper.rmi; <br /><br />import java.rmi.Naming; <br />import java.rmi.RemoteException; <br />import java.rmi.RMISecurityManager; <br />import java.rmi.server.UnicastRemoteObject; <br /><br />public class HelloImpl extends UnicastRemoteObject <br />implements Hello { <br /><br />public HelloImpl() throws RemoteException { <br />super(); <br />} <br /><br />public String sayHello() { <br />return "Hello World!"; <br />} <br /><br />public static void main(String args[]) { <br /><br />// Create and install a security manager <br />if (System.getSecurityManager() == null) { <br />System.setSecurityManager(new RMISecurityManager()); <br />} <br />try { <br />Hello obj = new HelloImpl(); <br />// Bind this object instance to the name "HelloServer" <br />Naming.rebind("HelloServer", obj); <br />System.out.println("HelloServer bound in registry"); <br />} catch (Exception e) { <br />System.out.println("HelloImpl err: " + e.getMessage()); <br />e.printStackTrace(); <br />} <br />} <br />} <br />存根（Stub）和框架(Skeleton) <br />f: <br />cd \server <br />javac -d . Hello.java <br />javac -d . HelloImpl.java <br />rmic -d . jdeveloper.rmi.HelloImpl <br /><br />jar cvf hello.jar jdeveloper\rmi\Hello.class 把hello.jar分发给Client端的开发者B。 <br /><br />存根（Stub）的存放！ <br />存根（Stub）是动态下载的。Client通过存根（Stub）和远程对象的框架(Skeleton)通讯，对Client来 <br />讲就象操作本地对象一样。在大多数情况下，可下载的代码放到http服务器的某个目录中。本例子放到http://hjc/rmi下。 <br />hjc:机器名，rmi:http的一个目录。如果只是单机测试则可以放到某个目录下 如f:\serverclasses. <br />本文将对以上两种方法都给出运行的步骤（policy文件和bat文件）。 <br /><br />2. 实现Client端程序 <br />// HelloClient.java <br />package jdeveloper.rmi; <br />import java.rmi.RMISecurityManager; <br />import java.rmi.Naming; <br />import java.rmi.RemoteException; <br />import java.rmi.NotBoundException; <br /><br />public class HelloClient { <br />public static void main(String args[]) throws Exception{ <br />System.setSecurityManager(new RMISecurityManager()); <br />Hello RemoteObj = (Hello)Naming.lookup("//"+ args[0] +"/HelloServer"); <br />System.out.println(RemoteObj.sayHello()); <br />} <br />} <br /><br />建立f:\client目录，把HelloClient.java拷贝到该目录中。 <br />建立f:\clientclasses目录，把hello.jar拷贝到该目录中。 <br />f: <br />cd \client <br />javac -classpath %CLASSPATH%;f:\clientclasses\hello.jar -d . HelloClient.java <br /><br />3. 运行程序 <br />启动DOS窗口 <br />set classpath= <br />start rmiregistry <br /><br />A.以单机方式运行 <br />建立f:\serverclasses\jdeveloper\rmi目录 <br />f: <br />cd f:\serverclasses <br />copy f:\server\hello.jar . <br />copy f:\server\jdeveloper\rmi\HelloImpl_Stub.class f:\serverclasses\jdeveloper\rmi\ <br />jar xvf hello.jar <br /><br />启动新的DOS窗口 <br />把 starthelloserver.bat 和 rmiserver.policy 放到f:\server\ <br />运行 starthelloserver <br /><br />starthelloserver.bat <br />SET CP=f:\server;f:\serverclasses\hello.jar <br />echo using classpath: %CP% <br />java -classpath %CP% -Djava.rmi.server.codebase=file:/f:\serverclasses/ <br />-Djava.rmi.server.hostname=hjc -Djava.security.policy=rmiserver.policy jdeveloper.rmi.HelloImpl <br /><br />rmiserver.policy <br />grant { <br />permission java.net.SocketPermission "*:1024-65535", <br />"connect"; <br />}; <br /><br />启动新的DOS窗口 <br />把 starthelloclient.bat 和 rmiclient.policy 放到f:\client\ <br />运行 starthelloclient <br /><br />starthelloclient.bat <br />@echo off <br />set CP=f:\client;f:\clientclasses\hello.jar <br />echo using classpath %CP% <br />@echo on <br />java -classpath %CP% -Djava.rmi.server.codebase=file:/f:\serverclasses/ <br />-Djava.security.policy=rmiclient.policy jdeveloper.rmi.HelloClient %1 <br />rmiclient.policy <br />grant { <br />permission java.net.SocketPermission "*:1024-65535", <br />"connect"; <br />permission java.io.FilePermission <br />"f:\\serverclasses\\-", "read"; <br />}; <br /><br />B.以网络方式运行 <br />建立 apache_path\htdocs\rmi\jdeveloper\rmi目录 <br />cd apache_path\htdocs\rmi <br />copy f:\server\hello.jar . <br />copy f:\server\jdeveloper\rmi\HelloImpl_Stub.class apache_path\htdocs\rmi\jdeveloper\rmi <br />jar xvf hello.jar <br />把 starthellohttpserver.bat 和 rmihttpserver.policy 放到f:\server\ <br /><br />启动新的DOS窗口 <br />运行 starthellohttpserver <br />starthellohttpserver.bat <br />SET CP=f:\server;f:\serverclasses\hello.jar <br />echo using classpath: %CP% <br />java -classpath %CP% -Djava.rmi.server.codebase=http://hjc/rmi/ <br />-Djava.security.policy=rmihttpserver.policy jdeveloper.rmi.HelloImpl <br />rmihttpserver.policy <br />grant { <br />permission java.net.SocketPermission "*:1099", "accept, connect, listen, resolve"; <br />permission java.net.SocketPermission "*:80", "accept, connect, listen, resolve"; <br />}; <br /><br />启动新的DOS窗口 <br />把 starthellohttpclient.bat 和 rmihttpclient.policy 放到f:\client\ <br />运行 starthellohttpclient <br />starthellohttpclient.bat <br />@echo off <br />set CP=f:\client;f:\clientclasses\hello.jar <br />echo using classpath %CP% <br />@echo on <br />java -classpath %CP% -Djava.rmi.server.codebase=http://hjc/rmi/ <br />-Djava.security.policy=rmihttpclient.policy jdeveloper.rmi.HelloClient %1 <br /><br />rmihttpclient.policy <br />grant { <br />permission java.net.SocketPermission "*:80", "connect"; <br />permission java.net.SocketPermission "*:1024-65535", "connect"; <br />}; <br /></td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
						<tr>
								<td>
										<table cellspacing="0" cellpadding="0" width="95%" align="center" border="0">
												<tbody>
														<tr>
																<td> </td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/weibogao/aggbug/48384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-05-26 17:16 <a href="http://www.blogjava.net/weibogao/archive/2006/05/26/48384.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式的有趣解释－追MM </title><link>http://www.blogjava.net/weibogao/archive/2006/05/26/48374.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Fri, 26 May 2006 08:58:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/05/26/48374.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/48374.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/05/26/48374.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/48374.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/48374.html</trackback:ping><description><![CDATA[
		<h2>
				<a id="viewpost1_TitleUrl" href="http://blog.yesky.com/blog/blueguy/archive/2005/01/14/65072.html">
						<font color="#223355">设计模式的有趣解释－追MM</font>
				</a>
		</h2>
		<div class="postbody">
				<span id="ArticleContent1_ArticleContent1_lblContent">
						<font size="4">
								<font color="#cc3333">//转自</font>
								<a id="ArticleContent1_ArticleContent1_AuthorBlogLink" href="http://blog.csdn.net/laurecn/" target="_blank">
										<font color="#cc3333">http://blog.csdn.net/laurecn/</font>
								</a>
								<br />创建型模式?<br /><br />1、FACTORY一追MM少不了请吃饭了，麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西，虽然口味有所不同，但不管你带MM去麦当劳或肯德基，只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory?<br /><br />工厂模式：客户类和工厂类分开。消费者任何时候需要某种产品，只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时，工厂类也要做相应的修改。如：如何创建及如何向客户端提供。?<br /><br />2、BUILDER—MM最爱听的就是“我爱你”这句话了，见到不同地方的MM,要能够用她们的方言跟她说这句话哦，我有一个多种语言翻译机，上面每种语言都有一个按键，见到MM我只要按对应的键，它就能够用相应的语言说出“我爱你”这句话了，国外的MM 也可以轻松搞掂，这就是我的“我爱你”builder。（这一定比美军在伊拉克用的翻译机好卖）?<br /><br />建造模式：将产品的内部表象和产品的生成过程分割开来，从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化，客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。?<br /><br />3、FACTORY?METHOD—请MM去麦当劳吃汉堡，不同的MM有不同的口味，要每个都记住是一件烦人的事情，我一般采用Factory?Method模式，带着MM到服务员那儿，说“要一个汉堡”，具体要什么样的汉堡呢，让MM直接跟服务员说就行 了。?<br /><br />工厂方法模式：核心工厂类不再负责所有产品的创建，而是将具体创建的工作交给子类去做，成为一个抽象工厂角色，仅负责给出具体工厂类必须实现的接口，而不接触哪一个产品类应当被实例化这种细节。?<br /><br />4、PROTOTYPE—跟MM用QQ聊天，一定要说些深情的话语了，我搜集了好多肉麻的情话，需要时只要copy出来放到QQ里面就行了，这就是我的情话prototype了。（100块钱一份，你要不要）?<br /><br />原始模型模式：通过给出一个原型对象来指明所要创建的对象的类型，然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类，产品类不需要非得有任何事先确定的等级结构，原始模型模式适用于任何的等级结构。缺点是每一 个类都必须配备一个克隆方法。?<br /><br />5、SINGLETON—俺有6个漂亮的老婆，她们的老公都是我，我就是我们家里的老公Sigleton，她们只要说道“老公”，都是指的同一个人，那就是我(刚才做了个梦啦，哪有这么好的事)?<br /><br />单例模式：单例模式确保某一个类只有一个实例，而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。?<br /><br />结构型模式?<br /><br />6、ADAPTER—在朋友聚会上碰到了一个美女Sarah，从香港来的，可我不会说粤语，她不会说普通话，只好求助于我的朋友kent了，他作为我和Sarah之间的Adapter，让我和Sarah可以相互交谈了(也不知道他会不会耍我)?<br /><br />适配器（变压器）模式：把一个类的接口变换成客户端所期待的另一种接口，从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。?<br /><br />7、BRIDGE—早上碰到MM，要说早上好，晚上碰到MM，要说晚上好；碰到MM穿了件新衣服，要说你的衣服好漂亮哦，碰到MM新做的发型，要说你的头发好漂亮哦。不要问我“早上碰到MM新做了个发型怎么说”这种问题，自己用BRIDGE组合一下不就行 了?<br /><br />桥梁模式：将抽象化与实现化脱耦，使得二者可以独立的变化，也就是说将他们之间的强关联变成弱关联，也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系，从而使两者可以独立的变化。?<br /><br />8、COMPOSITE—Mary今天过生日。“我过生日，你要送我一件礼物。”“嗯，好吧，去商店，你自己挑。”“这件T恤挺漂亮，买，这条裙子好看，买，这个包也不错，买。”“喂，买了三件了呀，我只答应送一件礼物的哦。”“什么呀，T恤加裙子加包包 ，正好配成一套呀，小姐，麻烦你包起来。”“……”，MM都会用Composite模式了，你会了没有？?<br /><br />合成模式：合成模式将对象组织到树结构中，可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。?<br /><br />9、DECORATOR—Mary过完轮到Sarly过生日，还是不要叫她自己挑了，不然这个月伙食费肯定玩完，拿出我去年在华山顶上照的照片，在背面写上“最好的的礼物，就是爱你的Fita”，再到街上礼品店买了个像框（卖礼品的MM也很漂亮哦），再找 隔壁搞美术设计的Mike设计了一个漂亮的盒子装起来……，我们都是Decorator，最终都在修饰我这个人呀，怎么样，看懂了吗？?<br /><br />装饰模式：装饰模式以对客户端透明的方式扩展对象的功能，是继承关系的一个替代方案，提供比继承更多的灵活性。动态给一个对象增加功能，这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。?<br /><br />10、FACADE—我有一个专业的Nikon相机，我就喜欢自己手动调光圈、快门，这样照出来的照片才专业，但MM可不懂这些，教了半天也不会。幸好相机有Facade设计模式，把相机调整到自动档，只要对准目标按快门就行了，一切由相机自动调整，这样 MM也可以用这个相机给我拍张照片了。?<br /><br />门面模式：外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口，使得子系统更易于使用。每一个子系统只有一个门面类，而且此门面类只有一个实例，也就是说它是一个单例模式。但整个系统可以有多个门面类。?<br /><br />11、FLYWEIGHT—每天跟MM发短信，手指都累死了，最近买了个新手机，可以把一些常用的句子存在手机里，要用的时候，直接拿出来，在前面加上MM的名字就可以发送了，再不用一个字一个字敲了。共享的句子就是Flyweight，MM的名字就是提 取出来的外部特征，根据上下文情况使用。?<br /><br />享元模式：FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部，不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状 态不能影响内蕴状态，它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来，将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象，而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量 。?<br /><br />12、PROXY—跟MM在网上聊天，一开头总是“hi,你好”,“你从哪儿来呀？”“你多大了？”“身高多少呀？”这些话，真烦人，写个程序做为我的Proxy吧，凡是接收到这些话都设置好了自动的回答，接收到其他的话时再通知我回答，怎么样，酷吧。? <br /><br />代理模式：代理模式给某一个对象提供一个代理对象，并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下，客户不想或者不能够直接引用一个对象，代理对象可以在客户和目标对象直接起到中介的作用。客户端 分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象，而仅仅持有一个被代理对象的接口，这时候代理对象不能够创建被代理对象，被代理对象必须有系统的其他角色代为创建并传入。?<br /><br />行为模式?<br /><br />13、CHAIN?OF?RESPONSIBLEITY—晚上去上英语课，为了好开溜坐到了最后一排，哇，前面坐了好几个漂亮的MM哎，找张纸条，写上“Hi,可以做我的女朋友吗？如果不愿意请向前传”，纸条就一个接一个的传上去了，糟糕，传到第一排的M M把纸条传给老师了，听说是个老处女呀，快跑!?<br /><br />责任链模式：在责任链模式中，很多对象由每一个对象对其下家的引用而接?<br /><br />起来形成一条链。请求在这个链上传递，直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求，系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择：承担责任或者把责任推给下家。一个请求可以最终不 被任何接收端对象所接受。?<br /><br />14、COMMAND—俺有一个MM家里管得特别严，没法见面，只好借助于她弟弟在我们俩之间传送信息，她对我有什么指示，就写一张纸条让她弟弟带给我。这不，她弟弟又传送过来一个COMMAND，为了感谢他，我请他吃了碗杂酱面，哪知道他说：“我同时给 我姐姐三个男朋友送COMMAND，就数你最小气，才请我吃面。”，:-(?<br /><br />命令模式：命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开，委派给不同的对象。命令模式允许请求的一方和发送的一方独立开来，使得请求的一方不必知道接收请求的一方的接口，更不必知道请求是怎么被接收，以及 操作是否执行，何时被执行以及是怎么被执行的。系统支持命令的撤消。?<br /><br />15、INTERPRETER—俺有一个《泡MM真经》，上面有各种泡MM的攻略，比如说去吃西餐的步骤、去看电影的方法等等，跟MM约会时，只要做一个Interpreter，照着上面的脚本执行就可以了。?<br /><br />解释器模式：给定一个语言后，解释器模式可以定义出其文法的一种表示，并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模式将描述怎样在有了一个简单的文法后，使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何 解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构，也就是一系列的组合规则。每一个命令对象都有一个解释方法，代表对命令对象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。?<br /><br />16、ITERATOR—我爱上了Mary，不顾一切的向她求婚。?<br /><br />Mary：“想要我跟你结婚，得答应我的条件”?<br /><br />我：“什么条件我都答应，你说吧”?<br /><br />Mary：“我看上了那个一克拉的钻石”?<br /><br />我：“我买，我买，还有吗？”?<br /><br />Mary：“我看上了湖边的那栋别墅”?<br /><br />我：“我买，我买，还有吗？”?<br /><br />Mary：“你的小弟弟必须要有50cm长”?<br /><br />我脑袋嗡的一声，坐在椅子上，一咬牙：“我剪，我剪，还有吗？”?<br /><br />……?<br /><br />迭代子模式：迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集，聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中，从而与聚集本身隔开。迭代子模式简化了聚集的 界面。每一个聚集对象都可以有一个或一个以上的迭代子对象，每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。?<br /><br />17、MEDIATOR—四个MM打麻将，相互之间谁应该给谁多少钱算不清楚了，幸亏当时我在旁边，按照各自的筹码数算钱，赚了钱的从我这里拿，赔了钱的也付给我，一切就OK啦，俺得到了四个MM的电话。?<br /><br />调停者模式：调停者模式包装了一系列对象相互作用的方式，使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时，不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转 化为一对多的相互作用。调停者模式将对象的行为和协作抽象化，把对象在小尺度的行为上与其他对象的相互作用分开处理。?<br /><br />18、MEMENTO—同时跟几个MM聊天时，一定要记清楚刚才跟MM说了些什么话，不然MM发现了会不高兴的哦，幸亏我有个备忘录，刚才与哪个MM说了什么话我都拷贝一份放到备忘录里面保存，这样可以随时察看以前的记录啦。?<br /><br />备忘录模式：备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下，将一个对象的状态捉住，并外部化，存储起来，从而可以在将来合适的时候把这个对象还原到存储起来的状态。?<br /><br />19、OBSERVER—想知道咱们公司最新MM情报吗？加入公司的MM情报邮件组就行了，tom负责搜集情报，他发现的新情报不用一个一个通知我们，直接发布给邮件组，我们作为订阅者（观察者）就可以及时收到情报啦?<br /><br />观察者模式：观察者模式定义了一种一队多的依赖关系，让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时，会通知所有观察者对象，使他们能够自动更新自己。?<br /><br />20、STATE—跟MM交往时，一定要注意她的状态哦，在不同的状态时她的行为会有不同，比如你约她今天晚上去看电影，对你没兴趣的MM就会说“有事情啦”，对你不讨厌但还没喜欢上的MM就会说“好啊，不过可以带上我同事么？”，已经喜欢上你的MM就会 说“几点钟？看完电影再去泡吧怎么样？”，当然你看电影过程中表现良好的话，也可以把MM的状态从不讨厌不喜欢变成喜欢哦。?<br /><br />状态模式：状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里，每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的 时候，其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时，系统便改变所选的子类。?<br /><br />21、STRATEGY—跟不同类型的MM约会，要用不同的策略，有的请电影比较好，有的则去吃小吃效果不错，有的去海边浪漫最合适，单目的都是为了得到MM的芳心，我的追MM锦囊中有好多Strategy哦。?<br /><br />策略模式：策略模式针对一组算法，将每一个算法封装到具有共同接口的独立的类中，从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类，各种算法在具体的策略类中提供。 由于算法和环境独立开来，算法的增减，修改都不会影响到环境和客户端。?<br /><br />22、TEMPLATE?METHOD——看过《如何说服女生上床》这部经典文章吗？女生从认识到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进去八大步骤(Template?method)，但每个步骤针对不同的情况，都有 不一样的做法，这就要看你随机应变啦(具体实现)；?<br /><br />模板方法模式：模板方法模式准备一个抽象类，将部分逻辑以具体方法以及具体构造子的形式实现，然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法，从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架，而将逻辑 的细节留给具体的子类去实现。?<br /><br />23、VISITOR—情人节到了，要给每个MM送一束鲜花和一张卡片，可是每个MM送的花都要针对她个人的特点，每张卡片也要根据个人的特点来挑，我一个人哪搞得清楚，还是找花店老板和礼品店老板做一下Visitor，让花店老板根据MM的特点选一束花 ，让礼品店老板也根据每个人特点选一张卡，这样就轻松多了；?<br /><br />访问者模式：访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话，接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统，它把数据结构和作用于结构上的操作之间的耦合解脱开，使得操作集合可以 相对自由的演化。访问者模式使得增加新的操作变的很容易，就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中，而不是分散到一个个的节点类中。当使用访问者模式时，要将尽可能多的对象浏览逻辑放在访问者类中，而不是放到它的子类中。 访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。</font>
				</span>
		</div>
<img src ="http://www.blogjava.net/weibogao/aggbug/48374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-05-26 16:58 <a href="http://www.blogjava.net/weibogao/archive/2006/05/26/48374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>iframe 标签的使用（来源：有风的日子）</title><link>http://www.blogjava.net/weibogao/archive/2006/04/03/38915.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Mon, 03 Apr 2006 05:14:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/04/03/38915.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/38915.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/04/03/38915.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/38915.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/38915.html</trackback:ping><description><![CDATA[
		<font size="1">纵观时下网站，本来网速就有些慢，可是几乎每页都要放什么Banner，栏目图片，版权等一大堆雷同的东西，当然，出于网站风格统一、广告效应的需要，本无可厚非，可毕竟让用户的钱包为这些“点缀”的东西“日益消得钱憔悴”了，有没有办法，让这些雷同的东西一次下载后就不用再下载，而只下载那些内容有变化区域的网页内容呢？ <br />　　答案很肯定：应用Iframe标记！</font>
		<p>
				<font size="1">　　<strong>一、Iframe标记的使用</strong></font>
		</p>
		<p>
				<font size="1">　　提起Iframe，可能你早已将之扔到“被遗忘的角落”了，不过，说起其兄弟Frame就不会陌生了。Frame标记即帧标记，我们所说的多帧结构就是在一个浏览器窗口中显示多个HTML文件。现在，我们遇到一种很现实的情况：如有一个教程，是一节一节地上，每页末尾做一个“上一节“、“下一节“的链接，除了每节教程内容不同之外，页面其它部分内容都是相同的，如果一页一页地做笨页面，这似乎太让人厌烦了，这时突发奇想，如果有一种方法让页面其它地方不变，只将教程做成一页一页的内容页，不含其它内容，在点击上下翻页链接时，只改变教程内容部分，其它保持不变，这样，一是省时，另则以后如教程有个三长两短的变动，也很方便，不致于牵一发而动全军了;更重要的是将那些广告Banner、栏目列表、导航等几乎每页的都有的东西只下载一次后就不再下载了。</font>
		</p>
		<p>
				<font size="1">　　Iframe标记，又叫浮动帧标记，你可以用它将一个HTML文档嵌入在一个HTML中显示。它不同于Frame标记最大的特征即这个标记所引用的HTML文件不是与另外的HTML文件相互独立显示，而是可以直接嵌入在一个HTML文件中，与这个HTML文件内容相互融合，成为一个整体，另外，还可以多次在一个页面内显示同一内容，而不必重复写内容，一个形象的比喻即“画中画“电视。</font>
		</p>
		<p>
				<font size="1">　　现在我们谈一下Iframe标记的使用。</font>
		</p>
		<p>
				<font size="1">　　Iframe标记的使用格式是：</font>
		</p>
		<p>
				<font size="1">　　&lt;Iframe src="URL" width="x" height="x" scrolling="[OPTION]" frameborder="x"&gt;&lt;/iframe&gt;<br />　　src：文件的路径，既可是HTML文件，也可以是文本、ASP等；<br />　　width、height："画中画"区域的宽与高；<br />　　scrolling:当SRC的指定的HTML文件在指定的区域不显不完时，滚动选项，如果设置为NO，则不出现滚动条；如为Auto：则自动出现滚动条；如为Yes，则显示;<br />　　FrameBorder：区域边框的宽度，为了让“画中画“与邻近的内容相融合，常设置为0。</font>
		</p>
		<p>
				<font size="1">　　比如：</font>
		</p>
		<p>
				<font size="1">　　&lt;Iframe src="</font>
				<a href="http://netschool.cpcw.com/homepage" target="_blank">
						<font size="1">http://netschool.cpcw.com/homepage</font>
				</a>
				<font size="1">" width="250" height="200" scrolling="no" frameborder="0"&gt;&lt;/iframe&gt;</font>
		</p>
		<p>
				<font size="1">　　<strong>二、父窗体与浮动帧之间的相互控制</strong></font>
		</p>
		<p>
				<font size="1">　　在脚本语言与对象层次中，包含Iframe的窗口我们称之为父窗体，而浮动帧则称为子窗体，弄清这两者的关系很重要，因为要在父窗体中访问子窗体或相反都必须清楚对象层次，才能通过程序来访问并控制窗体。</font>
		</p>
		<p>
				<font size="1">　　1、在父窗体中访问并控制子窗体中的对象</font>
		</p>
		<p>
				<font size="1">　　在父窗体中，Iframe即子窗体是document对象的一个子对象，可以直接在脚本中访问子窗体中的对象。</font>
		</p>
		<p>
				<font size="1">　　现在就有一个问题，即，我们怎样来控制这个Iframe，这里需要讲一下Iframe对象。当我们给这个标记设置了ID 属性后，就可通过文档对象模型DOM对Iframe所含的HTML进行一系列控制。 </font>
		</p>
		<p>
				<font size="1">　　比如在example.htm里嵌入test.htm文件，并控制test.htm里一些标记对象：<br />　　&lt;Iframe src="test.htm" id="test" width="250" height="200" scrolling="no" frameborder="0"&gt;&lt;/iframe&gt;<br />test.htm文件代码为:<br />　　&lt;html&gt;<br />　　　&lt;body&gt;<br />　　　　&lt;h1 id="myH1"&gt;hello,my boy&lt;/h1&gt;<br />　　　&lt;/body&gt;<br />　　&lt;/html&gt;<br />　　如我们要改变ID号为myH1的H1标记里的文字为hello,my dear，则可用:<br />　　document.myH1.innerText="hello,my dear"（其中，document可省）<br />　　在example.htm文件中，Iframe标记对象所指的子窗体与一般的DHTML对象模型一致，对对象访问控制方式一样，就不再赘述。</font>
		</p>
		<p>
				<font size="1">　　2、在子窗体中访问并控制父窗体中对象</font>
		</p>
		<p>
				<font size="1">　　在子窗体中我们可以通过其parent即父（双亲）对象来访问父窗口中的对象。<br />　　如example.htm：<br />　　&lt;html&gt;<br />　　　&lt;body onclick="alert(tt.myH1.innerHTML)"&gt;<br />　　　　&lt;Iframe name="tt" src="frame1.htm" width="250" height="200" scrolling="no" frameborder="0"&gt;&lt;/iframe&gt;<br />　　　　&lt;h1 id="myH2"&gt;hello,my wife&lt;/h1&gt;<br />　　　&lt;/body&gt;<br />　　&lt;/html&gt;<br />　　如果要在frame1.htm中访问ID号为myH2中的标题文字并将之改为"hello,my friend"，我们就可以这样写： <br />　　parent.myH2.innerText="hello,my friend"<br />　　这里parent对象就代表当前窗体（example.htm所在窗体），要在子窗体中访问父窗体中的对象，无一例外都通过parent对象来进行。 </font>
		</p>
		<p>
				<font size="1">　　Iframe虽然内嵌在另一个HTML文件中，但它保持相对的独立，是一个“独立王国”哟，在单一HTML中的特性同样适用于浮动帧中。</font>
		</p>
		<p>
				<font size="1">　　试想一下，通过Iframe标记，我们可将那些不变的内容以Iframe来表示，这样，不必重复写相同的内容，这有点象程序设计中的过程或函数，减省了多少繁琐的手工劳动！另外，至关重要的是，它使页面的修改更为可行，因为，不必因为版式的调整而修改每个页面，你只需修改一个父窗体的版式即可了。</font>
		</p>
		<p>
				<font size="1">　　有一点要注意，Nestscape浏览器不支持Iframe标记，但在时下IE的天下，这似乎也无大碍，广泛采用Iframe标记，既为自己（网站）着了想，又为网友节省了网费，何乐而不为？</font>
		</p>
<img src ="http://www.blogjava.net/weibogao/aggbug/38915.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-04-03 13:14 <a href="http://www.blogjava.net/weibogao/archive/2006/04/03/38915.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA开发者应该去的20个英文网站 </title><link>http://www.blogjava.net/weibogao/archive/2006/04/01/38622.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Sat, 01 Apr 2006 08:55:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/04/01/38622.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/38622.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/04/01/38622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/38622.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/38622.html</trackback:ping><description><![CDATA[
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.javaalmanac.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">Java开发者年鉴一书的在线版本. 要想快速查到某种Java技巧的用法及示例代码, 这是一个不错的去处. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.onjava.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">O'Reilly的Java网站. 每周都有新文章 </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://java.sun.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">官方的Java开发者网站 - 每周都有新文章发表 </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.developer.com/java </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">由Gamelan.com 维护的Java技术文章网站 </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.java.net </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">Sun公司维护的一个Java社区网站 </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.builder.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">Cnet的Builder.com网站 - 所有的技术文章, 以Java为主. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.ibm.com/developerworks/java </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">IBM的Developerworks技术网站; 这是其中的Java技术主页 </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.javaworld.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">最早的一个Java站点. 每周更新Java技术文章 </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.devx.com/java </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">DevX维护的一个Java技术文章网站 </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.fawcette.com/javapro </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">JavaPro在线杂志网站. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.sys-con.com/java </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">Java Developers Journal的在线杂志网站. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.javadesktop.org </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">位于Java.net的一个Java桌面技术社区网站. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.theserverside.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">这是一个讨论所有Java服务器端技术的网站. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.jars.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">提供Java评论服务. 包括各种framework和应用程序 </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.jguru.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">一个非常棒的采用Q&amp;A形式的Java技术资源社区. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.javaranch.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">一个论坛，得到Java问题答案的地方，初学者的好去处。 </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.ibiblio.org/javafaq/javafaq.html </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">comp.lang.java的FAQ站点 - 收集了来自comp.lang.java新闻组的问题和答案的分类目录. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://java.sun.com/docs/books/tutorial/ </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">来自SUN公司的官方Java指南 - 对于了解几乎所有的java技术特性非常有帮助. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://www.javablogs.com </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">互联网上最活跃的一个Java Blog网站. </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">http://java.about.com/ </font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">
				</font>
		</p>
		<p style="TEXT-INDENT: 2em">
				<font size="1">来自About.com的Java新闻和技术文章网站. </font>
		</p>
<img src ="http://www.blogjava.net/weibogao/aggbug/38622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-04-01 16:55 <a href="http://www.blogjava.net/weibogao/archive/2006/04/01/38622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DWR让AJAX如此简单</title><link>http://www.blogjava.net/weibogao/archive/2006/04/01/38621.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Sat, 01 Apr 2006 08:52:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/04/01/38621.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/38621.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/04/01/38621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/38621.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/38621.html</trackback:ping><description><![CDATA[
		<center>
				<b>
						<span style="FONT-SIZE: 20px">
								<font size="1">DWR让AJAX如此简单</font>
						</span>
				</b>
		</center>
		<br />
		<center>
				<font size="1">利用DWR开始在你的Web应用中使用AJAX</font>
		</center>
		<br />
		<center>
				<font size="1">作者：Cloves Carneiro</font>
		</center>
		<br />
		<center>
				<font size="1">译者:</font>
				<a href="http://www.matrix.org.cn/user.shtml?username=simmone" target="_new">
						<font size="1">simmone</font>
				</a>
		</center>
		<br />
		<br />
		<font size="1">
				<span style="COLOR: red">版权声明：任何获得Matrix授权的网站，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明</span>
				<br />作者:Cloves Carneiro;</font>
		<a href="http://www.matrix.org.cn/user.shtml?username=simmone" target="_new">
				<font size="1">simmone</font>
		</a>
		<br />
		<font size="1">原文地址:</font>
		<a href="http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-dwr.html" target="_new">
				<font size="1">http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-dwr.html</font>
		</a>
		<br />
		<font size="1">中文地址:</font>
		<a href="http://www.matrix.org.cn/resource/article/43/43926_DWR_AJAX.html" target="_new">
				<font size="1">http://www.matrix.org.cn/resource/article/43/43926_DWR_AJAX.html</font>
		</a>
		<br />
		<font size="1">关键词： DWR AJAX<br /><br /><br /><b><span style="FONT-SIZE: 16px">概述</span></b><br /><br />这篇文章阐述了使用开源项目DWR(直接Web远程控制)和AJAX(异步JavaScript和XML)的概念来提高Web应用的可用性。作者一步步来展示DWR如何使得AJAX的应用既简单又快捷。（1600字;2005年6月20日） <br /><br />AJAX，或者说是异步JavaScript和XML，描述了一种使用混合了HTML(或XHTML)和层叠样式表作为表达信息,来创建交互式的Web应用的开发技术;文档对象模型（DOM），JavaScript,动态地显示和与表达信息进行交互;并且，XMLHttpRequest对象与Web服务器异步地交换和处理数据。<br /><br />因特网上许多例子展示了在一个HTML文件内部使用XMLHttpRequest与服务器端进行交互的必要的步骤。当手工地编写和维护XMLHttpRequest代码时，开发者必须处理许多潜在的问题，特别是类似于跨浏览器的DOM实现的兼容性这样的问题。这将会导致在编码和调试Javascript代码上面花费数不清的时间，这显然对开发者来说很不友好。<br /><br />DWR(直接Web远程控制)项目是在Apache许可下的一个开源的解决方案，它供给那些想要以一种简单的方式使用AJAX和XMLHttpRequest的开发者。它具有一套Javascript功能集，它们把从HTML页面调用应用服务器上的Java对象的方法简化了。它操控不同类型的参数，并同时保持了HTML代码的可读性。<br /><br />DWR不是对一个设计的插入，也不强迫对象使用任何种类的继承结构。它和servlet框架内的应用配合的很好。对缺少DHTML编程经验的开发者来说，DWR也提供了一个JavaScript库包含了经常使用的DHTML任务，如组装表，用item填充select下拉框，改变HTML元素的内容，如&lt;div&gt;和&lt;span&gt;<br />DWR网站是详尽的并且有大量的文档，这也是这篇文章的基础。一些例子用来展示DWR如何使用和用它的库可以完成什么样的工作。<br /><br />这篇文章让读者看到了一个使用了DWR的Web应用是如何一步步建立的。我会展示创建这个简单的示例应用的必要的细节，这个应用是可下载的并且可以在你的环境中布署来看看DWR如何工作。<br />注意：找到有关AJAX的信息并不困难;网页上有几篇文章和博客的条目涵盖了这个主题，每一个都试图指出和评论这个概念的不同的方面。在资源部分，你会找到一些有趣的指向示例和文章的链接，来学习AJAX的更多的内容。<br /><br /><b><span style="FONT-SIZE: 16px">示例应用</span></b><br />这篇文章使用的示例应用模拟了多伦多的一个公寓出租搜索引擎。用户可以在搜索前选择一组搜索标准。为了提高交互性，AJAX中以下两种情况下使用：<br />·应用通告用户配合他的选择会返回多少搜索结果。这个数字是实时更新的-使用AJAX-当用户选择的卧室和浴室的数量，或者价格范围变化时。当符合标准的搜索结果没有或太多时，用户就没有必要点击搜索按纽。<br />·数据库查询并取回结果是由AJAX完成的。当用户按下显示结果按钮时，数据库执行搜索。这样，应用看起来更具响应了，而整个页面不需要重载来显示结果。<br /><br /><b><span style="FONT-SIZE: 16px">数据库</span></b><br />我们使用的数据库是HSQL，它是一种占用资源很小的Java SQL数据库引擎，可以不需要安装和配置的与Web应用捆绑在一起。一个SQL文件被用来在Web应用的上下文启动时创建一个内存中的表并添加一些记录。<br /><br /><b><span style="FONT-SIZE: 16px">Java类</span></b><br />应用包含了两个主要的类叫Apartment和ApartmentDAO。Apartment.java类是一个有着属性和getter/setter方法的简单的Java类。ApartmentDAO.java是数据访问类，用来查询数据库并基于用户的搜索标准来返回信息。ApartmentDAO类的实现的直接了当的;它直接使用了Java数据库联接调用来得到公寓的总数和符合用户请求的可用公寓的列表。<br /><br /><b><span style="FONT-SIZE: 16px">DWR配置和使用</span></b><br />设置DWR的使用是简单的：将DWR的jar文件拷入Web应用的WEB-INF/lib目录中，在web.xml中增加一个servlet声明，并创建DWR的配置文件。DWR的分发中需要使用一个单独的jar文件。你必须将DWR servlet加到应用的WEB-INF/web.xml中布署描述段中去。<br /></font>
		<pre class="overflow">
				<font size="1">    &lt;servlet&gt;<br />        &lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;<br />        &lt;display-name&gt;DWR Servlet&lt;/display-name&gt;<br />        &lt;description&gt;Direct Web Remoter Servlet&lt;/description&gt;<br />        &lt;servlet-class&gt;uk.ltd.getahead.dwr.DWRServlet&lt;/servlet-class&gt;<br />        &lt;init-param&gt;<br />            &lt;param-name&gt;debug&lt;/param-name&gt;<br />            &lt;param-value&gt;true&lt;/param-value&gt;<br />        &lt;/init-param&gt;<br />    &lt;/servlet&gt;<br /><br />    &lt;servlet-mapping&gt;<br />        &lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;<br />        &lt;url-pattern&gt;/dwr/*&lt;/url-pattern&gt;<br />    &lt;/servlet-mapping&gt;</font>
		</pre>
		<br />
		<br />
		<font size="1">一个可选的步骤是设置DWR为调试模式—象上面的例子那样—在servlet描述段中将debug参数设为true。当DWR在调试模式时，你可以从HTMl网页中看到所有的可访问的Java对象。包含了可用对象列表的网页会出现在/WEBAPP/dwr这个url上，它显示了对象的公共方法。所列方法可以从页面中调用，允许你，第一次，运行服务器上的对象的方法。下图显示了调试页的样子:<br /><br /><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/forum/2005_11_07_000336_lrylCwRMxo.jpg" onload="javascript:imgLoad(this);" border="0" resized="0" /><br />调试页<br /><br />现在你必须让DWR知道通过XMLHttpRequest对象，什么对象将会接收请求。这个任务由叫做dwr.xml的配置文件来完成。在配置文件中，定义了DWR允许你从网页中调用的对象。从设计上讲，DWR允许访问所有公布类的公共方法，但在我们的例子中，我们只允许访问几个方法。下面是我们示例的配置文件:<br /></font>
		<pre class="overflow">
				<font size="1">&lt;dwr&gt;<br />    &lt;allow&gt;<br />        &lt;convert converter="bean" match="dwr.sample.Apartment"/&gt;<br />        &lt;create creator="new" javascript="ApartmentDAO" class="dwr.sample.ApartmentDAO"&gt;<br />            &lt;include method="findApartments"/&gt;<br />            &lt;include method="countApartments"/&gt;<br />        &lt;/create&gt;<br />    &lt;/allow&gt;<br />&lt;/dwr&gt;</font>
		</pre>
		<br />
		<br />
		<font size="1">上面的文件实现了我们例子中的两个目标。首先，&lt;convert&gt;标记告诉DWR将dwr.sample.Apartment对象的类型转换为联合数组，因为，出于安全的原因，DWR默认的不会转换普通bean。第二，&lt;create&gt;标记让DWR暴露出dwr.sample.ApartmentDAO类给JavaScript调用;我们在页面中使用JavaScript文件被javascript属性定义。我们必须注意&lt;include&gt;标记，它指明了dwr.sample.ApartmentDAO类的哪些方法可用。<br /><br /><b><span style="FONT-SIZE: 16px">HTML/JSP代码</span></b><br />配置完成后，你就可以启动你的Web应用了，这时DWR会为从你的HTML或Java服务器端页面(JSP)上调用所需方法作好准备，并不需要你创建JavaScript文件。在search.jsp文件中， 我们必须增加由DWR提供的JavaScript接口，还有DWR引擎，加入以下三行到我们的代码中：<br /><br /></font>
		<pre class="overflow">
				<font size="1">  &lt;script src='dwr/interface/ApartmentDAO.js'&gt;&lt;/script&gt;<br />  &lt;script src='dwr/engine.js'&gt;&lt;/script&gt;<br />  &lt;script src='dwr/util.js'&gt;&lt;/script&gt;</font>
		</pre>
		<br />
		<br />
		<font size="1">我们注意到当用户改变搜索标准时，这是AJAX在示例程序中的首次应用;正如他所看到的，当标准改变时，可用的公寓数量被更新了。我创建了两个JavaScript函数：当某一个选择下拉框中的值变化时被调用。ApartmentDAO.countApartments()函数是最重要的部分。最有趣的是第一个参数, loadTotal()函数，它指明了当接收到服务端的返回时DWR将会调用的JavaScript方法。loadTotal于是被调用来在HTML页面的&lt;div&gt;中显示结果。下面是在这个交互场景中所使用到的JavaScript函数:<br /><br /></font>
		<pre class="overflow">
				<font size="1">function updateTotal() {<br />    $("resultTable").style.display = 'none';<br />    var bedrooms = document.getElementById("bedrooms").value;<br />    var bathrooms = document.getElementById("bathrooms").value;<br />    var price = document.getElementById("price").value;<br />    ApartmentDAO.countApartments(loadTotal, bedrooms, bathrooms, price);<br />}<br /><br />function loadTotal(data) {<br />    document.getElementById("totalRecords").innerHTML = data;<br />}</font>
		</pre>
		<br />
		<br />
		<font size="1">很明显，用户想看到符合他的搜索条件的公寓列表。那么，当用户对他的搜索标准感到满意，并且总数也是有效的话，他会按下显示结果的按纽，这将会调用updateResults() JavaScript方法：<br /><br /></font>
		<pre class="overflow">
				<font size="1">function updateResults() {<br />    <br />    DWRUtil.removeAllRows("apartmentsbody");<br />    var bedrooms = document.getElementById("bedrooms").value;<br />    var bathrooms = document.getElementById("bathrooms").value;<br />    var price = document.getElementById("price").value;<br />    ApartmentDAO.findApartments(fillTable, bedrooms, bathrooms, price);<br />    $("resultTable").style.display = '';<br />}<br /><br />function fillTable(apartment) {<br />    DWRUtil.addRows("apartmentsbody", apartment, [ getId, getAddress, getBedrooms, getBathrooms, getPrice ]);<br />}</font>
		</pre>
		<br />
		<br />
		<font size="1">updateResults()方法清空了存放搜索返回结果的表域，从用户界面上获取所需参数，并且将这些参数传给DWR创建的ApartmentDAO对象。然后数据库查询将被执行，fillTable()将会被调用，它解析了DWR返回的对象(apartment)，然后将其显示到页面中(apartmentsbody)。<br /><br /><b><span style="FONT-SIZE: 16px">安全因素</span></b><br />为了保持示例的简要，ApartmentDAO类尽可能的保持简单，但这样的一个类通常有一组设置方法来操作数据，如insert(), update()和delete()。DWR暴露了所有公共方法给所有的HTML页面调用。出于安全的原因，像这样暴露你的数据访问层是不明智的。开发者可以创建一个门面来集中所有JavaScript函数与底层业务组件之间的通信，这样就限制了过多暴露的功能。<br /><br /><b><span style="FONT-SIZE: 16px">结论</span></b><br />这篇文章仅仅让你在你的项目中使用由DWR支持的AJAX开了个头。DWR让你集中注意力在如何提高你的应用的交互模型上面，消除了编写和调试JavaScript代码的负担。使用AJAX最有趣的挑战是定义在哪里和如何提高可用性。DWR负责了操作Web页面与你的Java对象之间的通信，这样就帮助你完全集中注意力在如何让你的应用的用户界面更加友好，<br />我想感谢Mircea Oancea和Marcos Pereira,他们阅读了这篇文章并给予了非常有价值的返匮。<br /><br /><b>资源</b><br />·javaworld.com:</font>
		<a href="http://www.javaworld.com/" target="_new">
				<font size="1">javaworld.com</font>
		</a>
		<br />
		<font size="1">·Matrix-Java开发者社区:</font>
		<a href="http://www.matrix.org.cn/" target="_new">
				<font size="1">http://www.matrix.org.cn/</font>
		</a>
		<br />
		<font size="1">·onjava.com:</font>
		<a href="http://www.onjava.com/" target="_new">
				<font size="1">onjava.com</font>
		</a>
		<br />
		<font size="1">·下载示例程序的全部源码:</font>
		<a href="http://www.javaworld.com/javaworld/jw-06-2005/dwr/jw-0620-dwr.war" target="_new">
				<font size="1">http://www.javaworld.com/javaworld/jw-06-2005/dwr/jw-0620-dwr.war</font>
		</a>
		<br />
		<font size="1">·DWR: http://www.getahead.ltd.uk/dwr/index.html<br />·HSQL:http://hsqldb.sourceforge.net/<br />·AJAX的定义:http://en.wikipedia.org/wiki/AJAX<br />· “AJAX:通向Web应用的新途径": Jesse James Garrett (Adaptive Path, 2005.2): http://www.adaptivepath.com/publications/essays/archives/000385.php<br />· “非常动态的Web界面” Drew McLellan (xml.com, 2005.2): http://www.xml.com/pub/a/2005/02/09/xml-http-request.html<br />·XMLHttpRequest &amp; AJAX 工作范例: http://www.fiftyfoureleven.com/resources/programming/xmlhttprequest/examples<br />· “可用的XMLHttpRequest实践” Thomas Baekdal (Baekdal.com, 2005.3): http://www.baekdal.com/articles/Usability/usable-XMLHttpRequest/<br />·"XMLHttpRequest使用导引" Thomas Baekdal (Baekdal.com,  2005.2):http://www.baekdal.com/articles/Usability/XMLHttpRequest-guidelines/<br />·AJAX实质:http://www.ajaxmatters.com/<br /></font>
<img src ="http://www.blogjava.net/weibogao/aggbug/38621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-04-01 16:52 <a href="http://www.blogjava.net/weibogao/archive/2006/04/01/38621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转载)[TOMCAT]用web.xml控制Web应用的行为</title><link>http://www.blogjava.net/weibogao/archive/2006/04/01/38618.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Sat, 01 Apr 2006 08:38:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/04/01/38618.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/38618.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/04/01/38618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/38618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/38618.html</trackback:ping><description><![CDATA[
		<span class="oblog_text">
				<span class="tpc_content">
						<font size="1">一篇关于web.xml配置的详细说明<br /><br />(转载)[TOMCAT]用web.xml控制Web应用的行为 <br /><br /><br /><br />1 定义头和根元素<br /><br />部署描述符文件就像所有XML文件一样，必须以一个XML头开始。这个头声明可以使用的XML版本并给出文件的字符编码。<br />DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本（如2.2或2.3）并指定管理此文件其余部分内容的语法的DTD(Document Type Definition，文档类型定义)。<br />所有部署描述符文件的顶层（根）元素为web-app。请注意，XML元素不像HTML，他们是大小写敏感的。因此，web-App和WEB-APP都是不合法的，web-app必须用小写。<br /><br />2 部署描述符文件内的元素次序<br /><br />XML 元素不仅是大小写敏感的，而且它们还对出现在其他元素中的次序敏感。例如，XML头必须是文件中的第一项，DOCTYPE声明必须是第二项，而web- app元素必须是第三项。在web-app元素内，元素的次序也很重要。服务器不一定强制要求这种次序，但它们允许（实际上有些服务器就是这样做的）完全拒绝执行含有次序不正确的元素的Web应用。这表示使用非标准元素次序的web.xml文件是不可移植的。<br />下面的列表给出了所有可直接出现在web-app元素内的合法元素所必需的次序。例如，此列表说明servlet元素必须出现在所有servlet-mapping元素之前。请注意，所有这些元素都是可选的。因此，可以省略掉某一元素，但不能把它放于不正确的位置。<br />l icon icon元素指出IDE和GUI工具用来表示Web应用的一个和两个图像文件的位置。<br />l display-name display-name元素提供GUI工具可能会用来标记这个特定的Web应用的一个名称。<br />l description description元素给出与此有关的说明性文本。<br />l context-param context-param元素声明应用范围内的初始化参数。<br />l filter 过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联。<br />l filter-mapping 一旦命名了一个过滤器，就要利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。<br />l listener servlet API的版本2.3增加了对事件监听程序的支持，事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类。<br />l servlet 在向servlet或JSP页面制定初始化参数或定制URL时，必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。<br />l servlet-mapping 服务器一般为servlet提供一个缺省的URL：</font>
						<a href="http://host/webAppPrefix/servlet/ServletName" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/ServletName</font>
						</a>
						<font size="1">。但是，常常会更改这个URL，以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时，使用servlet-mapping元素。<br />l session-config 如果某个会话在一定时间内未被访问，服务器可以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveInterval方法明确设置单个会话对象的超时值，或者可利用session-config元素制定缺省超时值。<br />l mime-mapping 如果Web应用具有想到特殊的文件，希望能保证给他们分配特定的MIME类型，则mime-mapping元素提供这种保证。<br />l welcom-file-list welcome-file-list元素指示服务器在收到引用一个目录名而不是文件名的URL时，使用哪个文件。<br />l error-page error-page元素使得在返回特定HTTP状态代码时，或者特定类型的异常被抛出时，能够制定将要显示的页面。<br />l taglib taglib元素对标记库描述符文件（Tag Libraryu Descriptor file）指定别名。此功能使你能够更改TLD文件的位置，而不用编辑使用这些文件的JSP页面。<br />l resource-env-ref resource-env-ref元素声明与资源相关的一个管理对象。<br />l resource-ref resource-ref元素声明一个资源工厂使用的外部资源。<br />l security-constraint security-constraint元素制定应该保护的URL。它与login-config元素联合使用<br />l login-config 用login-config元素来指定服务器应该怎样给试图访问受保护页面的用户授权。它与sercurity-constraint元素联合使用。<br />l security-role security-role元素给出安全角色的一个列表，这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。分别地声明角色可使高级IDE处理安全信息更为容易。<br />l env-entry env-entry元素声明Web应用的环境项。<br />l ejb-ref ejb-ref元素声明一个EJB的主目录的引用。<br />l ejb-local-ref ejb-local-ref元素声明一个EJB的本地主目录的应用。<br /><br />3 分配名称和定制的UL<br /><br />在web.xml中完成的一个最常见的任务是对servlet或JSP页面给出名称和定制的URL。用servlet元素分配名称，使用servlet-mapping元素将定制的URL与刚分配的名称相关联。<br />3.1 分配名称<br />为了提供初始化参数，对servlet或JSP页面定义一个定制URL或分配一个安全角色，必须首先给servlet或JSP页面一个名称。可通过 servlet元素分配一个名称。最常见的格式包括servlet-name和servlet-class子元素（在web-app元素内），如下所示：<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />&lt;/servlet&gt; <br />这表示位于WEB-INF/classes/moreservlets/TestServlet的servlet已经得到了注册名Test。给 servlet一个名称具有两个主要的含义。首先，初始化参数、定制的URL模式以及其他定制通过此注册名而不是类名引用此servlet。其次,可在 URL而不是类名中使用此名称。因此，利用刚才给出的定义，URL </font>
						<a href="http://host/webAppPrefix/servlet/Test" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/Test</font>
						</a>
						<font size="1">可用于 </font>
						<a href="http://host/webAppPrefix/servlet/moreservlets.TestServlet" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/moreservlets.TestServlet</font>
						</a>
						<font size="1">的场所。<br />请记住：XML元素不仅是大小写敏感的，而且定义它们的次序也很重要。例如，web-app元素内所有servlet元素必须位于所有servlet- mapping元素（下一小节介绍）之前，而且还要位于5.6节和5.11节讨论的与过滤器或文档相关的元素（如果有的话）之前。类似地，servlet 的servlet-name子元素也必须出现在servlet-class之前。5.2节"部署描述符文件内的元素次序"将详细介绍这种必需的次序。<br />例如，程序清单5-1给出了一个名为TestServlet的简单servlet，它驻留在moreservlets程序包中。因为此servlet是扎根在一个名为deployDemo的目录中的Web应用的组成部分，所以TestServlet.class放在deployDemo/WEB- INF/classes/moreservlets中。程序清单5-2给出将放置在deployDemo/WEB-INF/内的web.xml文件的一部分。此web.xml文件使用servlet-name和servlet-class元素将名称Test与TestServlet.class相关联。图 5-1和图5-2分别显示利用缺省URL和注册名调用TestServlet时的结果。<br /><br />程序清单5-1 TestServlet.java<br />package moreservlets;<br /><br />import java.io.*;<br />import javax.servlet.*;<br />import javax.servlet.http.*;<br /><br />/** Simple servlet used to illustrate servlet naming<br />* and custom URLs.<br />* &lt;P&gt;<br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font>
						<a href="http://www.moreservlets.com/." target="_blank">
								<font size="1">http://www.moreservlets.com/.</font>
						</a>
						<br />
						<font size="1">* © 2002 Marty Hall; may be freely used or adapted.<br />*/<br /><br />public class TestServlet extends HttpServlet {<br />public void doGet(HttpServletRequest request,<br />HttpServletResponse response)<br />throws ServletException, IOException {<br />response.setContentType("text/html");<br />PrintWriter out = response.getWriter();<br />String uri = request.getRequestURI();<br />out.println(ServletUtilities.headWithTitle("Test Servlet") +<br />"&lt;BODY BGCOLOR=\"#FDF5E6\"&gt;\n" +<br />"&lt;H2&gt;URI: " + uri + "&lt;/H2&gt;\n" +<br />"&lt;/BODY&gt;&lt;/HTML&gt;");<br />}<br />}<br /><br /><br />程序清单5-2 web.xml（说明servlet名称的摘录）<br />&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />&lt;!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font>
						<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank">
								<font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font>
						</a>
						<font size="1">"&gt;<br /><br />&lt;web-app&gt;<br />&lt;!-- … --&gt;<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />&lt;/servlet&gt;<br />&lt;!-- … --&gt;<br />&lt;/web-app&gt;<br /><br />3.2 定义定制的URL<br />大多数服务器具有一个缺省的serlvet URL：<br /></font>
						<a href="http://host/webAppPrefix/servlet/packageName.ServletName" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/packageName.ServletName</font>
						</a>
						<font size="1">。虽然在开发中使用这个URL很方便，但是我们常常会希望另一个URL用于部署。例如，可能会需要一个出现在Web应用顶层的URL（如，http: //host/webAppPrefix/Anyname），并且在此URL中没有servlet项。位于顶层的URL简化了相对URL的使用。此外，对许多开发人员来说，顶层URL看上去比更长更麻烦的缺省URL更简短。<br />事实上，有时需要使用定制的URL。比如，你可能想关闭缺省URL映射，以便更好地强制实施安全限制或防止用户意外地访问无初始化参数的servlet。如果你禁止了缺省的URL，那么你怎样访问servlet呢？这时只有使用定制的URL了。<br />为了分配一个定制的URL，可使用servlet-mapping元素及其servlet-name和url-pattern子元素。Servlet- name元素提供了一个任意名称，可利用此名称引用相应的servlet；url-pattern描述了相对于Web应用的根目录的URL。url- pattern元素的值必须以斜杠（/）起始。<br />下面给出一个简单的web.xml摘录，它允许使用URL </font>
						<a href="http://host/webAppPrefix/UrlTest" target="_blank">
								<font size="1">http://host/webAppPrefix/UrlTest</font>
						</a>
						<font size="1">而不是</font>
						<a href="http://host/webAppPrefix/servlet/Test" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/Test</font>
						</a>
						<font size="1">或<br />http: //host/webAppPrefix/servlet/moreservlets.TestServlet。请注意，仍然需要XML头、 DOCTYPE声明以及web-app封闭元素。此外，可回忆一下，XML元素出现地次序不是随意的。特别是，需要把所有servlet元素放在所有 servlet-mapping元素之前。<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />&lt;/servlet&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />&lt;url-pattern&gt;/UrlTest&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br />URL模式还可以包含通配符。例如，下面的小程序指示服务器发送所有以Web应用的URL前缀开始，以..asp结束的请求到名为BashMS的servlet。<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;BashMS&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;msUtils.ASPTranslator&lt;/servlet-class&gt;<br />&lt;/servlet&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt;BashMS&lt;/servlet-name&gt;<br />&lt;url-pattern&gt;/*.asp&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br />3.3 命名JSP页面<br />因为JSP页面要转换成sevlet，自然希望就像命名servlet一样命名JSP页面。毕竟，JSP页面可能会从初始化参数、安全设置或定制的URL中受益，正如普通的serlvet那样。虽然JSP页面的后台实际上是servlet这句话是正确的，但存在一个关键的猜疑：即，你不知道JSP页面的实际类名（因为系统自己挑选这个名字）。因此，为了命名JSP页面，可将jsp-file元素替换为servlet-calss元素，如下所示：<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />&lt;jsp-file&gt;/TestPage.jsp&lt;/jsp-file&gt;<br />&lt;/servlet&gt;<br />命名JSP页面的原因与命名servlet的原因完全相同：即为了提供一个与定制设置（如，初始化参数和安全设置）一起使用的名称，并且，以便能更改激活 JSP页面的URL（比方说，以便多个URL通过相同页面得以处理，或者从URL中去掉.jsp扩展名）。但是，在设置初始化参数时，应该注意，JSP页面是利用jspInit方法，而不是init方法读取初始化参数的。<br />例如，程序清单5-3给出一个名为TestPage.jsp的简单JSP页面，它的工作只是打印出用来激活它的URL的本地部分。TestPage.jsp放置在deployDemo应用的顶层。程序清单5-4给出了用来分配一个注册名PageName，然后将此注册名与</font>
						<a href="http://host/webAppPrefix/UrlTest2/anything" target="_blank">
								<font size="1">http://host/webAppPrefix/UrlTest2/anything</font>
						</a>
						<font size="1">形式的URL相关联的web.xml文件（即，deployDemo/WEB-INF/web.xml）的一部分。<br /><br />程序清单5-3 TestPage.jsp<br />&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;<br />&lt;HTML&gt;<br />&lt;HEAD&gt;<br />&lt;TITLE&gt;<br />JSP Test Page<br />&lt;/TITLE&gt;<br />&lt;/HEAD&gt;<br />&lt;BODY BGCOLOR="#FDF5E6"&gt;<br />&lt;H2&gt;URI: &lt;%= request.getRequestURI() %&gt;&lt;/H2&gt;<br />&lt;/BODY&gt;<br />&lt;/HTML&gt;<br /><br /><br />程序清单5-4 web.xml（说明JSP页命名的摘录）<br />&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />&lt;!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font>
						<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank">
								<font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font>
						</a>
						<font size="1">"&gt;<br /><br />&lt;web-app&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />&lt;jsp-file&gt;/TestPage.jsp&lt;/jsp-file&gt;<br />&lt;/servlet&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt; PageName &lt;/servlet-name&gt;<br />&lt;url-pattern&gt;/UrlTest2/*&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br />&lt;!-- ... --&gt;<br />&lt;/web-app&gt;<br /><br /><br />4 禁止激活器servlet<br /><br />对servlet或JSP页面建立定制URL的一个原因是，这样做可以注册从 init（servlet）或jspInit（JSP页面）方法中读取得初始化参数。但是，初始化参数只在是利用定制URL模式或注册名访问 servlet或JSP页面时可以使用，用缺省URL </font>
						<a href="http://host/webAppPrefix/servlet/ServletName" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/ServletName</font>
						</a>
						<font size="1">访问时不能使用。因此，你可能会希望关闭缺省URL，这样就不会有人意外地调用初始化servlet了。这个过程有时称为禁止激活器servlet，因为多数服务器具有一个用缺省的servlet URL注册的标准servlet，并激活缺省的URL应用的实际servlet。<br />有两种禁止此缺省URL的主要方法：<br />l 在每个Web应用中重新映射/servlet/模式。<br />l 全局关闭激活器servlet。<br />重要的是应该注意到，虽然重新映射每个Web应用中的/servlet/模式比彻底禁止激活servlet所做的工作更多，但重新映射可以用一种完全可移植的方式来完成。相反，全局禁止激活器servlet完全是针对具体机器的，事实上有的服务器（如ServletExec）没有这样的选择。下面的讨论对每个Web应用重新映射/servlet/ URL模式的策略。后面提供在Tomcat中全局禁止激活器servlet的详细内容。<br />4.1 重新映射/servlet/URL模式<br />在一个特定的Web应用中禁止以</font>
						<a href="http://host/webAppPrefix/servlet/" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/</font>
						</a>
						<font size="1">开始的URL的处理非常简单。所需做的事情就是建立一个错误消息servlet，并使用前一节讨论的url-pattern元素将所有匹配请求转向该 servlet。只要简单地使用：<br />&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />作为servlet-mapping元素中的模式即可。<br />例如，程序清单5-5给出了将SorryServlet servlet（程序清单5-6）与所有以</font>
						<a href="http://host/webAppPrefix/servlet/" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/</font>
						</a>
						<font size="1">开头的URL相关联的部署描述符文件的一部分。<br /><br />程序清单5-5 web.xml（说明JSP页命名的摘录）<br />&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />&lt;!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font>
						<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank">
								<font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font>
						</a>
						<font size="1">"&gt;<br /><br />&lt;web-app&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;Sorry&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;moreservlets.SorryServlet&lt;/servlet-class&gt;<br />&lt;/servlet&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt; Sorry &lt;/servlet-name&gt;<br />&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br />&lt;!-- ... --&gt;<br />&lt;/web-app&gt;<br /><br /><br />程序清单5-6 SorryServlet.java<br />package moreservlets;<br /><br />import java.io.*;<br />import javax.servlet.*;<br />import javax.servlet.http.*;<br /><br />/** Simple servlet used to give error messages to<br />* users who try to access default servlet URLs<br />* (i.e., </font>
						<a href="http://host/webAppPrefix/servlet/ServletName" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/ServletName</font>
						</a>
						<font size="1">)<br />* in Web applications that have disabled this<br />* behavior.<br />* &lt;P&gt;<br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font>
						<a href="http://www.moreservlets.com/." target="_blank">
								<font size="1">http://www.moreservlets.com/.</font>
						</a>
						<br />
						<font size="1">* © 2002 Marty Hall; may be freely used or adapted.<br />*/<br /><br />public class SorryServlet extends HttpServlet {<br />public void doGet(HttpServletRequest request,<br />HttpServletResponse response)<br />throws ServletException, IOException {<br />response.setContentType("text/html");<br />PrintWriter out = response.getWriter();<br />String title = "Invoker Servlet Disabled.";<br />out.println(ServletUtilities.headWithTitle(title) +<br />"&lt;BODY BGCOLOR=\"#FDF5E6\"&gt;\n" +<br />"&lt;H2&gt;" + title + "&lt;/H2&gt;\n" +<br />"Sorry, access to servlets by means of\n" +<br />"URLs that begin with\n" +<br />"</font>
						<a href="http://host/webAppPrefix/servlet/" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/</font>
						</a>
						<font size="1">\n" +<br />"has been disabled.\n" + <br />"&lt;/BODY&gt;&lt;/HTML&gt;");<br />}<br /><br />public void doPost(HttpServletRequest request,<br />HttpServletResponse response)<br />throws ServletException, IOException {<br />doGet(request, response);<br />}<br />}<br /><br /><br />4.2 全局禁止激活器：Tomcat<br />Tomcat 4中用来关闭缺省URL的方法与Tomcat 3中所用的很不相同。下面介绍这两种方法：<br />1．禁止激活器： Tomcat 4<br />Tomcat 4用与前面相同的方法关闭激活器servlet，即利用web.xml中的url-mapping元素进行关闭。不同之处在于Tomcat使用了放在 install_dir/conf中的一个服务器专用的全局web.xml文件，而前面使用的是存放在每个Web应用的WEB-INF目录中的标准 web.xml文件。<br />因此，为了在Tomcat 4中关闭激活器servlet，只需在install_dir/conf/web.xml中简单地注释出/servlet/* URL映射项即可，如下所示：<br />&lt;!-- <br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt;invoker&lt;/servlet-name&gt;<br />&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br />--&gt;<br />再次提醒，应该注意这个项是位于存放在install_dir/conf的Tomcat专用的web.xml文件中的，此文件不是存放在每个Web应用的WEB-INF目录中的标准web.xml。<br />2．禁止激活器：Tomcat3<br />在Apache Tomcat的版本3中，通过在install_dir/conf/server.xml中注释出InvokerInterceptor项全局禁止缺省 servlet URL。例如，下面是禁止使用缺省servlet URL的server.xml文件的一部分。<br />&lt;!-- <br />&lt;RequsetInterceptor <br />className="org.apache.tomcat.request.InvokerInterceptor"<br />debug="0" prefix="/servlet/" /&gt;<br />--&gt;<br /><br />5 初始化和预装载servlet与JSP页面<br /><br />这里讨论控制servlet和JSP页面的启动行为的方法。特别是，说明了怎样分配初始化参数以及怎样更改服务器生存期中装载servlet和JSP页面的时刻。<br />5.1 分配servlet初始化参数<br />利用init-param元素向servlet提供初始化参数，init-param元素具有param-name和param-value子元素。例如，在下面的例子中，如果initServlet servlet是利用它的注册名（InitTest）访问的，它将能够从其方法中调用getServletConfig(). getInitParameter("param1")获得"Value 1"，调用getServletConfig().getInitParameter("param2")获得"2"。<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;InitTest&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;moreservlets.InitServlet&lt;/servlet-class&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;param1&lt;/param-name&gt;<br />&lt;param-value&gt;value1&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;param2&lt;/param-name&gt;<br />&lt;param-value&gt;2&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;/servlet&gt;<br />在涉及初始化参数时，有几点需要注意：<br />l 返回值。GetInitParameter的返回值总是一个String。因此，在前一个例子中，可对param2使用Integer.parseInt获得一个int。<br />l JSP中的初始化。JSP页面使用jspInit而不是init。JSP页面还需要使用jsp-file元素代替servlet-class。<br />l 缺省URL。初始化参数只在通过它们的注册名或与它们注册名相关的定制URL模式访问Servlet时可以使用。因此，在这个例子中，param1和 param2初始化参数将能够在使用URL </font>
						<a href="http://host/webAppPrefix/servlet/InitTest" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/InitTest</font>
						</a>
						<font size="1">时可用，但在使用URL </font>
						<a href="http://host/webAppPrefix/servlet/myPackage.InitServlet" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/myPackage.InitServlet</font>
						</a>
						<font size="1">时不能使用。<br />例如，程序清单5-7给出一个名为InitServlet的简单servlet，它使用init方法设置firstName和emailAddress字段。程序清单5-8给出分配名称InitTest给servlet的web.xml文件。<br />程序清单5-7 InitServlet.java<br />package moreservlets;<br /><br />import java.io.*;<br />import javax.servlet.*;<br />import javax.servlet.http.*;<br /><br />/** Simple servlet used to illustrate servlet<br />* initialization parameters.<br />* &lt;P&gt;<br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font>
						<a href="http://www.moreservlets.com/." target="_blank">
								<font size="1">http://www.moreservlets.com/.</font>
						</a>
						<br />
						<font size="1">* © 2002 Marty Hall; may be freely used or adapted.<br />*/<br /><br />public class InitServlet extends HttpServlet {<br />private String firstName, emailAddress;<br /><br />public void init() {<br />ServletConfig config = getServletConfig();<br />firstName = config.getInitParameter("firstName");<br />emailAddress = config.getInitParameter("emailAddress");<br />}<br /><br />public void doGet(HttpServletRequest request,<br />HttpServletResponse response)<br />throws ServletException, IOException {<br />response.setContentType("text/html");<br />PrintWriter out = response.getWriter();<br />String uri = request.getRequestURI();<br />out.println(ServletUtilities.headWithTitle("Init Servlet") +<br />"&lt;BODY BGCOLOR=\"#FDF5E6\"&gt;\n" +<br />"&lt;H2&gt;Init Parameters:&lt;/H2&gt;\n" +<br />"&lt;UL&gt;\n" +<br />"&lt;LI&gt;First name: " + firstName + "\n" +<br />"&lt;LI&gt;Email address: " + emailAddress + "\n" +<br />"&lt;/UL&gt;\n" + <br />"&lt;/BODY&gt;&lt;/HTML&gt;");<br />}<br />}<br /><br /><br />程序清单5-8 web.xml（说明初始化参数的摘录）<br />&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />&lt;!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font>
						<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank">
								<font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font>
						</a>
						<font size="1">"&gt;<br /><br />&lt;web-app&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;InitTest&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;moreservlets.InitServlet&lt;/servlet-class&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;firstName&lt;/param-name&gt;<br />&lt;param-value&gt;Larry&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;emailAddress&lt;/param-name&gt;<br />&lt;param-value&gt;</font>
						<a href="mailto:Ellison@Microsoft.com">
								<font size="1">Ellison@Microsoft.com</font>
						</a>
						<font size="1">&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;/servlet&gt;<br />&lt;!-- ... --&gt;<br />&lt;/web-app&gt;<br /><br />5.2 分配JSP初始化参数<br />给JSP页面提供初始化参数在三个方面不同于给servlet提供初始化参数。<br />1）使用jsp-file而不是servlet-class。因此，WEB-INF/web.xml文件的servlet元素如下所示：<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />&lt;jsp-file&gt;/RealPage.jsp&lt;/jsp-file&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;...&lt;/param-name&gt;<br />&lt;param-value&gt;...&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />...<br />&lt;/servlet&gt;<br />2) 几乎总是分配一个明确的URL模式。对servlet，一般相应地使用以</font>
						<a href="http://host/webAppPrefix/servlet/" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/</font>
						</a>
						<font size="1">开始的缺省URL。只需记住，使用注册名而不是原名称即可。这对于JSP页面在技术上也是合法的。例如，在上面给出的例子中，可用URL </font>
						<a href="http://host/webAppPrefix/servlet/PageName" target="_blank">
								<font size="1">http://host/webAppPrefix/servlet/PageName</font>
						</a>
						<font size="1">访问RealPage.jsp的对初始化参数具有访问权的版本。但在用于JSP页面时，许多用户似乎不喜欢应用常规的servlet的URL。此外，如果 JSP页面位于服务器为其提供了目录清单的目录中（如，一个既没有index.html也没有index.jsp文件的目录），则用户可能会连接到此 JSP页面，单击它，从而意外地激活未初始化的页面。因此，好的办法是使用url-pattern（5.3节）将JSP页面的原URL与注册的 servlet名相关联。这样，客户机可使用JSP页面的普通名称，但仍然激活定制的版本。例如，给定来自项目1的servlet定义，可使用下面的 servlet-mapping定义：<br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />&lt;url-pattern&gt;/RealPage.jsp&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br />3）JSP页使用jspInit而不是init。自动从JSP页面建立的servlet或许已经使用了inti方法。因此，使用JSP声明提供一个init方法是不合法的，必须制定jspInit方法。<br />为了说明初始化JSP页面的过程，程序清单5-9给出了一个名为InitPage.jsp的JSP页面，它包含一个jspInit方法且放置于 deployDemo Web应用层次结构的顶层。一般，</font>
						<a href="http://host/deployDemo/InitPage.jsp" target="_blank">
								<font size="1">http://host/deployDemo/InitPage.jsp</font>
						</a>
						<font size="1">形式的URL将激活此页面的不具有初始化参数访问权的版本，从而将对firstName和emailAddress变量显示null。但是， web.xml文件（程序清单5-10）分配了一个注册名，然后将该注册名与URL模式/InitPage.jsp相关联。<br /><br />程序清单5-9 InitPage.jsp<br />&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;<br />&lt;HTML&gt;<br />&lt;HEAD&gt;&lt;TITLE&gt;JSP Init Test&lt;/TITLE&gt;&lt;/HEAD&gt;<br />&lt;BODY BGCOLOR="#FDF5E6"&gt;<br />&lt;H2&gt;Init Parameters:&lt;/H2&gt;<br />&lt;UL&gt;<br />&lt;LI&gt;First name: &lt;%= firstName %&gt;<br />&lt;LI&gt;Email address: &lt;%= emailAddress %&gt;<br />&lt;/UL&gt;<br />&lt;/BODY&gt;&lt;/HTML&gt;<br />&lt;%!<br />private String firstName, emailAddress;<br /><br />public void jspInit() {<br />ServletConfig config = getServletConfig();<br />firstName = config.getInitParameter("firstName");<br />emailAddress = config.getInitParameter("emailAddress");<br />}<br />%&gt;<br /><br /><br />程序清单5-10 web.xml（说明JSP页面的init参数的摘录）<br />&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />&lt;!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font>
						<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank">
								<font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font>
						</a>
						<font size="1">"&gt;<br /><br />&lt;web-app&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;InitPage&lt;/servlet-name&gt;<br />&lt;jsp-file&gt;/InitPage.jsp&lt;/jsp-file&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;firstName&lt;/param-name&gt;<br />&lt;param-value&gt;Bill&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;init-param&gt;<br />&lt;param-name&gt;emailAddress&lt;/param-name&gt;<br />&lt;param-value&gt;</font>
						<a href="mailto:gates@oracle.com">
								<font size="1">gates@oracle.com</font>
						</a>
						<font size="1">&lt;/param-value&gt;<br />&lt;/init-param&gt;<br />&lt;/servlet&gt;<br />&lt;!-- ... --&gt; <br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt; InitPage&lt;/servlet-name&gt;<br />&lt;url-pattern&gt;/InitPage.jsp&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br />&lt;!-- ... --&gt;<br />&lt;/web-app&gt;<br /><br /><br />5.3 提供应用范围内的初始化参数<br />一般，对单个地servlet或JSP页面分配初始化参数。指定的servlet或JSP页面利用ServletConfig的getInitParameter方法读取这些参数。但是，在某些情形下，希望提供可由任意servlet或JSP页面借助ServletContext的getInitParameter方法读取的系统范围内的初始化参数。<br />可利用context-param元素声明这些系统范围内的初始化值。context-param元素应该包含param-name、param-value以及可选的description子元素，如下所示：<br />&lt;context-param&gt;<br />&lt;param-name&gt;support-email&lt;/param-name&gt;<br />&lt;param-value&gt;</font>
						<a href="mailto:blackhole@mycompany.com">
								<font size="1">blackhole@mycompany.com</font>
						</a>
						<font size="1">&lt;/param-value&gt;<br />&lt;/context-param&gt;<br />可回忆一下，为了保证可移植性，web.xml内的元素必须以正确的次序声明。但这里应该注意，context-param元素必须出现任意与文档有关的元素（icon、display-name或description）之后及filter、filter-mapping、listener或 servlet元素之前。<br />5.4 在服务器启动时装载servlet<br />假如servlet或JSP页面有一个要花很长时间执行的init （servlet）或jspInit（JSP）方法。例如，假如init或jspInit方法从某个数据库或ResourceBundle查找产量。这种情况下，在第一个客户机请求时装载servlet的缺省行为将对第一个客户机产生较长时间的延迟。因此，可利用servlet的load-on- startup元素规定服务器在第一次启动时装载servlet。下面是一个例子。<br />&lt;servlet&gt;<br />&lt;servlet-name&gt; … &lt;/servlet-name&gt;<br />&lt;servlet-class&gt; … &lt;/servlet-class&gt; &lt;!-- Or jsp-file --&gt;<br />&lt;load-on-startup/&gt;<br />&lt;/servlet&gt;<br />可以为此元素体提供一个整数而不是使用一个空的load-on-startup。想法是服务器应该在装载较大数目的servlet或JSP页面之前装载较少数目的servlet或JSP页面。例如，下面的servlet项（放置在Web应用的WEB-INF目录下的web.xml文件中的web-app元素内）将指示服务器首先装载和初始化SearchServlet，然后装载和初始化由位于Web应用的result目录中的index.jsp文件产生的 servlet。<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;Search&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;myPackage.SearchServlet&lt;/servlet-class&gt; &lt;!-- Or jsp-file --&gt;<br />&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />&lt;/servlet&gt;<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;Results&lt;/servlet-name&gt;<br />&lt;servlet-class&gt;/results/index.jsp&lt;/servlet-class&gt; &lt;!-- Or jsp-file --&gt;<br />&lt;load-on-startup&gt;2&lt;/load-on-startup&gt;<br />&lt;/servlet&gt;<br /><br />6 声明过滤器<br /><br />servlet版本2.3引入了过滤器的概念。虽然所有支持servlet API版本2.3的服务器都支持过滤器，但为了使用与过滤器有关的元素，必须在web.xml中使用版本2.3的DTD。<br />过滤器可截取和修改进入一个servlet或JSP页面的请求或从一个servlet或JSP页面发出的相应。在执行一个servlet或JSP页面之前，必须执行第一个相关的过滤器的doFilter方法。在该过滤器对其FilterChain对象调用doFilter时，执行链中的下一个过滤器。如果没有其他过滤器，servlet或JSP页面被执行。过滤器具有对到来的ServletRequest对象的全部访问权，因此，它们可以查看客户机名、查找到来的cookie等。为了访问servlet或JSP页面的输出，过滤器可将响应对象包裹在一个替身对象（stand-in object）中，比方说把输出累加到一个缓冲区。在调用FilterChain对象的doFilter方法之后，过滤器可检查缓冲区，如有必要，就对它进行修改，然后传送到客户机。<br />例如，程序清单5-11帝国难以了一个简单的过滤器，只要访问相关的servlet或JSP页面，它就截取请求并在标准输出上打印一个报告（开发过程中在桌面系统上运行时，大多数服务器都可以使用这个过滤器）。<br /><br />程序清单5-11 ReportFilter.java<br />package moreservlets;<br /><br />import java.io.*;<br />import javax.servlet.*;<br />import javax.servlet.http.*;<br />import java.util.*;<br /><br />/** Simple filter that prints a report on the standard output <br />* whenever the associated servlet or JSP page is accessed.<br />* &lt;P&gt;<br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font>
						<a href="http://www.moreservlets.com/." target="_blank">
								<font size="1">http://www.moreservlets.com/.</font>
						</a>
						<br />
						<font size="1">* © 2002 Marty Hall; may be freely used or adapted.<br />*/<br /><br />public class ReportFilter implements Filter {<br />public void doFilter(ServletRequest request,<br />ServletResponse response,<br />FilterChain chain)<br />throws ServletException, IOException {<br />HttpServletRequest req = (HttpServletRequest)request;<br />System.out.println(req.getRemoteHost() +<br />" tried to access " +<br />req.getRequestURL() +<br />" on " + new Date() + ".");<br />chain.doFilter(request,response);<br />}<br /><br />public void init(FilterConfig config)<br />throws ServletException {<br />}<br /><br />public void destroy() {}<br />}<br /><br />一旦建立了一个过滤器，可以在web.xml中利用filter元素以及filter-name（任意名称）、file-class（完全限定的类名）和（可选的）init-params子元素声明它。请注意，元素在web.xml的web-app元素中出现的次序不是任意的；允许服务器（但不是必需的）强制所需的次序，并且实际中有些服务器也是这样做的。但这里要注意，所有filter元素必须出现在任意filter-mapping元素之前， filter-mapping元素又必须出现在所有servlet或servlet-mapping元素之前。<br />例如，给定上述的ReportFilter类，可在web.xml中作出下面的filter声明。它把名称Reporter与实际的类ReportFilter（位于moreservlets程序包中）相关联。<br />&lt;filter&gt;<br />&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />&lt;filter-class&gt;moresevlets.ReportFilter&lt;/filter-class&gt;<br />&lt;/filter&gt;<br />一旦命名了一个过滤器，可利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。关于此项工作有两种选择。<br />首先，可使用filter-name和servlet-name子元素把此过滤器与一个特定的servlet名（此servlet名必须稍后在相同的 web.xml文件中使用servlet元素声明）关联。例如，下面的程序片断指示系统只要利用一个定制的URL访问名为SomeServletName 的servlet或JSP页面，就运行名为Reporter的过滤器。<br />&lt;filter-mapping&gt;<br />&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />&lt;servlet-name&gt;SomeServletName&lt;/servlet-name&gt;<br />&lt;/filter-mapping&gt;<br />其次，可利用filter-name和url-pattern子元素将过滤器与一组servlet、JSP页面或静态内容相关联。例如，相面的程序片段指示系统只要访问Web应用中的任意URL，就运行名为Reporter的过滤器。<br />&lt;filter-mapping&gt;<br />&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />&lt;/filter-mapping&gt;<br />例如，程序清单5-12给出了将ReportFilter过滤器与名为PageName的servlet相关联的web.xml文件的一部分。名字 PageName依次又与一个名为TestPage.jsp的JSP页面以及以模式http: //host/webAppPrefix/UrlTest2/ 开头的URL相关联。TestPage.jsp的源代码已经JSP页面命名的谈论在前面的3节"分配名称和定制的URL"中给出。事实上，程序清单5- 12中的servlet和servlet-name项从该节原封不动地拿过来的。给定这些web.xml项，可看到下面的标准输出形式的调试报告（换行是为了容易阅读）。<br />audit.irs.gov tried to access <br /></font>
						<a href="http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html" target="_blank">
								<font size="1">http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html</font>
						</a>
						<br />
						<font size="1">on Tue Dec 25 13:12:29 EDT 2001.<br /><br />程序清单5-12 Web.xml（说明filter用法的摘录）<br />&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />&lt;!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font>
						<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank">
								<font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font>
						</a>
						<font size="1">"&gt;<br /><br />&lt;web-app&gt;<br />&lt;filter&gt;<br />&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />&lt;filter-class&gt;moresevlets.ReportFilter&lt;/filter-class&gt;<br />&lt;/filter&gt;<br />&lt;!-- ... --&gt;<br />&lt;filter-mapping&gt;<br />&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />&lt;/filter-mapping&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet&gt;<br />&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />&lt;jsp-file&gt;/RealPage.jsp&lt;/jsp-file&gt;<br />&lt;/servlet&gt;<br />&lt;!-- ... --&gt;<br />&lt;servlet-mapping&gt;<br />&lt;servlet-name&gt; PageName &lt;/servlet-name&gt;<br />&lt;url-pattern&gt;/UrlTest2/*&lt;/url-pattern&gt;<br />&lt;/servlet-mapping&gt;<br />&lt;!-- ... --&gt;<br />&lt;/web-app&gt;<br /><br /><br />7 指定欢迎页<br /><br />假如用户提供了一个像http: //host/webAppPrefix/directoryName/ 这样的包含一个目录名但没有包含文件名的URL，会发生什么事情呢？用户能得到一个目录表？一个错误？还是标准文件的内容？如果得到标准文件内容，是 index.html、index.jsp、default.html、default.htm或别的什么东西呢？<br />Welcome-file-list 元素及其辅助的welcome-file元素解决了这个模糊的问题。例如，下面的web.xml项指出，如果一个URL给出一个目录名但未给出文件名，服务器应该首先试用index.jsp，然后再试用index.html。如果两者都没有找到，则结果有赖于所用的服务器（如一个目录列表）。<br />&lt;welcome-file-list&gt;<br />&lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;<br />&lt;welcome-file&gt;index.html&lt;/welcome-file&gt;<br />&lt;/welcome-file-list&gt;<br />虽然许多服务器缺省遵循这种行为，但不一定必须这样。因此，明确地使用welcom-file-list保证可移植性是一种良好的习惯。<br /><br />8 指定处理错误的页面<br /><br />现在我了解到，你在开发servlet和JSP页面时从不会犯错误，而且你的所有页面是那样的清晰，一般的程序员都不会被它们的搞糊涂。但是，是人总会犯错误的，用户可能会提供不合规定的参数，使用不正确的URL或者不能提供必需的表单字段值。除此之外，其它开发人员可能不那么细心，他们应该有些工具来克服自己的不足。<br />error-page元素就是用来克服这些问题的。它有两个可能的子元素，分别是：error-code和exception- type。第一个子元素error-code指出在给定的HTTP错误代码出现时使用的URL。第二个子元素excpetion-type指出在出现某个给定的Java异常但未捕捉到时使用的URL。error-code和exception-type都利用location元素指出相应的URL。此 URL必须以/开始。location所指出的位置处的页面可通过查找HttpServletRequest对象的两个专门的属性来访问关于错误的信息，这两个属性分别是：javax.servlet.error.status_code和javax.servlet.error.message。<br />可回忆一下，在web.xml内以正确的次序声明web-app的子元素很重要。这里只要记住，error-page出现在web.xml文件的末尾附近，servlet、servlet-name和welcome-file-list之后即可。<br /><br />8.1 error-code元素<br />为了更好地了解error-code元素的值，可考虑一下如果不正确地输入文件名，大多数站点会作出什么反映。这样做一般会出现一个404错误信息，它表示不能找到该文件，但几乎没提供更多有用的信息。另一方面，可以试一下在</font>
						<a href="http://www.microsoft.com/" target="_blank">
								<font size="1">www.microsoft.com</font>
						</a>
						<font size="1">、</font>
						<a href="http://www.ibm.com/" target="_blank">
								<font size="1">www.ibm.com</font>
						</a>
						<font size="1">处或者特别是在</font>
						<a href="http://www.bea.com/" target="_blank">
								<font size="1">www.bea.com</font>
						</a>
						<font size="1">处输出未知的文件名。这是会得出有用的消息，这些消息提供可选择的位置，以便查找感兴趣的页面。提供这样有用的错误页面对于Web应用来说是很有价值得。事实上rm-error-page子元素）。由form-login-page给出的HTML表单必须具有一个j_security_check的 ACTION属性、一个名为j_username的用户名文本字段以及一个名为j_password的口令字段。<br />例如，程序清单5-19指示服务器使用基于表单的验证。Web应用的顶层目录中的一个名为login.jsp的页面将收集用户名和口令，并且失败的登陆将由相同目录中名为login-error.jsp的页面报告。<br /><br />程序清单5-19 web.xml（说明login-config的摘录）<br />&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />&lt;!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font>
						<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank">
								<font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font>
						</a>
						<font size="1">"&gt;<br /><br />&lt;web-app&gt;<br />&lt;!-- ... --&gt;<br />&lt;security-constraint&gt; ... &lt;/security-constraint&gt;<br />&lt;login-config&gt;<br />&lt;auth-method&gt; FORM &lt;/auth-method&gt;<br />&lt;form-login-config&gt;<br />&lt;form-login-page&gt;/login.jsp&lt;/form-login-page&gt;<br />&lt;form-error-page&gt;/login-error.jsp&lt;/form-error-page&gt;<br />&lt;/form-login-config&gt;<br />&lt;/login-config&gt;<br />&lt;!-- ... --&gt;<br />&lt;/web-app&gt;<br /><br /><br />9.2 限制对Web资源的访问<br />现在，可以指示服务器使用何种验证方法了。"了不起，"你说道，"除非我能指定一个来收到保护的 URL，否则没有多大用处。"没错。指出这些URL并说明他们应该得到何种保护正是security-constriaint元素的用途。此元素在 web.xml中应该出现在login-config的紧前面。它包含是个可能的子元素，分别是：web-resource-collection、 auth-constraint、user-data-constraint和display-name。下面各小节对它们进行介绍。<br />l web-resource-collection<br />此元素确定应该保护的资源。所有security-constraint元素都必须包含至少一个web-resource-collection项。此元素由一个给出任意标识名称的web-resource-name元素、一个确定应该保护的URL的url-pattern元素、一个指出此保护所适用的 HTTP命令（GET、POST等，缺省为所有方法）的http-method元素和一个提供资料的可选description元素组成。例如，下面的 Web-resource-collection项（在security-constratint元素内）指出Web应用的proprietary目录中所有文档应该受到保护。<br />&lt;security-constraint&gt;<br />&lt;web-resource-coolection&gt;<br />&lt;web-resource-name&gt;Proprietary&lt;/web-resource-name&gt;<br />&lt;url-pattern&gt;/propritary/*&lt;/url-pattern&gt;<br />&lt;/web-resource-coolection&gt;<br />&lt;!-- ... --&gt;<br />&lt;/security-constraint&gt;<br />重要的是应该注意到，url-pattern仅适用于直接访问这些资源的客户机。特别是，它不适合于通过MVC体系结构利用 RequestDispatcher来访问的页面，或者不适合于利用类似jsp:forward的手段来访问的页面。这种不匀称如果利用得当的话很有好处。例如，servlet可利用MVC体系结构查找数据，把它放到bean中，发送请求到从bean中提取数据的JSP页面并显示它。我们希望保证决不直接访问受保护的JSP页面，而只是通过建立该页面将使用的bean的servlet来访问它。url-pattern和auth-contraint元素可通过声明不允许任何用户直接访问JSP页面来提供这种保证。但是，这种不匀称的行为可能让开发人员放松警惕，使他们偶然对应受保护的资源提供不受限制的访问。 <br />l auth-constraint<br />尽管web-resource-collention元素质出了哪些URL应该受到保护，但是auth-constraint元素却指出哪些用户应该具有受保护资源的访问权。此元素应该包含一个或多个标识具有访问权限的用户类别role- name元素，以及包含（可选）一个描述角色的description元素。例如，下面web.xml中的security-constraint元素部门规定只有指定为Administrator或Big Kahuna（或两者）的用户具有指定资源的访问权。<br />&lt;security-constraint&gt;<br />&lt;web-resource-coolection&gt; ... &lt;/web-resource-coolection&gt;<br />&lt;auth-constraint&gt;<br />&lt;role-name&gt;administrator&lt;/role-name&gt;<br />&lt;role-name&gt;kahuna&lt;/role-name&gt;<br />&lt;/auth-constraint&gt;<br />&lt;/security-constraint&gt;<br />重要的是认识到，到此为止，这个过程的可移植部分结束了。服务器怎样确定哪些用户处于任何角色以及它怎样存放用户的口令，完全有赖于具体的系统。<br />例如，Tomcat使用install_dir/conf/tomcat-users.xml将用户名与角色名和口令相关联，正如下面例子中所示，它指出用户joe（口令bigshot）和jane（口令enaj）属于administrator和kahuna角色。<br />&lt;tomcat-users&gt;<br />&lt;user name="joe" password="bigshot" roles="administrator,kahuna" /&gt;<br />&lt;user name="jane" password="enaj" roles="kahuna" /&gt;<br />&lt;/tomcat-users&gt;<br />l user-data-constraint<br />这个可选的元素指出在访问相关资源时使用任何传输层保护。它必须包含一个transport-guarantee子元素（合法值为NONE、 INTEGRAL或CONFIDENTIAL），并且可选地包含一个description元素。transport-guarantee为NONE值将对所用的通讯协议不加限制。INTEGRAL值表示数据必须以一种防止截取它的人阅读它的方式传送。虽然原理上（并且在未来的HTTP版本中），在 INTEGRAL和CONFIDENTIAL之间可能会有差别，但在当前实践中，他们都只是简单地要求用SSL。例如，下面指示服务器只允许对相关资源做 HTTPS连接：<br />&lt;security-constraint&gt;<br />&lt;!-- ... --&gt;<br />&lt;user-data-constraint&gt;<br />&lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;<br />&lt;/user-data-constraint&gt;<br />&lt;/security-constraint&gt;<br />l display-name<br />security-constraint的这个很少使用的子元素给予可能由GUI工具使用的安全约束项一个名称。<br />9.3 分配角色名<br />迄今为止，讨论已经集中到完全由容器（服务器）处理的安全问题之上了。但servlet以及JSP页面也能够处理它们自己的安全问题。<br />例如，容器可能允许用户从bigwig或bigcheese角色访问一个显示主管人员额外紧贴的页面，但只允许bigwig用户修改此页面的参数。完成这种更细致的控制的一种常见方法是调用HttpServletRequset的isUserInRole方法，并据此修改访问。<br />Servlet的 security-role-ref子元素提供出现在服务器专用口令文件中的安全角色名的一个别名。例如，假如编写了一个调用 request.isUserInRole（"boss"）的servlet，但后来该servlet被用在了一个其口令文件调用角色manager而不是boss的服务器中。下面的程序段使该servlet能够使用这两个名称中的任何一个。<br />&lt;servlet&gt;<br />&lt;!-- ... --&gt;<br />&lt;security-role-ref&gt;<br />&lt;role-name&gt;boss&lt;/role-name&gt; &lt;!-- New alias --&gt;<br />&lt;role-link&gt;manager&lt;/role-link&gt; &lt;!-- Real name --&gt;<br />&lt;/security-role-ref&gt;<br />&lt;/servlet&gt;<br />也可以在web-app内利用security-role元素提供将出现在role-name元素中的所有安全角色的一个全局列表。分别地生命角色使高级IDE容易处理安全信息。<br /><br />10 控制会话超时<br /><br />如果某个会话在一定的时间内未被访问，服务器可把它扔掉以节约内存。可利用HttpSession的setMaxInactiveInterval方法直接设置个别会话对象的超时值。如果不采用这种方法，则缺省的超时值由具体的服务器决定。但可利用session-config和session- timeout元素来给出一个适用于所有服务器的明确的超时值。超时值的单位为分钟，因此，下面的例子设置缺省会话超时值为三个小时（180分钟）。<br />&lt;session-config&gt;<br />&lt;session-timeout&gt;180&lt;/session-timeout&gt;<br />&lt;/session-config&gt;<br /><br />11 Web应用的文档化<br /><br />越来越多的开发环境开始提供servlet和JSP的直接支持。例子有Borland Jbuilder Enterprise Edition、Macromedia UltraDev、Allaire JRun Studio（写此文时，已被Macromedia收购）以及IBM VisuaAge for Java等。<br />大量的web.xml元素不仅是为服务器设计的，而且还是为可视开发环境设计的。它们包括icon、display-name和discription等。<br />可回忆一下，在web.xml内以适当地次序声明web-app子元素很重要。不过，这里只要记住icon、display-name和description是web.xml的web-app元素内的前三个合法元素即可。<br />l icon<br />icon元素指出GUI工具可用来代表Web应用的一个和两个图像文件。可利用small-icon元素指定一幅16 x 16的GIF或JPEG图像，用large-icon元素指定一幅32 x 32的图像。下面举一个例子： <br />&lt;icon&gt;<br />&lt;small-icon&gt;/images/small-book.gif&lt;/small-icon&gt;<br />&lt;large-icon&gt;/images/tome.jpg&lt;/large-icon&gt;<br />&lt;/icon&gt;<br />l display-name<br />display-name元素提供GUI工具可能会用来标记此Web应用的一个名称。下面是个例子。<br />&lt;display-name&gt;Rare Books&lt;/display-name&gt;<br />l description<br />description元素提供解释性文本，如下所示：<br />&lt;description&gt;<br />This Web application represents the store developed for<br />rare-books.com, an online bookstore specializing in rare<br />and limited-edition books.<br />&lt;/description&gt;<br /><br />12 关联文件与MIME类型<br /><br />服务器一般都具有一种让Web站点管理员将文件扩展名与媒体相关联的方法。例如，将会自动给予名为mom.jpg的文件一个image/jpeg的MIME 类型。但是，假如你的Web应用具有几个不寻常的文件，你希望保证它们在发送到客户机时分配为某种MIME类型。mime-mapping元素（具有 extension和mime-type子元素）可提供这种保证。例如，下面的代码指示服务器将application/x-fubar的MIME类型分配给所有以.foo结尾的文件。<br />&lt;mime-mapping&gt;<br />&lt;extension&gt;foo&lt;/extension&gt;<br />&lt;mime-type&gt;application/x-fubar&lt;/mime-type&gt;<br />&lt;/mime-mapping&gt;<br />或许，你的Web应用希望重载（override）标准的映射。例如，下面的代码将告诉服务器在发送到客户机时指定.ps文件作为纯文本（text/plain）而不是作为PostScript（application/postscript）。<br />&lt;mime-mapping&gt;<br />&lt;extension&gt;ps&lt;/extension&gt;<br />&lt;mime-type&gt;application/postscript&lt;/mime-type&gt;<br />&lt;/mime-mapping&gt;<br /><br /><br />13 定位TLD<br /><br />JSP taglib元素具有一个必要的uri属性，它给出一个TLD（Tag Library Descriptor）文件相对于Web应用的根的位置。TLD文件的实际名称在发布新的标签库版本时可能会改变，但我们希望避免更改所有现有JSP页面。此外，可能还希望使用保持taglib元素的简练性的一个简短的uri。这就是部署描述符文件的taglib元素派用场的所在了。Taglib包含两个子元素：taglib-uri和taglib-location。taglib-uri元素应该与用于JSP taglib元素的uri属性的东西相匹配。Taglib-location元素给出TLD文件的实际位置。例如，假如你将文件chart-tags- 1.3beta.tld放在WebApp/WEB-INF/tlds中。现在，假如web.xml在web-app元素内包含下列内容。<br />&lt;taglib&gt;<br />&lt;taglib-uri&gt;/charts.tld&lt;/taglib-uri&gt;<br />&lt;taglib-location&gt;<br />/WEB-INF/tlds/chart-tags-1.3beta.tld<br />&lt;/taglib-location&gt;<br />&lt;/taglib&gt;<br />给出这个说明后，JSP页面可通过下面的简化形式使用标签库。<br />&lt;%@ taglib uri="/charts.tld" prefix="somePrefix" %&gt;<br /><br />14 指定应用事件监听程序<br /><br />应用事件监听器程序是建立或修改servlet环境或会话对象时通知的类。它们是servlet规范的版本2.3中的新内容。这里只简单地说明用来向Web应用注册一个监听程序的web.xml的用法。<br />注册一个监听程序涉及在web.xml的web-app元素内放置一个listener元素。在listener元素内，listener-class元素列出监听程序的完整的限定类名，如下所示：<br />&lt;listener&gt;<br />&lt;listener-class&gt;package.ListenerClass&lt;/listener-class&gt;<br />&lt;/listener&gt;<br />虽然listener元素的结构很简单，但请不要忘记，必须正确地给出web-app元素内的子元素的次序。listener元素位于所有的servlet 元素之前以及所有filter-mapping元素之后。此外，因为应用生存期监听程序是serlvet规范的2.3版本中的新内容，所以必须使用 web.xml DTD的2.3版本，而不是2.2版本。<br />例如，程序清单5-20给出一个名为ContextReporter的简单的监听程序，只要Web应用的Servlet-Context建立（如装载Web应用）或消除（如服务器关闭）时，它就在标准输出上显示一条消息。程序清单5-21给出此监听程序注册所需要的web.xml文件的一部分。<br /><br />程序清单5-20 ContextReporterjava<br />package moreservlets;<br /><br />import javax.servlet.*;<br />import java.util.*;<br /><br />/** Simple listener that prints a report on the standard output <br />* when the ServletContext is created or destroyed.<br />* &lt;P&gt;<br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font>
						<a href="http://www.moreservlets.com/." target="_blank">
								<font size="1">http://www.moreservlets.com/.</font>
						</a>
						<br />
						<font size="1">* © 2002 Marty Hall; may be freely used or adapted.<br />*/<br /><br />public class ContextReporter implements ServletContextListener {<br />public void contextInitialized(ServletContextEvent event) {<br />System.out.println("Context created on " +<br />new Date() + ".");<br />}<br /><br />public void contextDestroyed(ServletContextEvent event) {<br />System.out.println("Context destroyed on " +<br />new Date() + ".");<br />}<br />}<br /><br /><br />程序清单5-21 web.xml（声明一个监听程序的摘录）<br />&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />&lt;!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font>
						<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank">
								<font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font>
						</a>
						<font size="1">"&gt;<br /><br />&lt;web-app&gt;<br />&lt;!-- ... --&gt;<br />&lt;filter-mapping&gt; … &lt;/filter-mapping&gt;<br />&lt;listener&gt;<br />&lt;listener-class&gt;package.ListenerClass&lt;/listener-class&gt;<br />&lt;/listener&gt;<br />&lt;servlet&gt; ... &lt;/servlet&gt;<br />&lt;!-- ... --&gt;<br />&lt;/web-app&gt;<br /><br /><br />15 J2EE元素<br /><br />本节描述用作J2EE环境组成部分的Web应用的web.xml元素。这里将提供一个简明的介绍，详细内容可以参阅</font>
						<a href="http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf" target="_blank">
								<font size="1">http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf</font>
						</a>
						<font size="1">的Java 2 Plantform Enterprise Edition版本1.3规范的第5章。<br />l distributable<br />distributable 元素指出，Web应用是以这样的方式编程的：即，支持集群的服务器可安全地在多个服务器上分布Web应用。例如，一个可分布的应用必须只使用 Serializable对象作为其HttpSession对象的属性，而且必须避免用实例变量（字段）来实现持续性。distributable元素直接出现在discription元素之后，并且不包含子元素或数据，它只是一个如下的标志。<br />&lt;distributable /&gt;<br />l resource-env-ref<br />resource -env-ref元素声明一个与某个资源有关的管理对象。此元素由一个可选的description元素、一个resource-env-ref- name元素（一个相对于java:comp/env环境的JNDI名）以及一个resource-env-type元素（指定资源类型的完全限定的类），如下所示：<br />&lt;resource-env-ref&gt;<br />&lt;resource-env-ref-name&gt;<br />jms/StockQueue<br />&lt;/resource-env-ref-name&gt;<br />&lt;resource-env-ref-type&gt;<br />javax.jms.Queue<br />&lt;/resource-env-ref-type&gt;<br />&lt;/resource-env-ref&gt;<br />l env-entry<br />env -entry元素声明Web应用的环境项。它由一个可选的description元素、一个env-entry-name元素（一个相对于java: comp/env环境JNDI名）、一个env-entry-value元素（项值）以及一个env-entry-type元素（java.lang程序包中一个类型的完全限定类名，java.lang.Boolean、java.lang.String等）组成。下面是一个例子：<br />&lt;env-entry&gt;<br />&lt;env-entry-name&gt;minAmout&lt;/env-entry-name&gt;<br />&lt;env-entry-value&gt;100.00&lt;/env-entry-value&gt;<br />&lt;env-entry-type&gt;minAmout&lt;/env-entry-type&gt;<br />&lt;/env-entry&gt;<br />l ejb-ref<br />ejb -ref元素声明对一个EJB的主目录的应用。它由一个可选的description元素、一个ejb-ref-name元素（相对于java: comp/env的EJB应用）、一个ejb-ref-type元素（bean的类型，Entity或Session）、一个home元素（bean的主目录接口的完全限定名）、一个remote元素（bean的远程接口的完全限定名）以及一个可选的ejb-link元素（当前bean链接的另一个 bean的名称）组成。<br />l ejb-local-ref<br />ejb-local-ref元素声明一个EJB的本地主目录的引用。除了用local-home代替home外，此元素具有与ejb-ref元素相同的属性并以相同的方式使用。<br /><br /><br /><br /><br /><br /><br />17:42 | 固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | 计算机与 Internet <br /><br /><br />固定链接 关闭 <br /><br /></font>
						<a href="http://spaces.msn.com/members/tsfy/Blog/cns!1pFtRRZqZXTCdE5YlUjqVIcQ!116.entry" target="_blank">
								<font size="1">http://spaces.msn.com/members/tsfy/Blog/cns!1pFtRRZqZXTCdE5YlUjqVIcQ!116.entry</font>
						</a>
						<font size="1">
								<br />
								<br />
								<br />
								<br />
								<br />
								<br />
								<br />
								<br />4月14日 <br /><br /><br /><br />给你的session加个监听器 <br /><br /><br />今天一个学生问我怎么实现在网页里显示在线用户的名称——他已经使用了session，但是无法处理用户离开的情况，然后导致在线用户列表的无限增大。跟他说了自己在application中进行超时检查，更新application的时候就比较当前所有列表中的session是否超过自己指定的时间间隔。后来想了想，又给他提了使用给session加监听器的方法。但是提的时候自己也没有做过，所以只是说这种方式很复杂，建议他还是自己进行超时检查。刚才又看了看资料，发现实际上给session加监听器的方式很简单，不禁觉得自己有点误人子弟了，现在将方法写在这，借以告诫自己以后要严谨。<br />首先写一个SessionBinder类,它实现了HttpSessionBindingListener接口的valueBound方法和valueUnbound方法，示例代码如下：<br />public class SessionBinder implements HttpSessionBindingListener {<br />  public void valueBound(HttpSessionBindingEvent event){<br />    //you can do anything you want!this method will be called when this binder is bind with any session.<br />  }<br /><br />  public void valueUnbound(HttpSessionBindingEvent event) {<br />    //you can do something while this session is invalidate<br />  }<br />}<br />现在写好了SessionBinder，我们现在选择在一个servlet中向session中加入这个监听器——在jsp中的代码书写与此相同<br />//省略前面的代码，此操作可能发生在servlet的doGet方法中，也可能是doPost方法中<br />  HttpSession session = req.getSession(true);//首先获得需要加入监听器的session对象，req是HttpRequest对象<br />  SessionBinder sb = new SessionBinder();//建立一个监听器对象<br />  session.putValue("BinderObject",sb);//将监听器加入此session中，从此时开始执行sb的valueBound方法<br />//省略后面的代码<br />随后，如果整个session超时或者被用户中止之后，sb的valueUnbound自动执行<br />呵呵，以上代码以供参</font>
				</span>
				<font size="1">
				</font>
		</span>
<img src ="http://www.blogjava.net/weibogao/aggbug/38618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-04-01 16:38 <a href="http://www.blogjava.net/weibogao/archive/2006/04/01/38618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>the study of website about java</title><link>http://www.blogjava.net/weibogao/archive/2006/03/30/38356.html</link><dc:creator>weibogao</dc:creator><author>weibogao</author><pubDate>Thu, 30 Mar 2006 12:43:00 GMT</pubDate><guid>http://www.blogjava.net/weibogao/archive/2006/03/30/38356.html</guid><wfw:comment>http://www.blogjava.net/weibogao/comments/38356.html</wfw:comment><comments>http://www.blogjava.net/weibogao/archive/2006/03/30/38356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/weibogao/comments/commentRss/38356.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/weibogao/services/trackbacks/38356.html</trackback:ping><description><![CDATA[it's necessary to sum up the worthy studying for java websites,and descing by frequecy,they are <a href="http://www.javaeye.com,www.ibm.com/developerworks/cn ,www.theserverside.com,www.csdn.net,www.matrix.org.cn,www.javaresearch.org,www.javafan.net,dev2dev.bea.com.cn,http://www.open-open.com,www.jdon.com">www.<font color="#0000ff">javaeye.com</font><font color="#0000ff">,<font size="2">www.ibm.com/developerworks/cn </font>,<br />www</font>.theserverside.com,www.csdn.net,www.matrix.org.cn,<br />www.javaresearch.org,www.javafan.net,dev2dev.bea.com.cn,http://www.open-open.com,www.jdon.com<br /></a>welcome to add your favourite website here  <img src ="http://www.blogjava.net/weibogao/aggbug/38356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/weibogao/" target="_blank">weibogao</a> 2006-03-30 20:43 <a href="http://www.blogjava.net/weibogao/archive/2006/03/30/38356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>