ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>青草伊人久久,亚洲欧洲美洲综合色网,中文在线资源http://www.aygfsteel.com/DenisLing/The only documentation is the code itselfzh-cnWed, 11 Jun 2025 01:25:53 GMTWed, 11 Jun 2025 01:25:53 GMT60Spring中的DAOå’ŒServicehttp://www.aygfsteel.com/DenisLing/archive/2006/02/05/daoAndServiceInSpring.htmlDenisLingDenisLingSun, 05 Feb 2006 09:17:00 GMThttp://www.aygfsteel.com/DenisLing/archive/2006/02/05/daoAndServiceInSpring.htmlhttp://www.aygfsteel.com/DenisLing/comments/29620.htmlhttp://www.aygfsteel.com/DenisLing/archive/2006/02/05/daoAndServiceInSpring.html#Feedback0http://www.aygfsteel.com/DenisLing/comments/commentRss/29620.htmlhttp://www.aygfsteel.com/DenisLing/services/trackbacks/29620.html阅读全文

DenisLing 2006-02-05 17:17 发表评论
]]>
数据库设计的范式大纲及一个小的实例说æ˜?/title><link>http://www.aygfsteel.com/DenisLing/archive/2005/12/20/24725.html</link><dc:creator>DenisLing</dc:creator><author>DenisLing</author><pubDate>Tue, 20 Dec 2005 02:54:00 GMT</pubDate><guid>http://www.aygfsteel.com/DenisLing/archive/2005/12/20/24725.html</guid><wfw:comment>http://www.aygfsteel.com/DenisLing/comments/24725.html</wfw:comment><comments>http://www.aygfsteel.com/DenisLing/archive/2005/12/20/24725.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.aygfsteel.com/DenisLing/comments/commentRss/24725.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/DenisLing/services/trackbacks/24725.html</trackback:ping><description><![CDATA[ <p class="MsoNormal" style="margin-bottom: 12pt;"><b><span style="font-size: 14pt; font-family: 宋体;" lang="EN-US"><o:p> </o:p></span></b></p> <p class="MsoNormal" style="text-align: center;" align="center"><b><span style="font-size: 26pt; font-family: 黑体; color: red;">数据库设计的范式大纲 </span></b><span style="font-size: 26pt; font-family: 黑体;" lang="EN-US"><o:p></o:p></span></p> <p class="MsoNormal" style=""><span style="font-size: 14pt; font-family: 宋体;">½W¬ä¸€èŒƒå¼<span lang="EN-US">:<o:p></o:p></span></span></p> <p class="MsoNormal" style="text-indent: 0.5in;"><span style="font-size: 14pt; font-family: 宋体;">对于表中的每一行,必须且仅仅有唯一的行å€?span lang="EN-US">.</span>åœ¨ä¸€è¡Œä¸­çš„æ¯ä¸€åˆ—ä»…æœ‰å”¯ä¸€çš„å€¼åÆˆä¸”å…·æœ‰åŽŸå­æ€?span lang="EN-US">.<o:p></o:p></span></span></p> <p class="MsoNormal" style=""><span style="font-size: 14pt; font-family: 宋体;">½W¬äºŒèŒƒå¼<span lang="EN-US">:<o:p></o:p></span></span></p> <p class="MsoNormal" style="text-indent: 0.5in;"><span style="font-size: 14pt; font-family: 宋体;">½W¬äºŒèŒƒå¼è¦æ±‚非主键列是主键的子集åQŒéžä¸»é”®åˆ—活动必™åÕd®Œå…¨ä¾èµ–整个主键。主键必™åÀLœ‰å”¯ä¸€æ€§çš„元素<span lang="EN-US">,</span>一个主键可以由一个或更多的组成唯一值的列组成。一旦创建,主键无法改变åQŒå¤–键关联一个表的主键。主外键兌™”意味着一对多的关¾p?span lang="EN-US">.<o:p></o:p></span></span></p> <p class="MsoNormal" style=""><span style="font-size: 14pt; font-family: 宋体;">½W¬ä¸‰èŒƒå¼<span lang="EN-US">:<o:p></o:p></span></span></p> <p class="MsoNormal" style="text-indent: 0.5in;"><span style="font-size: 14pt; font-family: 宋体;">½W¬ä¸‰èŒƒå¼è¦æ±‚非主键列互不依赖<span lang="EN-US">.<o:p></o:p></span></span></p> <p class="MsoNormal" style=""><span style="font-size: 14pt; font-family: 宋体;">½W¬å››èŒƒå¼<span lang="EN-US">:<o:p></o:p></span></span></p> <p class="MsoNormal" style="text-indent: 0.5in;"><span style="font-size: 14pt; font-family: 宋体;">½W¬å››èŒƒå¼¼›æ­¢ä¸»é”®åˆ—和非主键列一对多关系不受¾U¦æŸ<span lang="EN-US"><o:p></o:p></span></span></p> <p class="MsoNormal" style=""><span style="font-size: 14pt; font-family: 宋体;">½W¬äº”范式<span lang="EN-US">:<o:p></o:p></span></span></p> <p class="MsoNormal" style="text-indent: 0.5in;"><span style="font-size: 14pt; font-family: 宋体;">½W¬äº”范式ž®†è¡¨åˆ†å‰²æˆå°½å¯èƒ½ž®çš„块,ä¸ÞZº†æŽ’除在表中所有的冗余<span lang="EN-US">.<o:p></o:p></span></span></p> <p class="MsoNormal" style="margin-bottom: 12pt;"><b><span style="font-family: 宋体;" lang="EN-US"><o:p> </o:p></span></b></p> <p class="MsoNormal" style="margin-bottom: 12pt;"><b><span style="font-family: 宋体;" lang="EN-US"><font color="#ff0000">下面先讨论前<span lang="EN-US">3</span>个范式:(x¨¬)</font><o:p></o:p></span></b><span lang="EN-US"><o:p><br></o:p></span></p> <p class="MsoNormal" style="margin-bottom: 12pt;"><b><span style="font-family: 宋体;" lang="EN-US"><o:p> </o:p></span></b></p> <p class="MsoNormal" style="margin-bottom: 12pt;"><b><span style="font-family: 宋体;">引言</span></b><span style="font-family: 宋体;" lang="EN-US"><br> <br> </span><span style="font-family: 宋体;">  数据库的设计范式是数据库设计所需要满­‘³çš„规范åQŒæ»¡­‘Œ™¿™äº›è§„范的数据库是½Ž€‹zçš„、结构明晰的åQŒåŒæ—Óž¼Œä¸ä¼š(x¨¬)发生插入 åQ?span lang="EN-US">insert</span>åQ‰ã€åˆ é™¤ï¼ˆ<span lang="EN-US">delete</span>åQ‰å’Œæ›´æ–°åQ?span lang="EN-US">update</span>åQ‰æ“ä½œå¼‚å¸¸ã€‚åä¹‹åˆ™æ˜¯äØ•ä¸ƒå…«¾pŸï¼Œä¸ä»…¾l™æ•°æ®åº“的编½E‹äh员制造麻烦,而且面目可憎åQŒå¯èƒ½å­˜å‚¨äº† 大量不需要的冗余信息ã€?span lang="EN-US"><br> <br> </span>  设计范式是不是很难懂呢?非也åQŒå¤§å­¦æ•™æä¸Š¾l™æˆ‘们一堆数学公式我们当然看不懂åQŒä¹Ÿè®îC¸ä½ã€‚所以我们很多ähž®±æ ¹æœ¬ä¸æŒ‰ç…§èŒƒå¼æ¥è®¾è®¡æ•°æ®åº“ã€?span lang="EN-US"><br> <br> </span>  实质上,设计范式用很形象、很½Ž€‹zçš„话语ž®Þpƒ½è¯´æ¸…楚,道明白。本文将对范式进行通俗地说明,òq¶ä»¥½W”者曾¾lè®¾è®¡çš„ä¸€ä¸ªç®€å•è®ºå›çš„æ•°æ®åº“äØ“(f¨´)例来讲解怎样ž®†è¿™äº›èŒƒå¼åº”用于实际工程ã€?span lang="EN-US"><br> <br> </span>  <b>范式说明</b><span lang="EN-US"><br> <br> </span>  ½W¬ä¸€èŒƒå¼åQ?span lang="EN-US">1NF</span>åQ‰ï¼š(x¨¬)数据库表中的字段都是单一属性的åQŒä¸å¯å†åˆ†ã€‚这个单一属性由基本¾cÕdž‹æž„成åQŒåŒ…括整型、实数、字½W¦åž‹ã€é€»è¾‘型、日期型½{‰ã€?span lang="EN-US"><br> <br> </span>  例如åQŒå¦‚下的数据库表是符合第一范式的:(x¨¬)<span lang="EN-US"><o:p></o:p></span></span></p> <div align="center"> <table class="MsoNormalTable" style="width: 90%;" border="1" cellpadding="0" cellspacing="0" width="90%"> <tbody><tr style=""> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">1 <o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">2 <o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">3 <o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">4<o:p></o:p></span></span></p> </td> </tr> <tr style=""> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US"> <o:p></o:p></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US"> <o:p></o:p></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US"> <o:p></o:p></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US"> <o:p></o:p></span></p> </td> </tr> </tbody></table> </div> <p class="MsoNormal" style="margin-bottom: 12pt;"><span style="font-family: 宋体;" lang="EN-US"><br> </span><span style="font-family: 宋体;">  而这æ ïL(f¨¥ng)š„æ•°æ®åº“表是不½W¦åˆ½W¬ä¸€èŒƒå¼çš„:(x¨¬)<span lang="EN-US"><o:p></o:p></span></span></p> <div align="center"> <table class="MsoNormalTable" style="width: 90%;" border="1" cellpadding="0" cellspacing="0" width="90%"> <tbody><tr style=""> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">1 <o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">2 <o:p></o:p></span></span></p> </td> <td colspan="2" style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">3 <o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">4<o:p></o:p></span></span></p> </td> </tr> <tr style=""> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US"> <o:p></o:p></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US"> <o:p></o:p></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">3.1<o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">字段<span lang="EN-US">3.2 <o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US"> <o:p></o:p></span></p> </td> </tr> <!--[if !supportMisalignedColumns]--> <tr height="0"> <td style="border: medium none ;" width="119"><br></td> <td style="border: medium none ;" width="119"><br></td> <td style="border: medium none ;" width="157"><br></td> <td style="border: medium none ;" width="157"><br></td> <td style="border: medium none ;" width="119"><br></td> </tr> <!--[endif]--> </tbody></table> </div> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US"><br> </span><span style="font-family: 宋体;">  很显ç„Óž¼Œåœ¨å½“前的ä»ÖM½•关系数据库管理系¾lŸï¼ˆ<span lang="EN-US">DBMS</span>åQ‰ä¸­åQŒå‚»ç“œä¹Ÿä¸å¯èƒ½åšå‡ÞZ¸½W¦åˆ½W¬ä¸€èŒƒå¼çš„æ•°æ®åº“åQŒå› ä¸ø™¿™äº?span lang="EN-US">DBMS</span>ä¸å…è®æ€½ æŠŠæ•°æ®åº“表的一列再分成二列或多列。因此,你想在现有的<span lang="EN-US">DBMS</span>中设计出不符合第一范式的数据库都是不可能的ã€?span lang="EN-US"><br> <br> </span>  ½W¬äºŒèŒƒå¼åQ?span lang="EN-US">2NF</span>åQ‰ï¼š(x¨¬)数据库表中不存在非关键字ŒDµå¯¹ä»ÖM¸€å€™é€‰å…³é”®å­—ŒD늚„部分函数依赖åQˆéƒ¨åˆ†å‡½æ•îC¾èµ–指的是存在¾l„合关键字中的某些字ŒDµå†³å®šéžå…³é”®å­—段的情况)åQŒä¹ŸåÏx‰€æœ‰éžå…³é”®å­—段都完全依赖于ä»ÀL„ä¸€¾l„候选关键字ã€?span lang="EN-US"><br> <br> </span>ã€€ã€€å‡å®šé€‰è¯¾å…³ç³»è¡¨äØ“(f¨´)<span lang="EN-US">SelectCourse(</span>学号<span lang="EN-US">, </span>姓名<span lang="EN-US">, </span>òq´é¾„<span lang="EN-US">, </span>评¡¨‹åç§°<span lang="EN-US">, </span>成ç‡W<span lang="EN-US">, </span>学分<span lang="EN-US">)</span>åQŒå…³é”®å­—为组合关键字<span lang="EN-US">(</span>学号<span lang="EN-US">, </span>评¡¨‹åç§°<span lang="EN-US">)</span>åQŒå› ä¸ºå­˜åœ¨å¦‚下决定关¾p»ï¼š(x¨¬)<span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(</span>学号<span lang="EN-US">, </span>评¡¨‹åç§°<span lang="EN-US">) â†?(</span>姓名<span lang="EN-US">, </span>òq´é¾„<span lang="EN-US">, </span>成ç‡W<span lang="EN-US">, </span>学分<span lang="EN-US">)<br> <br> </span>  ˜q™ä¸ªæ•°æ®åº“表不满­‘³ç¬¬äºŒèŒƒå¼ï¼Œå› äØ“(f¨´)存在如下军_®šå…³ç³»åQ?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(</span>评¡¨‹åç§°<span lang="EN-US">) â†?(</span>学分<span lang="EN-US">)<br> <br> </span>  <span lang="EN-US">(</span>学号<span lang="EN-US">) â†?(</span>姓名<span lang="EN-US">, </span>òq´é¾„<span lang="EN-US">)<br> <br> </span>  卛_­˜åœ¨ç»„合关键字中的字段军_®šéžå…³é”®å­—的情å†üc€?span lang="EN-US"><br> <br> </span>  ç”׃ºŽä¸ç¬¦å?span lang="EN-US">2NF</span>åQŒè¿™ä¸ªé€‰è¯¾å…³ç³»è¡¨ä¼š(x¨¬)存在如下问题åQ?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(1) </span>数据冗余åQ?span lang="EN-US"><br> <br> </span>  同一门课½E‹ç”±<span lang="EN-US">n</span>个学生选修åQ?span lang="EN-US">"</span>学分<span lang="EN-US">"</span>ž®±é‡å¤?span lang="EN-US">n-1</span>‹Æ¡ï¼›åŒä¸€ä¸ªå­¦ç”Ÿé€‰ä¿®äº?span lang="EN-US">m</span>门课½E‹ï¼Œå§“名和年龄就重复äº?span lang="EN-US">m-1</span>‹Æ¡ã€?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(2) </span>更新异常åQ?span lang="EN-US"><br> <br> </span>  若调整了某门评¡¨‹çš„学分,数据表中所有行çš?span lang="EN-US">"</span>学分<span lang="EN-US">"</span>值都要更斎ͼŒå¦åˆ™ä¼?x¨¬)出现同一门课½E‹å­¦åˆ†ä¸åŒçš„æƒ…况ã€?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(3) </span>插入异常åQ?span lang="EN-US"><br> <br> </span>  假设要开设一门新的课½E‹ï¼Œæš‚æ—¶˜q˜æ²¡æœ‰ähé€‰ä¿®ã€‚è¿™æ øP¼Œç”׃ºŽ˜q˜æ²¡æœ?span lang="EN-US">"</span>学号<span lang="EN-US">"</span>关键字,评¡¨‹åç§°å’Œå­¦åˆ†ä¹Ÿæ— æ³•记录入数据库ã€?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(4) </span>删除异常åQ?span lang="EN-US"><br> <br> </span>  假设一批学生已¾lå®Œæˆè¯¾½E‹çš„选修åQŒè¿™äº›é€‰ä¿®è®°å½•ž®±åº”该从数据库表中删除。但是,与此同时åQŒè¯¾½E‹å¿U°å’Œå­¦åˆ†ä¿¡æ¯ä¹Ÿè¢«åˆ é™¤äº†ã€‚很昄¡„¶åQŒè¿™ä¹Ÿä¼š(x¨¬)坯D‡´æ’入异常ã€?span lang="EN-US"> <br> <br> </span>  把选课关系è¡?span lang="EN-US">SelectCourse</span>æ”¹äØ“(f¨´)如下三个表:(x¨¬)<span lang="EN-US"><br> <br> </span>  学生åQ?span lang="EN-US">Student(</span>学号<span lang="EN-US">, </span>姓名<span lang="EN-US">, </span>òq´é¾„<span lang="EN-US">)</span>åQ?span lang="EN-US"><br> <br> </span>  评¡¨‹åQ?span lang="EN-US">Course(</span>评¡¨‹åç§°<span lang="EN-US">, </span>学分<span lang="EN-US">)</span>åQ?span lang="EN-US"><br> <br> </span>  选课关系åQ?span lang="EN-US">SelectCourse(</span>学号<span lang="EN-US">, </span>评¡¨‹åç§°<span lang="EN-US">, </span>成ç‡W<span lang="EN-US">)</span>ã€?span lang="EN-US"><br> <br> </span>  ˜q™æ ·çš„æ•°æ®åº“表是½W¦åˆ½W¬äºŒèŒƒå¼çš„,消除了数据冗余、更新异常、插入异常和删除异常ã€?span lang="EN-US"><br> <br> </span>  另外åQŒæ‰€æœ‰å•å…³é”®å­—çš„æ•°æ®åº“è¡¨éƒ½ç¬¦åˆç¬¬äºŒèŒƒå¼ï¼Œå› äØ“(f¨´)不可能存在组合关键字ã€?span lang="EN-US"><br> <br> </span>   ½W¬ä¸‰èŒƒå¼åQ?span lang="EN-US">3NF</span>åQ‰ï¼š(x¨¬)在第二范式的基础上,数据表中如果不存在非关键字段对ä“Q一候选关键字ŒD늚„传递函æ•îC¾èµ–则½W¦åˆ½W¬ä¸‰èŒƒå¼ã€‚所谓传递函æ•îC¾èµ–,指的是如 果存åœ?span lang="EN-US">"A â†?B â†?C"</span>的决定关¾p»ï¼Œåˆ?span lang="EN-US">C</span>传递函æ•îC¾èµ–于<span lang="EN-US">A</span>。因此,满èƒö½W¬ä¸‰èŒƒå¼çš„æ•°æ®åº“表应该不存在如下依赖关系åQ?span lang="EN-US"><br> <br> </span>  关键字段<span lang="EN-US"> â†?</span>非关键字ŒD?span lang="EN-US">x â†?</span>非关键字ŒD?span lang="EN-US">y<br> <br> </span>ã€€ã€€å‡å®šå­¦ç”Ÿå…³ç³»è¡¨äØ“(f¨´)<span lang="EN-US">Student(</span>学号<span lang="EN-US">, </span>姓名<span lang="EN-US">, </span>òq´é¾„<span lang="EN-US">, </span>所在学é™?span lang="EN-US">, </span>学院地点<span lang="EN-US">, </span>学院ç”?sh¨´)è¯?span lang="EN-US">)</span>åQŒå…³é”®å­—为单一关键å­?span lang="EN-US">"</span>学号<span lang="EN-US">"</span>åQŒå› ä¸ºå­˜åœ¨å¦‚下决定关¾p»ï¼š(x¨¬)<span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(</span>学号<span lang="EN-US">) â†?(</span>姓名<span lang="EN-US">, </span>òq´é¾„<span lang="EN-US">, </span>所在学é™?span lang="EN-US">, </span>学院地点<span lang="EN-US">, </span>学院ç”?sh¨´)è¯?span lang="EN-US">)<br> <br> </span>  ˜q™ä¸ªæ•°æ®åº“是½W¦åˆ<span lang="EN-US">2NF</span>的,但是不符å?span lang="EN-US">3NF</span>åQŒå› ä¸ºå­˜åœ¨å¦‚下决定关¾p»ï¼š(x¨¬)<span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(</span>学号<span lang="EN-US">) â†?(</span>所在学é™?span lang="EN-US">) â†?(</span>学院地点<span lang="EN-US">, </span>学院ç”?sh¨´)è¯?span lang="EN-US">)<br> <br> </span>  卛_­˜åœ¨éžå…³é”®å­—段<span lang="EN-US">"</span>学院地点<span lang="EN-US">"</span>ã€?span lang="EN-US">"</span>学院ç”?sh¨´)è¯?span lang="EN-US">"</span>对关键字ŒD?span lang="EN-US">"</span>学号<span lang="EN-US">"</span>的传递函æ•îC¾èµ–ã€?span lang="EN-US"><br> <br> </span>  它也ä¼?x¨¬)存在数据冗余、更新异常、插入异常和删除异常的情况,读者可自行分析得知ã€?span lang="EN-US"><br> <br> </span>  把学生关¾p»è¡¨åˆ†äØ“(f¨´)如下两个表:(x¨¬)<span lang="EN-US"><br> <br> </span>  学生åQ?span lang="EN-US">(</span>学号<span lang="EN-US">, </span>姓名<span lang="EN-US">, </span>òq´é¾„<span lang="EN-US">, </span>所在学é™?span lang="EN-US">)</span>åQ?span lang="EN-US"><br> <br> </span>  学院åQ?span lang="EN-US">(</span>学院<span lang="EN-US">, </span>地点<span lang="EN-US">, </span>ç”?sh¨´)è¯?span lang="EN-US">)</span>ã€?span lang="EN-US"><br> <br> </span>  ˜q™æ ·çš„æ•°æ®åº“表是½W¦åˆ½W¬ä¸‰èŒƒå¼çš„,消除了数据冗余、更新异常、插入异常和删除异常ã€?span lang="EN-US"><br> <br> </span>  鲍依æ–?span lang="EN-US">-</span>¿U‘得范式åQ?span lang="EN-US">BCNF</span>åQ‰ï¼š(x¨¬)在第三范式的基础上,数据库表中如果不存在ä»ÖM½•字段对ä“Q一候选关键字ŒD늚„传递函æ•îC¾èµ–则½W¦åˆ½W¬ä¸‰èŒƒå¼ã€?span lang="EN-US"><br> <br> </span>  假设仓库½Ž¡ç†å…³ç³»è¡¨äØ“(f¨´)<span lang="EN-US">StorehouseManage(</span>仓库<span lang="EN-US">ID, </span>存储物品<span lang="EN-US">ID, </span>½Ž¡ç†å‘?span lang="EN-US">ID, </span>数量<span lang="EN-US">)</span>åQŒä¸”有一个管理员只在一个仓库工作;一个仓库可以存储多¿Uç‰©å“ã€‚这个数据库表中存在如下军_®šå…³ç³»åQ?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(</span>仓库<span lang="EN-US">ID, </span>存储物品<span lang="EN-US">ID) â†?</span>½Ž¡ç†å‘?span lang="EN-US">ID, </span>数量<span lang="EN-US">)<br> <br> </span>  <span lang="EN-US">(</span>½Ž¡ç†å‘?span lang="EN-US">ID, </span>存储物品<span lang="EN-US">ID) â†?(</span>仓库<span lang="EN-US">ID, </span>数量<span lang="EN-US">)<br> <br> </span>  所以,<span lang="EN-US">(</span>仓库<span lang="EN-US">ID, </span>存储物品<span lang="EN-US">ID)</span>å’?span lang="EN-US">(</span>½Ž¡ç†å‘?span lang="EN-US">ID, </span>存储物品<span lang="EN-US">ID)</span>都是<span lang="EN-US">StorehouseManage</span>的候选关键字åQŒè¡¨ä¸­çš„唯一非关键字ŒDµäØ“(f¨´)数量åQŒå®ƒæ˜¯ç¬¦åˆç¬¬ä¸‰èŒƒå¼çš„。但是,ç”׃ºŽå­˜åœ¨å¦‚下军_®šå…³ç³»åQ?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(</span>仓库<span lang="EN-US">ID) â†?(</span>½Ž¡ç†å‘?span lang="EN-US">ID)<br> <br> </span>  <span lang="EN-US">(</span>½Ž¡ç†å‘?span lang="EN-US">ID) â†?(</span>仓库<span lang="EN-US">ID)<br> <br> </span>  卛_­˜åœ¨å…³é”®å­—ŒDµå†³å®šå…³é”®å­—ŒD늚„情况åQŒæ‰€ä»¥å…¶ä¸ç¬¦å?span lang="EN-US">BCNF</span>范式。它ä¼?x¨¬)出现如下异常情况ï¼?x¨¬)<span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(1) </span>删除异常åQ?span lang="EN-US"><br> <br> </span>  当仓库被清空后,所æœ?span lang="EN-US">"</span>存储物品<span lang="EN-US">ID"</span>å’?span lang="EN-US">"</span>数量<span lang="EN-US">"</span>信息被删除的同时åQ?span lang="EN-US">"</span>仓库<span lang="EN-US">ID"</span>å’?span lang="EN-US">"</span>½Ž¡ç†å‘?span lang="EN-US">ID"</span>信息也被删除了ã€?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(2) </span>插入异常åQ?span lang="EN-US"><br> <br> </span>  当仓库没有存储ä“Q何物品时åQŒæ— æ³•给仓库分配½Ž¡ç†å‘˜ã€?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(3) </span>更新异常åQ?span lang="EN-US"><br> <br> </span>  如果仓库换了½Ž¡ç†å‘˜ï¼Œåˆ™è¡¨ä¸­æ‰€æœ‰è¡Œçš„管理员<span lang="EN-US">ID</span>都要修改ã€?span lang="EN-US"><br> <br> </span>  把仓库管理关¾p»è¡¨åˆ†è§£ä¸ÞZºŒä¸ªå…³¾p»è¡¨åQ?span lang="EN-US"><br> <br> </span>  仓库½Ž¡ç†åQ?span lang="EN-US">StorehouseManage(</span>仓库<span lang="EN-US">ID, </span>½Ž¡ç†å‘?span lang="EN-US">ID)</span>åQ?span lang="EN-US"><br> <br> </span>  仓库åQ?span lang="EN-US">Storehouse(</span>仓库<span lang="EN-US">ID, </span>存储物品<span lang="EN-US">ID, </span>数量<span lang="EN-US">)</span>ã€?span lang="EN-US"><br> <br> </span>  ˜q™æ ·çš„æ•°æ®åº“表是½W¦åˆ<span lang="EN-US">BCNF</span>范式的,消除了删除异常、插入异常和更新异常ã€?b><span lang="EN-US"><o:p></o:p></span></b></span></p> <p class="MsoNormal"><b><span style="font-family: 宋体;">范式应用<span lang="EN-US"><br> <br> </span></span></b><span style="font-family: 宋体;">  我们来逐步搞定一个论坛的数据库,有如下信息:(x¨¬)<span lang="EN-US"><br> <br> </span>  åQ?span lang="EN-US">1</span>åQ?用户åQšç”¨æˆ·ååQ?span lang="EN-US">email</span>åQŒä¸»™åµï¼Œç”?sh¨´)话åQŒè”¾pÕdœ°å€<span lang="EN-US"><br> <br> </span>  åQ?span lang="EN-US">2</span>åQ?帖子åQšå‘帖标题,发帖内容åQŒå›žå¤æ ‡é¢˜ï¼Œå›žå¤å†…容<span lang="EN-US"> <br> <br> </span>  ½W¬ä¸€‹Æ¡æˆ‘ä»¬å°†æ•°æ®åº“è®¾è®¡äØ“(f¨´)仅仅存在表:(x¨¬)<span lang="EN-US"><br> </span>  <span lang="EN-US"> <o:p></o:p></span></span></p> <div align="center"> <table class="MsoNormalTable" style="width: 90%;" border="1" cellpadding="0" cellspacing="0" width="90%"> <tbody><tr style=""> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">用户å?span lang="EN-US"> <o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US">email <o:p></o:p></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">主页<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">ç”?sh¨´)è¯?span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">联系地址<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">发帖标题<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">发帖内容<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">回复标题<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">回复内容<span lang="EN-US"><o:p></o:p></span></span></p> </td> </tr> </tbody></table> </div> <p class="MsoNormal" style="margin-bottom: 12pt;"><span style="font-family: 宋体;" lang="EN-US"><br> </span><span style="font-family: 宋体;">  ˜q™ä¸ªæ•°æ®åº“表½W¦åˆ½W¬ä¸€èŒƒå¼åQŒä½†æ˜¯æ²¡æœ‰ä“Q何一¾l„候选关键字能决定数据库表的整行åQŒå”¯ä¸€çš„关键字ŒD는¨æˆ·åä¹Ÿä¸èƒ½å®Œå…¨å†³å®šæ•´ä¸ªå…ƒ¾l„。我们需要增åŠ?span lang="EN-US">"</span>发帖<span lang="EN-US">ID"</span>ã€?span lang="EN-US">"</span>回复<span lang="EN-US">ID"</span>字段åQŒå³ž®†è¡¨ä¿®æ”¹ä¸ºï¼š(x¨¬)<span lang="EN-US"><o:p></o:p></span></span></p> <div align="center"> <table class="MsoNormalTable" style="width: 90%;" border="1" cellpadding="0" cellspacing="0" width="90%"> <tbody><tr style=""> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">用户å?span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US">email<o:p></o:p></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">主页<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">ç”?sh¨´)è¯?span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">联系地址<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">发帖<span lang="EN-US">ID<o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">发帖标题<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">发帖内容<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">回复<span lang="EN-US">ID<o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">回复标题<span lang="EN-US"><o:p></o:p></span></span></p> </td> <td style="padding: 1.5pt;"> <p class="MsoNormal"><span style="font-family: 宋体;">回复内容<span lang="EN-US"><o:p></o:p></span></span></p> </td> </tr> </tbody></table> </div> <p class="MsoNormal"><span style="font-family: 宋体;" lang="EN-US"><br> </span><span style="font-family: 宋体;">  ˜q™æ ·æ•°æ®è¡¨ä¸­çš„关键字<span lang="EN-US">(</span>用户名,发帖<span lang="EN-US">ID</span>åQŒå›žå¤?span lang="EN-US">ID)</span>能决定整行:(x¨¬)<span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(</span>用户å?span lang="EN-US">,</span>发帖<span lang="EN-US">ID,</span>回复<span lang="EN-US">ID) â†?(email,</span>主页<span lang="EN-US">,</span>ç”?sh¨´)è¯?span lang="EN-US">,</span>联系地址<span lang="EN-US">,</span>发帖标题<span lang="EN-US">,</span>发帖内容<span lang="EN-US">,</span>回复标题<span lang="EN-US">,</span>回复内容<span lang="EN-US">)<br> <br> </span>  但是åQŒè¿™æ ïL(f¨¥ng)š„è®¾è®¡ä¸ç¬¦åˆç¬¬äºŒèŒƒå¼ï¼Œå› äØ“(f¨´)存在如下军_®šå…³ç³»åQ?span lang="EN-US"><br> <br> </span>  <span lang="EN-US">(</span>用户å?span lang="EN-US">) â†?(email,</span>主页<span lang="EN-US">,</span>ç”?sh¨´)è¯?span lang="EN-US">,</span>联系地址<span lang="EN-US">)<br> <br> </span>  <span lang="EN-US">(</span>发帖<span lang="EN-US">ID) â†?(</span>发帖标题<span lang="EN-US">,</span>发帖内容<span lang="EN-US">)<br> <br> </span>  <span lang="EN-US">(</span>回复<span lang="EN-US">ID) â†?(</span>回复标题<span lang="EN-US">,</span>回复内容<span lang="EN-US">)<br> <br> </span>  即非关键字段部分函数依赖于候选关键字ŒDµï¼Œå¾ˆæ˜Žæ˜¾ï¼Œ˜q™ä¸ªè®¾è®¡ä¼?x¨¬)导致大量的数据冗余和操作异常ã€?span lang="EN-US"><br> <br> </span>  我们ž®†æ•°æ®åº“è¡¨åˆ†è§£äØ“(f¨´)åQˆå¸¦ä¸‹åˆ’¾U¿çš„为关键字åQ‰ï¼š(x¨¬)<span lang="EN-US"><br> <br> </span>  åQ?span lang="EN-US">1</span>åQ?用户信息åQšç”¨æˆ·ååQ?span lang="EN-US">email</span>åQŒä¸»™åµï¼Œç”?sh¨´)话åQŒè”¾pÕdœ°å€<span lang="EN-US"><br> <br> </span>  åQ?span lang="EN-US">2</span>åQ?帖子信息åQšå‘å¸?span lang="EN-US">ID</span>åQŒæ ‡é¢˜ï¼Œå†…容<span lang="EN-US"><br> <br> </span>  åQ?span lang="EN-US">3</span>åQ?回复信息åQšå›žå¤?span lang="EN-US">ID</span>åQŒæ ‡é¢˜ï¼Œå†…容<span lang="EN-US"><br> <br> </span>  åQ?span lang="EN-US">4</span>åQ?发脓(chu¨¤ng)åQšç”¨æˆ·ååQŒå‘å¸?span lang="EN-US">ID<br> <br> </span>  åQ?span lang="EN-US">5</span>åQ?回复åQšå‘å¸?span lang="EN-US">ID</span>åQŒå›žå¤?span lang="EN-US">ID<br> <br> </span>  ˜q™æ ·çš„设计是满èƒö½W?span lang="EN-US">1</span>ã€?span lang="EN-US">2</span>ã€?span lang="EN-US">3</span>范式å’?span lang="EN-US">BCNF</span>范式要求的,但是˜q™æ ·çš„设计是不是最好的呢?<span lang="EN-US"><br> <br> </span>  不一定ã€?span lang="EN-US"><br> <br> </span>   观察可知åQŒç¬¬<span lang="EN-US">4</span>™å?span lang="EN-US">"</span>发帖<span lang="EN-US">"</span>中的<span lang="EN-US">"</span>用户å?span lang="EN-US">"</span>å’?span lang="EN-US">"</span>发帖<span lang="EN-US">ID"</span>之间æ˜?span lang="EN-US">1</span>åQ?span lang="EN-US">N</span>的关¾p»ï¼Œå› æ­¤æˆ‘们可以æŠ?span lang="EN-US">"</span>发帖<span lang="EN-US">"</span>åˆåÆˆåˆ°ç¬¬<span lang="EN-US">2</span>™å¹çš„<span lang="EN-US">"</span>帖子信息<span lang="EN-US">"</span>中;½W?span lang="EN-US">5</span>™å?span lang="EN-US">"</span>回复<span lang="EN-US">"</span>中的<span lang="EN-US"> "</span>发帖<span lang="EN-US">ID"</span>å’?span lang="EN-US">"</span>回复<span lang="EN-US">ID"</span>之间也是<span lang="EN-US">1</span>åQ?span lang="EN-US">N</span>的关¾p»ï¼Œå› æ­¤æˆ‘们可以æŠ?span lang="EN-US">"</span>回复<span lang="EN-US">"</span>åˆåÆˆåˆ°ç¬¬<span lang="EN-US">3</span>™å¹çš„<span lang="EN-US">"</span>回复信息<span lang="EN-US">"</span>中。这样可以一定量地减ž®‘数据冗余,新的设计为:(x¨¬)<span lang="EN-US"><br> <br> </span>  åQ?span lang="EN-US">1</span>åQ?用户信息åQšç”¨æˆ·ååQ?span lang="EN-US">email</span>åQŒä¸»™åµï¼Œç”?sh¨´)话åQŒè”¾pÕdœ°å€<span lang="EN-US"><br> <br> </span>  åQ?span lang="EN-US">2</span>åQ?帖子信息åQšç”¨æˆ·ååQŒå‘å¸?span lang="EN-US">ID</span>åQŒæ ‡é¢˜ï¼Œå†…容<span lang="EN-US"><br> <br> </span>  åQ?span lang="EN-US">3</span>åQ?回复信息åQšå‘å¸?span lang="EN-US">ID</span>åQŒå›žå¤?span lang="EN-US">ID</span>åQŒæ ‡é¢˜ï¼Œå†…容<span lang="EN-US"><br> <br> </span>  数据库表<span lang="EN-US">1</span>昄¡„¶æ»¡èƒö所有范式的要求åQ?span lang="EN-US"><br> <br> </span>  数据库表<span lang="EN-US">2</span>中存在非关键字段<span lang="EN-US">"</span>标题<span lang="EN-US">"</span>ã€?span lang="EN-US">"</span>内容<span lang="EN-US">"</span>对关键字ŒD?span lang="EN-US">"</span>发帖<span lang="EN-US">ID"</span>的部分函æ•îC¾èµ–,即不满èƒö½W¬äºŒèŒƒå¼çš„要求,但是˜q™ä¸€è®¾è®¡òq¶ä¸ä¼?x¨¬)导致数据冗余和操作异常åQ?span lang="EN-US"><br> <br> </span>  数据库表<span lang="EN-US">3</span>中也存在非关键字ŒD?span lang="EN-US">"</span>标题<span lang="EN-US">"</span>ã€?span lang="EN-US">"</span>内容<span lang="EN-US">"</span>对关键字ŒD?span lang="EN-US">"</span>回复<span lang="EN-US">ID"</span>的部分函æ•îC¾èµ–,也不满èƒö½W¬äºŒèŒƒå¼çš„要求,但是与数据库è¡?span lang="EN-US">2</span>ç›æ€¼¼åQŒè¿™ä¸€è®¾è®¡ä¹Ÿä¸ä¼?x¨¬)导致数据冗余和操作异常ã€?span lang="EN-US"><br> <br> </span>  由此可以看出åQŒåÆˆä¸ä¸€å®šè¦å¼ø™¡Œæ»¡èƒö范式的要求,对于<span lang="EN-US">1</span>åQ?span lang="EN-US">N</span>关系åQŒå½“<span lang="EN-US">1</span>的一边合òq¶åˆ°<span lang="EN-US">N</span>的那边后åQ?span lang="EN-US">N</span>的那边就不再满èƒö½W¬äºŒèŒƒå¼äº†ï¼Œä½†æ˜¯˜q™ç§è®¾è®¡åè€Œæ¯”较好åQ?span lang="EN-US"><br> <br> </span>  对于<span lang="EN-US">M</span>åQ?span lang="EN-US">N</span>的关¾p»ï¼Œä¸èƒ½ž®?span lang="EN-US">M</span>一è¾ÒŽ(gu¨©)ˆ–<span lang="EN-US">N</span>一边合òq¶åˆ°å¦ä¸€è¾¹åŽ»åQŒè¿™æ ·ä¼š(x¨¬)坯D‡´ä¸ç¬¦åˆèŒƒå¼è¦æ±‚ï¼ŒåŒæ—¶å¯ÆD‡´æ“ä½œå¼‚常和数据冗余ã€?span lang="EN-US"> <br> </span>对于<span lang="EN-US">1</span>åQ?span lang="EN-US">1</span>的关¾p»ï¼Œæˆ‘们可以ž®†å·¦è¾¹çš„<span lang="EN-US">1</span>或者右边的<span lang="EN-US">1</span>åˆåÆˆåˆ°å¦ä¸€è¾¹åŽ»åQŒè®¾è®¡å¯¼è‡´ä¸½W¦åˆèŒƒå¼è¦æ±‚åQŒä½†æ˜¯åƈ不会(x¨¬)坯D‡´æ“ä½œå¼‚常和数据冗余ã€?span lang="EN-US"><br> <br> </span>  <b>¾l“论</b><span lang="EN-US"><br> <br> </span>  满èƒö范式要求的数据库设计是结构清晰的åQŒåŒæ—¶å¯é¿å…æ•°æ®å†—余和操作异常。这òq¶æ„å‘³ç€ä¸ç¬¦åˆèŒƒå¼è¦æ±‚的设计一定是错误的,在数据库表中存在<span lang="EN-US">1</span>åQ?span lang="EN-US">1</span>æˆ?span lang="EN-US">1</span>åQ?span lang="EN-US">N</span>关系˜q™ç§è¾ƒç‰¹ŒDŠçš„æƒ…å†µä¸‹ï¼ŒåˆåÆˆå¯ÆD‡´çš„不½W¦åˆèŒƒå¼è¦æ±‚反而是合理的ã€?span lang="EN-US"><br> <br> </span>  在我们设计数据库的时候,一定要时刻考虑范式的要求ã€?/span></p> <img src ="http://www.aygfsteel.com/DenisLing/aggbug/24725.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/DenisLing/" target="_blank">DenisLing</a> 2005-12-20 10:54 <a href="http://www.aygfsteel.com/DenisLing/archive/2005/12/20/24725.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对spring事务¾cÕdž‹è¯¦è§£çš„一点补充(关于嵌套事务åQ?/title><link>http://www.aygfsteel.com/DenisLing/archive/2005/12/19/extendsOfSpring.html</link><dc:creator>DenisLing</dc:creator><author>DenisLing</author><pubDate>Mon, 19 Dec 2005 08:02:00 GMT</pubDate><guid>http://www.aygfsteel.com/DenisLing/archive/2005/12/19/extendsOfSpring.html</guid><wfw:comment>http://www.aygfsteel.com/DenisLing/comments/24641.html</wfw:comment><comments>http://www.aygfsteel.com/DenisLing/archive/2005/12/19/extendsOfSpring.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.aygfsteel.com/DenisLing/comments/commentRss/24641.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/DenisLing/services/trackbacks/24641.html</trackback:ping><description><![CDATA[     摘要: 可能大家对PROPAGATION_NESTED˜q˜ä¸æ€Žä¹ˆäº†è§£åQŒè§‰å¾—有必要再补充一下^_^åQ?nbsp; <a href='http://www.aygfsteel.com/DenisLing/archive/2005/12/19/extendsOfSpring.html'>阅读全文</a><img src ="http://www.aygfsteel.com/DenisLing/aggbug/24641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/DenisLing/" target="_blank">DenisLing</a> 2005-12-19 16:02 <a href="http://www.aygfsteel.com/DenisLing/archive/2005/12/19/extendsOfSpring.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring事务¾cÕdž‹¼œ¥è§£http://www.aygfsteel.com/DenisLing/archive/2005/12/18/spring.htmlDenisLingDenisLingSun, 18 Dec 2005 08:30:00 GMThttp://www.aygfsteel.com/DenisLing/archive/2005/12/18/spring.htmlhttp://www.aygfsteel.com/DenisLing/comments/24503.htmlhttp://www.aygfsteel.com/DenisLing/archive/2005/12/18/spring.html#Feedback2http://www.aygfsteel.com/DenisLing/comments/commentRss/24503.htmlhttp://www.aygfsteel.com/DenisLing/services/trackbacks/24503.html

