??xml version="1.0" encoding="utf-8" standalone="yes"?>国产亚洲依依,久久只精品国产,日韩高清一区http://www.aygfsteel.com/weibogao/category/10168.htmlmy second lifespacezh-cnThu, 04 Mar 2010 18:38:07 GMTThu, 04 Mar 2010 18:38:07 GMT60常用的算法网站汇?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/weibogao/archive/2010/03/04/314514.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/314514.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2010/03/04/314514.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/314514.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/314514.html</trackback:ping><description><![CDATA[1.http://caterpillar.onlyfun.net/Gossip/AlgorithmGossip/AlgorithmGossip.htmQ包括cQjava{的不同实现Q基l习很有用)<br /> 2.http://www.javaeye.com/forums/tag/algorithmQ专业java|站上的论坛Q很不错Q?br /> 3.待箋。。。。。?br /> <img src ="http://www.aygfsteel.com/weibogao/aggbug/314514.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2010-03-04 14:21 <a href="http://www.aygfsteel.com/weibogao/archive/2010/03/04/314514.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate扚w处理的性能优化问题http://www.aygfsteel.com/weibogao/archive/2006/12/27/90245.htmlweibogaoweibogaoWed, 27 Dec 2006 03:16:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/12/27/90245.htmlhttp://www.aygfsteel.com/weibogao/comments/90245.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/12/27/90245.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/90245.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/90245.html
Hibernate扚w处理:

Hibernate扚w处理其实从性能上考虑Q它是很不可取的Q浪费了很大的内存。从它的机制上讲QHibernate它是先把W合条g的数据查出来Q放到内存当中,然后再进行操作。实际用下来性能非常不理?在笔者的实际
使用中采用下面的W三U优化方案的数据?100000条数据插入数据库,L台式机的配置,需要约30分钟,呵呵,晕?

ȝ下来有三U来处理以解x能问题Q?/p>

1Q绕qHibernate API Q直接通过 JDBC API 来做Q这个方法性能上是比较好的。也是最快的.

2Q运用存储过E?/p>

3Q还是用Hibernate API 来进行常规的扚w处理Q可以也有变Q变变在,我们可以在查扑և一定的量的时候,及时的将q些数据做完操作?/p>

删掉Qsession.flush();session.evict(XX对象?; q样也可以挽救一Ҏ能损失。这个“一定的量”要pҎ实际情况做定量参考了。一般ؓ30-60左右,但效果仍然不理想.

 

 

1Q绕qHibernate API Q直接通过 JDBC API 来做Q这个方法性能上是比较好的Q也是最快的?实例?更新操作)

 

Transaction tx=session.beginTransaction(); //注意用的是hibernate事务处理边界

Connection conn=session.connection();

PreparedStatement stmt=conn.preparedStatement("update CUSTOMER as C set C.sarlary=c.sarlary+1 where c.sarlary>1000");

stmt.excuteUpdate();

tx.commit(); //注意用的是hibernate事务处理边界

q小E序中,采用的是直接调用JDBC 的API 来访问数据库Q效率很高。避免了Hibernate 先查询出来加载到内存Q再q行操作引发的性能问题

?

2Q运用存储过E。但q种方式考虑到易植和E序部v的方便?不徏议?(实例?更新操作)

如果底层数据库(如OracleQ支持存储过E,也可以通过存储q程来执行批量更新。存储过E直接在数据库中q行Q速度更加快。在Oracle?/p>

据库中可以定义一个名为batchUpdateCustomer()的存储过E,代码如下Q?


代码内容
create or replace procedure batchUpdateCustomer(p_age in number) as
begin
update CUSTOMERS set AGE=AGE+1 where AGE>p_age;
end; 


以上存储q程有一个参数p_ageQ代表客Lq龄Q应用程序可按照以下方式调用存储q程Q?

代码内容
tx = session.beginTransaction();
Connection con=session.connection();
String procedure = "{call batchUpdateCustomer(?) }";
CallableStatement cstmt = con.prepareCall(procedure);
cstmt.setInt(1,0); //把年龄参数设?
cstmt.executeUpdate();
tx.commit(); 


从上面程序看出,应用E序也必ȝqHibernate APIQ直接通过JDBC API来调用存储过E?

3Q还是用Hibernate API 来进行常规的扚w处理Q可以也有变Q变变在,我们可以在查扑և一定的量的时候,及时的将q些数据做完操作?/p>

删掉Qsession.flush();session.evict(XX对象?; q样也可以挽救一Ҏ能损失。这个“一定的量”要pҎ实际情况做定量参考了。?/p>

(实例?保存操作)

业务逻辑为:我们要想数据库插?0 0000 条数?/p>

tx=session.beginTransaction();

for(int i=0;i<100000;i++)

{

Customer custom=new Customer();

custom.setName("user"+i);

session.save(custom);

if(i%50==0) // 以每50个数据作Z个处理单元,也就是我上面说的“一定的量”,q个量是要酌情考虑?/p>

{

session.flush();

session.clear();

}

}

q样可以把系l维持在一个稳定的范围....



weibogao 2006-12-27 11:16 发表评论
]]>
模式对话框的详细使用说明http://www.aygfsteel.com/weibogao/archive/2006/09/20/70715.htmlweibogaoweibogaoWed, 20 Sep 2006 02:27:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/09/20/70715.htmlhttp://www.aygfsteel.com/weibogao/comments/70715.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/09/20/70715.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/70715.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/70715.htmljavascript有许多内建的Ҏ来生对话框Q如Qwindow.alert(), window.confirm(),window.prompt().{?然而IE提供更多的方法支持对话框。如Q?

  showModalDialog() (IE 4+ 支持)
  showModelessDialog() (IE 5+ 支持)


window.showModalDialog()Ҏ用来创徏一个显CHTML内容的模态对话框Q由于是对话框,因此它ƈ没有一般用window.open()打开的窗口的所有属性?
window.showModelessDialog()Ҏ用来创徏一个显CHTML内容的非模态对话框?

当我们用showModelessDialog()打开H口Ӟ不必用window.close()d闭它Q当以非模态方式EIE5Q打开Ӟ 打开对话框的H口仍可以进行其他的操作Q即对话框不L最上面的焦点,当打开它的H口QRQ改变时Q它自动关闭。而模态EQIQ]方式的对话框始终有焦点(焦点不可U走Q直到它关闭Q。模态对话框和打开它的H口相联p,因此我们打开另外的窗口时Q他们的链接关系依然保存Qƈ且隐藏在zdH口的下面?

使用Ҏ如下Q?
vReturnvalue = window.showModalDialog(sURL [, vArguments] [, sFeatures])
vReturnvalue = window.showModelessDialog(sURL [, vArguments] [, sFeatures])
参数说明Q?
sURL
必选参敎ͼcdQ字W串。用来指定对话框要显C的文的URL?
vArguments
可选参敎ͼcdQ变体。用来向对话框传递参数。传递的参数cd不限Q包括数l等。对话框通过window.dialogArguments来取得传递进来的参数?
sFeatures
可选参敎ͼcdQ字W串。用来描q对话框的外观等信息Q可以用以下的一个或几个Q用分号?”隔开?
  dialogHeight 对话框高度,不小于1Q0pxQテQ4中dialogHeight ?dialogWidth 默认的单位是emQ而テQ5中是pxQؓ方便其见Q在定义modal方式的对话框Ӟ用px做单位?
  dialogWidth: 对话框宽度?
  dialogLeft: 距离桌面左的距离?
  dialogTop: L面上的距R?
  center: {yes | no | 1 | 0 }Q窗口是否居中,默认yesQ但仍可以指定高度和宽度?
  help: {yes | no | 1 | 0 }Q是否显C帮助按钮,默认yes?
  resizable: {yes | no | 1 | 0 } QテQ5Q]Q是否可被改变大。默认no?
  status: {yes | no | 1 | 0 } QIE5+Q:是否昄状态栏。默认ؓyes[ Modeless]或no[Modal]?
  scroll:{ yes | no | 1 | 0 | on | off }Q指明对话框是否昄滚动条。默认ؓyes?

  q有几个属性是用在HTA中的Q在一般的|页中一般不使用?
  dialogHide:{ yes | no | 1 | 0 | on | off }Q在打印或者打印预览时对话框是否隐藏。默认ؓno?
  edge:{ sunken | raised }Q指明对话框的边框样式。默认ؓraised?
  unadorned:{ yes | no | 1 | 0 | on | off }Q默认ؓno?

传入参数Q?
要想对话框传递参敎ͼ是通过vArguments来进行传递的。类型不限制Q对于字W串cdQ最大ؓ4096个字W。也可以传递对象,例如Q?

test1.htm
====================
<script>
  var mxh1 = new Array("mxh","net_lover","孟子E?)
  var mxh2 = window.open("about:blank","window_mxh")
  // 向对话框传递数l?
  window.showModalDialog("test2.htm",mxh1)
  // 向对话框传递window对象
  window.showModalDialog("test3.htm",mxh2)
</script>

test2.htm
====================
<script>
  var a = window.dialogArguments
  alert("您传递的参数为:" + a)
</script>

test3.htm
====================
<script>
  var a = window.dialogArguments
  alert("您传递的参数为window对象Q名Uͼ" + a.name)
</script>

可以通过window.returnvalue向打开对话框的H口q回信息Q当然也可以是对象。例如:

test4.htm
===================
<script>
  var a = window.showModalDialog("test5.htm")
  for(i=0;i<a.length;i++) alert(a[i])
</script>

test5.htm
===================
<script>
function sendTo()
{
  var a=new Array("a","b")
  window.returnvalue = a
  window.close()
}
</script>
<body>
<form>
  <input value="q回" type=button onclick="sendTo()">
</form>

常见问题Q?
1Q如何在模态对话框中进行提交而不新开H口Q?
如果??览器是IE5.5+,可以在对话框中用带name属性的iframeQ提交时可以制定targetiframe的name。对于IE4+Q你可以用高度ؓ0的frame来作Q例子,

test6.htm
===================
<script>
  window.showModalDialog("test7.htm")
</script>

test7.htm
===================
if(window.location.search) alert(window.location.search)
<frameset rows="0,*">
  <frame src="about:blank">
  <frame src="test8.htm">
</frameset>

test8.htm
===================
<form target="_self" method="get">
<input name=txt value="test">
<input type=submit>
</form>
<script>
if(window.location.search) alert(window.location.search)
</script>
2,可以通过http://servername/virtualdirname/test.htm?name=mxh方式直接向对话框传递参数吗Q?
{案是不能。但在frame里是可以的?

Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?
另外Q?
http://www.csdn.net/
本h整理

问:
1.模态窗口的打开
2.模态窗口的关闭
3.模态窗口的传递参数?
4.其他。。。?

hgknight(江雨.net){:
1.window.showModalDialog("DialogPage.aspx","newwin","dialogHeight: 200px; dialogWidth: 150px; dialogTop: 458px; dialogLeft: 166px; edge: Raised; center: Yes; help: Yes; resizable: Yes; status: Yes;");

2.window.close();

3.传?
ParentPage.aspx:
window.showModalDialog("DialogPage.aspx?para1=aaa¶2=bbb");

DialogPage.aspx:
string str1=Request.QueryString["para1"].toString();
string str2=Request.QueryString["para2"].toString();

q回?
DialogPage.aspx:
window.returnvalue="aaa";

ParentPage.aspx:
var str=window.showModalDialog("DialogPage.aspx");

4.
aspx面在showmodeldialog情况下ؓ什么一提交重新打开一个页?
showmodaldialog打开的页面中?lt;head></head>之间加入一行:<base target="_self">
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
snowjin78(方圆)
以前Q我也问q此c问题,现把收获贴如下(当然好多东西都是别h告诉我的Q:
最好不要用Response.Write(  "  <script....  </script  >  ")q样的方法注册客L脚本Q而应该用Page.RegisterStartupScript或Page.RegisterClientScriptBlockҎ来注?
Page.RegisterClientScriptBlockQ ?
在  Page  对象的   ?lt;form  runat=  server  >  元素的开始标记后立即发出客户端脚本 ?
Page.RegisterStartupScript:  
该方法在  Page  对象的   ?lt;form  runat=  server  >  元素的结束标C前发脚本

客户端代码有两个问题Q第一是把window写成了WindowQjavascript是严格区分大写的,用Window是肯定会出错的;W二个问题是讄对话框的宽度用dialogWidthQ高度用dialogHeightQ而不是height和width。!



weibogao 2006-09-20 10:27 发表评论
]]>
web面打印的相兌?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/weibogao/archive/2006/07/13/57929.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/57929.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2006/07/13/57929.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/57929.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/57929.html</trackback:ping><description><![CDATA[ <p style="LINE-HEIGHT: 150%"> <font class="f14" id="zoom" style="FONT-SIZE: 14px">1、控?U|"?横打”和“页面的边距?<br />Q?Q?lt;script defer> <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 /></script> <br /><br />Q?Q?<br /><script language="javascript"> <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 />  </script> <br /></head> <br /><body> <br /><OBJECT classid="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2" <br /><br />height=0 id=wb name=wb width=0></OBJECT> <br /><input type=button name=button_print value="打印" <br /><br />onclick="javascript:printit()"> <br /><input type=button name=button_setup value="打印面讄" <br /><br />onclick="javascript:printsetup();"> <br /><input type=button name=button_show value="打印预览" <br /><br />onclick="javascript:printpreview();"> <br /><input type=button name=button_fh value="关闭" <br /><br />onclick="javascript:window.close();"> <br /><br />------------------------------------------------ <br />关于q个lgq有其他的用法,列D如下Q?<br />WebBrowser.ExecWB(1,1) 打开 <br />Web.ExecWB(2,1) 关闭现在所有的IEH口Qƈ打开一个新H口 <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) 好像是撤销Q有待确?<br />Web.ExecWB(17,1) 全?<br />Web.ExecWB(22,1) h <br />Web.ExecWB(45,1) 关闭H体无提C?<br /><br />2、分|?<br /><HTML> <br /><HEAD> <br /><STYLE>   <br />  P {page-break-after: always} <br /></STYLE> <br /></HEAD> <br /><BODY> <br /><%while not rs.eof%> <br /><P><%=rs(0)%></P> <br /><%rs.movenext%> <br /><%wend%> <br /></BODY> <br /></HTML> <br /><br />3、ASP面打印时如何去掉页面底部的路径和顶端的늠~号 <br />Q?Qie的文?〉页面设|?〉讲里面的页眉和脚里面的东襉KLQ打印就不出来了?<br />Q?Q?lt;HTML> <br /><HEAD> <br /><TITLE> New Document </TITLE> <br /><META NAME="Generator" CONTENT="EditPlus"> <br /><META NAME="Author" CONTENT="YC"> <br /><script language="VBScript"> <br />dim hkey_root,hkey_path,hkey_key <br />hkey_root="HKEY_CURRENT_USER" <br />hkey_path="\Software\Microsoft\Internet Explorer\PageSetup" <br />'//讄|页打印的页眉页脚ؓI?<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,"&w&b늠Q?amp;p/&P" <br />  hkey_key="\footer" <br />  RegWsh.RegWrite hkey_root+hkey_path+hkey_key,"&u&b&d" <br />end function <br /></script> <br /></HEAD> <br /><br /><BODY> <br /><br/> <br /><br/> <br /><br/> <br /><br/> <br /><br/> <br /><br/><p align=center> <br /><input type="button" value="清空늠" onclick=pagesetup_null()> <input type="button" value="恢复吗" onclick=pagesetup_default()><br/> <br /><br /></p> <br /></BODY> <br /></HTML> <br />4、Q动打印 <br /><SCRIPT LANGUAGE=javascript> <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 /></SCRIPT> <br />4、用FileSystemlg实现WEB应用中的本地特定打印 <br /><script Language=VBScript> <br />function print_onclick //打印函数 <br />dim label <br />label=document.printinfo.label.value //获得HTML面的数?<br />set objfs=CreateObject("Scripting.FileSystemObject") //创徏FileSystemlg对象的实?<br />set objprinter=objfs.CreateTextFile ("LPT1:",true) //建立与打印机的连?<br />objprinter.Writeline("__________________________________") //输出打印的内?<br />objprinter.Writeline("| |") <br />objprinter.Writeline("| 您打印的数据是:"&label& " |? <br />objprinter.Writeline("| |") <br />objprinter.Writeline("|_________________________________|") <br />objprinter.close //断开与打印机的连?<br />set objprinter=nothing <br />set objfs=nothing // 关闭FileSystemlg对象 <br />end function <br /></script> <br />服务器端脚本Q?<br /><%……?<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 />……?%> //与数据库q行交互 <br />HTML面~码Q?<br /><HTML> <br />……?<br /><FORM ID=printinfo NAME="printinfo" > <br /><INPUT type="button" value="打印>>" id=print name=print > //调用打印函数 <br /><INPUT type=hidden id=text1 name=label value=<%=……?>> //保存服务器端传来的数?<br />……?<br /></HTML></font> </p> <img src ="http://www.aygfsteel.com/weibogao/aggbug/57929.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2006-07-13 11:25 <a href="http://www.aygfsteel.com/weibogao/archive/2006/07/13/57929.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jfreechart使用ȝhttp://www.aygfsteel.com/weibogao/archive/2006/07/11/57622.htmlweibogaoweibogaoTue, 11 Jul 2006 03:31:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/07/11/57622.htmlhttp://www.aygfsteel.com/weibogao/comments/57622.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/07/11/57622.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/57622.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/57622.html

q里分三部分来介l?jFreeChart 。第一部分介绍jFreeChart产生
囑Ş的流E及相关的重要的c;W二部分介绍四种常用的报表图Q饼图、柱状图、折U图、时间序列图Q;W三部分
介绍在图形中增加Item Lable ?
jFreeChart 的版本是jfreechart-1.0.0-pre2(1)

[b]一、jFreeChart产生囑Ş的流E[/b]
   创徏一个数据源QdatasetQ来包含要在图形中昄的数?创徏一?JFreeChart 对象来代表要昄的图?br />   把图形输?br />   重要的类和接口:
   org.jfree.data.general.Dataset  所有数据源c都要实现的接口
   org.jfree.chart.ChartFactory    由它来?JFreeChart 对象
   org.jfree.chart.JFreeChart    所有对囑Ş的调整都是通过它噢Q!
   org.jfree.chart.plot.Plot    通过JFreeChart 对象获得它,然后再通过它对囑Ş外部部分Q例Q坐标uQ调?br />                                注意Q它有很多子c,一般都下嗍造型到它的子c!
   org.jfree.chart.renderer.AbstractRenderer     通过JFreeChart 对象获得它,然后再通过它对囑Ş内部部分
                                                Q例Q折U的cdQ调整。同P针对不同cd的报表图Q它?br />                                                着不同的子cd玎ͼ在下面我们简U它?Renderer
   下面我们l合不同cd的图形来具体分析q个程?br />  
[b]二、饼图[/b]
   饼图的dataset 一般是用PieDataset 接口Q具体实现类?DefaultPieDataset
   1、创Z个数据源QdatasetQ:
    private static PieDataset createDataset()
    {
        DefaultPieDataset defaultpiedataset = new DefaultPieDataset(); //注意是DefaultPieDatasetQ!
        defaultpiedataset.setValue("One", new Double(43.200000000000003D));
        defaultpiedataset.setValue("Two", new Double(10D));
        defaultpiedataset.setValue("Three", new Double(27.5D));
        defaultpiedataset.setValue("Four", new Double(17.5D));
        return defaultpiedataset;
    }
   2、由ChartFactory  产生 JFreeChart 对象
    private static JFreeChart createChart(PieDataset piedataset)
    {
        JFreeChart jfreechart = ChartFactory.createPieChart("Pie Chart Demo 1",  //囑Ş标题名称
                                                              piedataset,   // dataset
                                                              true,      // legend?
                                                              true,     // tooltips?
                                                              false);  //URLs?
        PiePlot pieplot = (PiePlot)jfreechart.getPlot();  //通过JFreeChart 对象获得 plotQPiePlotQ!
        pieplot.setNoDataMessage("No data available");    // 没有数据的时候显C的内容
        return jfreechart;
    }
    一些重要的ҎQ?br />    pieplot.setExplodePercent(0,0.3D) //把Lable ?One" 的那一块”挖“出?0%   
   3、输出略 
  
[b]三、柱状图[/b]
   q囄dataset 一般是用CatagoryDataset接口(具体实现cLDefaultCategoryDataset),也会?IntervalXYDataset
   接口
   1、创Z个数据源QdatasetQ:
    private static CategoryDataset createDataset()
    {
        String series1 = "First";
        String series2 = "Second";
        String series3 = "Third";
        String category1 = "Category 1";
        String category2 = "Category 2";
        String category3 = "Category 3";
        String category4 = "Category 4";
        String category5 = "Category 5";
        DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();
        defaultcategorydataset.addValue(1.0D, series1, category1);
        defaultcategorydataset.addValue(4D, series1, category2);
        defaultcategorydataset.addValue(3D, series1, category3);
        defaultcategorydataset.addValue(5D, series1, category4);
        defaultcategorydataset.addValue(5D, series1, category5);
       
        defaultcategorydataset.addValue(5D, series2, category1);
        defaultcategorydataset.addValue(7D, series2, category2);
        defaultcategorydataset.addValue(6D, series2, category3);
        defaultcategorydataset.addValue(8D, series2, category4);
        defaultcategorydataset.addValue(4D, series2, category5);
       
        defaultcategorydataset.addValue(4D, series3, category1);
        defaultcategorydataset.addValue(3D, series3, category2);
        defaultcategorydataset.addValue(2D, series3, category3);
        defaultcategorydataset.addValue(3D, series3, category4);
        defaultcategorydataset.addValue(6D, series3, category5);
        return defaultcategorydataset;
    }
   2、由ChartFactory  产生 JFreeChart 对象   
    private static JFreeChart createChart(CategoryDataset categorydataset)
    {
        JFreeChart jfreechart = ChartFactory.createBarChart("Bar Chart Demo", //囑Ş标题名称
                                                            "Category",//domain ?Lable
                                                                         q里先简单理解ؓ横坐标Lable好了
                                                            "Value", //range ?Lable
                                                                       q里也先单理解ؓU坐标Lable好了
                                                            categorydataset, //  dataset
                                                            PlotOrientation.VERTICAL, //垂直昄
                                                            true, // legend?
                                                            true,  // tooltips?
                                                            false); //URLs?
        jfreechart.setBackgroundPaint(Color.white);   //讑֮背景色ؓ白色
        CategoryPlot categoryplot = jfreechart.getCategoryPlot(); //获得 plotQCategoryPlotQ!
        categoryplot.setBackgroundPaint(Color.lightGray); //讑֮图表数据昄部分背景?br />        categoryplot.setDomainGridlinePaint(Color.white); //横坐标网格线白色
        categoryplot.setDomainGridlinesVisible(true); //可见
        categoryplot.setRangeGridlinePaint(Color.white); //U坐标网格线白色
        //下面两行使纵坐标的最单位格为整?br />        NumberAxis numberaxis = (NumberAxis)categoryplot.getRangeAxis();
        numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        BarRenderer barrenderer = (BarRenderer)categoryplot.getRenderer(); //获得renderer 注意q里是下嗍造型
                                                                             到BarRendererQ!
        barrenderer.setDrawBarOutline(false); // Bar的外轮廓U不?br />        GradientPaint gradientpaint = new GradientPaint(0.0F, 0.0F, Color.blue,
        0.0F, 0.0F, new Color(0, 0, 64));   //讑֮特定颜色
        GradientPaint gradientpaint1 = new GradientPaint(0.0F, 0.0F, Color.green,
        0.0F, 0.0F, new Color(0, 64, 0));
        GradientPaint gradientpaint2 = new GradientPaint(0.0F, 0.0F, Color.red,
        0.0F, 0.0F, new Color(64, 0, 0));
        barrenderer.setSeriesPaint(0, gradientpaint); //lseries1 Bar讑֮上面定义的颜?br />        barrenderer.setSeriesPaint(1, gradientpaint1); //lseries2 Bar 讑֮上面定义的颜?br />        barrenderer.setSeriesPaint(2, gradientpaint2); //lseries3 Bar 讑֮上面定义的颜?br />        CategoryAxis categoryaxis = categoryplot.getDomainAxis();  //横u上的 Lable 45度倾斜
        categoryaxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);       
        return jfreechart;
    } 
    一些重要的ҎQ(增加一块标讎ͼ
        IntervalMarker intervalmarker = new IntervalMarker(4.5D, 7.5D);
        intervalmarker.setLabel("Target Range");
        intervalmarker.setLabelFont(new Font("SansSerif", 2, 11));
        intervalmarker.setLabelAnchor(RectangleAnchor.LEFT);
        intervalmarker.setLabelTextAnchor(TextAnchor.CENTER_LEFT);
        intervalmarker.setPaint(new Color(222, 222, 255, 128));
        categoryplot.addRangeMarker(intervalmarker, Layer.BACKGROUND);   
       
[b]四、折U图[/b]
   折线囄dataset 两种CatagoryDataset接口(具体实现cLDefaultCategoryDataset),XYDataset 接口
   1、CatagoryDataset接口Q       ?
   A、创Z个数据源QdatasetQ:
    private static CategoryDataset createDataset()
    {
        String series1 = "First";
        String series2 = "Second";
        String series3 = "Third";
        String type1 = "Type 1";
        String type2 = "Type 2";
        String type3 = "Type 3";
        String type4 = "Type 4";
        String type5 = "Type 5";
        String type6 = "Type 6";
        String type7 = "Type 7";
        String type8 = "Type 8";
        DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();
        defaultcategorydataset.addValue(1.0D, series1, type1);
        defaultcategorydataset.addValue(4D, series1, type2);
        defaultcategorydataset.addValue(3D, series1, type3);
        defaultcategorydataset.addValue(5D, series1, type4);
        defaultcategorydataset.addValue(5D, series1, type5);
        defaultcategorydataset.addValue(7D, series1, type6);
        defaultcategorydataset.addValue(7D, series1, type7);
        defaultcategorydataset.addValue(8D, series1, type8);
       
        defaultcategorydataset.addValue(5D, series2, type1);
        defaultcategorydataset.addValue(7D, series2, type2);
        defaultcategorydataset.addValue(6D, series2, type3);
        defaultcategorydataset.addValue(8D, series2, type4);
        defaultcategorydataset.addValue(4D, series2, type5);
        defaultcategorydataset.addValue(4D, series2, type6);
        defaultcategorydataset.addValue(2D, series2, type7);
        defaultcategorydataset.addValue(1.0D, series2, type8);
       
        defaultcategorydataset.addValue(4D, series3, type1);
        defaultcategorydataset.addValue(3D, series3, type2);
        defaultcategorydataset.addValue(2D, series3, type3);
        defaultcategorydataset.addValue(3D, series3, type4);
        defaultcategorydataset.addValue(6D, series3, type5);
        defaultcategorydataset.addValue(3D, series3, type6);
        defaultcategorydataset.addValue(4D, series3, type7);
        defaultcategorydataset.addValue(3D, series3, type8);
        return defaultcategorydataset;
    }
   B、由ChartFactory  产生 JFreeChart 对象     (与上面重复的部分׃再注释)
    private static JFreeChart createChart(CategoryDataset categorydataset)
    {
        JFreeChart jfreechart = ChartFactory.createLineChart("Line Chart Demo 1",
                                                             "Type",
                                                             "Value",
                                                             categorydataset,
                                                             PlotOrientation.VERTICAL,
                                                             true,
                                                             true,
                                                             false);
        jfreechart.setBackgroundPaint(Color.white);
        CategoryPlot categoryplot = (CategoryPlot)jfreechart.getPlot();
        categoryplot.setBackgroundPaint(Color.lightGray);
        categoryplot.setRangeGridlinePaint(Color.white);
        NumberAxis numberaxis = (NumberAxis)categoryplot.getRangeAxis();
        numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        numberaxis.setAutoRangeIncludesZero(true);
        //获得renderer 注意q里是下嗍造型到lineandshaperendererQ!
        LineAndShapeRenderer lineandshaperenderer = (LineAndShapeRenderer)categoryplot.getRenderer();
        lineandshaperenderer.setShapesVisible(true); //series 点(x据点Q可?br />        lineandshaperenderer.setSeriesStroke(0, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {
            10F, 6F
        }, 0.0F)); //定义series?First"的(即series1Q点之间的连U?Q这里是虚线Q默认是直线
        lineandshaperenderer.setSeriesStroke(1, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {
            6F, 6F
        }, 0.0F)); //定义series?Second"的(即series2Q点之间的连U?br />        lineandshaperenderer.setSeriesStroke(2, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {
            2.0F, 6F
        }, 0.0F)); //定义series?Third"的(即series3Q点之间的连U?br />        return jfreechart;
    }
        一些重要的ҎQ?br />        lineandshaperenderer.setLineVisible(true)  //series 点(x据点Q间有连U可?br />   2、XYDataset 接口Q?br />   A、创Z个数据源QdatasetQ:
    private static XYDataset createDataset()
    {
        XYSeries xyseries = new XYSeries("First"); //先生XYSeries 对象
        xyseries.add(1.0D, 1.0D);
        xyseries.add(2D, 4D);
        xyseries.add(3D, 3D);
        xyseries.add(4D, 5D);
        xyseries.add(5D, 5D);
        xyseries.add(6D, 7D);
        xyseries.add(7D, 7D);
        xyseries.add(8D, 8D);
       
        XYSeries xyseries1 = new XYSeries("Second");
        xyseries1.add(1.0D, 5D);
        xyseries1.add(2D, 7D);
        xyseries1.add(3D, 6D);
        xyseries1.add(4D, 8D);
        xyseries1.add(5D, 4D);
        xyseries1.add(6D, 4D);
        xyseries1.add(7D, 2D);
        xyseries1.add(8D, 1.0D);
       
        XYSeries xyseries2 = new XYSeries("Third");
        xyseries2.add(3D, 4D);
        xyseries2.add(4D, 3D);
        xyseries2.add(5D, 2D);
        xyseries2.add(6D, 3D);
        xyseries2.add(7D, 6D);
        xyseries2.add(8D, 3D);
        xyseries2.add(9D, 4D);
        xyseries2.add(10D, 3D);
       
        XYSeriesCollection xyseriescollection = new XYSeriesCollection(); //再用XYSeriesCollectiond入XYSeries 对象
        xyseriescollection.addSeries(xyseries);
        xyseriescollection.addSeries(xyseries1);
        xyseriescollection.addSeries(xyseries2);
        return xyseriescollection;
    }
   B、由ChartFactory  产生 JFreeChart 对象
    private static JFreeChart createChart(XYDataset xydataset)
    {
        JFreeChart jfreechart = ChartFactory.createXYLineChart("Line Chart Demo 2",
                                                               "X",
                                                               "Y",
                                                               xydataset,
                                                               PlotOrientation.VERTICAL,
                                                               true,
                                                               true,
                                                               false);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot)jfreechart.getPlot(); //获得 plotQXYPlotQ!
        xyplot.setBackgroundPaint(Color.lightGray); //讑֮图表数据昄部分背景?br />        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D)); //讑֮坐标轴与图表数据昄部分距离
        xyplot.setDomainGridlinePaint(Color.white); //|格UK?br />        xyplot.setRangeGridlinePaint(Color.white);
        //获得 renderer 注意q里是XYLineAndShapeRenderer Q!
        XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyplot.getRenderer();
        xylineandshaperenderer.setShapesVisible(true); //数据点可?br />        xylineandshaperenderer.setShapesFilled(true); //数据点被填充即不是空心点
        NumberAxis numberaxis = (NumberAxis)xyplot.getRangeAxis();
        numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        return jfreechart;
    }                     
   一些重要的ҎQ?br />        XYLineAndShapeRenderer xylineandshaperenderer = new XYLineAndShapeRenderer();
        xylineandshaperenderer.setSeriesLinesVisible(0, false); //W一个XYSeries数据炚wq线不可?br />        xylineandshaperenderer.setSeriesShapesVisible(1, false); //W二个XYSeries数据点不可见
        xyplot.setRenderer(xylineandshaperenderer);  
       