PROPAGATION_REQUIRED,readOnlyPROPAGATION_REQUIRED

估计有好多朋友还没有弄清楚里面的值的意思,仔细看完下面应该知道自己什么情况下面应该ä‹É用什么样的声明。^_^  é˜…读全文

DenisLing 2005-12-18 16:30 发表评论
]]>
spring声明式事务管理祥˜q?/title><link>http://www.aygfsteel.com/DenisLing/archive/2005/12/01/22096.html</link><dc:creator>DenisLing</dc:creator><author>DenisLing</author><pubDate>Thu, 01 Dec 2005 03:47:00 GMT</pubDate><guid>http://www.aygfsteel.com/DenisLing/archive/2005/12/01/22096.html</guid><wfw:comment>http://www.aygfsteel.com/DenisLing/comments/22096.html</wfw:comment><comments>http://www.aygfsteel.com/DenisLing/archive/2005/12/01/22096.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/DenisLing/comments/commentRss/22096.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/DenisLing/services/trackbacks/22096.html</trackback:ping><description><![CDATA[<p>Spring也提供了声明式事务管理。这是通过Spring AOP实现的ã€?/p><p>Spring 中进行事务管理的通常方式是利用AOPåQˆé¢å‘切片编½E‹ï¼‰çš„æ–¹å¼ï¼Œä¸ºæ™®é€šjava¾cÕd°è£…事务控åˆÓž¼Œå®ƒæ˜¯é€šè¿‡åŠ¨æ€ä»£ç†å®žçŽ°çš„åQŒç”±äºŽæŽ¥å£æ˜¯å»¶è¿Ÿå®žä¾‹åŒ–çš„åQ? spring在这ŒD‰|—¶é—´å†…é€šè¿‡æ‹¦æˆªå™¨ï¼ŒåŠ è²äº‹åŠ¡åˆ‡ç‰‡ã€‚åŽŸç†å°±æ˜¯è¿™æ øP¼Œå…·ä½“¾l†èŠ‚è¯·å‚è€ƒjdk中有兛_Š¨æ€ä»£ç†çš„æ–‡æ¡£ã€‚æœ¬æ–‡ä¸»è¦è®²è§£å¦‚ä½•åœ¨spring中进行事 务控制ã€?br>动态代理的一个重要特征是åQŒå®ƒæ˜¯é’ˆå¯ÒŽ(gu¨©)Ž¥å£çš„åQŒæ‰€ä»¥æˆ‘们的dao要通过动态代理来让spring接管事务åQŒå°±å¿…须在dao前面抽象å‡ÞZ¸€ä¸ªæŽ¥å£ï¼Œå½“然如果没有˜q™æ ·çš„æŽ¥å£ï¼Œé‚£ä¹ˆspringä¼?x¨¬)ä‹É用CGLIB来解决问题,但这不是spring推荐的方式,所以不做讨è®?</p><p><i><span id="wmqeeuq" class="remark">大多数Spring用户选择声明式事务管理。这是最ž®‘媄响应用代码的选择åQ?因而这是和<span id="wmqeeuq" class="emphasis"><em>非äçRå…¥æ€?/em></span>的轻量çñ”容器的观忉|˜¯ä¸€è‡´çš„ã€?</span></i></p><p>从考虑EJB CMTå’ŒSpringå£°æ˜Žå¼äº‹åŠ¡ç®¡ç†çš„ç›æ€¼¼ä»¥åŠä¸åŒä¹‹å¤„出发是很有益的ã€?å®ƒä»¬çš„åŸºæœ¬æ–¹æ³•æ˜¯ç›æ€¼¼çš„:(x¨¬)都可以指定事务管理到单独的方法;如果需要可以在事务ä¸?下文调用<tt class="literal"><font face="新宋ä½?>setRollbackOnly()</font></tt>æ–ÒŽ(gu¨©)³•。不同之处如下:(x¨¬)</p><div id="wmqeeuq" class="itemizedlist"><ul type="disc"><li><p>不象EJB CMT¾l‘定在JTA上,Spring声明式事务管理可以在ä»ÖM½•环境下ä‹É用ã€?只需更改配置文äšgåQŒå®ƒ?y¨­u)®±å¯ä»¥å’ŒJDBC、JDO、Hibernate或其他的事务机制一起工ä½?</p></li><li><p>Spring可以使声明式事务½Ž¡ç†åº”用到普通Java对象åQŒä¸ä»…仅是特ŒDŠçš„¾c»ï¼Œå¦‚EJB</p></li><li><p>Spring提供声明å¼?span class="emphasis"><em>回滚规则</em></span>åQšEJB没有对应的特性, 我们ž®†åœ¨ä¸‹é¢è®¨è®º˜q™ä¸ªç‰ÒŽ(gu¨©)€§ã€‚回滚可以声明式控制åQŒä¸ä»…仅是编½E‹å¼çš?</p></li><li><p>Spring允许你通过AOPå®šåˆ¶äº‹åŠ¡è¡ŒäØ“(f¨´)。例如,如果需要,你可以在事务 å›žæ»šä¸­æ’å…¥å®šåˆ¶çš„è¡ŒäØ“(f¨´)。你也可以增加ä“Q意的通知åQŒå°±è±¡äº‹åŠ¡é€šçŸ¥ä¸€æ —÷€‚ä‹Éç”?EJB CMTåQŒé™¤äº†ä‹Éç”?tt class="literal"><font face="新宋ä½?>setRollbackOnly()</font></tt>åQŒä½ æ²¡æœ‰åŠžæ³•èƒ?够媄响容器的事务½Ž¡ç†</p></li><li><p>Spring不提供高端应用服务器提供的跨­‘Šè¿œ½E‹è°ƒç”¨çš„事务上下文传播。如 果你需要这些特性,我们推荐你ä‹É用EJB。然而,不要è½ÀL˜“使用˜q™äº›ç‰ÒŽ(gu¨©)€§ã€‚通常æˆ?ä»¬åÆˆä¸å¸Œæœ›äº‹åŠ¡è·¨­‘Šè¿œ½E‹è°ƒç”?/p></li></ul></div><p>回滚规则的概忉|˜¯å¾ˆé‡è¦çš„åQšå®ƒä»¬ä‹É得我们可以指定哪些异常应该发赯‚‡ª 动回滚。我们在配置文äšg中,而不是Java代码中,以声明的方式指定。因此,虽然我们ä»?然可以编½E‹è°ƒç”?tt class="literal"><font face="新宋ä½?>TransactionStatus</font></tt>对象çš?<tt class="literal"><font face="新宋ä½?>setRollbackOnly()</font></tt>æ–ÒŽ(gu¨©)³•来回滚当前事务,多数时候我们可ä»?指定规则åQŒå¦‚<tt class="literal"><font face="新宋ä½?>MyApplicationException</font></tt>åº”è¯¥å¯ÆD‡´å›žæ»šã€?˜q™æœ‰æ˜¾è‘—的优点,业务对象不需要依赖事务基¼‹€è®¾æ–½ã€‚例如,它们通常不需要引 å…¥ä“Q何Spring APIåQŒäº‹åŠ¡æˆ–å…¶ä»–ä»ÖM½•东西ã€?/p><p>EJB的默认行为是遇到<span id="wmqeeuq" class="emphasis"><em>¾pȝ»Ÿå¼‚常</em></span>åQˆé€šå¸¸æ˜¯è¿è¡Œæ—¶å¼‚常åQ‰ï¼Œ EJB容器自动回滚事务。EJB CMT遇到<span id="wmqeeuq" class="emphasis"><em>应用½E‹åºå¼‚常</em></span> åQˆé™¤äº?span class="emphasis"><em>java.rmi.RemoteException</em></span>外的checked异常åQ‰æ—¶ä¸?ä¼?x¨¬)自动回滚事务。虽然Spring声明式事务管理沿用EJB的约定(遇到unchecked 异常自动回滚事务åQ‰ï¼Œä½†æ˜¯˜q™æ˜¯å¯ä»¥å®šåˆ¶çš„ã€?/p><p>按照我们的测试,Spring声明式事务管理的性能要胜˜q‡EJB CMTã€?/p><p>é€? 帔R€šè¿‡TransactionProxyFactoryBean讄¡½®Spring事务代理。我们需 要一个目标对象包装在事务代理中。这个目标对象一般是一个普通Java对象的bean。当æˆ? 们定义TransactionProxyFactoryBeanæ—Óž¼Œå¿…须提供一个相关的 PlatformTransactionManager的引用和<span id="wmqeeuq" class="bold"><b>事务属æ€?/b></span>ã€?<span id="wmqeeuq" class="bold"><b>事务属æ€?/b></span>含有上面描述的事务定义ã€?/p><pre class="programlisting"><bean id="petStore" <br> class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><br> <property name="transactionManager"><ref bean="transactionManager"/></property><br> <property name="target"><ref bean="petStoreTarget"/></property><br> <property name="transactionAttributes"><br> <props><br> <prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop><br> <prop key="update*">PROPAGATION_REQUIRED</prop><br> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop><br> </props><br> </property><br></bean></pre><p>äº? 务代理会(x¨¬)实现目标对象的接口:(x¨¬)˜q™é‡Œæ˜¯id为petStoreTargetçš„bean。(使用 CGLIB也可以实现具体类的代理。只要设¾|®proxyTargetClasså±žæ€§äØ“(f¨´)truež®±å¯ä»¥ã€? 如果目标对象没有实现ä»ÖM½•接口åQŒè¿™ž®†è‡ªåŠ¨è®¾¾|®è¯¥å±žæ€§äØ“(f¨´)true。通常åQŒæˆ‘们希望面向接口而不æ˜? ¾cȝ¼–½E‹ã€‚)使用proxyInterfaces属性来限定事务代理来代 理指定接口也是可以的åQˆä¸€èˆ¬æ¥è¯´æ˜¯ä¸ªå¥½æƒÏx³•åQ‰ã€‚也可以通过ä»?<tt class="literal"><font face="新宋ä½?>org.springframework.aop.framework.ProxyConfig</font></tt>¾l§æ‰¿æˆ–所有AOP代理工厂å…׃ín 的属性来定制TransactionProxyFactoryBean的行为ã€?</p><p>˜q™é‡Œçš„transactionAttributes属性定义在 <tt class="literal"><font face="新宋ä½?>org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource</font></tt> 中的属性格式来讄¡½®ã€‚这个包括通配½W¦çš„æ–ÒŽ(gu¨©)³•名称映射是很直观的。注æ„?insert*的映ž®„的值包括回滚规则。添加的<tt class="literal"><font face="新宋ä½?>-MyCheckedException</font></tt> 指定如果æ–ÒŽ(gu¨©)³•抛出<tt class="literal"><font face="新宋ä½?>MyCheckedException</font></tt>或它的子¾c»ï¼Œäº‹åŠ¡ž®?ä¼?x¨¬)自动回滚。可以用逗号分隔定义多个回滚规则ã€?font color="#ff0000"><strong>-前缀强制回滚åQ?前缀指定提交</strong></font>åQˆè¿™å…è®¸å³ä‹É抛出unchecked异常时也可以提交事务åQŒå½“然你自己要明白自å·?在做什么)ã€?/p><p><tt class="literal"><font face="新宋ä½?>TransactionProxyFactoryBean</font></tt>允许你通过 “preInterceptors”和“postInterceptors”属性设¾|®â€œå‰â€æˆ–“后”通知来提供额外的 æ‹¦æˆªè¡ŒäØ“(f¨´)。可以设¾|®ä“Q意数量的“前”和“后”通知åQŒå®ƒä»¬çš„¾cÕdž‹å¯ä»¥æ˜?<tt class="literal"><font face="新宋ä½?>Advisor</font></tt>åQˆå¯ä»¥åŒ…含一个切入点åQ‰ï¼Œ <tt class="literal"><font face="新宋ä½?>MethodInterceptor</font></tt>或被当前Spring配置支持的通知¾cÕdž‹ åQˆä¾‹å¦?tt class="literal"><font face="新宋ä½?>ThrowAdvice</font></tt>åQ?<tt class="literal"><font face="新宋ä½?>AfterReturningtAdvice</font></tt>æˆ?tt class="literal"><font face="新宋ä½?>BeforeAdvice</font></tt>åQ?˜q™äº›éƒ½æ˜¯é»˜è®¤æ”¯æŒçš„)。这些通知必须支持实例å…׃ín模式。如果你需要高¾U§AOPç‰?性来使用事务åQŒå¦‚有状态的maxinåQŒé‚£æœ€å¥½ä‹É用通用çš?<tt class="literal"><font face="新宋ä½?>org.springframework.aop.framework.ProxyFactoryBean</font></tt>åQ?而不æ˜?tt class="literal"><font face="新宋ä½?>TransactionProxyFactoryBean</font></tt>实用代理创徏者ã€?/p><p>也可以设¾|®è‡ªåŠ¨ä»£ç†ï¼š(x¨¬)配置AOP框架åQŒä¸éœ€è¦å•独的代理定义¾cÕd°±å¯ä»¥ç”Ÿæˆ¾cȝš„ 代理ã€?/p>附两个spring的事务配¾|®ä¾‹å­ï¼š(x¨¬)<br><prop key="add"><br>     PROPAGATION_REQUIRES_NEW, -MyException <br></prop><br>注:(x¨¬)上面的意思是addæ–ÒŽ(gu¨©)³•ž®†ç‹¬å ä¸€ä¸ªäº‹åŠ¡ï¼Œå½“äº‹åŠ¡å¤„ç†è¿‡½E‹ä¸­äº§ç”ŸMyException异常或者该异常的子¾cÕd°†å›žæ»šè¯¥äº‹åŠ¡ã€?br><br><prop key="loadAll"><br>    PROPAGATION_SUPPORTS, ISOLATION_READ_COMMITED, Readonly<br></prop><br>注:(x¨¬)表示loadAllæ–ÒŽ(gu¨©)³•支持事务åQŒè€Œä¸”不会(x¨¬)è¯Õd–æ²¡æœ‰æäº¤äº‹åŠ¡çš„æ•°æ®ã€‚å®ƒçš„æ•°æ®äØ“(f¨´)只读åQˆè¿™æ ähœ‰åŠ©äºŽæé«˜è¯Õd–的性能åQ?br><br>附A Spring中的所有事务策ç•?br><br>PROPAGATION_MANDATORY<br>PROPAGATION_NESTED <br>PROPAGATION_NEVER <br>PROPAGATION_NOT_SUPPORTED<br>PROPAGATION_REQUIRED<br>PROPAGATION_REQUIRED_NEW<br>PROPAGATION_SUPPORTS<br><br>附B Spring中所有的隔离½{–ç•¥åQ?br><br>ISOLATION_DEFAULT<br>ISOLATION_READ_UNCOMMITED<br>ISOLATION_COMMITED<br>ISOLATION_REPEATABLE_READ<br>ISOLATION_SERIALIZABLE<img src ="http://www.aygfsteel.com/DenisLing/aggbug/22096.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/DenisLing/" target="_blank">DenisLing</a> 2005-12-01 11:47 <a href="http://www.aygfsteel.com/DenisLing/archive/2005/12/01/22096.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>webwork开发团队加入StrutsåQˆåƒæƒŠï¼‰http://www.aygfsteel.com/DenisLing/archive/2005/11/28/21596.htmlDenisLingDenisLingMon, 28 Nov 2005 00:47:00 GMThttp://www.aygfsteel.com/DenisLing/archive/2005/11/28/21596.htmlhttp://www.aygfsteel.com/DenisLing/comments/21596.htmlhttp://www.aygfsteel.com/DenisLing/archive/2005/11/28/21596.html#Feedback6http://www.aygfsteel.com/DenisLing/comments/commentRss/21596.htmlhttp://www.aygfsteel.com/DenisLing/services/trackbacks/21596.html早上一˜q‡æ¥çœ‹åˆ°ä¸‹é¢çš„æ–°é—ÀL„Ÿè§‰æƒŠè®¶çš„要死åQä¸çŸ¥é“和我一样在strutså’Œwebwork之间一直在徘徊的朋友们看了ç”׃»€ä¹ˆæ„Ÿè§‰ã€‚本来我的态度是想慢慢攑ּƒstruts的…â€?看样子要重新看待struts了。原文如下:(x¨¬)

WebWork joining Struts


Yes, . The WebWork development team (Jason and I) have been working with the Struts development team (Don Brown and Ted Husted) and have come to the conclusion that the best thing for Java community would be to merge WebWork in to Struts.

Read Ted's email here, but the gist of it is this: WebWork is a great technology, and Struts is a great community. It's a perfect match and bringing the two together will only be better for WebWork and Struts users alike. The only down side for me is that I'll be working less with OpenSymphony, but I believe that is a small price for all the great benefits that come from this merger.

Just to be clear, WebWork is not going away. WebWork 2.2 is still coming out any day now, and there may even be a WebWork 2.3. But new minor/major versions won't be coming out under the WebWork name for much longer. Instead, they will be released under the Struts incubator program with the intent to eventually become Struts Action Framework 2.0.

So don't worry, WebWork 2.1.8, 2.2.1, and other bug fix releases will continue to come out and we will support the WebWork community as long as needed. In addition, we'll make compatibility with both Struts and WebWork a high priority, so future releases may help with that. To be clear: no one is leaving WebWork and it will continue to be supported for a very long time.

With this renewed energy, larger development team, and larger community, the combined efforts of Struts and WebWork will surely make the Struts platform the easiest, fastest, and most powerful Java web framework available. We hope that all the WebWork users and developers are as excited about this as we are and are ready to take WebWork to the next level.