[b]五、时间序列图[/b]
    旉序列囑֒折线囑־怼Q不同的是它?domain轴的数据是时间而不是数字?旉序列囄dataset ?br />    XYDataset 接口Q具体实现类是TimeSeriesCollection Q和上面cMQ有TimeSeries 对象Q它被添加入
    TimeSeriesCollection 。                                                                             ?
  1、创Z个数据源QdatasetQ:
    private static XYDataset createDataset()
    {
        TimeSeries timeseries = new TimeSeries("L&G European Index Trust",Month.class);
        timeseries.add(new Month(2, 2001), 181.8D);//q里用的是Month.classQ同栯有Day.class Year.class {等
        timeseries.add(new Month(3, 2001), 167.3D);
        timeseries.add(new Month(4, 2001), 153.8D);
        timeseries.add(new Month(5, 2001), 167.6D);
        timeseries.add(new Month(6, 2001), 158.8D);
        timeseries.add(new Month(7, 2001), 148.3D);
        timeseries.add(new Month(8, 2001), 153.9D);
        timeseries.add(new Month(9, 2001), 142.7D);
        timeseries.add(new Month(10, 2001), 123.2D);
        timeseries.add(new Month(11, 2001), 131.8D);
        timeseries.add(new Month(12, 2001), 139.6D);
        timeseries.add(new Month(1, 2002), 142.9D);
        timeseries.add(new Month(2, 2002), 138.7D);
        timeseries.add(new Month(3, 2002), 137.3D);
        timeseries.add(new Month(4, 2002), 143.9D);
        timeseries.add(new Month(5, 2002), 139.8D);
        timeseries.add(new Month(6, 2002), 137D);
        timeseries.add(new Month(7, 2002), 132.8D);
       
        TimeSeries timeseries1 = new TimeSeries("L&G UK Index Trust",Month.class);
        timeseries1.add(new Month(2, 2001), 129.6D);
        timeseries1.add(new Month(3, 2001), 123.2D);
        timeseries1.add(new Month(4, 2001), 117.2D);
        timeseries1.add(new Month(5, 2001), 124.1D);
        timeseries1.add(new Month(6, 2001), 122.6D);
        timeseries1.add(new Month(7, 2001), 119.2D);
        timeseries1.add(new Month(8, 2001), 116.5D);
        timeseries1.add(new Month(9, 2001), 112.7D);
        timeseries1.add(new Month(10, 2001), 101.5D);
        timeseries1.add(new Month(11, 2001), 106.1D);
        timeseries1.add(new Month(12, 2001), 110.3D);
        timeseries1.add(new Month(1, 2002), 111.7D);
        timeseries1.add(new Month(2, 2002), 111D);
        timeseries1.add(new Month(3, 2002), 109.6D);
        timeseries1.add(new Month(4, 2002), 113.2D);
        timeseries1.add(new Month(5, 2002), 111.6D);
        timeseries1.add(new Month(6, 2002), 108.8D);
        timeseries1.add(new Month(7, 2002), 101.6D);
        TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();
        timeseriescollection.addSeries(timeseries);
        timeseriescollection.addSeries(timeseries1);
        timeseriescollection.setDomainIsPointsInTime(true); //domain轴上的刻度点代表的是旉点而不是时间段
        return timeseriescollection;
    }
   2、由ChartFactory  产生 JFreeChart 对象
    private static JFreeChart createChart(XYDataset xydataset)
    {
        JFreeChart jfreechart = ChartFactory.createTimeSeriesChart("Legal & General Unit Trust Prices",
                                                                   "Date",
                                                                   "Price Per Unit",
                                                                   xydataset,
                                                                   true,
                                                                   true,
                                                                   false);
        jfreechart.setBackgroundPaint(Color.white);
        XYPlot xyplot = (XYPlot)jfreechart.getPlot(); //获得 plot : XYPlot!!
        xyplot.setBackgroundPaint(Color.lightGray);
        xyplot.setDomainGridlinePaint(Color.white);
        xyplot.setRangeGridlinePaint(Color.white);
        xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
        xyplot.setDomainCrosshairVisible(true);
        xyplot.setRangeCrosshairVisible(true);
        org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();
        if(xyitemrenderer instanceof XYLineAndShapeRenderer)
        {
            XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyitemrenderer;
            xylineandshaperenderer.setDefaultShapesVisible(true); //数据点可?br />            xylineandshaperenderer.setDefaultShapesFilled(true);  //数据Ҏ实心?br />        }
        DateAxis dateaxis = (DateAxis)xyplot.getDomainAxis(); //对domain 轴上日期昄格式定义
        dateaxis.setDateFormatOverride(new SimpleDateFormat("MMM-yyyy"));
        return jfreechart;
    } 
       一些重要的ҎQ?br />     A、增加标记线Q?
        xyplot.addRangeMarker(new ValueMarker(550D)); //数Du
        Quarter quarter = new Quarter(2, 2002);
        xyplot.addDomainMarker(new ValueMarker(quarter.getMiddleMillisecond()));  //旉?br />     B、数据点的调?br />        XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyplot.getRenderer();
        xylineandshaperenderer.setDefaultShapesVisible(true);  //数据点可?br />        xylineandshaperenderer.setSeriesFillPaint(0, Color.red);  //数据点填充ؓU色
        xylineandshaperenderer.setSeriesFillPaint(1, Color.white);  //数据点填充ؓ白色
        xylineandshaperenderer.setUseFillPaint(true);    //应用
     C、^均值曲U?
       q个曲线有什么用呢?很简单的例子Q这里有一个以半年每天为单位的数据l制的曲U,我们想看看以月ؓ单位数据
       的变化,q时可以用到它了?
        TimeSeries timeseries = createEURTimeSeries();  //是以半q每天ؓ单位的数?br />        TimeSeries timeseries1 = MovingAverage.createMovingAverage(timeseries,
                                                                   "30 day moving average",
                                                                   30, //30天ؓ一个周?br />                                                                   30); //最开始的30天蟩q?br />        TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();
        timeseriescollection.addSeries(timeseries);
        timeseriescollection.addSeries(timeseries1);
        return timeseriescollection;
    
[b]六、ȝ一下[/b]
                           dataset                          plot                    renderer                      
  饼图           PieDatasetQDefaultPieDatasetQ         ?PiePlot                    ------
  q图  ?CatagoryDatasetQDefaultCategoryDatasetQ  ?CategoryPlot                BarRenderer
  折线图  ?CatagoryDatasetQDefaultCategoryDatasetQ  ?CategoryPlot              LineAndShapeRenderer
                  XYDatasetQXYSeriesCollectionQ         ?XYPlot                XYLineAndShapeRenderer
  旉序列图   ?XYDataset QTimeSeriesCollectionQ       ?XYPlot                XYLineAndShapeRenderer
  q里只是一些常用的ҎQ具体还是看API ,主要的类ȝ如下Q?br />JFreeChart:生成图表的中间存攄?/p>

CategoryDataSet:图表的数据,主要包含行数据(String[] cdQ,列数?String[] cdQ和L据                  ?(double[][]cdQ。一般来说简单的图表L据都是double[1][]cd的?/div>
ChartFactory: 工厂c,提供多种Ҏ生成多达30多种图表Q用得比较多的是BarChart(q?,LineChart             Q折U图Q,PieChartQ饼状图Q。工厂方法看h比较l一QcreatXXXChart(图表标题Q            ?行标题,列标题,L据(CategoryDataSetQ?
ChartUtities: 公用c,提供各种持久保存图表数据的方法,比如saveChartAsJPEG(FileQ                           ?JFreeChart,width,height)
其他q有一些渲染类Q主要是用来化图表界面Q调整和优化昄风格{?/div>
ȝ来说q不错,比jasperReport要简单,上手很快Q图表效果也q不错,用来做普通数据图表够了



[b]七、Item Lable[/b]
   q里以柱状图Z说明Q具体来说就是在每个q上显C它的数据,具体有下面内容:
   A、 Item Lable 可见
   B、调?Item Lable 的颜艌Ӏ字体等
   C、调?Item Lable 的位|?br />   D、定?Item Lable 的内?br />   1、分配一?Lable Generator l?renderer
      BarRenderer barrenderer = (BarRenderer)categoryplot.getRenderer();
      GategoryLableGenerator generator =new StandardGategoryLableGenerator(
           "{2}", new DecimalFormat("0.00")    //调整昄的数字和字符格式
      );
      barrenderer.setLableGenerator(generator);
   2、 Item Lable 可见
      barrenderer.setItemLableVisible(true);
   3、调?Item Lable 的颜艌Ӏ字体等
      barrenderer.setItemLablePaint(Color.red);
      barrenderer.setItemLableFont(new Font("SansSerif",Font.PLAIN,10));
   4、调?Item Lable 的位|?br />      q里涉及C个新的对?ItemLablePosition , ItemLablePosition的构造函数有两个或四个参?br />      public ItemLabelPosition(ItemLabelAnchor itemLabelAnchor,
                         org.jfree.ui.TextAnchor textAnchor,
                         org.jfree.ui.TextAnchor rotationAnchor,
                         double angle)
      itemLabelAnchor - Item Lable 的位|?Q最重要的!Q)
      textAnchor - Item Lable里包含的正文相对于Item Lable 的位|?br />      rotationAnchor - Item Lable里包含的正文旋{的位|?br />      angle - 旋{的角?br />      ItemLabelPosition itemlabelposition = new ItemLabelPosition(ItemLabelAnchor.INSIDE12,
                                                      TextAnchor.CENTER_RIGHT,
                                                      TextAnchor.CENTER_RIGHT,
                                                      -1.57D);
      barrenderer.setPositiveItemLabelPosition(itemlabelposition);
   q样可以每个柱状上昄它的数据了,当然可以定制 Item Lable 的内容,比如 Item Lable text 过100的才
   昄Q这样就需要定制自qc,它要实现GategoryLableGenerator 接口Q实现generateItemLable()Ҏ?/p>

weibogao 2006-07-11 11:31 发表评论
]]>jsp标签结http://www.aygfsteel.com/weibogao/archive/2006/07/06/56954.htmlweibogaoweibogaoThu, 06 Jul 2006 07:05:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/07/06/56954.htmlhttp://www.aygfsteel.com/weibogao/comments/56954.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/07/06/56954.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/56954.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/56954.html阅读全文

weibogao 2006-07-06 15:05 发表评论
]]>
hibernate中的投媄查询http://www.aygfsteel.com/weibogao/archive/2006/07/05/56749.htmlweibogaoweibogaoWed, 05 Jul 2006 06:44:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/07/05/56749.htmlhttp://www.aygfsteel.com/weibogao/comments/56749.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/07/05/56749.html#Feedback1http://www.aygfsteel.com/weibogao/comments/commentRss/56749.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/56749.html

org.hibernate.criterion.Projections?Projection 的实例工厂。我们通过调用 setProjection()应用投媄C个查询?

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.rowCount() )
    .add( Restrictions.eq("color", Color.BLACK) )
    .list();
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();

在一个条件查询中没有必要昑ּ的?"group by" 。某些投q型就是被定义?span class="emphasis"> 分组投媄Q他们也出现在SQL?tt class="literal">group by子句中?

你可以选择把一个别名指z一个投影,q样可以使投影DU束或排序所引用。下面是两种不同的实现方式:

List results = session.createCriteria(Cat.class)
    .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
    .addOrder( Order.asc("colr") )
    .list();
List results = session.createCriteria(Cat.class)
    .setProjection( Projections.groupProperty("color").as("colr") )
    .addOrder( Order.asc("colr") )
    .list();

alias()?tt class="literal">as()Ҏ便的一个投影实例包装到另外一?别名?tt class="literal">Projection实例中。简而言之,当你d一个投影到一个投影列表中?你可以ؓ它指定一个别名:

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();
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();

你也可以使用Property.forName()来表C投影:

List results = session.createCriteria(Cat.class)
    .setProjection( Property.forName("name") )
    .add( Property.forName("color").eq(Color.BLACK) )
    .list();
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();


weibogao 2006-07-05 14:44 发表评论
]]>hibernate中多对多的两U保存方?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/weibogao/archive/2006/07/05/56740.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/56740.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2006/07/05/56740.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/56740.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/56740.html</trackback:ping><description><![CDATA[1.使用兌表实现多对多的关联,在实体一端的映射文g中定义:<br /><set name="unitTypes" lazy="true" table="IPMS_UNITTYPE" cascade="all"><br />   <key column="UNITID"/><br />   <many-to-many class="com.toone.ipms.common.dict.vo.CommDict" column="DICTID"/><br /></set><br />因ؓ配置中cascade="all"Q所以可以不使用中间表关联类来实玎ͼ而且不需要分别进行save操作<br />其中两个column都是兌表中的字D,key为本端外键,而另一个则是另一端外?<br />2.另一U方式ؓ生成兌表的映射文g和POQ写出关联类的基本管理类的增删改操作Q实C存时两个cȝ兌<img src ="http://www.aygfsteel.com/weibogao/aggbug/56740.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2006-07-05 14:31 <a href="http://www.aygfsteel.com/weibogao/archive/2006/07/05/56740.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DisplayTag应用(转蝲)http://www.aygfsteel.com/weibogao/archive/2006/07/03/56309.htmlweibogaoweibogaoMon, 03 Jul 2006 05:23:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/07/03/56309.htmlhttp://www.aygfsteel.com/weibogao/comments/56309.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/07/03/56309.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/56309.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/56309.html DisplayTag应用

  DisplayTag是一个非常好用的表格昄标签Q适合MVC模式Q其主页?a >http://displaytag.sourceforge.net/ 
一、最单的情况Q未使用<display:column/>标签
  <%request.setAttribute( "test", new ReportList(6) );%>
  <display:table name="test" />
  标签遍历List里的每一个对象,q将对象里的所有属性显C出来。一般用于开发的时候检查对象数据的完整性?br /> 
二、?lt;display:column/>标签的情?/strong>
<display:table name="test">
  <display:column property="id" title="ID" />
  <display:column property="name" />
  <display:column property="email" />
  <display:column property="status" />
  <display:column property="description" title="Comments"/>
</display:table>
   property对应List里对象的属性(用getXXX()Ҏ取得Q,title则对应表D头里的列名。定义列有两U方式:
   A?lt;display:column property="email" />
      使用<display:column/>标签里的property属性来定义
   B?lt;display:column title="email">email@it.com</display:column>
      ?lt;display:column/>标签体里增加内容Q可以是帔RQ也可以用其他标{{?br />   两种方式比较Q用property属性来定义更加快速和利于排序?br />  
三、表格显C样式的定义
  A、在<display:table/>?lt;display:column/>标签里指定标准的html属性,烦琐
  B、修Ҏ式表
<display:table name="test" class="mars">
  <display:column property="id" title="ID" class="idcol"/>
  <display:column property="name" />
  <display:column property="email" />
  <display:column property="status" class="tableCellError" />
  <display:column property="description" title="Comments"/>
</display:table>
   通过class属性来指定所要应用的样式。可以在光认样式表里(./css/screen.cssQ直接修?br />  
四、标{֏得数据的数据?br />  有四U范?br />   pageScope
   requestScope (默认)  <display:table name="test2" >
   sessionScope  <display:table name="sessionScope.holder.list" > 注意Q这里要指定范围Q非默认
   applicationScope
  
五、通过增加id属性创建隐含的对象
<display:table name="test" id="testit">
    <display:column property="id" title="ID" />
    <display:column property="name" />
    <display:column title="static value">static</display:column>
    <display:column title="row number (testit_rowNum)"><%=pageContext.getAttribute("testit_rowNum")%></display:column>
    <display:column title="((ListObject)testit).getMoney()"><%=((ListObject)pageContext.getAttribute("testit")).getMoney()%></display:column>
</display:table>
   注意到在<display:table/>里增加了id属性,q时在page context里创Z一个隐含对象,指向List里的当前对象Q?br />   可以通过(ListObject)pageContext.getAttribute("id")来捕莯个对象。同时还创徏了一个id_rowNum对象Q同P?br />   通过pageContext.getAttribute("testit_rowNum")来捕P它仅仅代表当前行的行数?br />   有了q两个隐含对象,可以通过其他标签来访问,例如Jstl:
  <display:table id="row" name="mylist">
    <display:column title="row number" >
      <c:out value="${row_rowNum}"/>
    </display:column>
    <display:column title="name" >
      <c:out value="${row.first_name}"/>
      <c:out value="${row.last_name}"/>
    </display:column>
  </display:table>
 
六、显C部分数?/strong>
   昄开始五条数据:通过讑֮length属?br /><display:table name="test" length="5">
  <display:column property="id" title="ID" />
  <display:column property="email" />
  <display:column property="status" />
</display:table>
   昄W三到第八条数据Q通过讑֮offset和length属?br /><display:table name="test" offset="3" length="5">
  <display:column property="id" title="ID" />
  <display:column property="email" />
  <display:column property="status" />
</display:table> 

七、对email和url地址的直接连?/strong>
 <display:table name="test" >
  <display:column property="id" title="ID" />
  <display:column property="email" autolink="true" />
  <display:column property="url" autolink="true" />
 </display:table>
 如果要显C的对象里包含email和url地址Q则可以在display:column里直接设定autolink="true"来直接连?br /> 
八、用装饰模式{换数据显C(写自q decorator Q?/strong>
  A、对整个表格应用decorator
  <display:table name="test" decorator="org.displaytag.sample.Wrapper" >
      <display:column property="id" title="ID" />
      <display:column property="email" />
      <display:column property="status" />
      <display:column property="date" />
      <display:column property="money" />
  </display:table>
    org.displaytag.sample.Wrapper卌己写的decoratorQ它要承TableDecoratorc,看看它的一个方法:
        public String getMoney()
    {
        return this.moneyFormat.format(((ListObject) this.getCurrentRowObject()).getMoney());
    }
    很明显,它通过父类的getCurrentRowObject()Ҏ获得当前对象Q然后对其getMoney()Ҏq行‘a漆?br />  B、对单独的column应用decorator
  <display:table name="test">
     <display:column property="id" title="ID" />
     <display:column property="email" />
     <display:column property="status" />
     <display:column property="date" decorator="org.displaytag.sample.LongDateWrapper" />
  </display:table>
    org.displaytag.sample.LongDateWrapper要实现ColumnDecorator接口Q它的方法:
        public final String decorate(Object columnValue)
    {
        Date date = (Date) columnValue;
        return this.dateFormat.format(date);
    }
    昄Q它获得不了当前对象Q因为它实现的是接口Q,仅仅是获得该对象的columnValueQ然后‘a漆?br />   
九、创建动态连?br />   有两U方法创建动态连接:
   A、在<display:column/>里通过增加href、paramId、paramName、paramScope、paramProperty属?br />      href             基本的URL 地址
      paramId          加在URL 地址后的参数名称
      paramName        数据bean的名Uͼ一般ؓnullQ即使用当前List里的对象Q?br />      paramScope       数据bean的范_一般ؓnull
      paramProperty    数据bean的属性名Uͼ用来填充URL 地址后的参数?br /><display:table name="sessionScope.details">
  <display:column property="id" title="ID" href="details.jsp" paramId="id" />
  <display:column property="email" href="details.jsp" paramId="action" paramName="testparam" paramScope="request" />
  <display:column property="status" href="details.jsp" paramId="id" paramProperty="id" />
</display:table> 
    q种Ҏ便直接,但缺Ҏ无法产生cMdetails.jsp?id=xx&action=xx的复合URL
   B、应用decorator 创徏动态连接:
<display:table name="sessionScope.details" decorator="org.displaytag.sample.Wrapper" >
  <display:column property="link1" title="ID" />
  <display:column property="email" />
  <display:column property="link2" title="Actions" />
</display:table>
   org.displaytag.sample.Wrapper里的ҎQ?br /> public String getLink1()
 {
  ListObject lObject= (ListObject)getCurrentRowObject();
  int lIndex= getListIndex();
  return "<a href=\"details.jsp?index=" + lIndex + "\">" + lObject.getId() + "</a>";
 }


 public String getLink2()
 {
  ListObject lObject= (ListObject)getCurrentRowObject();
  int lId= lObject.getId();

  return "<a href=\"details.jsp?id=" + lId
   + "&action=view\">View</a> | "
   + "<a href=\"details.jsp?id=" + lId
   + "&action=edit\">Edit</a> | "
   + "<a href=\"details.jsp?id=" + lId
   + "&action=delete\">Delete</a>";
 }

十、分?br />   实现分页非常的简单,增加一个pagesize属性指定一ơ想昄的行数即?br /><display:table name="sessionScope.test" pagesize="10">
 <display:column property="id" title="ID" />
 <display:column property="name" />
 <display:column property="email" />
 <display:column property="status" />
</display:table>

十一、排?br />   排序实现也是很简单,在需要排序的column里增加sortable="true"属性,headerClass="sortable"仅仅?br />   指定昄的样式。column里的属性对象要实现Comparable接口Q如果没有的话可以应用decorator
   defaultsort="1"              默认W一个column排序
   defaultorder="descending"    默认递减排序
<display:table name="sessionScope.stest" defaultsort="1" defaultorder="descending">
  <display:column property="id" title="ID" sortable="true" headerClass="sortable" />
  <display:column property="name" sortable="true" headerClass="sortable"/>
  <display:column property="email" />
  <display:column property="status" sortable="true" headerClass="sortable"/>
</display:table>
  注意的是Q当同时存在分页时排序仅仅针对的是当前页面,而不是整个List都进行排?br /> 
十二、column 分组
   分组只是需要在column里增加group属?br /><display:table name="test" class="simple">
  <display:column property="city" title="CITY" group="1"/>
  <display:column property="project" title="PROJECT" group="2"/>
  <display:column property="amount" title="HOURS"/>
  <display:column property="task" title="TASK"/>
</display:table>

十三、导出数据到其他格式Q页面溢出filter??Q?/strong>
   ?lt;display:table/>里设定export="true"
   ?lt;display:column/>里设定media="csv excel xml pdf" 军_该字D在导出到其他格式时被包不包含,不设定则都包?br />   <display:setProperty name="export.csv" value="false" />
   军_该种格式能不能在面中导?br /><display:table name="test" export="true" id="currentRowObject">
  <display:column property="id" title="ID"/>
  <display:column property="email" />
  <display:column property="status" />
  <display:column property="longDescription" media="csv excel xml pdf" title="Not On HTML"/>
  <display:column media="csv excel" title="URL" property="url"/>
  <display:setProperty name="export.pdf" value="true" />
  <display:setProperty name="export.csv" value="false" />
</display:table>

十四、配|属性,覆盖默认
  两种ҎQ?br />  A、在E序classpath下新建displaytag.properties文g
  B、对于单个表|应用<display:setProperty>标签
  具体可配|的属性:http://displaytag.sourceforge.net/configuration.html
 
十五、一个完整的例子
<display:table name="test" export="true" sort="list" pagesize="8">
  <display:column property="city" title="CITY" group="1" sortable="true"    headerClass="sortable"/>
  <display:column property="project" title="PROJECT" group="2" sortable="true" headerClass="sortable"/>
  <display:column property="amount" title="HOURS"/>
  <display:column property="task" title="TASK"/>
</display:table>
   sort="list" Ҏ个listq行排序
   导出数据到其他格式时Qgroup无效



weibogao 2006-07-03 13:23 发表评论
]]>
关于ClassName.class.getResourceAsStream的\径问?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/weibogao/archive/2006/06/20/54010.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/54010.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2006/06/20/54010.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/54010.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/54010.html</trackback:ping><description><![CDATA[ <h2> <a id="viewpost1_TitleUrl" >关于ClassName.class.getResourceAsStream的\径问?/a> </h2> <p>对ClassName.class.getResourceAsStream的\径问题比较模p,现在把研I的l果写一下:</p> <p>ClassName是这个Class的名Uͼq里假设为MyClassQ处于MyPackage.MyChildPackage包中Q如果你source.props文g攑֜Classes文g夹中的时候,可以q样写ClassName.class.getResourceAsStream(/source.props)</p> <p>如果你想把props文g攑֜包中的时候,假设攑ֈMyPackage.MyChildPackage中的res文g夹,可以q样写ClassName.class.getResourceAsStream(/MyPackage/MyChildPackage/res/source.props)Q?代表的是包的.</p> <img src ="http://www.aygfsteel.com/weibogao/aggbug/54010.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2006-06-20 16:20 <a href="http://www.aygfsteel.com/weibogao/archive/2006/06/20/54010.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate中很用的one-to-one配置注意事项Q一对一的本质是一对多的特例)http://www.aygfsteel.com/weibogao/archive/2006/06/19/53800.htmlweibogaoweibogaoMon, 19 Jun 2006 07:43:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/06/19/53800.htmlhttp://www.aygfsteel.com/weibogao/comments/53800.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/06/19/53800.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/53800.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/53800.html hibernate:one-to-one注意事项
one-to-one在hibernate中可以用来作Z张表之间的主键关联,q也是hibernate中主键关联的一U用法,q样在一张表中的IDQ在生成另外一张表的同时回自动插入到相应的ID字段中去Q相应的XML文g讄比较单,举例如下Q?br />
    <!-- 建立一对一的到Address的映,q个是写在User的XML配置文g中的 -->
    <!-- 相应的User beanQPOQ中也要d属?com.xx.Address  address-->
    <one-to-one name="address" cascade="all" class="com.xx.Address"/>
   
   <!-- cascade的属性设|不再重复了Q可以查看hibernate文 -->

    <!-- 建立一对一的到User的映,q个是写在Address的XML配置文g中的 -->
    <!-- 相应的Address beanQPOQ中也要d属?com.xx.User user--> -->
    <one-to-one name="user" class="com.xx.User" constrained="true"/>

      Z在Address中用User中的主键ID|我们需要设|Address中的主键生成规则Q如下所C,采用foreign关键?br />
   <id column="ID" name="id" type="long" unsaved-value="0">
      <generator class="foreign">
        <param name="property">user</param> 
      </generator>
   </id>


      q里需要注意的是property的属性值必M上面到User的映所填写的name属性g?/em>Q这样就完成了one-to-one的映关pR?br />
上面的过E都很简单,下面我来说说q里需要注意的地方Q?br />
  1.   在设|属性ID的时候必L意字D늚长度Q如W者这样用oracle的sequence来生成IDQ其长度?4位之长,则应选择hibernatecdlongQ对应的实体中应选择LongQ这样不会出现溢出的情况?/strong>


  2.   在测试的时候必要注意q两张表之间因ؓ已经存在了一对一的关p,所以我们不能只?br />         user.setAddress(address);
         而忽略了
         address.setUser(user);
         q样在做插入的时候会报出attempted to assign id from null one-to-one property: address的错误,q一点初学者会l常犯,W者也是其中之一?br />

 3.   如果不写cascade="all"或者写成cascade="none"的话Q即使你写了
         user.setAddress(address);
         address.setUser(user);
       也不会发生Q何事情,只有user会被存储?/div>

weibogao 2006-06-19 15:43 发表评论
]]>设计模式之食堂版http://www.aygfsteel.com/weibogao/archive/2006/05/29/48728.htmlweibogaoweibogaoMon, 29 May 2006 05:09:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/05/29/48728.htmlhttp://www.aygfsteel.com/weibogao/comments/48728.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/05/29/48728.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/48728.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/48728.html转脓:

设计模式是美国一位徏{大师(同时也是信息工程师,dQ机械工E师…的Q克里斯蒂安.亚历山大首先提出来的Q很快被软g界的技术员们所接受推广Q成Y件工E里至高无上的法则之一Q有兴趣的h可以找他的《徏{的永恒之道》一书看看,怿会受益非)。简单地说就是在面对对象的基上,包括面对对象Q把要设计的整体的各个部分模式化Q层ơ化Q细_度化,高度复用化,可控化,人性化。其中至高无上的原则是徏立在需求的基础之上Q也是_无论做什么,人的需求要攑֜W一位考虑Q从q个角度考虑整个pȝ是否_合理。这门学问是非常有趣的,其在flash中,可以应用到很多很好玩的实例中厅R下面我按照一些通用的设计模式,举例说明Q有错误的地方,敬请高手指正Q?br />
1Q抽象工厂模式(Abstract FactoryQ:

食堂里吃的东西很多,而我只想吃一P那么食堂q个概念Ҏ来说是个抽象工厂,每个H口可以看成它的一个具体实玎ͼ我要做的是Q去食堂Q找到那个窗口,从窗口里买我要吃的东ѝ?br />
举例Qflash前台与asp后台的交互,讉K某个动态页面,从数据库里取出需要的数据Q通常的做法是在后台就把数据集解析成xml字符Ԍ再送给swf。每个业务逻辑模块Q所取出的数据结构,也就是xml的结构是不一LQ我们要针对各个具体的业务逻辑Q对相应的xml字符串解析,转换成可供显C的数组。也要把flash里文本输入的内容转换?xml字符Ԍ提交l后C?br />
AbstractFactory.as
//抽象工厂的接?br />Interface AbstractFactory{
//生成xml解析工厂的具体实?br />function createXmlParseFactory();
}

XMLParserGetFactory.as
//生成解析d的xml的对象的工厂
class XMLParserGetFactory implements AbstractFactory.{
var xmlParser;
function XMLParserGetFactory(str:String){
//生成解析器的具体实现Q在后面会提?br />}
function createXmlParser(){
return xmlParser;
}
}
XMLParserPostFactory.as
//生成解析输出的xml的对象的工厂
class XMLParserPostFactory implements AbstractFactory.{
var xmlParser;
function XMLParserPostFactory(str:String){
//生成解析器的具体实现
}
function createXmlParser(){
return xmlParser;
}
}

q样Q我们读入某个xml字符串时Q在onLoad里面加入
//生成对留a板的留言列表解析的工?br />var xmlParser=new XMLParserGetFactory(“xmlParseGuestbookList?
xmlParser= XMLParserGetFactory. createXmlParser()

备注Q抽象工厂模式是软g工程里最常用的设计模式之一Q实现过E在于,需要某个类的实例时Q通过某个工厂创徏Q而不是直接创建,坦白地说Q它加大了开发工作量Q但是对E序的层ơ性变得分明和降低耦合度有极大帮助?br />

2Q生成器模式QbuilderQ:

q是那个说法Q我要吃东西去相应的食堂窗口,但我不能吃食堂窗口,H口里的东西也许不少Q我要跟师傅_要这个,q个Q还有这个?br />
举例Q我已经建立?xml解析器的工厂Q现在要q回解析器本w,p工厂创徏Q返回给我?br />
XMLParserGetFactory.as
//生成解析d的xml的对象的工厂
class XMLParserGetFactory implements AbstractFactory.{
var xmlParser;
function XMLParserGetFactory(str:String){
//如果要求留言板列表解析器Q就生成一?br />if(str==?xmlParseGuestbookList?{
xmlParser=new xmlParserGuestbookList();
}
}
function createXmlParser(){
//q回所要求的解析器
return xmlParser;
}
}

AbstractXmlParser.as
//抽象xml解析?br />Interface AbstractXmlParser{
function ParseXml();
}
xmlParserGuestBookList.as
//留言板列表解析器
Class xmlParserGuestBookList implements AbstractXmlParser{
//把xml字符串里的内容解析到一堆数l里
function ParseXml(xml:XML,arrayID:Array,arrayTitle:Array){
//具体循环操作
}
}

使用的时候:
var xmlParser=new XMLParserGetFactory(“xmlParseGuestbookList?
xmlParser= XMLParserGetFactory. createXmlParser(xml,arrayID,arrayTitle);

3Q工厂方法模式(Factory MethodQ?br />我到了食堂窗口,如果师傅跟那儿抽烟,我还是吃不着东西。我_师傅Q打饭!师傅才会完成打饭q一动作。这是工厂方法模式,抽象工厂的实现通常用工厂方法模式来完成?br />
举例Q还是上一条,我本来想用一句话带一个参数就实现具体xml解析器的实现Q无奈构造函数没有返回|所以必ȝ
xmlParser= XMLParserGetFactory. createXmlParser(xml,arrayID,arrayTitle);
实现?br />
备注Q抽象工厂模式,生成器模式和工厂Ҏ模式需要灵zd用?br />

4Q单件模式(singletonQ?br />
我前面一个hC一条巨大的鸡腿Q我说我也要一条,师傅_p一?br />
举例Q单件模式的应用是相当广泛的Q它保每个实例在全局范围内只被创Zơ,我们flash里的mc大多数是单g。内栔R的核心组件也只是单gQ比如我的消息映列表(见后Q?br />按照单g模式的严格定义,应该让类负责保存它的唯一实例。但是我在Flash里还想不到怎么实现q一点,或者实现它的意义所在,但另外一Ҏ们可以做刎ͼ是在全局范围内只提供该对象的唯一讉K炏V这可以由层ơ关pd刎ͼ把对该对象的讉K具体实现全部装在下层,只给上层提供唯一的访问点Q原因是Q上层不知道q个单g的具体信息,比如路径Q?br />看我内核文g的一部分Q?br />Core.as
//内核
class Core {
var strucGlobalParam:ConfigVariables;
//站点信息
var xmlConfig:XML;
//站点信息的xml化对?br />var ArrayStructureInitial:Array;
//用来提供lloadObject对象的数l?br />var ArrayForBtn:Array;
//用来初始化导航条lg的数l?br />var objInitial:loadObject;
//dq的对?br />var objMessageMap:MessageMap;
//消息映射lg
…?br />}
q是我的内核cM是全站最核心cȝ数据l构。里面的数据只有通过下层的BasicMovieQOriginalFunctionObject{类Q见后)直接讉K?br />
备注Q核心思想是,保只有一个?br />

5Q原型模式(protoTypeQ?br />
到小炒窗口,看前面的哥们炒的青椒炒肉不错的样子。“师傅,我也要这L。?br />
举例Q这对flash的用h说再熟悉不过了,我们l常用duplicateMovieClip()?br />attachMovie()q两个函数。按照一个原型复制相应的实例Q各自执行自q动作。在我的blog列表Q导航条的生成。。几乎用得到多项数据的地方就要用原型模式?br />
6.责Q链模式,7.中介者模式,8.观察者模式:

食堂里厨房最q的H口没熬白菜了,要告诉厨房,快送过来?br />责Q链模式:一个窗口一个窗口地传话Q一直传到食堂,食堂一看不妙,赶快做好送过厅R?br />中介者模式:专门z一个h负责传话QQ何窗口没菜了Q就要这个h赶快d房催?br />观察者模式:厨房那边z一个盯着Q看哪个H口没菜了就开始大声嚷嚗?br />
举例Q之所以要把这三个设计模式攑֜一块儿Q是因ؓ我在我的站里面结合这三者徏立了一个好玩的东西Q可以说是我的网站的核心所在。它解决了我的flash里面各个mc的通信问题?br />比如Q媄片A攑֮了,要通知qB开始播放,直接的做法是在A的最后一帧,写从A到B的相对\径或B的绝对\径,让B play()。这样做A和B的耦合性是相当高的Q也是_怺依赖E度太高。运用设计模式的解决Ҏ如下Q?br />
MessageMap.as
//消息映射c?br />class MessageMap extends Object {
var Message:String;
var MessageWatcher:Function;
var Target;
var MessageList:Array;
var Num_Msg:Number;
function MessageMap() {
Num_Msg = 0;
MessageList = new Array();
Message = "HANG_UP";
MessageWatcher = function (prop, oldVar, newVar, Param) {
for (var i = 0; iif (newVar == MessageList[i][0]) {
MessageList[i][1].apply(MessageList[i][3], MessageList[i][2]);
if (!MessageList[i][4]) {
MessageList.splice(i, 1);
Num_Msg--;
i-=1;
}
}
}

};
this.watch("Message", MessageWatcher, "test");
}
function SendMessage(Msg:String, mc:MovieClip) {
Message = Msg;
}
function UpdateMessageMap(Msg:String, objFunction:Function, ArrayParam:Array, objRefer,IsMultiUsed:Boolean) {
MessageList[Num_Msg] = new Array();
MessageList[Num_Msg][0] = new String();
MessageList[Num_Msg][0] = Msg;
MessageList[Num_Msg][1] = new Function();
MessageList[Num_Msg][1] = objFunction;
MessageList[Num_Msg][2] = new Array();
MessageList[Num_Msg][2] = ArrayParam;
MessageList[Num_Msg][3] = objRefer;
MessageList[Num_Msg][4] = IsMultiUsed;
Num_Msg++;
}
function DeleteMessageMap(objRefer) {
for (var i = 0; iif (MessageList[i][2] == objRefer) {
MessageList.splice(i, 1);
Num_Msg--;
}
}
}
}

class SubTemplateMovie extends BaseMovie {
var MovieRemoveFunction:Function;
function SubTemplateMovie() {
this.stop();
MovieStartFunction = function () {
Lock();
this.play();
};
MovieEndFunction = function () {
Lock();
this.play();
};

MovieRemoveFunction = function () {
this.stop();
SendMsg("SUB_TEMPLATE_REMOVED", this);
_parent.unloadMovie();
};
MovieMainFunction = function () {
stop();
SendMsg("SUB_TEMPLATE_OPEN", this);
};
UpdateMessage("LOADING_BAR_OVER", MovieStartFunction, null, this, false);
UpdateMessage("BACK_TO_INDEX", MovieEndFunction, null, this, false);
}
}

大概机制是Q媄片提前提交一个数据结构,声明Q如果有q提交q条消息Q就执行q条函数。原理在于,发送消息,实际上是把消息映的一个变量赋|׃消息映射l承自objectc,可以用watchҎ对该变量q行监视Q一旦改变,在已l提交上来的消息映射列表里检查,如果有,执行对应函数。实际上q也造成了一定程度的耦合性,但是我们已经成功地把耦合性控制在了下U类Q上U子cd全不用理会这一套消息机制的实现q程?br />
q个机制可以让我们对oop的真正目的有更深的看法。D例说明,qA播放完了Q就声明自己播放完了Q至于我播完了你要干什么,不是我的事,我不控制你。所谓的降低耦合度是个相Ҏ念,别忘了在计算机最底层Q耦合度还是一PcpuL不断的直接或间接dQ但我们需要做的是Q改变系l的拓扑l构Q把耦合度控制在某一个范围之内?br />
整个消息映射cȝ当于一个中介者,内部生成一个观察器Q一旦触发消息,以责任链的方式执行?br />

9.桥接模式QBridgeQ?br />
菜太淡,不合有些人的胃口Q所以要求食堂的师傅Q专门开一个窗口,专门在做好的菜里多加些G椒?br />
我在自己的站里运用了桥接模式Q所有的q都承自我定义的BasicMovie c(BasicMoviel承自MovieClipc)Q但是在四个下栏目的媄片里Q需要定义相同的Ҏ和事件来响应消息QBasicMovie没有q些函数Q不W合要求Q这时候,在四个媄片里都写一遍是愚蠢的,我又写了一个SubTemplateMoviecȝ承自BaseMovieQ里面加q一些通用的方法,然后四个下模板q都承它Q这样大大简化了后期开发?br />
BasicMovie.as
//基类q
/所有媄片的原始c,一切媄片的父类都承此c而来
class BaseMovie extends MovieClip {
var isLocked:Boolean;
//初始cd始媄片函?br />var MovieStartFunction:Function;
//初始cd片主功能函数
var MovieMainFunction:Function;
//初始cȝ束媄片函?br />var MovieEndFunction:Function;
var GlobalParam
//初始cL造函?br />function BaseMovie() {
}
//

//发送消?br />function SendMsg(Msg:String, Mc:MovieClip) {
_root.objCore.objMessageMap.SendMessage(Msg, Mc);
}
//d消息映射
function UpdateMessage(Msg:String, MsgMapFunction:Function, ArrayParam, obj, IsMultiUsed) {
_root.objCore.objMessageMap.UpdateMessageMap(Msg, MsgMapFunction, ArrayParam, obj, IsMultiUsed);
}
//删除消息映射
function DeleteMessage(obj) {
_root.objCore.objMessageMap.DeleteMessageMap(obj);
}
function GetGlobalParam() {
GlobalParam=_root.objCore.strucGlobalParam;
}
}

SubTemplateMovie.as
//下模板qc?br />class SubTemplateMovie extends BaseMovie {
var MovieRemoveFunction:Function;
function SubTemplateMovie() {
this.stop();
MovieStartFunction = function () {
Lock();
this.play();
};
MovieEndFunction = function () {
Lock();
this.play();
};

MovieRemoveFunction = function () {
this.stop();
SendMsg("SUB_TEMPLATE_REMOVED", this);
_parent.unloadMovie();
};
MovieMainFunction = function () {
stop();
SendMsg("SUB_TEMPLATE_OPEN", this);
};
UpdateMessage("LOADING_BAR_OVER", MovieStartFunction, null, this, false);
UpdateMessage("BACK_TO_INDEX", MovieEndFunction, null, this, false);
}
}
注(关于消息映射机制?责Q链模式)


10.适配器模式(AdapterQ?br />
我要一汤Q但是只有纸饭盒Q还没勺Q所以食堂的师傅l了我一ơ性的汤碗和勺Q这叫适配器?br />
适配器解决的是某一个类的对外接口不合用的问题,可能是参数或者返回值类型不W等问题造成的,q时候我们需要在工作对象和这个类之间加一层间接的层次?br />q个模式我在底层的数据交换层用过。我说过Qflash和asp.net之间交换数据全以xml体。返回xml在底层只有三层,数据库操作,数据操作Q数据显C,由数据操作层q回l数据显C层一个xml字符串就可以了。然后我遇C个小问题Q在另一斚wQ我需要提交数据到数据库,也是提交一个xml字符Ԍ但是我需要数据库里对应的表的数据集的xml表现形式的xsd验证Q(一口气说完Q差Ҏ憋死Q。就是说我至需要取个表里的一条记录,问题在于Q我装的类从来只返回xmlQ没有返回xsd的。解军_法就是适配器,新徏一个项目,加了一层专用于获得xml验证格式Q这样就完成了不同接口之间的转换?br />
备注Q适配器和桥接很象Q都是在已有cMW合要求的时候,加入一层间接的元素以达到目的。不同的是适配器是解决不兼Ҏ口之间的转换Q桥接一般不涉及q个问题Q只是完成一个一对多的{换?br />

11.外观模式QFacadeQ?br />
每天都要去食堂,每个人去不同的窗口吃不同的菜Q很累,今天全寝室推丄子去打饭Q?br />你吃q个Q三两饭Q我吃那个,五两饭,所有h都只跟猴子一个h交涉Q食堂所有的师傅也只见猴子一个h?br />
举例Q这个模式在E序的上下层的通信之间可以应用得十分广泛。Asp的每个模块要M同的数据Q访问数据库的不同表Q就要跟不同的下层数据访问组件打交道。就是说Q每个mc模块必须知道Q我要去哪个具体的数据访问组件取数据。每个模块要l持自己的一个,臛_是字W串?br />如果q用外观模式。我们可以让所有的需要数据交互的mc讉K同一个aspx面Q比如getStrXml.aspx。只要传送一个标C符Q就可以通知q个唯一的取数据的叶面,讉K哪个下层lg获取数据。下层组件不知道哪个mc要求数据Qmc也不知道数据的具体来源,q样Q上下层之间互相都显得不透明。这降低了耦合度?br />

12.代理模式QProxyQ?br />
可能我们不是每个人每天都惛_饭,所以我们要求猴子每天中午必d寝室Q如果我们要吃,他就去,如果我们都不吃,他爱q嘛q嘛?br />
举例Q这恐怕是每个人在flash里都会无意中用到的模式。比如,一个网站,它的下栏目不用在整个网站初始化的时候一开始就读进来,但是我们要确保,在浏览者想看ƈ且点d航条上的某个按钮Ӟ能够正确地读q相应的q文gQ前提是Q我们必d内部保留一个烦引,可以UC代理。通常是一个空mc


13.{略模式Q(strategyQ?br />
我每天先在食堂找座位Q再打饭Q再打菜Q再买杯酸奶。这已经模式化。要是食堂有服务员,我也会要他这么做?br />
举例Q策略模式是把一pd的算法封装v来,形成一个类。这个模式几乎是随时随地都可以整合到别的模式里去的,我的那一堆xml解析器实际上是{略模式的应用,q个模式q应用到我网站的下层Q因为flash提交laspx面的数据也是xml字符Ԍ下层模块也需要相应的解析法。同LQ我把对xml的解析封装进了一个类?br />
//Cs文g里的解析函数

Class DataModel.BlogMsgs{
?br />Public DataSet parseXML(string strXml){
DataSet ds=new DataSet();
//。。把xml装蝲到DataSet ?br />Return ds
}
?br />}


14.享元模式QFlyweightQ?br />
东西不够吃?l你?0面镜子~
师傅Q东西还是只有一份。。?br />
关于q个模式十分抱歉Q我暂时q没惛_在flash昄层里面的实现。需要D例说明的是,览器的机制是,在有大量文字的英文文里Q相同的字母׃n一个FlyweightQ在内存里其实只占一份空_然后在文不同的地方昄Q这样对于大量细_度的效果来_可以节省很多资源。在下层Q我们可以做到的是Q对某个全局对象只在某处真正保存QQ何对象想要这个全局对象Q只引用它而不复制它?br />
在显C层里有哪位惛_了该怎么做请一定赐教?br />

15.讉K者模式(VisitorQ?br />
只要愿意Q我随时都可以跑到哪个窗口打要吃的东西,前提是,我必跑q一?br />
举例Q我说过Q我的所有mc都承自BasicMovieq个c,但不是我的所有mc都要从后来获取数据库数据。获取数据库数据所要访问的信息Q比如ipQ\径,文g保存在配|文仉Q初始化的时候读入内核,q且只有内核那里有一份。在BasicMovie里加入对q些全局变量的引用是不合适的Q因为只有少数mc要用刎ͼ而且׃某些原因我无法再使用桥接模式Q我已经有了SubTemplateMovieQ不能多l承Q,所以我用了讉K者模式?br />
BasicMovie.as

//获取全局变量
function GetGlobalParam() {
GlobalParam=_root.objCore.strucGlobalParam;
}

如果上mc不执行这个函敎ͼ是不能获取全局变量的,如果要用Q就执行?br />也就是说Q需要的时候,我去讉K它?br />
备注Q声明一个visit操作Q得访问者可以正访问需要的cR?br />

16.状态模式(stateQ?br />
我今天想吃面Q师傅问我:要什么料Q西U柿鸡蛋Q排骨还是牛肉?

举例Q状态模式是指将对象当前的某些状态局部化Q当对象改变状态时Q看h好像改变了类。例子还是我的滚动条。如果要滚动的是文本框,p引用一个TextField的Scroll,maxscroll属性,如果是mcQ引用的是_y,_height属性,我用一个参数将二者区分,׃个if语句控制Q让滚动条可以自由区别状态?br />另外一个解x案是定义ScrollBar的不同子c,q两者本质区别不大,在状态比较多Ӟ可能要维持一个庞大的if法Q这样就用生成子cȝҎ比较好?br />
ScrollBar.as
//滚动条组?br />function BindTo(mc,type:String,intMcHeight:Number,yinitial:Number){
ScrollType=type;
if(type=="TXT"){
scrollTxt=mc;
}
if(type=="MC"){
initialY=yinitial;
McHeight=intMcHeight;
scrollMc=mc;
}
}
function Scroll() {
if(ScrollType=="TXT")
this.onEnterFrame = function() {
scrollTxt.scroll = scrollTxt.maxscroll*mcBlock._y/(BgLength-BlockLength*3/2)
};
if(ScrollType=="MC"){
this.onEnterFrame=function(){
if(scrollMc._height>McHeight){
scrollMc._y=initialY-(scrollMc._height-McHeight)*mcBlock._y/(BgLength-BlockLength*3/2)}
}
}
}

备注Q这也是常见模式Q在flash的逻辑控制里尤光处可?br />

17.装饰模式QDecoratorQ?br />
在食堂吃饭,没筷子怎么行?我是从来不带饭盆的。师傅很人性化Q每个窗口都攄一大把{子Q随用随ѝ?br />
q个模式如果用好Q有的地方可以很省力。比如,我网站里的滚动条Q?br />
ScrollBar.as
//滚动条组?br />class ScrollBar extends BaseMovie {
var BgLength:Number;
var BlockLength:Number;
var mcBlock:MovieClip
var Width:Number;
var ScrollType;
var scrollTxt:TextField;
var scrollMc:MovieClip;
var McHeight:Number
var initialY:Number
function ScrollBar() {
}
function InitialScrollBar(BgLength, BlockLength) {
this.BlockLength = BlockLength;
this.BgLength = BgLength;
}
function BindTo(mc,type:String,intMcHeight:Number,yinitial:Number){
ScrollType=type;
if(type=="TXT"){
scrollTxt=mc;
}
if(type=="MC"){
initialY=yinitial;
McHeight=intMcHeight;
scrollMc=mc;
}
}
function Scroll() {
if(ScrollType=="TXT")
this.onEnterFrame = function() {
scrollTxt.scroll = scrollTxt.maxscroll*mcBlock._y/(BgLength-BlockLength*3/2)
};
if(ScrollType=="MC"){
this.onEnterFrame=function(){
if(scrollMc._height>McHeight){
scrollMc._y=initialY-(scrollMc._height-McHeight)*mcBlock._y/(BgLength-BlockLength*3/2)}
}
}
}
function ScrollMc() {

}
function StopScroll() {
this.onEnterFrame=null;
}
function Reset(){
mcBlock._y=0;
}
}

核心函数是BindToQ)Q把q个滚动条的实例l定到某个动态文本框或者某个mc上,可以实现滚动?br />
备注Q装饰模式的思想是,在不影响其他对象的情况下Q以动态,透明的方式给单个对象d职责?br />

18.l合模式QcompositeQ?br />
我中午吃六两饭,猪肉炖粉条,辣子鸡,gQ咸鸭蛋Q外加两杯酸Ӟ猪!Q?br />q些东西都是对象Q他们共同组成了我的午饭?br />
举例Q应该说在Flash里组合模式是无处不在的,因ؓ只要q有mc的嵌套,有l合模式存在。几个mc装在一个mc里,q个装蝲用的mcUC容器?br />但是p么说Q恐怕没Z重视q个模式Q因Z理不理解他我们都在用。他的确有很多种实现方式Q我的方式之一是这L?br />
//blog.as
我的Blog
class Blog extends BaseMovie {
//blogW一界面Q包括日记列表,日历Q最q留a
var mcBlogList: mcBlogList;
//blogW二界面Q包括日记全文,回复Q对该日记的留言?br />var mcBlogDairy:MovieClip;
var currentState:String;
var currentDairyID:Number;
function blog(){
}
}

mcBlogList.as
//blogW一界面
class mcBlogList extends BaseMovie {
//最q留a
var recentMsgs:blogMsgsSC;
//日记列表
var blogList:BlogList;
//日历
var calendar:CalenderForBlog;

?br />mcblogDairy.as
//blogW二界面
class mcBlogDairy extends BaseMovie {
//日记全文昄
var BlogDairy:BlogDairy;
//留言?br />var GuestBook:BlogInputMsg;
//留言列表昄
var BlogMsgs:BlogMsgs;
}

然后里面每个lg都还包含另外的组Ӟ比如滚动条,动态文本框什么的Q我惌的是Q我写在as里的mc嵌套模式q不一定就W合fla文g里的具体物理嵌套模式Q有很多装饰性的mc不需要包含进来,也有很多具体原因Q需要改写\径。比如在BlogDairy下,滚动条的实际路径是BlogDairy.mc1.ScrollBarQ不做成BlogDairy.ScrollBar可能是因为我需要mc1的动画,也可能是别的具体原因。但是我们可以在mc1的时间u上加一?br />_parent. ScrollBar =This.ScrollBar
把\径指向改写,辑ֈ我们要用的模式QScrollBar是BlogDairy的直接成员。另外我没有语句初始化mcQ我习惯在库里设|mc的linkage?br />
备注Q虽然组合模式是每个人必不可要用的Q但正因为如此,我们可以惛_他更多更好更灉|的实现方?br />

19.备忘录模式(mementoQ?br />
~师傅,晚上的鸡腿没中午的新鲜啊?br />~胡_q就是中午的?br />
举例Q开个玩W,上面两句话不是备忘录模式的本意,实际上我一时想不出在食堂里备忘录是什么样子。备忘录的意思是Q在不破坏对象封装型的前提下Q保存对象的当前状态,当需要时Q恢复这个状态或提取q个状态?br />
备忘录被q泛地运用到逻辑关系里,它似乎是目前我提到的唯一跟时间有关的模式Q在控制论里可以涉及到因果系l。备忘录的应用非常广泛,最常见的是览器或|站的后退功能Q返回到上一个界面,但是在我的站里没有用刎ͼ因ؓ我的站是树状拓扑l构Q每个栏目都只能唯一Cȝ面进入或退回到ȝ面,那些|状拓扑l构的站点,每个栏目都可以通向其他的Q何栏目,很可能就需要这么一个功能,其实现方法往往是维持一个堆栈型的数l?br />
另外一个我惛_现的东西是网站内部自动记录,׃某些原因我暂时没有把它加到网站里。很单,是监视览者的每一步操作,在哪个栏目,停了多久Q做了些什么之c,如果d了,下次讉K|站时让他选择是否直接q入上次览的界面(比如他上ơ在看我写的说而没看完Q。这个可以通过sharedObject实现Q差不多也就是flash内部的cookie?br />
备注Q备忘录的实现要求还是很高的Q在提取对象状态的时候不要破坏对象的装性。理想的备忘录作Z个对象需要两个借口Q一个给理者,它不知道备忘录里装了什么状态,只负责地把状态移交给需要的对象Q一个留l原发者,原发者只能了解ƈ操作备忘录里装的状态,不能做别的操作?br />

结Q?

结Q我会随时补充这文章。但是我要D的一些例子暂时已l说完了。其实设计模式远q不止这几种Q经典的有2Q种Q我已知的有Q1U,而这里只有1Q种Q还有命令模式,解释器模式,q代器模式,模板Ҏ模式我没写到。我的站q用了一些我没有提到的,自己都还没细惌的设计模式。但是一一列D其实是意义不大的Q有兴趣的同志们要做的就是接触一下这些设计模式的l节和思想Q然后统l忘掉,和张无忌学太极拻I先学后忘是一L。招式要看,要学Q但是要领会其中的深意,灉|圎ͼ创造地Q相互结合,融会贯通地使用招式Q不能拘泥于招式Q更不能Z用招而用招。设计模式作为UML的重要组成部分,能够极大E度Cq我们的开发效率,使我们养成好的书写习惯,做出更h性,更和谐,更清晎ͼ复用性和可控性更高的作品?br />不要说你不是E序员,可以跟着感觉赎ͼ随心所Ԍ当然我们无权q涉。我也说了,as本来是x么写就怎么写,但接不接触,学不学习先进的思维模式Q这也是你的自由。更不要说你是搞艺术的,头脑偏重感性,不适合接触q些Q我之所以要带拉K堂D例,是想说明Q我要说的其实是Christian Alexander先生的,建筑的永恒之道,无论是徏{本w,q是M软g工程Q或者Flash 的asQ甚至Flash 的矢量绘图,工Q^面设计,一直到世界q一整体Q无不是遵@一个结构化的,由模式构成的永恒之道Q有着惊h的高度相通和怼性。参悟了q一点,不仅对做FlashQ对整个生活都会有新的看法。区别仅仅在于,从哪里开始入手思考,在这里,可以从Flash开始?/num_msg;>


weibogao 2006-05-29 13:09 发表评论
]]>
Java2 RMI 入门http://www.aygfsteel.com/weibogao/archive/2006/05/26/48384.htmlweibogaoweibogaoFri, 26 May 2006 09:16:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/05/26/48384.htmlhttp://www.aygfsteel.com/weibogao/comments/48384.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/05/26/48384.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/48384.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/48384.html Java2 RMI 入门 ?期:2004-12-30 14:36:22  ?处:原创  ?者:admin  ?读:128?/td>  
RMI从Java1.1开始,RMI使得q行于不同JVM(包括不同L)上的Java应用E序可以彼此通话?
卻I一个JVM中的Java应用E序可以调用另一JVM上的对象Q远E对象)所定义的方法?
Java RMI有着重要的意义。RMI在Java|络~程和高U编E中都有重要的应用,如EJB, Jini{?
Java2对RMI做了很多增强和改q,如安全性,动态代码下载等?
本文l出了一个最单的例子Q以说明其中的一些基本原理。本文的特点是注重了实际开发和真正的运?
环境相结合,模拟了RMI真正的开发和q行q程?

1. 实现q程接口Q生成远E对象,存根QStubQ和框架(Skeleton)

实现q程接口,q程接口告诉JVMQ实C该接口的对象可以q程调用及有哪些Ҏ可以调用?
本例子中定义了sayHelloQ)。由于远E调用会涉及到网l通讯Q因此这些方法都要抛出RemoteException.
q程接口和远E对象可以由A开发,q把q程接口(Hello)d打包分给Client端开发者B?

建立f:\server目录Q把Hello.java和HelloImpl.java拯到该目录中?

// Hello.java
package jdeveloper.rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Hello extends Remote {
String sayHello() throws RemoteException;
}

生成q程对象.
// HelloImpl.java
package jdeveloper.rmi;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.rmi.server.UnicastRemoteObject;

public class HelloImpl extends UnicastRemoteObject
implements Hello {

public HelloImpl() throws RemoteException {
super();
}

public String sayHello() {
return "Hello World!";
}

public static void main(String args[]) {

// Create and install a security manager
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
try {
Hello obj = new HelloImpl();
// Bind this object instance to the name "HelloServer"
Naming.rebind("HelloServer", obj);
System.out.println("HelloServer bound in registry");
} catch (Exception e) {
System.out.println("HelloImpl err: " + e.getMessage());
e.printStackTrace();
}
}
}
存根QStubQ和框架(Skeleton)
f:
cd \server
javac -d . Hello.java
javac -d . HelloImpl.java
rmic -d . jdeveloper.rmi.HelloImpl

jar cvf hello.jar jdeveloper\rmi\Hello.class 把hello.jar分发lClient端的开发者B?

存根QStubQ的存放Q?
存根QStubQ是动态下载的。Client通过存根QStubQ和q程对象的框?Skeleton)通讯Q对Client?
讲就象操作本地对象一栗在大多数情况下Q可下蝲的代码放到http服务器的某个目录中。本例子攑ֈhttp://hjc/rmi下?
hjc:机器名,rmi:http的一个目录。如果只是单机测试则可以攑ֈ某个目录?如f:\serverclasses.
本文对以上两种Ҏ都给行的步骤Qpolicy文g和bat文gQ?

2. 实现Client端程?
// HelloClient.java
package jdeveloper.rmi;
import java.rmi.RMISecurityManager;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.NotBoundException;

public class HelloClient {
public static void main(String args[]) throws Exception{
System.setSecurityManager(new RMISecurityManager());
Hello RemoteObj = (Hello)Naming.lookup("http://"+ args[0] +"/HelloServer");
System.out.println(RemoteObj.sayHello());
}
}

建立f:\client目录Q把HelloClient.java拯到该目录中?
建立f:\clientclasses目录Q把hello.jar拯到该目录中?
f:
cd \client
javac -classpath %CLASSPATH%;f:\clientclasses\hello.jar -d . HelloClient.java

3. q行E序
启动DOSH口
set classpath=
start rmiregistry

A.以单机方式运?
建立f:\serverclasses\jdeveloper\rmi目录
f:
cd f:\serverclasses
copy f:\server\hello.jar .
copy f:\server\jdeveloper\rmi\HelloImpl_Stub.class f:\serverclasses\jdeveloper\rmi\
jar xvf hello.jar

启动新的DOSH口
?starthelloserver.bat ?rmiserver.policy 攑ֈf:\server\
q行 starthelloserver

starthelloserver.bat
SET CP=f:\server;f:\serverclasses\hello.jar
echo using classpath: %CP%
java -classpath %CP% -Djava.rmi.server.codebase=file:/f:\serverclasses/
-Djava.rmi.server.hostname=hjc -Djava.security.policy=rmiserver.policy jdeveloper.rmi.HelloImpl

rmiserver.policy
grant {
permission java.net.SocketPermission "*:1024-65535",
"connect";
};

启动新的DOSH口
?starthelloclient.bat ?rmiclient.policy 攑ֈf:\client\
q行 starthelloclient

starthelloclient.bat
@echo off
set CP=f:\client;f:\clientclasses\hello.jar
echo using classpath %CP%
@echo on
java -classpath %CP% -Djava.rmi.server.codebase=file:/f:\serverclasses/
-Djava.security.policy=rmiclient.policy jdeveloper.rmi.HelloClient %1
rmiclient.policy
grant {
permission java.net.SocketPermission "*:1024-65535",
"connect";
permission java.io.FilePermission
"f:\\serverclasses\\-", "read";
};

B.以网l方式运?
建立 apache_path\htdocs\rmi\jdeveloper\rmi目录
cd apache_path\htdocs\rmi
copy f:\server\hello.jar .
copy f:\server\jdeveloper\rmi\HelloImpl_Stub.class apache_path\htdocs\rmi\jdeveloper\rmi
jar xvf hello.jar
?starthellohttpserver.bat ?rmihttpserver.policy 攑ֈf:\server\

启动新的DOSH口
q行 starthellohttpserver
starthellohttpserver.bat
SET CP=f:\server;f:\serverclasses\hello.jar
echo using classpath: %CP%
java -classpath %CP% -Djava.rmi.server.codebase=http://hjc/rmi/
-Djava.security.policy=rmihttpserver.policy jdeveloper.rmi.HelloImpl
rmihttpserver.policy
grant {
permission java.net.SocketPermission "*:1099", "accept, connect, listen, resolve";
permission java.net.SocketPermission "*:80", "accept, connect, listen, resolve";
};

启动新的DOSH口
?starthellohttpclient.bat ?rmihttpclient.policy 攑ֈf:\client\
q行 starthellohttpclient
starthellohttpclient.bat
@echo off
set CP=f:\client;f:\clientclasses\hello.jar
echo using classpath %CP%
@echo on
java -classpath %CP% -Djava.rmi.server.codebase=http://hjc/rmi/
-Djava.security.policy=rmihttpclient.policy jdeveloper.rmi.HelloClient %1

rmihttpclient.policy
grant {
permission java.net.SocketPermission "*:80", "connect";
permission java.net.SocketPermission "*:1024-65535", "connect";
};
 


weibogao 2006-05-26 17:16 发表评论
]]>
设计模式的有解释-qMM http://www.aygfsteel.com/weibogao/archive/2006/05/26/48374.htmlweibogaoweibogaoFri, 26 May 2006 08:58:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/05/26/48374.htmlhttp://www.aygfsteel.com/weibogao/comments/48374.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/05/26/48374.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/48374.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/48374.html 设计模式的有解释-qMM
//转自 http://blog.csdn.net/laurecn/
创徏型模?

1、FACTORY一qMM不了请吃饭了,麦当劳的鸡翅和肯德基的鸡都是MM爱吃的东西,虽然口味有所不同Q但不管你带MM去麦当劳或肯德基Q只向服务员说“来四个鸡翅”就行了。麦当劳和肯德基是生鸡翅的Factory?

工厂模式Q客L和工厂类分开。消费者Q何时候需要某U品,只需向工厂请求即可。消费者无M改就可以接纳C品。缺Ҏ当品修ҎQ工厂类也要做相应的修改。如Q如何创建及如何向客L提供?

2、BUILDER—MM最爱听的就是“我׃”这句话了,见到不同地方的MM,要能够用她们的方a跟她说这句话哦,我有一个多U语a译机,上面每种语言都有一个按键,见到MM我只要按对应的键Q它p够用相应的语a说出“我׃”这句话了,国外的MM 也可以轻松搞掂,q就是我的“我׃”builder。(q一定比军在伊拉克用的译机好卖)?

建造模式:品的内部表象和品的生成q程分割开来,从而一个徏造过E生成具有不同的内部表象的品对象。徏造模式得品内部表象可以独立的变化Q客户不必知道品内部组成的l节。徏造模式可以强制实行一U分步骤q行的徏造过E?

3、FACTORY?METHOD—请MM去麦当劳吃汉堡,不同的MM有不同的口味Q要每个都记住是一件烦人的事情Q我一般采用Factory?Method模式Q带着MM到服务员那儿Q说“要一个汉堡”,具体要什么样的汉堡呢Q让MM直接跟服务员说就?了?

工厂Ҏ模式Q核心工厂类不再负责所有品的创徏Q而是具体创建的工作交给子类dQ成Z个抽象工厂角Ԍ仅负责给出具体工厂类必须实现的接口,而不接触哪一个品类应当被实例化q种l节?

4、PROTOTYPE—跟MM用QQ聊天Q一定要说些深情的话语了Q我搜集了好多肉ȝ情话Q需要时只要copy出来攑ֈQQ里面p了,q就是我的情话prototype了。(100块钱一份,你要不要Q?

原始模型模式Q通过l出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的Ҏ创徏出更多同cd的对象。原始模型模式允许动态的增加或减品类Q品类不需要非得有M事先定的等U结构,原始模型模式适用于Q何的{l构。缺Ҏ每一 个类都必配备一个克隆方法?

5、SINGLETON—俺?个漂亮的老婆Q她们的老公都是我,我就是我们家里的老公SigletonQ她们只要说道“老公”,都是指的同一个hQ那是?刚才做了个梦啦,哪有q么好的??

单例模式Q单例模式确保某一个类只有一个实例,而且自行实例化ƈ向整个系l提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用?

l构型模?

6、ADAPTER—在朋友聚会上碰C一个美女SarahQ从香港来的Q可我不会说_语Q她不会说普通话Q只好求助于我的朋友kent了,他作为我和Sarah之间的AdapterQ让我和Sarah可以怺交谈?也不知道他会不会耍我)?

适配器(变压器)模式Q把一个类的接口变换成客户端所期待的另一U接口,从而原本因接口原因不匚w而无法一起工作的两个c能够一起工作。适配cd以根据参数返q一个合适的实例l客L?

7、BRIDGE—早上碰到MMQ要说早上好Q晚上碰到MMQ要说晚上好Q碰到MMI了件新衣服Q要说你的服好漂亮哦,到MM新做的发型,要说你的头发好漂亮哦。不要问我“早上碰到MM新做了个发型怎么说”这U问题,自己用BRIDGEl合一下不p ?

桥梁模式Q将抽象化与实现化脱耦,使得二者可以独立的变化Q也是说将他们之间的强兌变成弱关联,也就是指在一个Y件系l的抽象化和实现化之间用组?聚合关系而不是承关p,从而两者可以独立的变化?

8、COMPOSITE—Mary今天q生日。“我q生日,你要送我一件礼物。”“嗯Q好吧,d店,你自己挑。”“这件T恤挺漂亮Q买Q这条裙子好看,乎ͼq个包也不错Q买。”“喂Q买了三件了呀Q我只答应送一件礼物的哦。”“什么呀QT恤加裙子加包?Q正好配成一套呀Q小姐,ȝ你包h。”“……”,MM都会用Composite模式了,你会了没有??

合成模式Q合成模式将对象l织到树l构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树l构表示出来。合成模式得客L把一个个单独的成分对象和׃们复合而成的合成对象同{看待?

9、DECORATOR—Maryq完轮到Sarlyq生日,q是不要叫她自己挑了Q不然这个月伙食费肯定玩完,拿出我去q在华山上照的照片Q在背面写上“最好的的礼物,是׃的Fita”,再到街上C品店买了个像框Q卖C品的MM也很漂亮哦)Q再?隔壁搞美术设计的Mike设计了一个漂亮的盒子装v来……,我们都是DecoratorQ最l都在修饰我q个人呀Q怎么P看懂了吗Q?

装饰模式Q装饰模式以对客L透明的方式扩展对象的功能Q是l承关系的一个替代方案,提供比承更多的灉|性。动态给一个对象增加功能,q些功能可以再动态的撤消。增加由一些基本功能的排列l合而生的非常大量的功能?

10、FACADE—我有一个专业的Nikon相机Q我喜Ƣ自己手动调光圈、快门,q样照出来的照片才专业,但MM可不懂这些,教了半天也不会。幸好相机有Facade设计模式Q把相机调整到自动Q只要对准目标按快门p了,一切由相机自动调整Q这?MM也可以用q个相机l我拍张照片了?

门面模式Q外部与一个子pȝ的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系l更易于使用。每一个子pȝ只有一个门面类Q而且此门面类只有一个实例,也就是说它是一个单例模式。但整个pȝ可以有多个门面类?

11、FLYWEIGHT—每天跟MM发短信,手指都篏MQ最q买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上MM的名字就可以发送了Q再不用一个字一个字敲了。共享的句子是FlyweightQMM的名字就是提 取出来的外部特征Q根据上下文情况使用?

享元模式QFLYWEIGHT在拳L赛中指最轻量U。n元模式以׃n的方式高效的支持大量的细_度对象。n元模式能做到׃n的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部Q不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状 态不能媄响内蕴状态,它们是相互独立的。将可以׃n的状态和不可以共享的状态从常规cM区分开来,不可以׃n的状态从c里剔除出去。客L不可以直接创׃n的对象,而应当用一个工厂对象负责创׃n的对象。n元模式大q度的降低内存中对象的数??

12、PROXY—跟MM在网上聊天,一开头L“hi,你好?“你从哪儿来呀Q”“你多大了?”“n高多呀Q”这些话Q真烦hQ写个程序做为我的Proxy吧,凡是接收到这些话都设|好了自动的回答Q接收到其他的话时再通知我回{,怎么P酷吧?

代理模式Q代理模式给某一个对象提供一个代理对象,q由代理对象控制Ҏ对象的引用。代理就是一个h或一个机构代表另一个h或者一个机构采取行动。某些情况下Q客户不x者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客L 分L不出代理主题对象与真实主题对象。代理模式可以ƈ不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,q时候代理对象不能够创徏被代理对象,被代理对象必Lpȝ的其他角色代为创建ƈ传入?

行ؓ模式?

13、CHAIN?OF?RESPONSIBLEITY—晚上去上英语课Qؓ了好开溜坐C最后一排,哇,前面坐了好几个漂亮的MM哎,扑ּU条Q写上“Hi,可以做我的女朋友吗?如果不愿意请向前传”,U条׃个接一个的传上MQ糟p,传到W一排的M M把纸条传l老师了,听说是个老处奛_Q快??

责Q链模式:在责任链模式中,很多对象由每一个对象对其下家的引用而接?

h形成一条链。请求在q个链上传递,直到链上的某一个对象决定处理此h。客户ƈ不知道链上的哪一个对象最l处理这个请求,pȝ可以在不影响客户端的情况下动态的重新l织铑֒分配责Q。处理者有两个选择Q承担责L者把责Q推给下家。一个请求可以最l不 被Q何接收端对象所接受?

14、COMMAND—俺有一个MM安得特别严,没法见面Q只好借助于她弟弟在我们俩之间传送信息,她对我有什么指C,写一张纸条让她弟弟带l我。这不,她弟弟又传送过来一个COMMANDQؓ了感谢他Q我请他吃了杂酱面Q哪知道他说Q“我同时l?我姐姐三个男朋友送COMMANDQ就C最气Q才h吃面。”,:-(?

命o模式Q命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命o的责d执行命o的责d割开Q委z不同的对象。命令模式允许请求的一方和发送的一方独立开来,使得h的一方不必知道接收请求的一方的接口Q更不必知道h是怎么被接Ӟ以及 操作是否执行Q何时被执行以及是怎么被执行的。系l支持命令的撤消?

15、INTERPRETER—俺有一个《MM真经》,上面有各UMM的攻略,比如说去吃西的步骤、去看电qҎ{等Q跟MMU会Ӟ只要做一个InterpreterQ照着上面的脚本执行就可以了?

解释器模式:l定一个语a后,解释器模式可以定义出其文法的一U表C,q同时提供一个解释器。客L可以使用q个解释器来解释q个语言中的句子。解释器模式描q怎样在有了一个简单的文法后,使用模式设计解释q些语句。在解释器模式里面提到的语言是指M 解释器对象能够解释的Ml合。在解释器模式中需要定义一个代表文法的命ocȝ{l构Q也是一pd的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。命令对象的{l构中的对象的Q何排列组合都是一个语a?

16、ITERATOR—我׃了MaryQ不一切的向她求婚?

MaryQ“想要我跟你l婚Q得{应我的条g?

我:“什么条件我都答应,你说吧?

MaryQ“我看上了那个一克拉的钻石?

我:“我乎ͼ我买Q还有吗Q?

MaryQ“我看上了湖边的那栋别墅?

我:“我乎ͼ我买Q还有吗Q?

MaryQ“你的小弟弟必须要有50cm镎?

我脑袋嗡的一壎ͼ坐在椅子上,一咬牙Q“我剪,我剪Q还有吗Q?

…?

q代子模式:q代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起Ş成的MUC集,聚集对象是能够包容一l对象的容器对象。P代子模式P代逻辑装C个独立的子对象中Q从而与聚集本n隔开。P代子模式化了聚集?界面。每一个聚集对象都可以有一个或一个以上的q代子对象,每一个P代子的P代状态可以是彼此独立的。P代算法可以独立于聚集角色变化?

17、MEDIATOR—四个MM打麻,怺之间谁应该给谁多钱不清楚了,q怺当时我在旁边Q按照各自的{码数算钱,赚了q从我q里拿,赔了q也付l我Q一切就OK啦,俺得C四个MM的电话?

调停者模式:调停者模式包装了一pd对象怺作用的方式,使得q些对象不必怺明显作用。从而他们可以松散偶合。当某些对象之间的作用发生改变时Q不会立卛_响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的怺作用?化ؓ一对多的相互作用。调停者模式将对象的行为和协作抽象化,把对象在尺度的行ؓ上与其他对象的相互作用分开处理?

18、MEMENTO—同时跟几个MM聊天Ӟ一定要记清楚刚才跟MM说了些什么话Q不然MM发现了会不高兴的哦,q怺我有个备忘录Q刚才与哪个MM说了什么话我都拯一份放到备忘录里面保存Q这样可以随时察看以前的记录啦?

备忘录模式:备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏装的条件下Q将一个对象的状态捉住,q外部化Q存储v来,从而可以在来合适的时候把q个对象q原到存储v来的状态?

19、OBSERVER—想知道׃公司最新MM情报吗?加入公司的MM情报邮gl就行了Qtom负责搜集情报Q他发现的新情报不用一个一个通知我们Q直接发布给邮gl,我们作ؓ订阅者(观察者)可以及时收到情报啦?

观察者模式:观察者模式定义了一U一队多的依赖关p,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化Ӟ会通知所有观察者对象,使他们能够自动更新自己?

20、STATE—跟MM交往Ӟ一定要注意她的状态哦Q在不同的状态时她的行ؓ会有不同Q比如你U她今天晚上ȝ电媄Q对你没兴趣的MM׃说“有事情啦”,对你不讨厌但q没喜欢上的MM׃说“好啊,不过可以带上我同事么Q”,已经喜欢上你的MM׃ 说“几炚wQ看完电影再L吧怎么P”,当然你看电媄q程中表现良好的话,也可以把MM的状态从不讨厌不喜欢变成喜欢哦?

状态模式:状态模式允怸个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一栗状态模式把所研究的对象的行ؓ包装在不同的状态对象里Q每一个状态对象都属于一个抽象状态类的一个子cR状态模式的意图是让一个对象在其内部状态改变的 时候,其行Z随之改变。状态模式需要对每一个系l可能取得的状态创立一个状态类的子cR当pȝ的状态变化时Q系l便改变所选的子类?

21、STRATEGY—跟不同cd的MMU会Q要用不同的{略Q有的请电媄比较好,有的则去吃小吃效果不错,有的LvҎ漫最合适,单目的都是ؓ了得到MM的芳心,我的qMM锦囊中有好多Strategy哦?

{略模式Q策略模式针对一l算法,每一个算法封装到h共同接口的独立的cMQ从而得它们可以相互替换。策略模式得算法可以在不媄响到客户端的情况下发生变化。策略模式把行ؓ和环境分开。环境类负责l持和查询行为类Q各U算法在具体的策略类中提供?׃法和环境独立开来,法的增减,修改都不会媄响到环境和客L?

22、TEMPLATE?METHOD——看q《如何说服女生上床》这部经典文章吗Q女生从认识C床的不变的步骤分为y遇、打破僵局、展开q求、接吅R前戏、动手、爱抚、进d大步?Template?method)Q但每个步骤针对不同的情况,都有 不一L做法Q这p看你随机应变?具体实现)Q?

模板Ҏ模式Q模板方法模式准备一个抽象类Q将部分逻辑以具体方法以及具体构造子的Ş式实玎ͼ然后声明一些抽象方法来q子类实现剩余的逻辑。不同的子类可以以不同的方式实现q些抽象ҎQ从而对剩余的逻辑有不同的实现。先制定一个顶U逻辑框架Q而将逻辑 的细节留l具体的子类d现?

23、VISITOR—情CQ要l每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个h的特点,每张卡片也要Ҏ个h的特Ҏ挑,我一个h哪搞得清楚,q是找花店老板和礼品店老板做一下VisitorQ让花店老板ҎMM的特炚w一束花 Q让C品店老板也根据每个h特点选一张卡Q这样就L多了Q?

讉K者模式:讉K者模式的目的是封装一些施加于某种数据l构元素之上的操作。一旦这些操作需要修改的话,接受q个操作的数据结构可以保持不变。访问者模式适用于数据结构相Ҏ定的pȝQ它把数据结构和作用于结构上的操作之间的耦合解脱开Q得操作集合可?相对自由的演化。访问者模式得增加新的操作变的很ҎQ就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中Q而不是分散到一个个的节点类中。当使用讉K者模式时Q要尽可能多的对象览逻辑攑֜讉K者类中,而不是放到它的子cM?讉K者模式可以跨q几个类的等U结构访问属于不同的{l构的成员类?/font>


weibogao 2006-05-26 16:58 发表评论
]]>
iframe 标签的用(来源Q有风的日子Q?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/weibogao/archive/2006/04/03/38915.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/38915.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2006/04/03/38915.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/38915.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/38915.html</trackback:ping><description><![CDATA[ <font size="1">U观时下|站Q本来网速就有些慢,可是几乎每页都要放什么BannerQ栏目图片,版权{一大堆雷同的东西,当然Q出于网站风格统一、广告效应的需要,本无可厚非,可毕竟让用户的钱包ؓq些“点~”的东西“日益消得钱憔悴”了Q有没有办法Q让q些雷同的东西一ơ下载后׃用再下蝲Q而只下蝲那些内容有变化区域的|页内容呢? <br />  {案很肯定:应用Iframe标记Q?/font> <p> <font size="1">  <strong>一、Iframe标记的?/strong></font> </p> <p> <font size="1">  提vIframeQ可能你早已之扔到“被遗忘的角落”了Q不q,说v其兄弟Frame׃会陌生了。Frame标记卛_标记Q我们所说的多l构是在一个浏览器H口中显C多个HTML文g。现在,我们遇到一U很现实的情况:如有一个教E,是一节一节地上,每页末尾做一个“上一节“、“下一节“的链接Q除了每节教E内容不同之外,面其它部分内容都是相同的,如果一一地做笨面Q这g太让人厌烦了Q这时突发奇惻I如果有一U方法让面其它地方不变Q只教E做成一一늚内容,不含其它内容Q在点击上下页链接Ӟ只改变教E内定w分,其它保持不变Q这P一是省Ӟ另则以后如教E有个三长两短的变动Q也很方便,不致于牵一发而动全军?更重要的是将那些q告Banner、栏目列表、导航等几乎每页的都有的东西只下载一ơ后׃再下载了?/font> </p> <p> <font size="1">  Iframe标记Q又叫Q动标记Q你可以用它一个HTML文档嵌入在一个HTML中显C。它不同于Frame标记最大的特征卌个标记所引用的HTML文g不是与另外的HTML文g怺独立昄Q而是可以直接嵌入在一个HTML文g中,与这个HTML文g内容怺融合Q成Z个整体,另外Q还可以多次在一个页面内昄同一内容Q而不必重复写内容Q一个Ş象的比喻即“画中画“电视?/font> </p> <p> <font size="1">  现在我们谈一下Iframe标记的用?/font> </p> <p> <font size="1">  Iframe标记的用格式是Q?/font> </p> <p> <font size="1">  <Iframe src="URL" width="x" height="x" scrolling="[OPTION]" frameborder="x"></iframe><br />  srcQ文件的路径Q既可是HTML文gQ也可以是文本、ASP{;<br />  width、heightQ?M?区域的宽与高Q?br />  scrolling:当SRC的指定的HTML文g在指定的区域不显不完Ӟ滚动选项Q如果设|ؓNOQ则不出现滚动条Q如为AutoQ则自动出现滚动条;如ؓYesQ则昄;<br />  FrameBorderQ区域边框的宽度Qؓ了让“画中画“与邻近的内容相融合Q常讄??/font> </p> <p> <font size="1">  比如Q?/font> </p> <p> <font size="1">  <Iframe src="</font> <a target="_blank"> <font size="1">http://netschool.cpcw.com/homepage</font> </a> <font size="1">" width="250" height="200" scrolling="no" frameborder="0"></iframe></font> </p> <p> <font size="1">  <strong>二、父H体与Q动之间的相互控?/strong></font> </p> <p> <font size="1">  在脚本语a与对象层ơ中Q包含Iframe的窗口我们称之ؓ父窗体,而Q动则称为子H体Q弄清这两者的关系很重要,因ؓ要在父窗体中讉K子窗体或相反都必L楚对象层ơ,才能通过E序来访问ƈ控制H体?/font> </p> <p> <font size="1">  1、在父窗体中讉Kq控制子H体中的对象</font> </p> <p> <font size="1">  在父H体中,Iframe卛_H体是document对象的一个子对象Q可以直接在脚本中访问子H体中的对象?/font> </p> <p> <font size="1">  现在有一个问题,卻I我们怎样来控制这个IframeQ这里需要讲一下Iframe对象。当我们l这个标记设|了ID 属性后Q就可通过文对象模型DOM对Iframe所含的HTMLq行一pd控制?</font> </p> <p> <font size="1">  比如在example.htm里嵌入test.htm文gQƈ控制test.htm里一些标记对象:<br />  <Iframe src="test.htm" id="test" width="250" height="200" scrolling="no" frameborder="0"></iframe><br />test.htm文g代码?<br />  <html><br />   <body><br />    <h1 id="myH1">hello,my boy</h1><br />   </body><br />  </html><br />  如我们要改变ID号ؓmyH1的H1标记里的文字为hello,my dearQ则可用:<br />  document.myH1.innerText="hello,my dear"Q其中,document可省Q?br />  在example.htm文g中,Iframe标记对象所指的子窗体与一般的DHTML对象模型一_对对象访问控制方式一P׃再赘q?/font> </p> <p> <font size="1">  2、在子窗体中讉Kq控制父H体中对?/font> </p> <p> <font size="1">  在子H体中我们可以通过其parent即父Q双Ԍ对象来访问父H口中的对象?br />  如example.htmQ?br />  <html><br />   <body onclick="alert(tt.myH1.innerHTML)"><br />    <Iframe name="tt" src="frame1.htm" width="250" height="200" scrolling="no" frameborder="0"></iframe><br />    <h1 id="myH2">hello,my wife</h1><br />   </body><br />  </html><br />  如果要在frame1.htm中访问ID号ؓmyH2中的标题文字q将之改?hello,my friend"Q我们就可以q样写: <br />  parent.myH2.innerText="hello,my friend"<br />  q里parent对象׃表当前窗体(example.htm所在窗体)Q要在子H体中访问父H体中的对象Q无一例外都通过parent对象来进行?</font> </p> <p> <font size="1">  Iframe虽然内嵌在另一个HTML文g中,但它保持相对的独立,是一个“独立王国”哟Q在单一HTML中的Ҏ同样适用于Q动中?/font> </p> <p> <font size="1">  试想一下,通过Iframe标记Q我们可那些不变的内容以Iframe来表C,q样Q不必重复写相同的内容,q有点象E序设计中的q程或函敎ͼ减省了多繁琐的手工力_Q另外,臛_重要的是Q它佉K面的修改更ؓ可行Q因为,不必因ؓ版式的调整而修Ҏ个页面,你只需修改一个父H体的版式即可了?/font> </p> <p> <font size="1">  有一点要注意QNestscape览器不支持Iframe标记Q但在时下IE的天下,q似乎也无大,q泛采用Iframe标记Q既己(|站Q着了想Q又为网友节省了|费Q何乐而不为?</font> </p> <img src ="http://www.aygfsteel.com/weibogao/aggbug/38915.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2006-04-03 13:14 <a href="http://www.aygfsteel.com/weibogao/archive/2006/04/03/38915.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA开发者应该去?0个英文网?http://www.aygfsteel.com/weibogao/archive/2006/04/01/38622.htmlweibogaoweibogaoSat, 01 Apr 2006 08:55:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/04/01/38622.htmlhttp://www.aygfsteel.com/weibogao/comments/38622.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/04/01/38622.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/38622.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/38622.html http://www.javaalmanac.com

Java开发者年鉴一书的在线版本. 要想快速查到某UJava技巧的用法及示例代? q是一个不错的d.

http://www.onjava.com

O'Reilly的Java|站. 每周都有新文?

http://java.sun.com

官方的Java开发者网?- 每周都有新文章发?

http://www.developer.com/java

由Gamelan.com l护的Java技术文章网?

http://www.java.net

Sun公司l护的一个JavaC֌|站

http://www.builder.com

Cnet的Builder.com|站 - 所有的技术文? 以JavaZ.

http://www.ibm.com/developerworks/java

IBM的Developerworks技术网? q是其中的Java技术主?

http://www.javaworld.com

最早的一个Java站点. 每周更新Java技术文?

http://www.devx.com/java

DevXl护的一个Java技术文章网?

http://www.fawcette.com/javapro

JavaPro在线杂志|站.

http://www.sys-con.com/java

Java Developers Journal的在U杂志网?

http://www.javadesktop.org

位于Java.net的一个Java桌面技术社区网?

http://www.theserverside.com

q是一个讨论所有Java服务器端技术的|站.

http://www.jars.com

提供Java评论服务. 包括各种framework和应用程?

http://www.jguru.com

一个非常棒的采用Q&A形式的Java技术资源社?

http://www.javaranch.com

一个论坛,得到Java问题{案的地方,初学者的好去处?

http://www.ibiblio.org/javafaq/javafaq.html

comp.lang.java的FAQ站点 - 攉了来自comp.lang.java新闻l的问题和答案的分类目录.

http://java.sun.com/docs/books/tutorial/

来自SUN公司的官方Java指南 - 对于了解几乎所有的java技术特性非常有帮助.

http://www.javablogs.com

互联|上最z跃的一个Java Blog|站.

http://java.about.com/

来自About.com的Java新闻和技术文章网?



weibogao 2006-04-01 16:55 发表评论
]]>
DWR让AJAX如此?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/weibogao/archive/2006/04/01/38621.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/38621.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2006/04/01/38621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/38621.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/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 target="_new"> <font size="1">simmone</font> </a> </center> <br /> <br /> <font size="1"> <span style="COLOR: red">版权声明QQ何获得Matrix授权的网站,转蝲时请务必以超链接形式标明文章原始出处和作者信息及本声?/span> <br />作?Cloves Carneiro;</font> <a target="_new"> <font size="1">simmone</font> </a> <br /> <font size="1">原文地址:</font> <a 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 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 />q篇文章阐述了用开源项目DWR(直接Webq程控制)和AJAX(异步JavaScript和XML)的概忉|提高Web应用的可用性。作者一步步来展CDWR如何使得AJAX的应用既单又快捷。(1600?2005q??0日) <br /><br />AJAXQ或者说是异步JavaScript和XMLQ描qC一U用؜合了HTML(或XHTML)和层叠样式表作ؓ表达信息,来创Z互式的Web应用的开发技?文对象模型QDOMQ,JavaScript,动态地昄和与表达信息q行交互;q且QXMLHttpRequest对象与Web服务器异步地交换和处理数据?br /><br />因特|上许多例子展示了在一个HTML文g内部使用XMLHttpRequest与服务器端进行交互的必要的步骤。当手工地编写和l护XMLHttpRequest代码Ӟ开发者必d理许多潜在的问题Q特别是cM于跨览器的DOM实现的兼Ҏ这L问题。这会D在编码和调试Javascript代码上面pC清的旉Q这昄对开发者来说很不友好?br /><br />DWR(直接Webq程控制)目是在Apache许可下的一个开源的解决ҎQ它供给那些惌以一U简单的方式使用AJAX和XMLHttpRequest的开发者。它h一套Javascript功能集,它们把从HTML面调用应用服务器上的Java对象的方法简化了。它操控不同cd的参敎ͼq同时保持了HTML代码的可L?br /><br />DWR不是对一个设计的插入Q也不强q对象用Q何种cȝl承l构。它和servlet框架内的应用配合的很好。对~少DHTML~程l验的开发者来_DWR也提供了一个JavaScript库包含了l常使用的DHTMLdQ如l装表,用item填充select下拉框,改变HTML元素的内容,?lt;div>?lt;span><br />DWR|站是详的q且有大量的文Q这也是q篇文章的基。一些例子用来展CDWR如何使用和用它的库可以完成什么样的工作?br /><br />q篇文章让读者看C一个用了DWR的Web应用是如何一步步建立的。我会展C创个简单的CZ应用的必要的l节Q这个应用是可下载的q且可以在你的环境中布v来看看DWR如何工作?br />注意Q找到有关AJAX的信息ƈ不困?|页上有几篇文章和博客的条目늛了这个主题,每一个都试图指出和评个概늚不同的方面。在资源部分Q你会找C些有的指向CZ和文章的链接Q来学习AJAX的更多的内容?br /><br /><b><span style="FONT-SIZE: 16px">CZ应用</span></b><br />q篇文章使用的示例应用模拟了多u多的一个公寓出U搜索引擎。用户可以在搜烦前选择一l搜索标准。ؓ了提高交互性,AJAX中以下两U情况下使用Q?br />·应用通告用户配合他的选择会返回多搜索结果。这个数字是实时更新?使用AJAX-当用户选择的卧室和室的数量,或者hD围变化时。当W合标准的搜索结果没有或太多Ӟ用户没有必要点L索按U?br />·数据库查询ƈ取回l果是由AJAX完成的。当用户按下昄l果按钮Ӟ数据库执行搜索。这P应用看v来更具响应了Q而整个页面不需要重载来昄l果?br /><br /><b><span style="FONT-SIZE: 16px">数据?/span></b><br />我们使用的数据库是HSQLQ它是一U占用资源很的Java SQL数据库引擎,可以不需要安装和配置的与Web应用捆绑在一赗一个SQL文g被用来在Web应用的上下文启动时创Z个内存中的表q添加一些记录?br /><br /><b><span style="FONT-SIZE: 16px">Javac?/span></b><br />应用包含了两个主要的cdApartment和ApartmentDAO。Apartment.javacL一个有着属性和getter/setterҎ的简单的JavacRApartmentDAO.java是数据访问类Q用来查询数据库q基于用L搜烦标准来返回信息。ApartmentDAOcȝ实现的直接了当的;它直接用了Java数据库联接调用来得到公寓的L和符合用戯求的可用公寓的列表?br /><br /><b><span style="FONT-SIZE: 16px">DWR配置和?/span></b><br />讄DWR的用是单的Q将DWR的jar文g拷入Web应用的WEB-INF/lib目录中,在web.xml中增加一个servlet声明Qƈ创徏DWR的配|文件。DWR的分发中需要用一个单独的jar文g。你必须DWR servlet加到应用的WEB-INF/web.xml中布|描q段中去?br /></font> <pre class="overflow"> <font size="1">    <servlet><br />        <servlet-name>dwr-invoker</servlet-name><br />        <display-name>DWR Servlet</display-name><br />        <description>Direct Web Remoter Servlet</description><br />        <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class><br />        <init-param><br />            <param-name>debug</param-name><br />            <param-value>true</param-value><br />        </init-param><br />    </servlet><br /><br />    <servlet-mapping><br />        <servlet-name>dwr-invoker</servlet-name><br />        <url-pattern>/dwr/*</url-pattern><br />    </servlet-mapping></font> </pre> <br /> <br /> <font size="1">一个可选的步骤是设|DWR试模式—象上面的例子那样—在servlet描述D中debug参数设ؓtrue。当DWR在调试模式时Q你可以从HTMl|页中看到所有的可访问的Java对象。包含了可用对象列表的网会出现?WEBAPP/dwrq个url上,它显CZ对象的公共方法。所列方法可以从面中调用,允许你,W一ơ,q行服务器上的对象的Ҏ。下图显CZ调试늚样子:<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对象Q什么对象将会接收请求。这个Q务由叫做dwr.xml的配|文件来完成。在配置文g中,定义了DWR允许你从|页中调用的对象。从设计上讲QDWR允许讉K所有公布类的公共方法,但在我们的例子中Q我们只允许讉K几个Ҏ。下面是我们CZ的配|文?<br /></font> <pre class="overflow"> <font size="1"><dwr><br />    <allow><br />        <convert converter="bean" match="dwr.sample.Apartment"/><br />        <create creator="new" javascript="ApartmentDAO" class="dwr.sample.ApartmentDAO"><br />            <include method="findApartments"/><br />            <include method="countApartments"/><br />        </create><br />    </allow><br /></dwr></font> </pre> <br /> <br /> <font size="1">上面的文件实C我们例子中的两个目标。首先,<convert>标记告诉DWRdwr.sample.Apartment对象的类型{换ؓ联合数组Q因为,Z安全的原因,DWR默认的不会{换普通bean。第二,<create>标记让DWR暴露出dwr.sample.ApartmentDAOcȝJavaScript调用;我们在页面中使用JavaScript文g被javascript属性定义。我们必L?lt;include>标记Q它指明了dwr.sample.ApartmentDAOcȝ哪些Ҏ可用?br /><br /><b><span style="FONT-SIZE: 16px">HTML/JSP代码</span></b><br />配置完成后,你就可以启动你的Web应用了,q时DWR会ؓ从你的HTML或Java服务器端面(JSP)上调用所需Ҏ作好准备Qƈ不需要你创徏JavaScript文g。在search.jsp文g中, 我们必须增加由DWR提供的JavaScript接口Q还有DWR引擎Q加入以下三行到我们的代码中Q?br /><br /></font> <pre class="overflow"> <font size="1">  <script src='dwr/interface/ApartmentDAO.js'></script><br />  <script src='dwr/engine.js'></script><br />  <script src='dwr/util.js'></script></font> </pre> <br /> <br /> <font size="1">我们注意到当用户改变搜烦标准Ӟq是AJAX在示例程序中的首ơ应?正如他所看到的,当标准改变时Q可用的公寓数量被更C。我创徏了两个JavaScript函数Q当某一个选择下拉框中的值变化时被调用。ApartmentDAO.countApartments()函数是最重要的部分。最有趣的是W一个参? loadTotal()函数Q它指明了当接收到服务端的返回时DWR会调用的JavaScriptҎ。loadTotal于是被调用来在HTML面?lt;div>中显C结果。下面是在这个交互场景中所使用到的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">很明显,用户想看到符合他的搜索条件的公寓列表。那么,当用户对他的搜烦标准感到满意Qƈ且L也是有效的话Q他会按下显C结果的按纽Q这会调用updateResults() JavaScriptҎQ?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()Ҏ清空了存放搜索返回结果的表域Q从用户界面上获取所需参数Qƈ且将q些参数传给DWR创徏的ApartmentDAO对象。然后数据库查询被执行QfillTable()会被调用,它解析了DWRq回的对?apartment)Q然后将其显C到面?apartmentsbody)?br /><br /><b><span style="FONT-SIZE: 16px">安全因素</span></b><br />Z保持CZ的简要,ApartmentDAOcd可能的保持简单,但这L一个类通常有一l设|方法来操作数据Q如insert(), update()和delete()。DWR暴露了所有公共方法给所有的HTML面调用。出于安全的原因Q像q样暴露你的数据讉K层是不明智的。开发者可以创Z个门面来集中所有JavaScript函数与底层业务组件之间的通信Q这样就限制了过多暴露的功能?br /><br /><b><span style="FONT-SIZE: 16px">l论</span></b><br />q篇文章仅仅让你在你的项目中使用由DWR支持的AJAX开了个头。DWR让你集中注意力在如何提高你的应用的交互模型上面,消除了编写和调试JavaScript代码的负担。用AJAX最有趣的挑战是定义在哪里和如何提高可用性。DWR负责了操作Web面与你的Java对象之间的通信Q这样就帮助你完全集中注意力在如何让你的应用的用L面更加友好,<br />我想感谢Mircea Oancea和Marcos Pereira,他们阅读了这文章ƈl予了非常有价值的q匮?br /><br /><b>资源</b><br />·javaworld.com:</font> <a target="_new"> <font size="1">javaworld.com</font> </a> <br /> <font size="1">·Matrix-Java开发者社?</font> <a target="_new"> <font size="1">http://www.matrix.org.cn/</font> </a> <br /> <font size="1">·onjava.com:</font> <a target="_new"> <font size="1">onjava.com</font> </a> <br /> <font size="1">·下蝲CZE序的全部源?</font> <a 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 & 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.aygfsteel.com/weibogao/aggbug/38621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2006-04-01 16:52 <a href="http://www.aygfsteel.com/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.aygfsteel.com/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.aygfsteel.com/weibogao/archive/2006/04/01/38618.html</guid><wfw:comment>http://www.aygfsteel.com/weibogao/comments/38618.html</wfw:comment><comments>http://www.aygfsteel.com/weibogao/archive/2006/04/01/38618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/weibogao/comments/commentRss/38618.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/weibogao/services/trackbacks/38618.html</trackback:ping><description><![CDATA[ <span id="wmqeeuq" class="oblog_text"> <span id="wmqeeuq" class="tpc_content"> <font size="1">一关于web.xml配置的详l说?br /><br />(转蝲)[TOMCAT]用web.xml控制Web应用的行?<br /><br /><br /><br />1 定义头和根元?br /><br />部v描述W文件就像所有XML文g一P必须以一个XML头开始。这个头声明可以使用的XML版本q给出文件的字符~码?br />DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本(?.2?.3Qƈ指定理此文件其余部分内容的语法的DTD(Document Type DefinitionQ文档类型定??br />所有部|描q符文g的顶层(根)元素为web-app。请注意QXML元素不像HTMLQ他们是大小写敏感的。因此,web-App和WEB-APP都是不合法的Qweb-app必须用小写?br /><br />2 部v描述W文件内的元素次?br /><br />XML 元素不仅是大写敏感的,而且它们q对出现在其他元素中的次序敏感。例如,XML头必L文g中的W一,DOCTYPE声明必须是第二项Q而web- app元素必须是第三项。在web-app元素内,元素的次序也很重要。服务器不一定强制要求这U次序,但它们允许(实际上有些服务器是q样做的Q完全拒l执行含有次序不正确的元素的Web应用。这表示使用非标准元素次序的web.xml文g是不可移植的?br />下面的列表给Z所有可直接出现在web-app元素内的合法元素所必需的次序。例如,此列表说明servlet元素必须出现在所有servlet-mapping元素之前。请注意Q所有这些元素都是可选的。因此,可以省略掉某一元素Q但不能把它放于不正的位置?br />l icon icon元素指出IDE和GUI工具用来表示Web应用的一个和两个囑փ文g的位|?br />l display-name display-name元素提供GUI工具可能会用来标记这个特定的Web应用的一个名U?br />l description description元素l出与此有关的说明性文本?br />l context-param context-param元素声明应用范围内的初始化参数?br />l filter qo器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联?br />l filter-mapping 一旦命名了一个过滤器Q就要利用filter-mapping元素把它与一个或多个servlet或JSP面相关联?br />l listener servlet API的版?.3增加了对事g监听E序的支持,事g监听E序在徏立、修改和删除会话或servlet环境时得到通知。Listener元素指出事g监听E序cR?br />l servlet 在向servlet或JSP面制定初始化参数或定制URLӞ必须首先命名servlet或JSP面。Servlet元素是用来完成此项d的?br />l servlet-mapping 服务器一般ؓservlet提供一个缺省的URLQ?/font> <a href="http://host/webAppPrefix/servlet/ServletName" target="_blank"> <font size="1">http://host/webAppPrefix/servlet/ServletName</font> </a> <font size="1">。但是,常常会更改这个URLQ以便servlet可以讉K初始化参数或更容易地处理相对URL。在更改~省URLӞ使用servlet-mapping元素?br />l session-config 如果某个会话在一定时间内未被讉KQ服务器可以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveIntervalҎ明确讄单个会话对象的超时|或者可利用session-config元素制定~省时倹{?br />l mime-mapping 如果Web应用h惛_Ҏ的文Ӟ希望能保证给他们分配特定的MIMEcdQ则mime-mapping元素提供q种保证?br />l welcom-file-list welcome-file-list元素指示服务器在收到引用一个目录名而不是文件名的URLӞ使用哪个文g?br />l error-page error-page元素使得在返回特定HTTP状态代码时Q或者特定类型的异常被抛出时Q能够制定将要显C的面?br />l taglib taglib元素Ҏ记库描述W文ӞTag Libraryu Descriptor fileQ指定别名。此功能使你能够更改TLD文g的位|,而不用编辑用这些文件的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元素来指定服务器应该怎样l试图访问受保护面的用h权。它与sercurity-constraint元素联合使用?br />l security-role security-role元素l出安全角色的一个列表,q些角色出现在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的本C目录的应用?br /><br />3 分配名称和定制的UL<br /><br />在web.xml中完成的一个最常见的Q务是对servlet或JSP面l出名称和定制的URL。用servlet元素分配名称Q用servlet-mapping元素定制的URL与刚分配的名U相兌?br />3.1 分配名称<br />Z提供初始化参敎ͼ对servlet或JSP面定义一个定制URL或分配一个安全角Ԍ必须首先lservlet或JSP面一个名U。可通过 servlet元素分配一个名U。最常见的格式包括servlet-name和servlet-class子元素(在web-app元素内)Q如下所C:<br /><servlet><br /><servlet-name>Test</servlet-name><br /><servlet-class>moreservlets.TestServlet</servlet-class><br /></servlet> <br />q表CZ于WEB-INF/classes/moreservlets/TestServlet的servlet已经得到了注册名Test。给 servlet一个名U具有两个主要的含义。首先,初始化参数、定制的URL模式以及其他定制通过此注册名而不是类名引用此servlet。其?可在 URL而不是类名中使用此名U。因此,利用刚才l出的定义,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元素Q下一节介绍Q之前,而且q要位于5.6节和5.11节讨论的与过滤器或文档相关的元素Q如果有的话Q之前。类似地Qservlet 的servlet-name子元素也必须出现在servlet-class之前?.2?部v描述W文件内的元素次?详l介l这U必需的次序?br />例如Q程序清?-1l出了一个名为TestServlet的简单servletQ它ȝ在moreservletsE序包中。因为此servlet是扎根在一个名为deployDemo的目录中的Web应用的组成部分,所以TestServlet.class攑֜deployDemo/WEB- INF/classes/moreservlets中。程序清?-2l出放|在deployDemo/WEB-INF/内的web.xml文g的一部分。此web.xml文g使用servlet-name和servlet-class元素名UTest与TestServlet.class相关联。图 5-1和图5-2分别昄利用~省URL和注册名调用TestServlet时的l果?br /><br />E序清单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 />* <P><br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font> <a 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 />"<BODY BGCOLOR=\"#FDF5E6\">\n" +<br />"<H2>URI: " + uri + "</H2>\n" +<br />"</BODY></HTML>");<br />}<br />}<br /><br /><br />E序清单5-2 web.xmlQ说明servlet名称的摘录)<br /><?xml version="1.0" encoding="ISO-8859-1"?><br /><!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font> <a target="_blank"> <font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font> </a> <font size="1">"><br /><br /><web-app><br /><!-- ?--><br /><servlet><br /><servlet-name>Test</servlet-name><br /><servlet-class>moreservlets.TestServlet</servlet-class><br /></servlet><br /><!-- ?--><br /></web-app><br /><br />3.2 定义定制的URL<br />大多数服务器h一个缺省的serlvet URLQ?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">。虽然在开发中使用q个URL很方便,但是我们常常会希望另一个URL用于部v。例如,可能会需要一个出现在Web应用层的URLQ如Qhttp: //host/webAppPrefix/AnynameQ,q且在此URL中没有servletV位于顶层的URL化了相对URL的用。此外,对许多开发h员来_层URL看上L更长更麻烦的~省URL更简短?br />事实上,有时需要用定制的URL。比如,你可能想关闭~省URL映射Q以便更好地强制实施安全限制或防止用h外地讉K无初始化参数的servlet。如果你止了缺省的URLQ那么你怎样讉Kservlet呢?q时只有使用定制的URL了?br />Z分配一个定制的URLQ可使用servlet-mapping元素及其servlet-name和url-pattern子元素。Servlet- name元素提供了一个Q意名Uͼ可利用此名称引用相应的servletQurl-pattern描述了相对于Web应用的根目录的URL。url- pattern元素的值必M斜杠Q?Qv始?br />下面l出一个简单的web.xml摘录Q它允许使用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。请注意Q仍焉要XML头?DOCTYPE声明以及web-app闭元素。此外,可回忆一下,XML元素出现地次序不是随意的。特别是Q需要把所有servlet元素攑֜所?servlet-mapping元素之前?br /><servlet><br /><servlet-name>Test</servlet-name><br /><servlet-class>moreservlets.TestServlet</servlet-class><br /></servlet><br /><!-- ... --><br /><servlet-mapping><br /><servlet-name>Test</servlet-name><br /><url-pattern>/UrlTest</url-pattern><br /></servlet-mapping><br />URL模式q可以包含通配W。例如,下面的小E序指示服务器发送所有以Web应用的URL前缀开始,?.aspl束的请求到名ؓBashMS的servlet?br /><servlet><br /><servlet-name>BashMS</servlet-name><br /><servlet-class>msUtils.ASPTranslator</servlet-class><br /></servlet><br /><!-- ... --><br /><servlet-mapping><br /><servlet-name>BashMS</servlet-name><br /><url-pattern>/*.asp</url-pattern><br /></servlet-mapping><br />3.3 命名JSP面<br />因ؓJSP面要{换成sevletQ自然希望就像命名servlet一样命名JSP面。毕竟,JSP面可能会从初始化参数、安全设|或定制的URL中受益,正如普通的serlvet那样。虽然JSP面的后台实际上是servletq句话是正确的,但存在一个关键的猜疑Q即Q你不知道JSP面的实际类名(因ؓpȝ自己挑选这个名字)。因此,Z命名JSP面Q可jsp-file元素替换为servlet-calss元素Q如下所C:<br /><servlet><br /><servlet-name>Test</servlet-name><br /><jsp-file>/TestPage.jsp</jsp-file><br /></servlet><br />命名JSP面的原因与命名servlet的原因完全相同:即ؓ了提供一个与定制讄Q如Q初始化参数和安全设|)一起用的名称Qƈ且,以便能更Ҏz?JSP面的URLQ比方说Q以便多个URL通过相同面得以处理Q或者从URL中去?jsp扩展名)。但是,在设|初始化参数Ӟ应该注意QJSP面是利用jspInitҎQ而不是initҎd初始化参数的?br />例如Q程序清?-3l出一个名为TestPage.jsp的简单JSP面Q它的工作只是打印出用来Ȁzd的URL的本地部分。TestPage.jsp攄在deployDemo应用的顶层。程序清?-4l出了用来分配一个注册名PageNameQ然后将此注册名?/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文gQ即QdeployDemo/WEB-INF/web.xmlQ的一部分?br /><br />E序清单5-3 TestPage.jsp<br /><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><br /><HTML><br /><HEAD><br /><TITLE><br />JSP Test Page<br /></TITLE><br /></HEAD><br /><BODY BGCOLOR="#FDF5E6"><br /><H2>URI: <%= request.getRequestURI() %></H2><br /></BODY><br /></HTML><br /><br /><br />E序清单5-4 web.xmlQ说明JSP命名的摘录Q?br /><?xml version="1.0" encoding="ISO-8859-1"?><br /><!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font> <a target="_blank"> <font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font> </a> <font size="1">"><br /><br /><web-app><br /><!-- ... --><br /><servlet><br /><servlet-name>PageName</servlet-name><br /><jsp-file>/TestPage.jsp</jsp-file><br /></servlet><br /><!-- ... --><br /><servlet-mapping><br /><servlet-name> PageName </servlet-name><br /><url-pattern>/UrlTest2/*</url-pattern><br /></servlet-mapping><br /><!-- ... --><br /></web-app><br /><br /><br />4 止Ȁzdservlet<br /><br />对servlet或JSP面建立定制URL的一个原因是Q这样做可以注册?initQservletQ或jspInitQJSP面Q方法中d得初始化参数。但是,初始化参数只在是利用定制URL模式或注册名讉K 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">讉K时不能用。因此,你可能会希望关闭~省URLQ这样就不会有h意外地调用初始化servlet了。这个过E有时称为禁止激zdservletQ因为多数服务器h一个用~省的servlet URL注册的标准servletQƈȀzȝ省的URL应用的实际servlet?br />有两U禁止此~省URL的主要方法:<br />l 在每个Web应用中重新映?servlet/模式?br />l 全局关闭Ȁzdservlet?br />重要的是应该注意刎ͼ虽然重新映射每个Web应用中的/servlet/模式比彻底禁止激zservlet所做的工作更多Q但重新映射可以用一U完全可UL的方式来完成。相反,全局止Ȁzdservlet完全是针对具体机器的Q事实上有的服务器(如ServletExecQ没有这L选择。下面的讨论Ҏ个Web应用重新映射/servlet/ URL模式的策略。后面提供在Tomcat中全局止Ȁzdservlet的详l内宏V?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的处理非常简单。所需做的事情是建立一个错误消息servletQƈ使用前一节讨论的url-pattern元素所有匹配请求{向该 servlet。只要简单地使用Q?br /><url-pattern>/servlet/*</url-pattern><br />作ؓservlet-mapping元素中的模式卛_?br />例如Q程序清?-5l出了将SorryServlet servletQ程序清?-6Q与所有以</font> <a href="http://host/webAppPrefix/servlet/" target="_blank"> <font size="1">http://host/webAppPrefix/servlet/</font> </a> <font size="1">开头的URL相关联的部v描述W文件的一部分?br /><br />E序清单5-5 web.xmlQ说明JSP命名的摘录Q?br /><?xml version="1.0" encoding="ISO-8859-1"?><br /><!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font> <a target="_blank"> <font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font> </a> <font size="1">"><br /><br /><web-app><br /><!-- ... --><br /><servlet><br /><servlet-name>Sorry</servlet-name><br /><servlet-class>moreservlets.SorryServlet</servlet-class><br /></servlet><br /><!-- ... --><br /><servlet-mapping><br /><servlet-name> Sorry </servlet-name><br /><url-pattern>/servlet/*</url-pattern><br /></servlet-mapping><br /><!-- ... --><br /></web-app><br /><br /><br />E序清单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 />* <P><br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font> <a 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 />"<BODY BGCOLOR=\"#FDF5E6\">\n" +<br />"<H2>" + title + "</H2>\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 />"</BODY></HTML>");<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 全局止ȀzdQTomcat<br />Tomcat 4中用来关闭缺省URL的方法与Tomcat 3中所用的很不相同。下面介l这两种ҎQ?br />1Q禁止激zdQ?Tomcat 4<br />Tomcat 4用与前面相同的方法关闭激zdservletQ即利用web.xml中的url-mapping元素q行关闭。不同之处在于Tomcat使用了放?install_dir/conf中的一个服务器专用的全局web.xml文gQ而前面用的是存攑֜每个Web应用的WEB-INF目录中的标准 web.xml文g?br />因此Qؓ了在Tomcat 4中关闭激zdservletQ只需在install_dir/conf/web.xml中简单地注释?servlet/* URL映射即可,如下所C:<br /><!-- <br /><servlet-mapping><br /><servlet-name>invoker</servlet-name><br /><url-pattern>/servlet/*</url-pattern><br /></servlet-mapping><br />--><br />再次提醒Q应该注意这个项是位于存攑֜install_dir/conf的Tomcat专用的web.xml文g中的Q此文g不是存放在每个Web应用的WEB-INF目录中的标准web.xml?br />2Q禁止激zdQTomcat3<br />在Apache Tomcat的版?中,通过在install_dir/conf/server.xml中注释出InvokerInterceptor全局止~省 servlet URL。例如,下面是禁止用缺省servlet URL的server.xml文g的一部分?br /><!-- <br /><RequsetInterceptor <br />className="org.apache.tomcat.request.InvokerInterceptor"<br />debug="0" prefix="/servlet/" /><br />--><br /><br />5 初始化和预装载servlet与JSP面<br /><br />q里讨论控制servlet和JSP面的启动行为的Ҏ。特别是Q说明了怎样分配初始化参C及怎样更改服务器生存期中装载servlet和JSP面的时刅R?br />5.1 分配servlet初始化参?br />利用init-param元素向servlet提供初始化参敎ͼinit-param元素hparam-name和param-value子元素。例如,在下面的例子中,如果initServlet servlet是利用它的注册名QInitTestQ访问的Q它能够从其方法中调用getServletConfig(). getInitParameter("param1")获得"Value 1"Q调用getServletConfig().getInitParameter("param2")获得"2"?br /><servlet><br /><servlet-name>InitTest</servlet-name><br /><servlet-class>moreservlets.InitServlet</servlet-class><br /><init-param><br /><param-name>param1</param-name><br /><param-value>value1</param-value><br /></init-param><br /><init-param><br /><param-name>param2</param-name><br /><param-value>2</param-value><br /></init-param><br /></servlet><br />在涉及初始化参数Ӟ有几炚w要注意:<br />l q回倹{GetInitParameter的返回值L一个String。因此,在前一个例子中Q可对param2使用Integer.parseInt获得一个int?br />l JSP中的初始化。JSP面使用jspInit而不是init。JSP面q需要用jsp-file元素代替servlet-class?br />l ~省URL。初始化参数只在通过它们的注册名或与它们注册名相关的定制URL模式讉KServlet时可以用。因此,在这个例子中Qparam1?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 />例如Q程序清?-7l出一个名为InitServlet的简单servletQ它使用initҎ讄firstName和emailAddress字段。程序清?-8l出分配名称InitTestlservlet的web.xml文g?br />E序清单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 />* <P><br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font> <a 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 />"<BODY BGCOLOR=\"#FDF5E6\">\n" +<br />"<H2>Init Parameters:</H2>\n" +<br />"<UL>\n" +<br />"<LI>First name: " + firstName + "\n" +<br />"<LI>Email address: " + emailAddress + "\n" +<br />"</UL>\n" + <br />"</BODY></HTML>");<br />}<br />}<br /><br /><br />E序清单5-8 web.xmlQ说明初始化参数的摘录)<br /><?xml version="1.0" encoding="ISO-8859-1"?><br /><!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font> <a target="_blank"> <font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font> </a> <font size="1">"><br /><br /><web-app><br /><!-- ... --><br /><servlet><br /><servlet-name>InitTest</servlet-name><br /><servlet-class>moreservlets.InitServlet</servlet-class><br /><init-param><br /><param-name>firstName</param-name><br /><param-value>Larry</param-value><br /></init-param><br /><init-param><br /><param-name>emailAddress</param-name><br /><param-value></font> <a href="mailto:Ellison@Microsoft.com"> <font size="1">Ellison@Microsoft.com</font> </a> <font size="1"></param-value><br /></init-param><br /></servlet><br /><!-- ... --><br /></web-app><br /><br />5.2 分配JSP初始化参?br />lJSP面提供初始化参数在三个斚w不同于给servlet提供初始化参数?br />1Q用jsp-file而不是servlet-class。因此,WEB-INF/web.xml文g的servlet元素如下所C:<br /><servlet><br /><servlet-name>PageName</servlet-name><br /><jsp-file>/RealPage.jsp</jsp-file><br /><init-param><br /><param-name>...</param-name><br /><param-value>...</param-value><br /></init-param><br />...<br /></servlet><br />2) 几乎L分配一个明的URL模式。对servletQ一般相应地使用?/font> <a href="http://host/webAppPrefix/servlet/" target="_blank"> <font size="1">http://host/webAppPrefix/servlet/</font> </a> <font size="1">开始的~省URL。只需CQ用注册名而不是原名称卛_。这对于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">讉KRealPage.jsp的对初始化参数具有访问权的版本。但在用于JSP面Ӟ许多用户g不喜Ƣ应用常规的servlet的URL。此外,如果 JSP面位于服务器ؓ其提供了目录清单的目录中Q如Q一个既没有index.html也没有index.jsp文g的目录)Q则用户可能会连接到?JSP面Q单dQ从而意外地ȀzL初始化的面。因此,好的办法是用url-patternQ?.3节)JSP面的原URL与注册的 servlet名相兌。这P客户机可使用JSP面的普通名Uͼ但仍然激zd制的版本。例如,l定来自目1的servlet定义Q可使用下面?servlet-mapping定义Q?br /><servlet-mapping><br /><servlet-name>PageName</servlet-name><br /><url-pattern>/RealPage.jsp</url-pattern><br /></servlet-mapping><br />3QJSP用jspInit而不是init。自动从JSP面建立的servlet或许已经使用了intiҎ。因此,使用JSP声明提供一个initҎ是不合法的,必须制定jspInitҎ?br />Z说明初始化JSP面的过E,E序清单5-9l出了一个名为InitPage.jsp的JSP面Q它包含一个jspInitҎ且放|于 deployDemo Web应用层次l构的顶层。一般,</font> <a href="http://host/deployDemo/InitPage.jsp" target="_blank"> <font size="1">http://host/deployDemo/InitPage.jsp</font> </a> <font size="1">形式的URL激zL面的不h初始化参数访问权的版本,从而将对firstName和emailAddress变量昄null。但是, web.xml文gQ程序清?-10Q分配了一个注册名Q然后将该注册名与URL模式/InitPage.jsp相关联?br /><br />E序清单5-9 InitPage.jsp<br /><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><br /><HTML><br /><HEAD><TITLE>JSP Init Test</TITLE></HEAD><br /><BODY BGCOLOR="#FDF5E6"><br /><H2>Init Parameters:</H2><br /><UL><br /><LI>First name: <%= firstName %><br /><LI>Email address: <%= emailAddress %><br /></UL><br /></BODY></HTML><br /><%!<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 />%><br /><br /><br />E序清单5-10 web.xmlQ说明JSP面的init参数的摘录)<br /><?xml version="1.0" encoding="ISO-8859-1"?><br /><!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font> <a target="_blank"> <font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font> </a> <font size="1">"><br /><br /><web-app><br /><!-- ... --><br /><servlet><br /><servlet-name>InitPage</servlet-name><br /><jsp-file>/InitPage.jsp</jsp-file><br /><init-param><br /><param-name>firstName</param-name><br /><param-value>Bill</param-value><br /></init-param><br /><init-param><br /><param-name>emailAddress</param-name><br /><param-value></font> <a href="mailto:gates@oracle.com"> <font size="1">gates@oracle.com</font> </a> <font size="1"></param-value><br /></init-param><br /></servlet><br /><!-- ... --> <br /><servlet-mapping><br /><servlet-name> InitPage</servlet-name><br /><url-pattern>/InitPage.jsp</url-pattern><br /></servlet-mapping><br /><!-- ... --><br /></web-app><br /><br /><br />5.3 提供应用范围内的初始化参?br />一般,对单个地servlet或JSP面分配初始化参数。指定的servlet或JSP面利用ServletConfig的getInitParameterҎdq些参数。但是,在某些情形下Q希望提供可׃Q意servlet或JSP面借助ServletContext的getInitParameterҎd的系l范围内的初始化参数?br />可利用context-param元素声明q些pȝ范围内的初始化倹{context-param元素应该包含param-name、param-value以及可选的description子元素,如下所C:<br /><context-param><br /><param-name>support-email</param-name><br /><param-value></font> <a href="mailto:blackhole@mycompany.com"> <font size="1">blackhole@mycompany.com</font> </a> <font size="1"></param-value><br /></context-param><br />可回忆一下,Z保证可移植性,web.xml内的元素必须以正的ơ序声明。但q里应该注意Qcontext-param元素必须出现L与文有关的元素Qicon、display-name或descriptionQ之后及filter、filter-mapping、listener?servlet元素之前?br />5.4 在服务器启动时装载servlet<br />假如servlet或JSP面有一个要花很长时间执行的init QservletQ或jspInitQJSPQ方法。例如,假如init或jspInitҎ从某个数据库或ResourceBundle查找产量。这U情况下Q在W一个客hh时装载servlet的缺省行为将对第一个客h产生较长旉的gq。因此,可利用servlet的load-on- startup元素规定服务器在W一ơ启动时装蝲servlet。下面是一个例子?br /><servlet><br /><servlet-name> ?</servlet-name><br /><servlet-class> ?</servlet-class> <!-- Or jsp-file --><br /><load-on-startup/><br /></servlet><br />可以为此元素体提供一个整数而不是用一个空的load-on-startup。想法是服务器应该在装蝲较大数目的servlet或JSP面之前装蝲较少数目的servlet或JSP面。例如,下面的servlet(攄在Web应用的WEB-INF目录下的web.xml文g中的web-app元素内)指C服务器首先装蝲和初始化SearchServletQ然后装载和初始化由位于Web应用的result目录中的index.jsp文g产生?servlet?br /><servlet><br /><servlet-name>Search</servlet-name><br /><servlet-class>myPackage.SearchServlet</servlet-class> <!-- Or jsp-file --><br /><load-on-startup>1</load-on-startup><br /></servlet><br /><servlet><br /><servlet-name>Results</servlet-name><br /><servlet-class>/results/index.jsp</servlet-class> <!-- Or jsp-file --><br /><load-on-startup>2</load-on-startup><br /></servlet><br /><br />6 声明qo?br /><br />servlet版本2.3引入了过滤器的概c虽然所有支持servlet API版本2.3的服务器都支持过滤器Q但Z使用与过滤器有关的元素,必须在web.xml中用版?.3的DTD?br />qo器可截取和修改进入一个servlet或JSP面的请求或从一个servlet或JSP面发出的相应。在执行一个servlet或JSP面之前Q必L行第一个相关的qo器的doFilterҎ。在该过滤器对其FilterChain对象调用doFilterӞ执行链中的下一个过滤器。如果没有其他过滤器Qservlet或JSP面被执行。过滤器h对到来的ServletRequest对象的全部访问权Q因此,它们可以查看客户机名、查扑ֈ来的cookie{。ؓ了访问servlet或JSP面的输出,qo器可响应对象包裹在一个替w对象(stand-in objectQ中Q比方说把输出篏加到一个缓冲区。在调用FilterChain对象的doFilterҎ之后Q过滤器可检查缓冲区Q如有必要,对它进行修改,然后传送到客户机?br />例如Q程序清?-11帝国难以了一个简单的qo器,只要讉K相关的servlet或JSP面Q它截取请求ƈ在标准输Z打印一个报告(开发过E中在桌面系l上q行Ӟ大多数服务器都可以用这个过滤器Q?br /><br />E序清单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 />* <P><br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font> <a 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 />一旦徏立了一个过滤器Q可以在web.xml中利用filter元素以及filter-nameQQ意名Uͼ、file-classQ完全限定的cdQ和Q可选的Qinit-params子元素声明它。请注意Q元素在web.xml的web-app元素中出现的ơ序不是L的;允许服务器(但不是必需的)强制所需的次序,q且实际中有些服务器也是q样做的。但q里要注意,所有filter元素必须出现在Q意filter-mapping元素之前Q?filter-mapping元素又必d现在所有servlet或servlet-mapping元素之前?br />例如Q给定上q的ReportFilterc,可在web.xml中作Z面的filter声明。它把名UReporter与实际的cReportFilterQ位于moreservletsE序包中Q相兌?br /><filter><br /><filter-name>Reporter</filter-name><br /><filter-class>moresevlets.ReportFilter</filter-class><br /></filter><br />一旦命名了一个过滤器Q可利用filter-mapping元素把它与一个或多个servlet或JSP面相关联。关于此工作有两种选择?br />首先Q可使用filter-name和servlet-name子元素把此过滤器与一个特定的servlet名(此servlet名必ȝ后在相同?web.xml文g中用servlet元素声明Q关联。例如,下面的程序片断指C系l只要利用一个定制的URL讉K名ؓSomeServletName 的servlet或JSP面Q就q行名ؓReporter的过滤器?br /><filter-mapping><br /><filter-name>Reporter</filter-name><br /><servlet-name>SomeServletName</servlet-name><br /></filter-mapping><br />其次Q可利用filter-name和url-pattern子元素将qo器与一lservlet、JSP面或静态内容相兌。例如,盔R的程序片D|C系l只要访问Web应用中的LURLQ就q行名ؓReporter的过滤器?br /><filter-mapping><br /><filter-name>Reporter</filter-name><br /><url-pattern>/*</url-pattern><br /></filter-mapping><br />例如Q程序清?-12l出了将ReportFilterqo器与名ؓPageName的servlet相关联的web.xml文g的一部分。名?PageName依次又与一个名为TestPage.jsp的JSP面以及以模式http: //host/webAppPrefix/UrlTest2/ 开头的URL相关联。TestPage.jsp的源代码已经JSP面命名的谈论在前面??分配名称和定制的URL"中给出。事实上Q程序清?- 12中的servlet和servlet-name从该节原封不动地拿q来的。给定这些web.xml,可看C面的标准输出形式的调试报告(换行是ؓ了容易阅读)?br />audit.irs.gov tried to access <br /></font> <a 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 />E序清单5-12 Web.xmlQ说明filter用法的摘录)<br /><?xml version="1.0" encoding="ISO-8859-1"?><br /><!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font> <a target="_blank"> <font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font> </a> <font size="1">"><br /><br /><web-app><br /><filter><br /><filter-name>Reporter</filter-name><br /><filter-class>moresevlets.ReportFilter</filter-class><br /></filter><br /><!-- ... --><br /><filter-mapping><br /><filter-name>Reporter</filter-name><br /><servlet-name>PageName</servlet-name><br /></filter-mapping><br /><!-- ... --><br /><servlet><br /><servlet-name>PageName</servlet-name><br /><jsp-file>/RealPage.jsp</jsp-file><br /></servlet><br /><!-- ... --><br /><servlet-mapping><br /><servlet-name> PageName </servlet-name><br /><url-pattern>/UrlTest2/*</url-pattern><br /></servlet-mapping><br /><!-- ... --><br /></web-app><br /><br /><br />7 指定Ƣ迎?br /><br />假如用户提供了一个像http: //host/webAppPrefix/directoryName/ q样的包含一个目录名但没有包含文件名的URLQ会发生什么事情呢Q用戯得到一个目录表Q一个错误?q是标准文g的内容?如果得到标准文g内容Q是 index.html、index.jsp、default.html、default.htm或别的什么东西呢Q?br />Welcome-file-list 元素及其辅助的welcome-file元素解决了这个模p的问题。例如,下面的web.xmlҎ出,如果一个URLl出一个目录名但未l出文g名,服务器应该首先试用index.jspQ然后再试用index.html。如果两者都没有扑ֈQ则l果有赖于所用的服务器(如一个目录列表)?br /><welcome-file-list><br /><welcome-file>index.jsp</welcome-file><br /><welcome-file>index.html</welcome-file><br /></welcome-file-list><br />虽然许多服务器缺省遵循这U行为,但不一定必这栗因此,明确C用welcom-file-list保证可移植性是一U良好的习惯?br /><br />8 指定处理错误的页?br /><br />现在我了解到Q你在开发servlet和JSP面时从不会犯错误,而且你的所有页面是那样的清晎ͼ一般的E序员都不会被它们的搞糊涂。但是,是hM犯错误的Q用户可能会提供不合规定的参敎ͼ使用不正的URL或者不能提供必需的表单字D倹{除此之外,其它开发h员可能不那么l心Q他们应该有些工h克服自己的不?br />error-page元素是用来克服q些问题的。它有两个可能的子元素,分别是:error-code和exception- type。第一个子元素error-code指出在给定的HTTP错误代码出现时用的URL。第二个子元素excpetion-type指出在出现某个给定的Java异常但未捕捉到时使用的URL。error-code和exception-type都利用location元素指出相应的URL。此 URL必须?开始。location所指出的位|处的页面可通过查找HttpServletRequest对象的两个专门的属性来讉K关于错误的信息,q两个属性分别是Qjavax.servlet.error.status_code和javax.servlet.error.message?br />可回忆一下,在web.xml内以正确的次序声明web-app的子元素很重要。这里只要记住,error-page出现在web.xml文g的末Nq,servlet、servlet-name和welcome-file-list之后卛_?br /><br />8.1 error-code元素<br />Z更好C解error-code元素的|可考虑一下如果不正确地输入文件名Q大多数站点会作Z么反映。这样做一般会出现一?04错误信息Q它表示不能扑ֈ该文Ӟ但几乎没提供更多有用的信息。另一斚wQ可以试一下在</font> <a target="_blank"> <font size="1">www.microsoft.com</font> </a> <font size="1">?/font> <a target="_blank"> <font size="1">www.ibm.com</font> </a> <font size="1">处或者特别是?/font> <a target="_blank"> <font size="1">www.bea.com</font> </a> <font size="1">处输出未知的文g名。这是会得出有用的消息,q些消息提供可选择的位|,以便查找感兴的面。提供这h用的错误面对于Web应用来说是很有h值得。事实上rm-error-page子元素)。由form-login-pagel出的HTML表单必须h一个j_security_check?ACTION属性、一个名为j_username的用户名文本字段以及一个名为j_password的口令字Dc?br />例如Q程序清?-19指示服务器用基于表单的验证。Web应用的顶层目录中的一个名为login.jsp的页面将攉用户名和口oQƈ且失败的登陆由相同目录中名为login-error.jsp的页面报告?br /><br />E序清单5-19 web.xmlQ说明login-config的摘录)<br /><?xml version="1.0" encoding="ISO-8859-1"?><br /><!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font> <a target="_blank"> <font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font> </a> <font size="1">"><br /><br /><web-app><br /><!-- ... --><br /><security-constraint> ... </security-constraint><br /><login-config><br /><auth-method> FORM </auth-method><br /><form-login-config><br /><form-login-page>/login.jsp</form-login-page><br /><form-error-page>/login-error.jsp</form-error-page><br /></form-login-config><br /></login-config><br /><!-- ... --><br /></web-app><br /><br /><br />9.2 限制对Web资源的访?br />现在Q可以指C服务器使用何种验证Ҏ了?了不P"你说道,"除非我能指定一个来收到保护?URLQ否则没有多大用处?没错。指些URLq说明他们应该得CU保护正是security-constriaint元素的用途。此元素?web.xml中应该出现在login-config的紧前面。它包含是个可能的子元素Q分别是Qweb-resource-collection?auth-constraint、user-data-constraint和display-name。下面各节对它们进行介l?br />l web-resource-collection<br />此元素确定应该保护的资源。所有security-constraint元素都必d含至一个web-resource-collectionV此元素׃个给ZQ意标识名U的web-resource-name元素、一个确定应该保护的URL的url-pattern元素、一个指出此保护所适用?HTTP命oQGET、POST{,~省为所有方法)的http-method元素和一个提供资料的可选description元素l成。例如,下面?Web-resource-collection(在security-constratint元素内)指出Web应用的proprietary目录中所有文档应该受C护?br /><security-constraint><br /><web-resource-coolection><br /><web-resource-name>Proprietary</web-resource-name><br /><url-pattern>/propritary/*</url-pattern><br /></web-resource-coolection><br /><!-- ... --><br /></security-constraint><br />重要的是应该注意刎ͼurl-pattern仅适用于直接访问这些资源的客户机。特别是Q它不适合于通过MVC体系l构利用 RequestDispatcher来访问的面Q或者不适合于利用类似jsp:forward的手D|讉K的页面。这U不匀U如果利用得当的话很有好处。例如,servlet可利用MVC体系l构查找数据Q把它放到bean中,发送请求到从bean中提取数据的JSP面q显C它。我们希望保证决不直接访问受保护的JSP面Q而只是通过建立该页面将使用的bean的servlet来访问它。url-pattern和auth-contraint元素可通过声明不允怓Q何用L接访问JSP面来提供这U保证。但是,q种不匀U的行ؓ可能让开发h员放松警惕,使他们偶然对应受保护的资源提供不受限制的讉K?<br />l auth-constraint<br />管web-resource-collention元素质出了哪些URL应该受到保护Q但是auth-constraint元素却指出哪些用户应该具有受保护资源的访问权。此元素应该包含一个或多个标识h讉K权限的用L别role- name元素Q以及包含(可选)一个描q角色的description元素。例如,下面web.xml中的security-constraint元素部门规定只有指定为Administrator或Big KahunaQ或两者)的用户具有指定资源的讉K权?br /><security-constraint><br /><web-resource-coolection> ... </web-resource-coolection><br /><auth-constraint><br /><role-name>administrator</role-name><br /><role-name>kahuna</role-name><br /></auth-constraint><br /></security-constraint><br />重要的是认识刎ͼ到此为止Q这个过E的可移植部分结束了。服务器怎样定哪些用户处于M角色以及它怎样存放用户的口令,完全有赖于具体的pȝ?br />例如QTomcat使用install_dir/conf/tomcat-users.xml用户名与角色名和口令相兌Q正如下面例子中所C,它指出用户joeQ口令bigshotQ和janeQ口令enajQ属于administrator和kahuna角色?br /><tomcat-users><br /><user name="joe" password="bigshot" roles="administrator,kahuna" /><br /><user name="jane" password="enaj" roles="kahuna" /><br /></tomcat-users><br />l user-data-constraint<br />q个可选的元素指出在访问相兌源时使用M传输层保护。它必须包含一个transport-guarantee子元素(合法gؓNONE?INTEGRAL或CONFIDENTIALQ,q且可选地包含一个description元素。transport-guarantee为NONE值将Ҏ用的通讯协议不加限制。INTEGRALDC数据必M一U防止截取它的h阅读它的方式传送。虽然原理上Qƈ且在未来的HTTP版本中)Q在 INTEGRAL和CONFIDENTIAL之间可能会有差别Q但在当前实践中Q他们都只是单地要求用SSL。例如,下面指示服务器只允许对相兌源做 HTTPSq接Q?br /><security-constraint><br /><!-- ... --><br /><user-data-constraint><br /><transport-guarantee>CONFIDENTIAL</transport-guarantee><br /></user-data-constraint><br /></security-constraint><br />l display-name<br />security-constraint的这个很用的子元素给予可能由GUI工具使用的安全约束项一个名U?br />9.3 分配角色?br />q今为止Q讨论已l集中到完全由容器(服务器)处理的安全问题之上了。但servlet以及JSP面也能够处理它们自q安全问题?br />例如Q容器可能允许用户从bigwig或bigcheese角色讉K一个显CZh员额外紧贴的面Q但只允许bigwig用户修改此页面的参数。完成这U更l致的控制的一U常见方法是调用HttpServletRequset的isUserInRoleҎQƈ据此修改讉K?br />Servlet?security-role-ref子元素提供出现在服务器专用口令文件中的安全角色名的一个别名。例如,假如~写了一个调?request.isUserInRoleQ?boss"Q的servletQ但后来该servlet被用在了一个其口o文g调用角色manager而不是boss的服务器中。下面的E序D该servlet能够使用q两个名UC的Q何一个?br /><servlet><br /><!-- ... --><br /><security-role-ref><br /><role-name>boss</role-name> <!-- New alias --><br /><role-link>manager</role-link> <!-- Real name --><br /></security-role-ref><br /></servlet><br />也可以在web-app内利用security-role元素提供出现在role-name元素中的所有安全角色的一个全局列表。分别地生命角色佉KUIDEҎ处理安全信息?br /><br />10 控制会话时<br /><br />如果某个会话在一定的旉内未被访问,服务器可把它扔掉以节U内存。可利用HttpSession的setMaxInactiveIntervalҎ直接讄个别会话对象的超时倹{如果不采用q种ҎQ则~省的超时值由具体的服务器军_。但可利用session-config和session- timeout元素来给Z个适用于所有服务器的明的时倹{超时值的单位为分钟,因此Q下面的例子讄~省会话时gؓ三个时Q?80分钟Q?br /><session-config><br /><session-timeout>180</session-timeout><br /></session-config><br /><br />11 Web应用的文档化<br /><br />来多的开发环境开始提供servlet和JSP的直接支持。例子有Borland Jbuilder Enterprise Edition、Macromedia UltraDev、Allaire JRun StudioQ写此文Ӟ已被Macromedia收购Q以及IBM VisuaAge for Java{?br />大量的web.xml元素不仅是ؓ服务器设计的Q而且q是为可视开发环境设计的。它们包括icon、display-name和discription{?br />可回忆一下,在web.xml内以适当地次序声明web-app子元素很重要。不q,q里只要Cicon、display-name和description是web.xml的web-app元素内的前三个合法元素即可?br />l icon<br />icon元素指出GUI工具可用来代表Web应用的一个和两个囑փ文g。可利用small-icon元素指定一q?6 x 16的GIF或JPEG囑փQ用large-icon元素指定一q?2 x 32的图像。下面D一个例子: <br /><icon><br /><small-icon>/images/small-book.gif</small-icon><br /><large-icon>/images/tome.jpg</large-icon><br /></icon><br />l display-name<br />display-name元素提供GUI工具可能会用来标记此Web应用的一个名U。下面是个例子?br /><display-name>Rare Books</display-name><br />l description<br />description元素提供解释性文本,如下所C:<br /><description><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 /></description><br /><br />12 兌文g与MIMEcd<br /><br />服务器一般都h一U让Web站点理员将文g扩展名与媒体相关联的Ҏ。例如,会自动l予名ؓmom.jpg的文件一个image/jpeg的MIME cd。但是,假如你的Web应用h几个不寻常的文gQ你希望保证它们在发送到客户机时分配为某UMIMEcd。mime-mapping元素Q具?extension和mime-type子元素)可提供这U保证。例如,下面的代码指C服务器application/x-fubar的MIMEcd分配l所有以.fool尾的文件?br /><mime-mapping><br /><extension>foo</extension><br /><mime-type>application/x-fubar</mime-type><br /></mime-mapping><br />或许Q你的Web应用希望重蝲QoverrideQ标准的映射。例如,下面的代码将告诉服务器在发送到客户机时指定.ps文g作ؓU文本(text/plainQ而不是作为PostScriptQapplication/postscriptQ?br /><mime-mapping><br /><extension>ps</extension><br /><mime-type>application/postscript</mime-type><br /></mime-mapping><br /><br /><br />13 定位TLD<br /><br />JSP taglib元素h一个必要的uri属性,它给Z个TLDQTag Library DescriptorQ文件相对于Web应用的根的位|。TLD文g的实际名U在发布新的标签库版本时可能会改变,但我们希望避免更Ҏ有现有JSP面。此外,可能q希望用保持taglib元素的简l性的一个简短的uri。这是部v描述W文件的taglib元素z场的所在了。Taglib包含两个子元素:taglib-uri和taglib-location。taglib-uri元素应该与用于JSP taglib元素的uri属性的东西相匹配。Taglib-location元素l出TLD文g的实际位|。例如,假如你将文gchart-tags- 1.3beta.tld攑֜WebApp/WEB-INF/tlds中。现在,假如web.xml在web-app元素内包含下列内宏V?br /><taglib><br /><taglib-uri>/charts.tld</taglib-uri><br /><taglib-location><br />/WEB-INF/tlds/chart-tags-1.3beta.tld<br /></taglib-location><br /></taglib><br />l出q个说明后,JSP面可通过下面的简化Ş式用标{ֺ?br /><%@ taglib uri="/charts.tld" prefix="somePrefix" %><br /><br />14 指定应用事g监听E序<br /><br />应用事g监听器程序是建立或修改servlet环境或会话对象时通知的类。它们是servlet规范的版?.3中的新内宏V这里只单地说明用来向Web应用注册一个监听程序的web.xml的用法?br />注册一个监听程序涉及在web.xml的web-app元素内放|一个listener元素。在listener元素内,listener-class元素列出监听E序的完整的限定cdQ如下所C:<br /><listener><br /><listener-class>package.ListenerClass</listener-class><br /></listener><br />虽然listener元素的结构很单,但请不要忘记Q必L地l出web-app元素内的子元素的ơ序。listener元素位于所有的servlet 元素之前以及所有filter-mapping元素之后。此外,因ؓ应用生存期监听程序是serlvet规范?.3版本中的新内容,所以必M?web.xml DTD?.3版本Q而不?.2版本?br />例如Q程序清?-20l出一个名为ContextReporter的简单的监听E序Q只要Web应用的Servlet-Context建立Q如装蝲Web应用Q或消除Q如服务器关闭)Ӟ它就在标准输Z昄一条消息。程序清?-21l出此监听程序注册所需要的web.xml文g的一部分?br /><br />E序清单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 />* <P><br />* Taken from More Servlets and JavaServer Pages<br />* from Prentice Hall and Sun Microsystems Press,<br />* </font> <a 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 />E序清单5-21 web.xmlQ声明一个监听程序的摘录Q?br /><?xml version="1.0" encoding="ISO-8859-1"?><br /><!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />"</font> <a target="_blank"> <font size="1">http://java.sun.com/dtd/web-app_2_3.dtd</font> </a> <font size="1">"><br /><br /><web-app><br /><!-- ... --><br /><filter-mapping> ?</filter-mapping><br /><listener><br /><listener-class>package.ListenerClass</listener-class><br /></listener><br /><servlet> ... </servlet><br /><!-- ... --><br /></web-app><br /><br /><br />15 J2EE元素<br /><br />本节描述用作J2EE环境l成部分的Web应用的web.xml元素。这里将提供一个简明的介绍Q详l内容可以参?/font> <a 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 元素指出QWeb应用是以q样的方式编E的Q即Q支持集的服务器可安全地在多个服务器上分布Web应用。例如,一个可分布的应用必d使用 Serializable对象作ؓ其HttpSession对象的属性,而且必须避免用实例变量(字段Q来实现持箋性。distributable元素直接出现在discription元素之后Qƈ且不包含子元素或数据Q它只是一个如下的标志?br /><distributable /><br />l resource-env-ref<br />resource -env-ref元素声明一个与某个资源有关的管理对象。此元素׃个可选的description元素、一个resource-env-ref- name元素Q一个相对于java:comp/env环境的JNDI名)以及一个resource-env-type元素Q指定资源类型的完全限定的类Q,如下所C:<br /><resource-env-ref><br /><resource-env-ref-name><br />jms/StockQueue<br /></resource-env-ref-name><br /><resource-env-ref-type><br />javax.jms.Queue<br /></resource-env-ref-type><br /></resource-env-ref><br />l env-entry<br />env -entry元素声明Web应用的环境项。它׃个可选的description元素、一个env-entry-name元素Q一个相对于java: comp/env环境JNDI名)、一个env-entry-value元素Q项|以及一个env-entry-type元素Qjava.langE序包中一个类型的完全限定cdQjava.lang.Boolean、java.lang.String{)l成。下面是一个例子:<br /><env-entry><br /><env-entry-name>minAmout</env-entry-name><br /><env-entry-value>100.00</env-entry-value><br /><env-entry-type>minAmout</env-entry-type><br /></env-entry><br />l ejb-ref<br />ejb -ref元素声明对一个EJB的主目录的应用。它׃个可选的description元素、一个ejb-ref-name元素Q相对于java: comp/env的EJB应用Q、一个ejb-ref-type元素Qbean的类型,Entity或SessionQ、一个home元素Qbean的主目录接口的完全限定名Q、一个remote元素Qbean的远E接口的完全限定名)以及一个可选的ejb-link元素Q当前bean链接的另一?bean的名Uͼl成?br />l ejb-local-ref<br />ejb-local-ref元素声明一个EJB的本C目录的引用。除了用local-home代替home外,此元素具有与ejb-ref元素相同的属性ƈ以相同的方式使用?br /><br /><br /><br /><br /><br /><br />17:42 | 固定链接 | 评论 (0) | 引用通告 (0) | 记录?| 计算Z Internet <br /><br /><br />固定链接 关闭 <br /><br /></font> <a 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?4?<br /><br /><br /><br />l你的session加个监听?<br /><br /><br />今天一个学生问我怎么实现在网里昄在线用户的名U——他已经使用了sessionQ但是无法处理用L开的情况,然后D在线用户列表的无限增大。跟他说了自己在application中进行超时检查,更新application的时候就比较当前所有列表中的session是否过自己指定的时间间隔。后来想了想Q又l他提了使用lsession加监听器的方法。但是提的时候自׃没有做过Q所以只是说q种方式很复杂,他还是自p行超时检查。刚才又看了看资料,发现实际上给session加监听器的方式很单,不禁觉得自己有点误h子弟了,现在方法写在这Q借以告诫自己以后要严谨?br />首先写一个SessionBinderc?它实CHttpSessionBindingListener接口的valueBoundҎ和valueUnboundҎQ示例代码如下:<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 />现在写好了SessionBinderQ我们现在选择在一个servlet中向session中加入这个监听器——在jsp中的代码书写与此相同<br />//省略前面的代码,此操作可能发生在servlet的doGetҎ中,也可能是doPostҎ?br />  HttpSession session = req.getSession(true);//首先获得需要加入监听器的session对象Qreq是HttpRequest对象<br />  SessionBinder sb = new SessionBinder();//建立一个监听器对象<br />  session.putValue("BinderObject",sb);//监听器加入此session中,从此时开始执行sb的valueBoundҎ<br />//省略后面的代?br />随后Q如果整个session时或者被用户中止之后Qsb的valueUnbound自动执行<br />呵呵Q以上代码以供参</font> </span> <font size="1"> </font> </span> <img src ="http://www.aygfsteel.com/weibogao/aggbug/38618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/weibogao/" target="_blank">weibogao</a> 2006-04-01 16:38 <a href="http://www.aygfsteel.com/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 javahttp://www.aygfsteel.com/weibogao/archive/2006/03/30/38356.htmlweibogaoweibogaoThu, 30 Mar 2006 12:43:00 GMThttp://www.aygfsteel.com/weibogao/archive/2006/03/30/38356.htmlhttp://www.aygfsteel.com/weibogao/comments/38356.htmlhttp://www.aygfsteel.com/weibogao/archive/2006/03/30/38356.html#Feedback0http://www.aygfsteel.com/weibogao/comments/commentRss/38356.htmlhttp://www.aygfsteel.com/weibogao/services/trackbacks/38356.htmlwww.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
welcome to add your favourite website here  

weibogao 2006-03-30 20:43 发表评论
]]>
վ֩ģ壺 | Ӣɳ| | | ٲ| | | | | Դ| | | ֻ| | | | ֦| | ƽ| ũ| | | Ʊ| | ϼ| | ľ| ɽ| Ͽ| | ɽ| Ұ| ʱ| | ʷ| | ־| | Ȫ| | |