原文地址åQšhttp://www.opensymphony.com/webwork/

以前一直在strutså’Œwebwork之间犹èõUåQŒçœ‹æ¥struts气数未尽呀。apache¾l„织˜q˜æ˜¯æ¯”较只值得信赖的。呵å‘?



DenisLing 2005-11-28 08:47 发表评论
]]>
自定义标½{¾èŽ·å–struts中action的全部èµ\径(原创åQ?/title><link>http://www.aygfsteel.com/DenisLing/archive/2005/11/21/20781.html</link><dc:creator>DenisLing</dc:creator><author>DenisLing</author><pubDate>Mon, 21 Nov 2005 07:52:00 GMT</pubDate><guid>http://www.aygfsteel.com/DenisLing/archive/2005/11/21/20781.html</guid><wfw:comment>http://www.aygfsteel.com/DenisLing/comments/20781.html</wfw:comment><comments>http://www.aygfsteel.com/DenisLing/archive/2005/11/21/20781.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.aygfsteel.com/DenisLing/comments/commentRss/20781.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/DenisLing/services/trackbacks/20781.html</trackback:ping><description><![CDATA[      ç”׃ºŽ™å¹ç›®é‡Œé¢ç”±éœ€è¦ä¸€ä¸ªform可以提交多个actionåQˆæœ¬æ¥å¯ä»¥ç”¨ dispatch值来实现åQŒåŽæ¥è€ƒè™‘到要使用validator框架验证åQ‰ã€‚åŽæ¥è€ƒè™‘çš„æ–¹æ¡ˆäØ“(f¨´)使用js来控制form的流向,例如<br>        <div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 0);">form.action</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">'/bookstore/checkId.</span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);">'</span></div> <br> 不过新的问题来了åQå¦‚何能不用hardcode而拿到我要的action的实际èµ\径呢åQŸæ¯”如我定义的struts-configæ–‡äšg里面的actionæ˜?nbsp; <br> <div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 0);">path</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">/checkId</span><span style="color: rgb(0, 0, 0);">"</span></div> 但是实际解释后的path是:(x¨¬)<br> <div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 0);">actionåQ?</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">bookstore</span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);">checkId.</span><span style="color: rgb(0, 0, 255);">do</span><span style="color: rgb(0, 0, 0);">'</span></div> å‰? ¾~€å’ŒåŽé¢çš„后缀.do都是æ ÒŽ(gu¨©)®ä½ çš„™å¹ç›®éƒ¨çÖvçš„èµ\径和你在web.xml中配¾|®çš„mapping的后¾~€æœ‰å…³¾p»ï¼Œå¦‚果我把内容写死到jsp中那以后我要是想æŠ? checkId.doæ”ÒŽ(gu¨©)ˆcheckId.action那就要更改jspåQŒç”±äºŽstruts本来提供的几个taglib里面çš?br> <br> <div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 0);"><</span><span style="color: rgb(0, 0, 0);">html:form action</span><span style="color: rgb(0, 0, 0);">="</span><span style="color: rgb(0, 0, 0);">/checkId"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">></span></div> <br> ¾l¼åˆäº†ä¸€ä¸‹å†³å®šè¿˜æ˜¯è‡ªå·±å†™ä¸ªtaglib来实玎ͼŒå…¶å®žåªéœ€è¦ç…§ç€struts 中的 FormTag.java æ–‡äšgä¾è‘«èŠ¦ç”»ç“¢å°±å¯ä»¥äº†ï¼Œä¸€ä¸‹äØ“(f¨´)本äh的代码部åˆ?br> <br> StrutsActionCustomTag.java<br> <div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);"> com.denis.framework.common.taglib.strutsActionExt;<br><br></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> javax.servlet.http.HttpServletResponse;<br></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> javax.servlet.jsp.JspException;<br></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> javax.servlet.jsp.tagext.TagSupport;<br><br></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> org.apache.struts.taglib.TagUtils;<br><br><img id="Codehighlighter1_288_1030_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_288_1030_Closed_Text.style.display='none'; Codehighlighter1_288_1030_Open_Image.style.display='inline'; Codehighlighter1_288_1030_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> StrutsActionCustomTag </span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);"> TagSupport </span><span id="Codehighlighter1_288_1030_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_288_1030_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><br>    </span><span style="color: rgb(0, 0, 255);">protected</span><span style="color: rgb(0, 0, 0);"> String actionName </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br>    <br><img id="Codehighlighter1_370_394_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_370_394_Closed_Text.style.display='none'; Codehighlighter1_370_394_Open_Image.style.display='inline'; Codehighlighter1_370_394_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> String getActionName() </span><span id="Codehighlighter1_370_394_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_370_394_Open_Text"><span style="color: rgb(0, 0, 0);">{<br>        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> actionName;<br>    }</span></span><span style="color: rgb(0, 0, 0);"><br><br><img id="Codehighlighter1_443_478_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_443_478_Closed_Text.style.display='none'; Codehighlighter1_443_478_Open_Image.style.display='inline'; Codehighlighter1_443_478_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setActionName(String actionName) </span><span id="Codehighlighter1_443_478_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_443_478_Open_Text"><span style="color: rgb(0, 0, 0);">{<br>        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.actionName </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> actionName;<br>    }</span></span><span style="color: rgb(0, 0, 0);"><br><br><img id="Codehighlighter1_526_934_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_526_934_Closed_Text.style.display='none'; Codehighlighter1_526_934_Open_Image.style.display='inline'; Codehighlighter1_526_934_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> doStartTag() </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> JspException </span><span id="Codehighlighter1_526_934_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_526_934_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><br>        StringBuffer results </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> StringBuffer();<br>        HttpServletResponse response </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"><br>            (HttpServletResponse) </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.pageContext.getResponse();<br>        <br>        results.append(response.encodeURL( TagUtils.getInstance().getActionMappingURL( </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.actionName , </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.pageContext)) );<br><br>        TagUtils.getInstance().write(pageContext, results.toString());<br><br>        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> (EVAL_BODY_INCLUDE);<br>    }</span></span><span style="color: rgb(0, 0, 0);"><br><br><img id="Codehighlighter1_963_1028_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_963_1028_Closed_Text.style.display='none'; Codehighlighter1_963_1028_Open_Image.style.display='inline'; Codehighlighter1_963_1028_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> release() </span><span id="Codehighlighter1_963_1028_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_963_1028_Open_Text"><span style="color: rgb(0, 0, 0);">{<br>        </span><span style="color: rgb(0, 0, 255);">super</span><span style="color: rgb(0, 0, 0);">.release();<br>        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.actionName </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);"> ;<br><br>    }</span></span><span style="color: rgb(0, 0, 0);"><br>}</span></span></div> <br> <br> tld定义部分<br> <br> framework-struts.tld<br> <div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 255);"><?</span><span style="color: rgb(255, 0, 255);">xml version="1.0" encoding="UTF-8"</span><span style="color: rgb(0, 0, 255);">?></span><span style="color: rgb(0, 0, 0);"><br><br></span><span style="color: rgb(0, 0, 255);"><!</span><span style="color: rgb(255, 0, 255);">DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">taglib</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><br></span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">tlibversion</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">1.0</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">tlibversion</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">    <</span><span style="color: rgb(128, 0, 0);">jspversion</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">1.1</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">jspversion</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">    <</span><span style="color: rgb(128, 0, 0);">shortname</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">framework</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">shortname</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">    <</span><span style="color: rgb(128, 0, 0);">uri</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">http://www.denisFramework.org/Framework-Tag</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">uri</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">    <</span><span style="color: rgb(128, 0, 0);">tag</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">    <</span><span style="color: rgb(128, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">getActionUrl</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">    <</span><span style="color: rgb(128, 0, 0);">tagclass</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">com.denis.framework.common.taglib.strutsActionExt.StrutsActionCustomTag</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">tagclass</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">    <</span><span style="color: rgb(128, 0, 0);">bodycontent</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">empty</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">bodycontent</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">    <</span><span style="color: rgb(128, 0, 0);">attribute</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">         <</span><span style="color: rgb(128, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">actionName</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">         <</span><span style="color: rgb(128, 0, 0);">required</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">true</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">required</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">         <</span><span style="color: rgb(128, 0, 0);">rtexprvalue</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">true</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">rtexprvalue</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">    </</span><span style="color: rgb(128, 0, 0);">attribute</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">tag</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><br></span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">taglib</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><br><br> </span></div> <br> ok ! 直接在jsp中如下ä‹É用即可取到action的真正èµ\å¾?br> <br> <div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><span style="color: rgb(0, 0, 0);"> <br><img id="Codehighlighter1_4_25_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_4_25_Closed_Text.style.display='none'; Codehighlighter1_4_25_Open_Image.style.display='inline'; Codehighlighter1_4_25_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 0);"><%</span><span id="Codehighlighter1_4_25_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_4_25_Open_Text"><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">@ page language</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">=</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">java</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span></span><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 0);">%></span><span style="color: rgb(0, 0, 0);"><br><img id="Codehighlighter1_31_101_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_31_101_Closed_Text.style.display='none'; Codehighlighter1_31_101_Open_Image.style.display='inline'; Codehighlighter1_31_101_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 0);"><%</span><span id="Codehighlighter1_31_101_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_31_101_Open_Text"><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">@ taglib uri</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">=</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">http://jakarta.apache.org/struts/tags-bean</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"> prefix</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">=</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">bean</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span></span><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 0);">%></span><span style="color: rgb(0, 0, 0);"> <br><img id="Codehighlighter1_108_178_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_108_178_Closed_Text.style.display='none'; Codehighlighter1_108_178_Open_Image.style.display='inline'; Codehighlighter1_108_178_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 0);"><%</span><span id="Codehighlighter1_108_178_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_108_178_Open_Text"><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">@ taglib uri</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">=</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">http://jakarta.apache.org/struts/tags-html</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"> prefix</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">=</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">html</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span></span><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 0);">%></span><span style="color: rgb(0, 0, 0);"><br><img id="Codehighlighter1_184_247_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_184_247_Closed_Text.style.display='none'; Codehighlighter1_184_247_Open_Image.style.display='inline'; Codehighlighter1_184_247_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 0);"><%</span><span id="Codehighlighter1_184_247_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_184_247_Open_Text"><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">@ taglib uri</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">=</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">/WEB-INF/framework-struts.tld</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"> prefix</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">=</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">framework</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);">"</span><span style="color: rgb(0, 0, 0); background-color: rgb(245, 245, 245);"> </span></span><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 0);">%></span><span style="color: rgb(0, 0, 0);"><br> <br></span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">html</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"> <br>    </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">head</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br>        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">title</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);">JSP for loginForm form</span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">title</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br>    </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">head</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br>    </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">body</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br>        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">framework:getActionUrl </span><span style="color: rgb(255, 0, 0);">actionName</span><span style="color: rgb(0, 0, 255);">="login"</span><span style="color: rgb(255, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br>        </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">html:form </span><span style="color: rgb(255, 0, 0);">action</span><span style="color: rgb(0, 0, 255);">="/login"</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br>            name : </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">html:text </span><span style="color: rgb(255, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">="name"</span><span style="color: rgb(0, 0, 255);">/><</span><span style="color: rgb(128, 0, 0);">html:errors </span><span style="color: rgb(255, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">="name"</span><span style="color: rgb(0, 0, 255);">/><</span><span style="color: rgb(128, 0, 0);">br</span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br>            password : </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">html:password </span><span style="color: rgb(255, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">="password"</span><span style="color: rgb(0, 0, 255);">/><</span><span style="color: rgb(128, 0, 0);">html:errors </span><span style="color: rgb(255, 0, 0);">property</span><span style="color: rgb(0, 0, 255);">="password"</span><span style="color: rgb(0, 0, 255);">/><</span><span style="color: rgb(128, 0, 0);">br</span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br>            </span><span style="color: rgb(0, 0, 255);"><</span><span style="color: rgb(128, 0, 0);">html:submit</span><span style="color: rgb(0, 0, 255);">/><</span><span style="color: rgb(128, 0, 0);">html:cancel</span><span style="color: rgb(0, 0, 255);">/></span><span style="color: rgb(0, 0, 0);"><br>        </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">html:form</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br>    </span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">body</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);"></</span><span style="color: rgb(128, 0, 0);">html</span><span style="color: rgb(0, 0, 255);">></span><span style="color: rgb(0, 0, 0);"><br><br> </span></div> <br> <br> 大家要是有更好的解决æ–ÒŽ(gu¨©)³•希望能指正!谢谢åQ?img src ="http://www.aygfsteel.com/DenisLing/aggbug/20781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/DenisLing/" target="_blank">DenisLing</a> 2005-11-21 15:52 <a href="http://www.aygfsteel.com/DenisLing/archive/2005/11/21/20781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 Spring 更好地处ç?Struts 动作 (转自ibm 个äh感觉受益非浅)http://www.aygfsteel.com/DenisLing/archive/2005/11/21/20779.htmlDenisLingDenisLingMon, 21 Nov 2005 07:42:00 GMThttp://www.aygfsteel.com/DenisLing/archive/2005/11/21/20779.htmlhttp://www.aygfsteel.com/DenisLing/comments/20779.htmlhttp://www.aygfsteel.com/DenisLing/archive/2005/11/21/20779.html#Feedback2http://www.aygfsteel.com/DenisLing/comments/commentRss/20779.htmlhttp://www.aygfsteel.com/DenisLing/services/trackbacks/20779.htmlStruts Recipes 的合著è€?George Franciscus ž®†ä»‹¾lå¦ä¸€ä¸ªé‡å¤§çš„ Struts 整合½Hé—¨ —â€?˜q™æ¬¡æ˜¯å°† Struts 应用½E‹åºå¯¼å…¥ Spring 框架。请跟随 GeorgeåQŒä»–ž®†å‘æ‚(zh¨¨n)¨å±•½Cºå¦‚何改å? Struts 动作åQŒä‹É得管ç?Struts 动作ž®±åƒ½Ž¡ç† Spring beans 那样。结果是一个增强的 web 框架åQŒè¿™ä¸ªæ¡†æž¶å¯ä»¥æ–¹ä¾¿åœ°åˆ©ç”¨ Spring AOP 的优åŠÑ€?/font>

æ‚(zh¨¨n)¨è‚¯å®šå·²¾lå¬è¯´è¿‡æŽ§åˆ¶åè{ (IOC) 设计模式åQŒå› ä¸ºå¾ˆé•¿ä¸€ŒD‰|—¶é—´ä»¥æ¥ä¸€ç›´åœ¨‹¹ä¼ å…³äºŽå®ƒçš„信息。如果æ?zh¨¨n)¨åœ¨ä“Q何功能中使用˜q?Spring 框架åQŒé‚£ä¹ˆæ?zh¨¨n)¨ž®ÞqŸ¥é“其原理的作用。在本文中,我利用这一原理把一ä¸?Struts 应用½E‹åºæ³¨å…¥ Spring 框架åQŒæ?zh¨¨n)¨ž®†äº²íw«ä½“ä¼?x¨¬)åˆ?IOC 模式的强大ã€?/font>

ž®†ä¸€ä¸?Struts 应用½E‹åºæ•´åˆ˜q?Spring 框架å…ähœ‰å¤šæ–¹é¢çš„优点。首先,Spring æ˜¯äØ“(f¨´)解决一些关äº? JEE 的真实世界问题而设计的åQŒæ¯”如复杂性、低性能和可‹¹‹è¯•性,½{‰ç­‰ã€‚第二,Spring 框架包含一ä¸?AOP 实现åQŒå…è®¸æ?zh¨¨n)¨ž®†é¢å‘方面技术应用于面向对象的代码。第三,一些äh可能ä¼?x¨¬)è¯?Spring 框架只有处理 Struts æ¯?Struts 处理自己好。但是这是观炚w—®é¢˜ï¼Œæˆ‘æ¼”½CÞZ¸‰¿Uå°† Struts 应用½E‹åºæ•´åˆåˆ?Spring 框架的方法后åQŒå…·ä½“ç”±æ‚(zh¨¨n)¨è‡ªå·±å†³å®šä‹É用哪一¿Uã€?/font>

我所演示的方法都是执行è“v来相对简单的åQŒä½†æ˜¯å®ƒä»¬å´å…ähœ‰æ˜Žæ˜¾ä¸åŒçš„优炏V€‚我为每一¿Uæ–¹æ³•创å»ÞZº†ä¸€ä¸ªç‹¬ç«‹è€Œå¯ç”¨çš„例子åQŒè¿™æ äh‚¨ž®±å¯ä»¥å®Œå…¨ç†è§£æ¯¿Uæ–¹æ³•ã€? 请参é˜?下蝲 部分获得完整例子源代码。请参阅 参考资æ–?/a>åQŒä¸‹è½?Struts MVC å’?Spring 框架ã€?/font>

ä¸ÞZ»€ä¹?Spring ˜q™ä¹ˆäº†ä¸èµøP¼Ÿ

Spring 的创立è€?Rod Johnson 以一¿Uæ‰¹åˆ¤çš„眼光看待 Javaâ„?企业软äšg开发,òq¶ä¸”提议很多企业éšùN¢˜éƒ½èƒ½å¤Ÿé€šè¿‡æˆ˜ç•¥åœîC‹Éç”?IOC 模式åQˆä¹Ÿ¿UîC½œä¾èµ–注入åQ‰æ¥è§£å†³ã€‚当 Rod 和一个具有奉献精¼œžçš„开放源码开发者团队将˜q™ä¸ªç†è®ºåº”用于实跉|—¶åQŒç»“果就产生äº?Spring 框架。简­a€ä¹‹ï¼ŒSpring 是一个轻型的容器åQŒåˆ©ç”¨å®ƒå¯ä»¥ä½¿ç”¨ä¸€ä¸ªå¤–éƒ?XML 配置文äšg方便地将对象˜qžæŽ¥åœ¨ä¸€èµ—÷€‚每个对象都可以通过昄¡¤ºä¸€ä¸? JavaBean 属性收åˆîC¸€ä¸ªåˆ°ä¾èµ–对象的引用,留给æ‚(zh¨¨n)¨çš„½Ž€å•ä“Q务就只是在一ä¸?XML 配置文äšg中把它们˜qžæŽ¥å¥½ã€?/font>

IOC å’?Spring

IOC 是一¿Uä‹É应用½E‹åºé€»è¾‘外在化的设计模式åQŒæ‰€ä»¥å®ƒæ˜¯è¢«æ³¨å…¥è€Œä¸æ˜¯è¢«å†™å…¥å®¢æˆ·æœÞZ»£ç ä¸­ã€‚å°† IOC 与接口编½E‹åº”用结合,ž®±åƒ Spring 框架那样åQŒäñ”生了一¿Uæž¶æž„,˜q™ç§æž¶æž„能够减少客户机对特定实现逻辑的依赖。请参阅 参考资æ–?/a> 了解更多关于 IOC å’?Spring 的信息ã€?/font>

ä¾? 赖注入是一个强大的ç‰ÒŽ(gu¨©)€§ï¼Œä½†æ˜¯ Spring 框架能够提供更多ç‰ÒŽ(gu¨©)€§ã€‚Spring 支持可插拔的事务½Ž¡ç†å™¨ï¼Œå¯ä»¥¾l™æ?zh¨¨n)¨çš„事务处理提供更òq¿æ³›çš„选择范围。它集成了领先的持久性框æžÓž¼Œòq¶ä¸”提供一个一致的异常层次¾l“构。Spring ˜q˜æä¾›äº†ä¸€¿Uä‹É用面向方面代码代替正常的面向对象代码的简单机制ã€?/font>

Spring AOP 允许æ‚(zh¨¨n)¨ä‹Éç”?i>拦截å™?/i> 在一个或多个执行点上拦截应用½E‹åºé€»è¾‘。加强应用程序在拦截器中的日志记录逻辑ä¼?x¨¬)äñ”生一个更可读的、实用的代码基础åQŒæ‰€ä»¥æ‹¦æˆªå™¨òq¿æ³›ç”¨äºŽæ—¥å¿—记录。æ?zh¨¨n)¨å¾ˆå¿«ž®×ƒ¼?x¨¬)看到åQŒäØ“(f¨´)了处理横切关注点åQŒSpring AOP 发布了它自己的拦截器åQŒæ?zh¨¨n)¨ä¹Ÿå¯ä»¥ç¼–写æ‚(zh¨¨n)¨è‡ªå·±çš„æ‹¦æˆªå™¨ã€?/font>





整合 Struts �Spring

ä¸? Struts ç›æ€¼¼åQŒSpring å¯ä»¥ä½œäØ“(f¨´)一ä¸?MVC 实现。这两种框架都具有自å·Þqš„优点和缺点,ž®½ç®¡å¤§éƒ¨åˆ†äh同意 Struts åœ?MVC æ–šw¢ä»ç„¶æ˜¯æœ€å¥½çš„。很多开发团队已¾lå­¦ä¼?x¨¬)在旉™—´ç´§è¿«çš„æ—¶å€™åˆ©ç”?Struts ä½œäØ“(f¨´)构造高品质软äšg的基¼‹€ã€‚Struts å…ähœ‰å¦‚此大的推动力,以至于开发团队宁愿整å?Spring 框架的特性,而不愿意转换æˆ?Spring MVC。没必要˜q›è¡Œè½¬æ¢å¯ÒŽ(gu¨©)‚¨æ¥è¯´æ˜¯ä¸€ä¸ªå¥½æ¶ˆæ¯ã€‚Spring 架构允许æ‚(zh¨¨n)¨å°† Struts ä½œäØ“(f¨´) Web 框架˜qžæŽ¥åˆ°åŸºäº?Spring 的业务和持久层。最后的¾l“æžœž®±æ˜¯çŽ°åœ¨ä¸€åˆ‡æ¡ä»‰™ƒ½å…·å¤‡äº†ã€?/font>

在接下来的小½Hé—¨ä¸­ï¼Œæ‚(zh¨¨n)¨å°†ä¼?x¨¬)了解到三种ž?Struts MVC 整合åˆ?Spring 框架的方法。我ž®†æ­½Cºæ¯¿Uæ–¹æ³•çš„¾~ºé™·òq¶ä¸”å¯ÒŽ(gu¨©)¯”它们的优炏V€?一旦æ?zh¨¨n)¨äº†è§£åˆ°æ‰€æœ‰ä¸‰¿Uæ–¹æ³•的作用åQŒæˆ‘ž®†ä¼š(x¨¬)向æ?zh¨¨n)¨å±•示一个ä×o人兴奋的应用½E‹åºåQŒè¿™ä¸ªç¨‹åºä‹É用的是这三种æ–ÒŽ(gu¨©)³•中我最喜欢的一¿Uã€?/font>





三个ž®çªé—?/span>

接下来的每种整合技术(或者窍门)都有自己的优点和特点。我偏爱其中的一¿Uï¼Œä½†æ˜¯æˆ‘知道这三种都能够加深æ?zh¨¨n)¨å?Struts å’?Spring 的理解。在处理各种不同情况的时候,˜q™å°†¾l™æ?zh¨¨n)¨æä¾›ä¸€ä¸ªå¹¿é˜”的选择范围。方法如下:(x¨¬)

  • 使用 Spring çš?ActionSupport ¾cÀL•´å?Structs
  • 使用 Spring çš?DelegatingRequestProcessor 覆盖 Struts çš? RequestProcessor
  • ž®?Struts Action ½Ž¡ç†å§”托¾l?Spring 框架

装蝲应用½E‹åºçŽ¯å¢ƒ

无论æ‚(zh¨¨n)¨ä‹É用哪¿UæŠ€æœ¯ï¼Œéƒ½éœ€è¦ä‹Éç”?Spring çš?ContextLoaderPlugin ä¸?Struts çš?ActionServlet 装蝲 Spring 应用½E‹åºçŽ¯å¢ƒã€‚å°±åƒæ·»åŠ ä“Qä½•å…¶ä»–æ’ä»¶ä¸€æ øP¼Œ½Ž€å•地向æ?zh¨¨n)¨ç?struts-config.xml æ–‡äšgæ·ÕdŠ è¯¥æ’ä»Óž¼Œå¦‚下所½Cºï¼š(x¨¬)


<plug-in className=
"org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property=
"contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>


前面已经提到˜q‡ï¼Œåœ?下蝲 部分åQŒæ?zh¨¨n)¨èƒ½å¤Ÿæ‰‘Öˆ°˜q™ä¸‰ä¸ªå®Œå…¨å¯ä½¿ç”¨çš„例子的完整源代码。每个例子都ä¸ÞZ¸€ä¸ªä¹¦¾cæœç´¢åº”用程序提供一¿Uä¸åŒçš„ Struts å’?Spring 的整合方法。æ?zh¨¨n)¨å¯ä»¥åœ¨è¿™é‡Œçœ‹åˆîC¾‹å­çš„要点åQŒä½†æ˜¯æ?zh¨¨n)¨ä¹Ÿå¯ä»¥ä¸‹è½½åº”用程序以查看所有的¾l†èŠ‚ã€?/font>





½Hé—¨ 1. 使用 Spring çš?ActionSupport

手动创徏一ä¸?Spring 环境是一¿Uæ•´å?Struts å’?Spring çš„æœ€ç›´è§‚çš„æ–¹å¼ã€‚äØ“(f¨´)了ä‹É它变得更½Ž€å•,Spring æä¾›äº†ä¸€äº›å¸®åŠ©ã€‚äØ“(f¨´)了方便地获得 Spring 环境åQ?font size="3">org.springframework.web.struts.ActionSupport ¾cÀLä¾›äº†ä¸€ä¸?getWebApplicationContext() æ–ÒŽ(gu¨©)³•。æ?zh¨¨n)¨æ‰€åšçš„只是ä»?Spring çš?ActionSupport 而不æ˜?font size="3"> Struts Action ¾cÀL‰©å±•æ?zh¨¨n)¨çš„动作,如清å?1 所½Cºï¼š(x¨¬)


清单 1. 使用 ActionSupport 整合 Struts

package ca.nexcel.books.actions;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
import org.springframework.context.ApplicationContext;
import org.springframework.web.struts.ActionSupport;

import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;

public class SearchSubmit extends ActionSupport { |(1)


public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {

DynaActionForm searchForm = (DynaActionForm) form;
String isbn = (String) searchForm.get("isbn");

//the old fashion way
//BookService bookService = new BookServiceImpl();

ApplicationContext ctx =
getWebApplicationContext(); |(2)
BookService bookService =
(BookService) ctx.getBean("bookService"); |(3)

Book book = bookService.read(isbn.trim());

if (null == book) {
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,new ActionError
("message.notfound"));
saveErrors(request, errors);
return mapping.findForward("failure") ;
}

request.setAttribute("book", book);
return mapping.findForward("success");
}
}


让我们快速思考一下这里到底发生了什么。在 (1) 处,我通过ä»?Spring çš?ActionSupport ¾c»è€Œä¸æ˜?Struts çš?Action ¾c»è¿›è¡Œæ‰©å±•,创徏了一个新çš?Actionã€?/font>åœ?(2) 处,我ä‹Éç”?getWebApplicationContext() æ–ÒŽ(gu¨©)³•获得一ä¸?ApplicationContextã€?/font>ä¸ÞZº†èŽ·å¾—ä¸šåŠ¡æœåŠ¡åQŒæˆ‘使用åœ?(2) 处获得的环境åœ?(3) 处查找一ä¸?Spring beanã€?/font>

˜q? ¿UæŠ€æœ¯å¾ˆ½Ž€å•åÆˆä¸”æ˜“äºŽç†è§£ã€‚ä¸òq¸çš„æ˜¯ï¼Œå®ƒå°† Struts 动作ä¸?Spring 框架耦合在一赗÷€‚如果æ?zh¨¨n)¨æƒÏx›¿æ¢æŽ‰ SpringåQŒé‚£ä¹ˆæ?zh¨¨n)¨å¿…é¡»é‡å†™ä»£ç ã€‚åÆˆä¸”ï¼Œç”׃ºŽ Struts 动作不在 Spring 的控制之下,所以它不能获得 Spring AOP 的优åŠÑ€‚当使用多重独立çš?Spring 环境æ—Óž¼Œ˜q™ç§æŠ€æœ¯å¯èƒ½æœ‰ç”¨ï¼Œä½†æ˜¯åœ¨å¤§å¤šæ•°æƒ…况下,˜q™ç§æ–ÒŽ(gu¨©)³•不如另外两种æ–ÒŽ(gu¨©)³•合适ã€?/font>





½Hé—¨ 2. 覆盖 RequestProcessor

ž®?Spring ä»?Struts 动作中分¼›ÀL˜¯ä¸€ä¸ªæ›´å·§å¦™çš„设计选择。分¼›Èš„一¿Uæ–¹æ³•是使用 org.springframework.web.struts.DelegatingRequestProcessor ¾cÀL¥è¦†ç›– Struts çš?font size="3"> RequestProcessor 处理½E‹åºåQŒå¦‚清单 2 所½Cºï¼š(x¨¬)


清单 2. 通过 Spring çš?DelegatingRequestProcessor ˜q›è¡Œæ•´åˆ

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
<form-beans>
<form-bean name="searchForm"
type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="isbn" type="java.lang.String"/>
</form-bean>

</form-beans>

<global-forwards type="org.apache.struts.action.ActionForward">
<forward name="welcome" path="/welcome.do"/>
<forward name="searchEntry" path="/searchEntry.do"/>
<forward name="searchSubmit" path="/searchSubmit.do"/>
</global-forwards>

<action-mappings>
<action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
<action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
<action path="/searchSubmit"
type="ca.nexcel.books.actions.SearchSubmit"
input="/searchEntry.do"
validate="true"
name="searchForm">
<forward name="success" path="/WEB-INF/pages/detail.jsp"/>
<forward name="failure" path="/WEB-INF/pages/search.jsp"/>
</action>

</action-mappings>

<message-resources parameter="ApplicationResources"/>

<controller processorClass="org.springframework.web.struts.
DelegatingRequestProcessor"/> |(1)

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>


<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>

</struts-config>


我利用了 <controller> 标记来用 DelegatingRequestProcessor 覆盖默认çš?Struts RequestProcessorã€?/font>下一步是在我çš?Spring 配置文äšg中注册该动作åQŒå¦‚清单 3 所½Cºï¼š(x¨¬)


清单 3. åœ?Spring 配置文äšg中注册一个动ä½?/b>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

<bean name="/searchSubmit"
class="ca.nexcel.books.actions.SearchSubmit"> |(1)
<property name="bookService">
<ref bean="bookService"/>
</property>
</bean>
</beans>


注意åQšåœ¨ (1) 处,我ä‹É用名¿U°å±žæ€§æ³¨å†Œäº†ä¸€ä¸?beanåQŒä»¥åŒšw… struts-config 动作映射名称ã€?code>SearchSubmit 动作揭示了一ä¸?JavaBean 属性,允许 Spring 在运行时填充属性,如清å?4 所½Cºï¼š(x¨¬)


清单 4. å…ähœ‰ JavaBean 属性的 Struts 动作

package ca.nexcel.books.actions;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;

import ca.nexcel.books.beans.Book;
import ca.nexcel.books.business.BookService;

public class SearchSubmit extends Action {

private BookService bookService;
public BookService getBookService() {
return bookService;
}

public void setBookService(BookService bookService) { | (1)
this.bookService = bookService;
}

public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {

DynaActionForm searchForm = (DynaActionForm) form;
String isbn = (String) searchForm.get("isbn");

Book book = getBookService().read(isbn.trim()); |(2)

if (null == book) {
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));
saveErrors(request, errors);
return mapping.findForward("failure") ;
}

request.setAttribute("book", book);
return mapping.findForward("success");
}

}


在清å?4 中,æ‚(zh¨¨n)¨å¯ä»¥äº†è§£åˆ°å¦‚何创徏 Struts 动作。在 (1) 处,我创å»ÞZº†ä¸€ä¸?JavaBean 属性ã€?code>DelegatingRequestProcessorè‡? 动地配置˜q™ç§å±žæ€§ã€‚è¿™¿Uè®¾è®¡ä‹É Struts 动作òq¶ä¸çŸ¥é“它正è¢?Spring ½Ž¡ç†åQŒåƈ且ä‹Éæ‚(zh¨¨n)¨èƒ½å¤Ÿåˆ©ç”?Sping 的动作管理框架的所有优炏V€‚由于æ?zh¨¨n)¨ç?Struts 动作注意不到 Spring 的存在,所以æ?zh¨¨n)¨ä¸éœ€è¦é‡å†™æ?zh¨¨n)¨ç?Struts 代码ž®±å¯ä»¥ä‹É用其他控制反转容器来替换æŽ?Springã€?/font>

DelegatingRequestProcessor æ–ÒŽ(gu¨©)³•的确比第一¿Uæ–¹æ³•好åQŒä½†æ˜¯ä»ç„¶å­˜åœ¨ä¸€äº›é—®é¢˜ã€‚如果æ?zh¨¨n)¨ä½¿ç”¨ä¸€ä¸ªä¸åŒçš„ RequestProcessoråQ?/font>则需要手动整å?Spring çš?DelegatingRequestProcessorã€?/font>æ·ÕdŠ çš„ä»£ç ä¼š(x¨¬)造成¾l´æŠ¤çš„éº»çƒ¦åÆˆä¸”å°†æ¥ä¼š(x¨¬)降低æ‚(zh¨¨n)¨çš„应用½E‹åºçš„灵‹zÀL€§ã€‚此外,˜q˜æœ‰˜q‡ä¸€äº›ä‹É用一¾pÕdˆ—命ä×o来代æ›?Struts RequestProcessor 的传闅R€?˜q™ç§æ”¹å˜ž®†ä¼š(x¨¬)对这¿Uè§£å†Ïx–¹æ³•的使用寿命造成负面的媄响ã€?/font>





½Hé—¨ 3. ž®†åŠ¨ä½œç®¡ç†å§”æ‰˜ç»™ Spring

一个更好的解决æ–ÒŽ(gu¨©)³•是将 Strut 动作½Ž¡ç†å§”托¾l?Spring。æ?zh¨¨n)¨å¯ä»¥é€šè¿‡åœ?struts-config 动作映射中注册一个代理来实现。代理负责在 Spring 环境中查æ‰?Struts 动作。由于动作在 Spring 的控制之下,所以它可以填充动作çš?JavaBean 属性,òq¶äØ“(f¨´)应用诸如 Spring çš?AOP 拦截器之¾cȝš„ç‰ÒŽ(gu¨©)€§å¸¦æ¥äº†å¯èƒ½ã€?

清单 5 中的 Action ¾cÖM¸Žæ¸…单 4 中的相同。但æ˜?struts-config 有一些不同:(x¨¬)


清单 5. Spring 整合的委托方�/b>

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
<form-beans>
<form-bean name="searchForm"
type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="isbn" type="java.lang.String"/>
</form-bean>

</form-beans>

<global-forwards type="org.apache.struts.action.ActionForward">
<forward name="welcome" path="/welcome.do"/>
<forward name="searchEntry" path="/searchEntry.do"/>
<forward name="searchSubmit" path="/searchSubmit.do"/>
</global-forwards>

<action-mappings>
<action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
<action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
<action path="/searchSubmit"
type="org.springframework.web.struts.DelegatingActionProxy" |(1)
input="/searchEntry.do"
validate="true"
name="searchForm">
<forward name="success" path="/WEB-INF/pages/detail.jsp"/>
<forward name="failure" path="/WEB-INF/pages/search.jsp"/>
</action>

</action-mappings>

<message-resources parameter="ApplicationResources"/>


<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property
property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>


<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>


</struts-config>


清单 5 是一个典型的 struts-config.xml æ–‡äšgåQŒåªæœ‰ä¸€ä¸ªå°ž®çš„差别。它注册 Spring 代理¾cȝš„名称åQŒè€Œä¸æ˜¯å£°æ˜ŽåŠ¨ä½œçš„¾cÕdåQŒå¦‚åQ?åQ‰å¤„所½Cºã€‚DelegatingActionProxy ¾cÖM‹É用动作映ž®„名¿U°æŸ¥æ‰?Spring 环境中的动作。这ž®±æ˜¯æˆ‘们使用 ContextLoaderPlugIn 声明的环境ã€?/font>

ž®†ä¸€ä¸?Struts 动作注册ä¸ÞZ¸€ä¸?Spring bean 是非常直观的åQŒå¦‚清单 6 所½Cºã€‚我利用动作映射使用 <bean> 标记的名¿U°å±žæ€§ï¼ˆåœ¨è¿™ä¸ªä¾‹å­ä¸­æ˜?"/searchSubmit"åQ‰ç®€å•地创徏了一ä¸?bean。这个动作的 JavaBean 属性像ä»ÖM½• Spring bean 一栯‚¢«å¡«å……åQ?


清单 6. �Spring 环境中注册一�Struts 动作

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

<bean name="/searchSubmit"
class="ca.nexcel.books.actions.SearchSubmit">
<property name="bookService">
<ref bean="bookService"/>
</property>
</bean>

</beans>






动作委托的优�/span>

动作委托解决æ–ÒŽ(gu¨©)³•是这三种æ–ÒŽ(gu¨©)³•中最好的。Struts 动作不了è§?SpringåQŒä¸å¯¹ä»£ç ä½œä»ÖM½•改变ž®±å¯ç”¨äºŽé?Spring 应用½E‹åºä¸­ã€?font size="3">RequestProcessor 的改变不ä¼?x¨¬)媄响它åQŒåƈ且它可以利用 Spring AOP ç‰ÒŽ(gu¨©)€§çš„优点ã€?

动作委托的优点不止如此。一旦让 Spring 控制æ‚(zh¨¨n)¨çš„ Struts 动作åQŒæ?zh¨¨n)¨ž®±å¯ä»¥ä‹Éç?Spring ¾l™åŠ¨ä½œè¡¥å……æ›´å¼ºçš„‹zÕdŠ›ã€‚ä¾‹å¦‚ï¼Œæ²¡æœ‰ Spring 的话åQŒæ‰€æœ‰çš„ Struts 动作都必™åÀL˜¯¾U¿ç¨‹å®‰å…¨çš„。如果æ?zh¨¨n)¨è®„¡½?<bean> 标记çš?singleton å±žæ€§äØ“(f¨´)“false”,那么不管用何¿Uæ–¹æ³•,æ‚(zh¨¨n)¨çš„应用½E‹åºéƒ½å°†åœ¨æ¯ä¸€ä¸ªè¯·æ±‚上有一个新生成的动作对象。æ?zh¨¨n)¨å¯èƒ½ä¸éœ€è¦è¿™¿Uç‰¹æ€§ï¼Œä½†æ˜¯æŠŠå®ƒæ”‘Öœ¨æ‚(zh¨¨n)¨çš„工具½Ž×ƒ¸­ä¹? 很好。æ?zh¨¨n)¨ä¹Ÿå¯ä»¥åˆ©ç?Spring 的生命周期方法。例如,当实例化 Struts 动作æ—Óž¼Œ<bean> 标记çš?init-method 属性被用于˜qè¡Œä¸€ä¸ªæ–¹æ³•。类似地åQŒåœ¨ä»Žå®¹å™¨ä¸­åˆ é™¤ bean 之前åQŒdestroy-method 属性执行一个方法。这些方法是½Ž¡ç†æ˜‚贵对象的好办法åQŒå®ƒä»¬ä»¥ä¸€¿Uä¸Ž Servlet 生命周期相同的方式进行管理ã€?/font>





拦截 Struts

å‰? 面提到过åQŒé€šè¿‡ž®?Struts 动作委托¾l?Spring 框架而整å?Struts å’?Spring 的一个主要的优点是:(x¨¬)æ‚(zh¨¨n)¨å¯ä»¥å°† Spring çš?AOP 拦截器应用于æ‚(zh¨¨n)¨çš„ Struts 动作。通过ž®?Spring 拦截器应用于 Struts 动作åQŒæ?zh¨¨n)¨å¯ä»¥ç”¨æœ€ž®çš„代ä­h(hu¨¢n)处理横切å…Ïx³¨ç‚V€?/font>

虽然 Spring 提供很多内置拦截器,但是我将向æ?zh¨¨n)¨å±•示如何创徏自己的拦截器òq¶æŠŠå®ƒåº”用于一ä¸?Struts åŠ¨ä½œã€‚äØ“(f¨´)了ä‹É用拦截器åQŒæ?zh¨¨n)¨éœ€è¦åšä¸‰äšg事:(x¨¬)

  1. 创徏拦截器�/font>
  2. 注册拦截器�/font>
  3. 声明在何处拦截代码�/font>

˜q™çœ‹èµäh¥éžå¸¸½Ž€å•的几句话却非常强大。例如,在清å?7 ä¸­ï¼Œæˆ‘äØ“(f¨´) Struts 动作创徏了一个日志记录拦截器ã€? ˜q™ä¸ªæ‹¦æˆªå™¨åœ¨æ¯ä¸ªæ–ÒŽ(gu¨©)³•调用之前打印一句话åQ?/font>


清单 7. 一个简单的日志记录拦截�/b>

package ca.nexcel.books.interceptors;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class LoggingInterceptor implements MethodBeforeAdvice {

public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("logging before!");
}
}


˜q™ä¸ªæ‹¦æˆªå™¨éžå¸¸ç®€å•ã€?code>before() æ–ÒŽ(gu¨©)³•在拦截点中每个方法之前运行。在本例中,它打印出一句话åQŒå…¶å®žå®ƒå¯ä»¥åšæ?zh¨¨n)¨æƒ›_šçš„ä“Q何事。下一步就是在 Spring 配置文äšg中注册这个拦截器åQŒå¦‚清单 8 所½Cºï¼š(x¨¬)


清单 8. åœ?Spring 配置文äšg中注册拦截器

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>

<bean name="/searchSubmit"
class="ca.nexcel.books.actions.SearchSubmit">
<property name="bookService">
<ref bean="bookService"/>
</property>
</bean>

<!-- Interceptors -->
<bean name="logger"
class="ca.nexcel.books.interceptors.LoggingInterceptor"/> |(1)

<!-- AutoProxies -->
<bean name="loggingAutoProxy"
class="org.springframework.aop.framework.autoproxy.
BeanNameAutoProxyCreator"> |(2)
<property name="beanNames">
<value>/searchSubmit</valuesgt; |(3)
</property>
<property name="interceptorNames">
<list>
<value>logger</value> |(4)
</list>
</property>
</bean>

</beans>


æ‚(zh¨¨n)¨å¯èƒ½å·²¾læ³¨æ„åˆ°äº†ï¼Œæ¸…单 8 扩展äº?清单 6 中所½Cºçš„应用½E‹åºä»¥åŒ…含一个拦截器。具体细节如下:(x¨¬)

  • åœ?(1) 处,我注册了˜q™ä¸ªæ‹¦æˆªå™¨ã€?/font>
  • åœ?(2) 处,我创å»ÞZº†ä¸€ä¸?bean 名称自动代理åQŒå®ƒæè¿°å¦‚何应用拦截器。还有其他的æ–ÒŽ(gu¨©)³•定义拦截点,但是˜q™ç§æ–ÒŽ(gu¨©)³•常见而简ä¾Ñ€?/font>
  • åœ?(3) 处,我将 Struts 动作注册为将被拦截的 bean。如果æ?zh¨¨n)¨æƒŒ™¦æ‹¦æˆªå…¶ä»–ç?Struts 动作åQŒåˆ™åªéœ€è¦åœ¨ "beanNames" 下面创徏附加çš?<value> 标记ã€?/font>
  • åœ?(4) 处,当拦截发生时åQŒæˆ‘执行了在 (1) 处创建的拦截å™?bean 的名¿U°ã€‚这里列出的所有拦截器都应用于“beanNames”ã€?/font>

ž®±æ˜¯˜q™æ ·ã€‚就像这个例子所展示的,ž®†æ?zh¨¨n)¨ç?Struts 动作¾|®äºŽ Spring 框架的控制之下,为处理æ?zh¨¨n)¨ç?Struts 应用½E‹åºæä¾›äº†ä¸€¾pÕdˆ—全新的选择。在本例中,使用动作委托可以è½ÀL¾åœ°åˆ©ç”?Spring 拦截器提é«?Struts 应用½E‹åºä¸­çš„æ—¥å¿—记录能力ã€?/font>





¾l“束è¯?/span>

在本文中åQŒæ?zh¨¨n)¨å·²ç»å­¦ä¹?f¨¤n)了将 Struts 动作整合åˆ?Spring 框架中的三种½Hé—¨ã€‚ä‹Éç”?Spring çš?ActionSupport 来整å?StrutsåQˆç¬¬ä¸€¿Uçªé—¨ä¸­ž®±æ˜¯˜q™æ ·åšçš„åQ‰ç®€å•è€Œå¿«æøP¼Œä½†æ˜¯ä¼?x¨¬)å°?Struts 动作ä¸?Spring 框架耦合在一赗÷€‚如果æ?zh¨¨n)¨éœ€è¦å°†åº”用½E‹åº¿UÀL¤åˆîC¸€ä¸ªä¸åŒçš„æ¡†æž¶åQŒåˆ™éœ€è¦é‡å†™ä»£ç ã€‚第二种解决æ–ÒŽ(gu¨©)³•通过委托 RequestProcessor 巧妙地解开代码的耦合åQŒä½†æ˜¯å®ƒçš„可扩展性不强,òq¶ä¸”å½?Struts çš?RequestProcessor 变成一¾pÕdˆ—命ä×oæ—Óž¼Œ˜q™ç§æ–ÒŽ(gu¨©)³•ž®±æŒ¾l­ä¸äº†å¾ˆé•¿æ—¶é—´ã€‚第三种æ–ÒŽ(gu¨©)³•是这三种æ–ÒŽ(gu¨©)³•中最好的åQšå°† Struts 动作委托¾l?Spring 框架可以使代码解耦,从而ä‹Éæ‚(zh¨¨n)¨å¯ä»¥åœ¨æ‚(zh¨¨n)¨çš„ Struts 应用½E‹åºä¸­åˆ©ç”?Spring 的特性(比如日志记录拦截器)ã€?/p>

三种 Struts-Spring 整合½Hé—¨ä¸­çš„æ¯ä¸€¿Uéƒ½è¢«å®žçŽ°æˆä¸€ä¸ªå®Œæ•´å¯ç”¨çš„åº”ç”¨½E‹åºã€‚请参阅 下蝲 部分仔细研究它们ã€?/font>






下蝲
描述名字大小 ä¸‹è²æ–ÒŽ(gu¨©)³•
ActionSupport sample codej-sr2-actionsupport.zip5 MB  FTP
RequestProcessor sample codej-sr2-requestprocessor.zip5 MB  FTP
Delegate sample codej-sr2-delegate.zip5 MB  FTP


]]>
Ö÷Õ¾Ö©Öë³ØÄ£°å£º ºÎ÷ÊÐ| »´ÄÏÊÐ| ¬ÍåÇø| ãÏÖÐÊÐ| ÓÜÁÖÊÐ| çõ´ºÊÐ| ÔÀÎ÷ÏØ| »áÔóÏØ| Ð˺ÍÏØ| ±±º£ÊÐ| ÓÜÁÖÊÐ| ̨ÄÏÊÐ| ¶¨ÖÝÊÐ| ºº´¨ÊÐ| ä»Ë®ÏØ| ÄþÁêÏØ| ¶«°¢ÏØ| ·ÊÎ÷ÏØ| ÒÀ°²ÏØ| ¼ÎÒåÏØ| ½ºÓÏØ| ɳƺ°ÓÇø| ¾ÞÒ°ÏØ| ÕýÀ¶Æì| ËìÆ½ÏØ| ºôºÍºÆÌØÊÐ| Æ½ÒØÏØ| ÍпËÍÐÏØ| ²ìÓçÏØ| ¶«Ô´ÏØ| ÌØ¿ËË¹ÏØ| ³¤Ñô| ÏìË®ÏØ| ¶¼ÔÈÊÐ| °¢¶ûɽÊÐ| »ôÉ½ÏØ| Ë«ÅÆÏØ| ÂåÂ¡ÏØ| ÎÚ³ľÆëÏØ| ÇåË®ºÓÏØ| ÖÐÑôÏØ|