锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
緇間笂錛岀畝鍗曠殑璁劇疆鏂規硶濡備笅錛?br />
jsp聽(gbk)聽聽聽聽 ---->聽聽聽聽 java(ISO-8859-1)聽 -------> mysql(gbk)
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 杞崲
榪欐牱璁劇疆涔嬪悗錛岃繕鏈変竴縐嶆儏鍐典細鍑虹幇涔辯爜錛氬綋浣犲湪jsp绔彁浜や竴涓猧d鍙鳳紝鐒跺悗鍦╦ava澶勭悊绔氳繃id鍙峰緱鍒版暟鎹簱涓殑gbk錛堟眽瀛楋級鏁版嵁錛岃繖鏄氨浼氬嚭鐜頒貢鐮侊紝鍥犱負java澶勭悊鐨勬槸ISO-8859-1錛屼綘鍦╦ava鍒癿ysql涓湁浜嗕竴涓狪SO-8859-1鍒癵bk鐨勮漿鎹紝鑰岃繖浜涙暟鎹湰韜氨鏄疘SO-8859-1,鎵浠ヨ漿鎹㈠悗灝卞嚭鐜伴棶棰樹簡銆?br />瑙e喅鍔炴硶錛氬皢鍦╦ava涓鐞嗙殑gbk鏁版嵁杞崲涓篒SO-8859-1鍗沖彲銆?br />
鎬諱箣錛氬湪jsp錛宩ava錛宮ysql涓夎呬箣闂寸殑緙栫爜鏂瑰紡蹇呴』緇熶竴錛屼笉鑳介敊璇殑杞崲鎴栬呬笉杞崲銆?img src ="http://m.tkk7.com/soochow_hhb/aggbug/78845.html" width = "1" height = "1" />
鍦ㄥ疄闄呯殑緋葷粺涓紝瑕佸涓被鍏卞悓鍗忎綔鏉ュ畬鎴愭煇涓欏逛換鍔★紝涓鑸О涓哄鍚堛傚湪緋葷粺鐨勮璁¤繃紼嬩腑錛岃﹀悎鏄笉鍙伩鍏嶇殑錛屾槸蹇呴』鐨勶紝浣嗘槸瀹冧細甯︽潵浠ヤ笅闂錛?br />錛嶏紞闅句互嫻嬭瘯錛氱湅涓嬮潰鐨勪袱涓被錛?br />KnightOfTheRoundTable
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽 |聽聽new
聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽V
聽聽聽聽聽聽聽聽 HolyGrailQuest
鍦↘nightOfTheRoundTable綾諱腑浣跨敤浜咹olyGrailQuest綾伙紝騫朵笖鍙兘浣跨敤涓嶅悓鐨凲uest綾匯傝繖涓や釜綾葷殑鍔熻兘鏄獞澹幓鎵ц涓嶅悓鐨勪換鍔★紝HolyGrail鍙槸浠h〃浜嗕竴縐嶄換鍔°傝繖縐嶉氳繃鍥絥ew鐨勬柟寮忥紝浣垮緱knight鍜宷uest涓や釜綾葷揣瀵嗙殑鑰﹀悎鍦ㄤ竴璧楓傝璁″畬鎴愬悗鍋氬崟鍏冩祴璇曪紝鐪嬩笅闈㈢殑浠g爜錛?br />KnightOfTheRoundTable knight = new KnightOfTheRoundTable("Bedivere");
HolyGrail grail = knight.embarkOnQuery();
assertNotNull(grail);
assertTrue(grail.isHoly());
鍦ㄦ祴璇昁nightOfTheRoundTable綾葷殑鏃跺欙紝闂存帴鐨勬祴璇曚簡HolyGrailQuest綾伙紝浣嗘槸瀵逛簬HolyGrailQuest綾葷殑鎯呭喌騫舵病鏈夊緢鏄懼紡鐨勬祴璇曪紝鎵浠ヤ嬌鐢ㄤ簡鏈鍚庣殑涓よ浠g爜鏉ユ祴璇曪紝鏄懼緱寰堢鎷欍備笉鐭ラ亾鏄惁嫻嬭瘯浜嗘墍鏈夊彲鑳界殑鎯呭喌銆?br />錛嶏紞闅句互緇存姢
濡傛灉浠ュ悗淇敼浜嗕唬鐮侊紝鎴栬呭鍔犱簡/鏀瑰彉浜唊night鐨勪換鍔★紝浠g爜蹇呴』鏀瑰姩錛屾祴璇曚唬鐮佷篃瑕佹敼鍔紝騫朵笖鏀瑰姩涓涓湴鏂癸紝鍙兘浼氬獎鍝嶅埌鍏朵粬寰堝鍦版柟錛屼負鏃ュ悗鐨勭淮鎶ゅ伐浣滃甫鏉ヤ簡楹葷儲
錛嶏紞绱ц﹀悎
鎻愮ず錛氳繖縐嶆ā寮忓紩璧風殑闂錛屼富瑕佹槸鍥犱負绱ц﹀悎鎵鑷達紝鎵浠ヨ瑙e喅榪欑闂鐨勯瑕佹柟妗堝氨鏄В鑰﹀悎錛屼絾濡備綍鏉ヨВ鑰﹀悎鍛紵璇風戶緇湅錛?br />錛?錛夎В鑰﹀悎鈥斺旈氳繃鎺ュ彛interface鏉ュ疄鐜?br />鍥犱負楠戝+鍙兘鎵ц涓嶅悓鐨勪換鍔★紝涔熸湁涓嶅悓縐嶇被鐨勯獞澹紝鎵浠ユ垜浠彲浠ュ皢浠誨姟鍜岄獞澹娊璞′負鎺ュ彛錛屽皢鍏蜂綋鐨勫疄鐜伴殣钘忓湪鎺ュ彛涔嬩笅錛岃繖鏍峰氨涓嶅繀鍦╧night綾諱腑閫氳繃鏄劇ず鐨?HolyGrailQuest quest = new HolyGrailQuest ()榪欐牱鐨勮鍙ユ潵鍒涘緩Quest瀵硅薄錛岃屽彲浠ラ氳繃鎺ュ彛Quest quest 錛?new HolyGrailQuest()鏉ュ疄鐜般傝繖鏍峰氨褰㈡垚浜嗗涓嬬殑綾誨浘錛?br />
榪欐牱錛岃櫧鐒朵嬌鐢ㄤ簡鎺ュ彛錛屼嬌寰楀眰嬈″垎鏄庯紝閫氳繃鎺ュ彛Quest鏉ュ疄鐜版帰闄╋紝浣嗘槸榪樻槸鍙兘浠庝簨涓縐嶆帰闄╀換鍔★紝鑰屽浣曟墠鑳借楠戝+浠庝簨浠諱綍涓縐嶄換鍔″憿錛熻緇х畫鐪嬶紒
錛?錛夌粰浜堜笌鑾峰緱
楠戝+鎵ц鎺㈤櫓浠誨姟鏈変袱縐嶆柟寮忥細
絎竴銆佽楠戝+涓誨姩鑾峰緱鎺㈤櫓浠誨姟錛屽墠闈㈢殑瀹炵幇鏂瑰紡灞炰簬榪欑被錛岄氳繃new鏉ュ疄鐜幫紱
絎簩錛岃楠戝+琚姩鐨勮幏寰椾換鍔★紝鍗崇粰浜堥獞澹煇欏規帰闄╀換鍔★紝榪欐牱灝辮В鍐充簡涓婇潰鐨勯棶棰橈紙璁╅獞澹彲浠ヤ粠浜嬩換浣曚竴縐嶄換鍔★紝鍙緇欎粬浠垎閰嶅嵆鍙級銆?br />瀹為檯瀹炵幇鐨勬柟寮忓緢綆鍗曪紝鐪嬪涓嬩唬鐮侊細
public void setQuest(Quest quest){
聽聽 this.quest = quest;
}
綆鍗曠殑浠g爜瀹炵幇浜嗘柟寮忕殑鏀瑰彉錛岃繖鏍風粰KnightOfTheRoundTable綾諱紶鍏ヤ換浣曠殑Quest浠誨姟錛岄兘鍙互鎺ュ彈浜嗐?br />鍒拌繖閲屽彲浠ュ緢鏄庢樉鐨勭湅鍑烘潵錛屾垜浠皢浠ュ墠鐨刵ew鏂瑰紡錛岀炕杞繃鏉ワ紝鍗充笉鏄涓誨姩鑾峰緱渚濊禆綾伙紝鑰屾槸琚姩鐨勮幏寰椾緷璧栫被錛岃繖灝辨槸IoC鐨勬牳蹇冿紝瀹為檯Fowler璇村緱渚濊禆娉ㄥ叆涔熷緢璐村垏錛屽嵆鍚戠被涓滄敞鍏モ濆畠渚濊禆鐨勫叾浠栫被銆?br />
濂戒簡錛屽埌榪欓噷錛屽簲璇ョ煡閬撲簡IoC鐨勫熀鏈蹇典簡鍚э紝涔熺煡閬撲簡IoC鐨勫熀鏈姛鑳戒簡鍚с?br />瑕佹兂鏇存繁鍏ョ殑浜嗚В錛岃鍏蟲敞鎴戠殑鏂囩珷銆?/span>
鐗?/SPAN> 寰?/SPAN> |
Struts1.1 |
WebWork2 |
Action綾?/SPAN> |
鍦?/SPAN>Struts閲岄潰錛屾瘡涓涓?/SPAN>Action綾誨繀闇瑕佺戶鎵夸竴涓娊璞$殑綾?/SPAN>org.apache.struts.action.Action銆傝繖涓湪Java緙栫▼涓細寮曟潵涓浜涢棶棰橈紝灝辨槸鍏充簬澶氱緇ф壙鐨勯棶棰樸?/SPAN> |
WebWork鐨?/SPAN>Action綾諱粎闇瑕佸疄鐜版帴鍙?/SPAN>com.opensymphony.xwork.Action錛屼篃鍙互瀹炵幇鍏跺畠鐨勬帴鍙f潵瀹炵幇鏇村鐨勫姛鑳斤紝璀錛?/SPAN>validate錛堥獙璇侊級錛?/SPAN>localware(鍥介檯鍖?/SPAN>)絳夈傚綋鐒訛紝瀹冧篃鎻愪緵浜嗕竴涓被ActionSupport闆嗘垚浜嗕笂闈㈢殑鎵鏈夊姛鑳斤紝鎴戜滑鍦ㄥ紑鍙戜腑鍙互鏍規嵁闇瑕侀夋嫨銆?/SPAN> |
綰跨▼妯″瀷 |
Struts 鐨?/SPAN>Action蹇呴渶鏄?/SPAN>thread錛?/SPAN>safe鏂瑰紡錛屽畠浠呬粎鍏佽涓涓疄渚嬪幓澶勭悊鎵鏈夌殑璇鋒眰銆傛墍浠?/SPAN>action鐢ㄥ埌鐨勬墍鏈夌殑璧勬簮閮藉繀闇緇熶竴鍚屾錛岃繖涓氨寮曡搗浜嗙嚎紼嬪畨鍏ㄧ殑闂銆?/SPAN> |
鍦?/SPAN>WebWork涓紝姣忎釜璇鋒眰瀵瑰簲涓涓?/SPAN>Action錛屽洜姝ゆ病鏈夌嚎紼嬬殑瀹夊叏闂銆傚疄闄呬笂Servlet瀹瑰櫒瀵規瘡涓姹備篃浜х敓澶氫釜瀵硅薄錛屽畠涔熸病鏈夎瘉鏄庡鎬ц兘鍜屽瀮鍦懼洖鏀朵駭鐢熷お澶氱殑褰卞搷銆?/SPAN> |
Servlet鐨勪緷璧?/SPAN> |
Struts澶勭悊Action鏃跺繀闇瑕佷緷璧?/SPAN>ServletRequest 鍜?/SPAN>ServletResponse錛屾墍鏈夊畠鎽嗚劚涓嶄簡Servlet瀹瑰櫒銆?/SPAN> |
WebWork鐨?/SPAN>Action涓嶇敤渚濊禆Web灞傚拰鍏跺畠鐨勫鍣ㄣ傚畠鍙互閫氳繃ActionContext錛岀洿鎺ュ幓璁塊棶Request鍜?/SPAN>Response錛屼絾榪欎釜鏄彲閫夌殑錛屽彧鏈夊湪蹇呴渶鐨勮姹備笅浣跨敤銆?/SPAN> |
嫻嬭瘯 |
Struts鐨勬瘡涓?/SPAN>Action閮藉悓Web灞傝﹀悎鍦ㄤ竴璧鳳紝榪欐牱瀹冪殑嫻嬭瘯渚濊禆浜?/SPAN>Web瀹瑰櫒錛屽崟鍏冩祴璇曚篃寰堥毦瀹炵幇銆備笉榪囨湁涓涓?/SPAN>Junit鐨勬墿灞曞伐鍏?/SPAN>Struts TestCase鍙互瀹炵幇瀹冪殑鍗曞厓嫻嬭瘯銆?/SPAN> |
Webwork鐨?/SPAN>action鑳藉閫氳繃璧嬩簣涓瀹氱殑灞炴э紝灝卞彲浠ユ墽琛屽崟鍏冩祴璇曘傚悓鏃朵篃鍙互浣跨敤涓涓?/SPAN>mock鐨勫疄渚嬪幓嫻嬭瘯錛岃屼笉鏄氳繃鍚姩web瀹瑰櫒鏉ヨ繘琛屾祴璇曘?/SPAN> |
FormBean |
Struts瑕佹眰鏈?/SPAN>FormBean瀵瑰簲姣忎竴涓〃鍗曪紝鑰屼笖FormBean蹇呴渶緇ф壙鎶借薄綾?/SPAN>ActionForm銆傝屼嬌鐢?/SPAN>DynaBeans瀹為檯涓婃病鏈夊お澶х殑鎰忎箟銆備笉鑳藉寰堝ソ鐨勫鐞嗙幇鏈夌殑妯″瀷銆?/SPAN> |
Webwork 鑳藉鍔ㄦ佺殑鏀墮泦web鐨勬暟鎹劧鍚庡啀璧嬪肩粰bean銆傚畠涔熷彲浠ヤ嬌鐢?/SPAN>FormBean鐨勫艦寮忥紝FormBean鍙互鏄櫘閫氱殑DTO鍜屽煙瀵硅薄錛屽畠涓嶇敤閲嶆柊鏍規嵁鍩熷璞℃潵鐢熸垚鏂扮殑FormBean錛屼篃涓嶉渶緇ф壙鎶借薄綾?/SPAN>ActionForm銆?/SPAN> |
鍓嶇琛ㄨ揪寮忚璦 |
Struts闆嗘垚浜?/SPAN>JSTL錛屾墍浠ュ畠涓昏浣跨敤JSTL鐨勮〃杈懼紡璇█鏉ヨ幏鍙栨暟鎹傚彲鏄?/SPAN>JSTL鐨勮〃杈懼紡璇█鍦?/SPAN>Collection鍜岀儲寮曞睘鎬ф柟闈㈠鐞嗘樉寰楀緢寮便?/SPAN> |
WebWork鐨勮〃杈懼紡璇█浣跨敤浜嗗姛鑳藉己澶х殑OGNL銆傚畠浣跨敤OGNL寤虹珛涓涓?/SPAN>OgnlValueStack鏉ユ悳绱㈡暟鎹?/SPAN>Webwork鍓嶇涔熷彲浠ヤ嬌鐢?/SPAN>JSTL錛屼絾瀹冨悓鏃舵敮鎸侊細velocity銆?/SPAN>freemaker銆?/SPAN>jspparer銆?/SPAN>xml銆?/SPAN> |
綾誨瀷鐨勮漿鎹?/SPAN> |
Struts鐨?/SPAN>FormBean鎶婃墍鏈夌殑鏁版嵁閮戒綔涓?/SPAN>String綾誨瀷錛屽畠鍙互浣跨敤宸ュ叿Commons-Beanutils榪涜綾誨瀷杞寲銆備絾瀹冪殑杞寲閮芥槸鍦?/SPAN>Class綰у埆錛岃屼笖杞寲鐨勭被鍨嬫槸涓嶅彲閰嶇疆鐨勩傜被鍨嬭漿鍖栨椂鐨勯敊璇俊鎭繑鍥炵粰鐢ㄦ埛涔熸槸闈炲父鍥伴毦鐨勩?/SPAN> |
WebWork浣跨敤OGNL榪涜綾誨瀷杞寲錛屾彁渚涗簡鎵鏈夊熀鏈被鍨嬬殑杞寲鍔熻兘銆傜被鍨嬭漿鍖栧彲浠ョ洿鎺ュ涓涓?/SPAN>Class榪涜錛?/SPAN>Class綰у埆錛夎漿鍖栵紝涔熷彲浠ュClass鐨勫瓧孌佃繘琛岀被鍨嬭漿鍖栥傚畠浣跨敤鎷︽埅鍣ㄥ彲浠ュ緢瀹規槗鐨勫皢綾誨瀷杞寲鐨勯敊璇俊鎭繑鍥炵粰鐢ㄦ埛錛岃屼笖閿欒淇℃伅鍙互瀵瑰簲鍒頒竴涓浉搴旂殑瀛楁銆?/SPAN> |
瀵?/SPAN>Action 鎵ц鍓嶅拰鍚庣殑澶勭悊 |
Struts澶勭悊Action鐨勬椂鍊欐槸鍩轟簬class鐨?/SPAN>hierarchies錛屽緢闅懼湪action澶勭悊鍓嶅拰鍚庤繘琛屾搷浣溿?/SPAN> |
Webwork2 鍏佽鎮ㄥ鐞?/SPAN>Action鍙互閫氳繃鎷︽埅鍣紝灝辨槸鍦ㄦ瘡涓涓?/SPAN>Action澶勭悊鍓嶆垨鑰呭悗榪涜鍏跺畠鎿嶄綔銆傚畠鐨勬嫤鎴櫒鍙互鍦ㄩ厤緗枃浠朵腑鍔ㄦ佹坊鍔狅紝榪欐牱Action鍜屾嫤鎴櫒涔嬮棿瀹屽叏瑙h棔錛屾洿濂界殑瀹炵幇浜嗙粍浠跺寲銆?/SPAN> |
楠岃瘉澶勭悊 |
Struts鐨勯獙璇佹槸璋冪敤FormBean鐨?/SPAN>validator()鏂規硶錛屽叾瀹炲氨鏄FormBean鐨勯獙璇併傚畠涓鑸嬌鐢ㄦ鏋?/SPAN>Commons Validation榪涜鏁版嵁楠岃瘉澶勭悊銆傚畠浣跨敤浜嗕竴涓叏灞鐨勯厤緗枃浠?/SPAN>validation.xml瀹氫箟浜?/SPAN>FormBean鐨勯獙璇佷俊鎭?/SPAN>Struts鐨?/SPAN>FormBean灞炴ч兘琚涓烘槸String綾誨瀷錛屾墍浠ュ畠鍦ㄩ獙璇佹椂涔熼渶瑕侀澶栫殑綾誨瀷杞寲銆?/SPAN> |
WebWork浣跨敤Xwork鐨勯獙璇佹鏋惰繘琛岄獙璇佸鐞嗭紝瀹冨彲浠ラ氳繃閰嶇疆鎷︽埅鍣ㄦ潵嬋媧匯傚畠鍙互涓烘瘡涓渶瑕侀獙璇佺殑Class鎸囧畾涓涓?/SPAN>xml楠岃瘉鏂囦歡錛屼篃鍙互涓轟竴涓?/SPAN>Class鍦ㄤ笉鍚岀殑鎯呭喌鎸囧畾涓嶅悓鐨?/SPAN>xml楠岃瘉鏂囦歡銆?/SPAN>WebWork璇佸彲浠ョ粰姣忎釜Action綾繪寚瀹氬搴旂殑楠岃瘉鏂囦歡錛屼篃鍙互緇?/SPAN>Action鐨勫瓧孌靛幓鎸囧畾楠岃瘉鏂囦歡銆傞氳繃鎷︽埅鍣ㄦ潵緇勮Action鍜屽叾楠岃瘉鏂囦歡錛屼嬌瀹冧滑涔嬮棿瀹屽叏瑙h棔銆?/SPAN> |
瀵?/SPAN>Action鎵ц鐨勬帶鍒?/SPAN> |
Struts鍒涘緩涓涓?/SPAN>Action錛屽鏋滄兂鎺у埗瀹冪殑鎵ц欏哄簭灝嗕細闈炲父鍥伴毦銆傜敋鑷充綘瑕侀噸鏂板幓鍐?/SPAN>Servlet鏉ュ疄鐜頒綘鐨勮繖涓姛鑳介渶姹傘?/SPAN> |
鍦ㄨ繖涓柟闈紝WebWork鐨勬嫤鎴櫒鏍堟彁渚涗簡寮哄ぇ鐨勫姛鑳姐?/SPAN>Action鐨勬墍鏈夊垏闈㈠姛鑳介兘鏈夋嫤鎴櫒鏉ュ疄鐜幫紙姣斿錛氬彇寰?/SPAN>request璇鋒眰鍙傛暟銆侀獙璇佸鐞嗙瓑錛夛紝榪欐牱浣犲氨鍙互鐢ㄦ嫤鎴櫒鏍堟潵緇勭粐鎷︽埅鍣ㄧ殑鎵ц欏哄簭銆備緥濡傦細浣犻渶瑕佸湪浣跨敤request璇鋒眰鍙傛暟鏉ヨ緗?/SPAN>Action灞炴т箣鍓嶏紝浣跨敤IoC妗嗘灦璁劇疆Action鐨勫睘鎬э紝鍙嶄箣宸茬劧銆傝繖鏃訛紝浣犲氨鍙互涓?/SPAN>package鎴?/SPAN>Action鎸囧畾涓涓嫤鎴櫒鏍堟潵瀹炵幇銆?/SPAN> |
Feature |
Struts |
WebWork 1.x |
WebWork 2.x |
Action classes |
Struts requires Action classes to extend an Abstract base class. This shows a common problem in Struts of programming to abstract classes instead of interfaces. |
Action classes must implement the webwork.Action Interface. There are other Interfaces which can be implemented for other services, such as storing error messages, getting localized texts, etc. The ActionSupport class implements many of these Interfaces and can act as a base class. WebWork is all written to Interfaces, which allows for plugging in your own implementations. |
An Action must implement the com.opensymphony.xwork.Action Interface, with a series of other Interfaces for other services, like in WebWork 1.x. WebWork2 has its own ActionSupport to implement these Interfaces. |
Threading Model |
Struts Actions must be thread-safe because there will only be one instance to handle all requests. This places restrictions on what can be done with Struts Actions as any resources held must be thread-safe or access to them must be synchronized. |
WebWork Actions are instantiated for each request, so there are no thread-safety issues. In practice, Servlet containers generate many throw-away objects per request, and one more Object does not prove to be a problem for performance or garbage collection. |
ditto |
Servlet Dependency |
Struts Actions have dependencies on Servlets because they get the ServletRequest and ServletResponse (not HttpServletRequest and HttpServletResponse, I've been told) when they are executed. This tie to Servlets (although not Http*) is a defacto tie to a Servlet container, which is an unneeded dependency. Servlets may be used outside a Web context, but it's not a good fit for JMS, for instance. |
WebWork Actions are not tied to the web or any container. WebWork actions CAN choose to access the request and response from the ActionContext, but it is not required and should be done only when ABSOLUTELY neccessary to avoid tieing code to the Web. |
ditto |
Testability |
Many strategies have sprung up around testing Struts applications, but the major hurdle is the fact that Struts Actions are so tightly tied to the web (receiving a Request and Response object). This often leads people to test Struts Actions inside a container, which is both slow and NOT UNIT TESTING. There is a Junit extension : Struts TestCase (http://strutstestcase.sourceforge.net/) |
WebWork actions can be tested by instantiating your action, setting the properties, and executing them |
ditto, but the emphasis on Inversion of Control makes testing even simpler, as you can just set a Mock implementation of your services into your Action for testing, instead of having to set up service registries or static singletons |
FormBeans |
Struts requires the use of FormBeans for every form, necessitating either a lot of extra classes or the use of DynaBeans, which are really just a workaround for the limitation of requiring FormBeans |
WebWork 1.x allows you to have all of your properties directly accessible on your Action as regular Javabeans properties, including rich Object types which can have their own properties which can be accessed from the web page. WebWork also allows the FormBean pattern, as discussed in "WW1:Populate Form Bean and access its value" |
WebWork 2 allows the same features as WebWork 1, but adds ModelDriven Actions, which allow you to have a rich Object type or domain object as your form bean, with its properties directly accessible to the web page, rather than accessing them as sub-properties of a property of the Action. |
Expression Language |
Struts 1.1 integrates with JSTL, so it uses the JSTL EL. This EL has basic object graph traversal, but relatively weak collection and indexed property support. |
WebWork 1.x has its own Expression language which is built for accessing the ValueStack. Collection and indexed property support are basic but good. WebWork can also be made to work directly with JSTL using the Filter described in WW1:Using JSTL seamlessly with WebWork |
WebWork 2 uses XW:Ognl which is a VERY powerful expression language, with additions for accessing the value stack. Ognl supports very powerful collection and indexed property support. Ognl also supports powerful features like projections (calling the same method on each member of a collection and building a new collection of the results), selections (filtering a collection with a selector expression to return a subset), list construction, and lambda expressions (simple functions which can be reused). Ognl also allows access to static methods, static fields, and constructors of classes. WebWork2 may also use JSTL as mentioned in WW1:Using JSTL seamlessly with WebWork |
Binding values into views |
Struts uses the standard JSP mechanism for binding objects into the page context for access, which tightly couples your view to the form beans being rendered |
WebWork sets up a ValueStack which the WebWork taglibs access to dynamically find values very flexibly without tightly coupling your view to the types it is rendering. This allows you to reuse views across a range of types which have the same properties. |
ditto |
Type Conversion |
Struts FormBeans properties are usually all Strings. Struts uses Commons-Beanutils for type conversion. Converters are per-class, and not configurable per instance. Getting a meaningful type conversion error out and displaying it to the user can be difficult. |
WebWork 1.x uses PropertyEditors for type conversion. PropertyEditors are per type and not settable per Action, but field error messages are added to the field error map in the Action to be automatically displayed to the user with the field. |
WebWork2 uses Ognl for type conversion with added converters provided for all basic types. Type converters default to these converters, but type conversion can be specified per field per class. Type conversion errors also have a default error message but can be set per field per class using the localization mechanism in WW2 and will be set into the field error messages of the Action. |
Modular Before & After Processing |
Class hierarchies of base Actions must be built up to do processing before and after delegating to the Action classes, which can lead deep class hierarchies and limitations due to the inability to have multiple inheritance WW:Comparison to Struts#1 |
Class hierarchies |
WebWork 2 allows you to modularize before and after processing in Interceptors. Interceptors can be applied dynamically via the configuration without any coupling between the Action classes and the Interceptors. |
Validation |
Struts calls validate() on the FormBean. Struts users often use Commons Validation for validation. I don't know a lot about this, so I'll put some questions here: |
WebWork1.x calls the validate() method on Actions, which can either do programmatic validations or call an outside validation framework (this is apparently the same as Struts) |
WebWork2 can use the validate() method of WebWork and Struts and / or use the XW:Validation Framework, which is activated using an XWork Interceptor. The Xwork Validation Framework allows you to define validations in an XML format with default validations for a class and custom validations added for different validation contexts. The Xwork Validation Framework is enabled via an Interceptor and is therefore completely decoupled from your Action class. The Xwork Validation Framework also allows you to chain the validation process down into sub-properties using the VisitorFieldValidator which will use the validations defined for the properties class type and the validation context. |
Control Of Action Execution |
As far as I know Struts sets up the Action object for you, and you have very little control over the order of operations. To change them I think |
The ActionFactory chain controls the order in which an Action is constructed and initialised, but this requires writing a class |
The interceptor stacks in WebWork 2 are hugely powerful in this regard. All aspects of Action setup have been moved into Interceptor implementations (ie setting paramters from the web, validation etc), so you can control on a per action basis the order in which they are performed. For example you might want your IOC framework to setup the action before the parameters are set from the request or vice versa - you can thusly control this on a per package or per action basis with interceptor stacks. |
My search criteria for all of these was "framework and java" from the front page on dice.com. I did filter a bunch out for WebWork b/c there's some product called "WebWorks" that folks want to hire for.
In my own experience, these numbers are not as accurate as you might think. Since I gave my original presentation, I've been contacted a number of times to work on projects. It's about even between Struts, Spring MVC, WebWork and JSF. I haven't had a single inquiry to do Tapestry development. The bad part about Struts jobs is there's so many of them, that rates are likely pretty low (i.e. 35-45/hour), whereas the others can get you upwards of 80-90/hour.
渚濇垜涓漢鐨勭粡楠岋紝榪欎簺鏁板瓧涓嶄竴瀹氬氨寰堝噯紜?鑷粠鎴戝彂琛ㄧ涓綃囦粙緇嶄互鏉ワ紝鎴戝凡緇忓湪欏圭洰涓嬌鐢ㄤ簡濂藉嬈★紝鍖呮嫭Struts, Spring MVC錛?WebWorks 鍜孞SF錛?鎴戣繕娌℃湁鍋歍apestry寮鍙戙?Struts涓嶅ソ鐨勬柟闈㈠氨鏄お澶氫簡錛屽叾宸ヨ祫鍙兘紼嶅井浣庝竴鐐癸紙35/45/hour) ,鑰岀敤鍏朵粬妗嗘灦鑳戒嬌浣犳彁楂樺埌80-90/hour銆?/FONT>
So what do these numbers mean? Do they mean you should tailor your learnings and skills to the most popular frameworks? In a sense, it's important to do so. If nothing else, Struts skills are import so you can migrate all the Struts applications to your favorite framework. However, I don't think these numbers are that important when choosing a framework to start your project with. I think the most important thing in choosing a framework is passion. Which one do you want to work with the most? It's likely that your productivity will be higher if you're enthusiastic about the framework, rather than bored with all the skills you've accumulated using it. Then again, if you're motivated by productivity more than enthusiasm - using your skills to crank out applications quickly is probably a good idea.
閭d箞榪欎簺鏁板瓧鎰忓懗鐫鎴戜滑搴旇鍋氫粈涔堝憿錛熸槸涓嶆槸鎰忓懗鐫搴旇瀛︿範閭d簺鏈嫻佽鐨勬鏋訛紵涔嶇溂鐪嬫潵錛岃繖鏍峰仛鏄緢閲嶈鐨勩?濡傛灉娌℃湁鍒殑錛孲truts鏄緢閲嶈鐨勶紝騫朵笖浣犲彲浠ュ皢浣犳墍鏈夌殑Struts搴旂敤榪佺Щ鍒頒綘閽熺埍鐨勬鏋朵腑銆備笉榪囷紝鎴戣涓鴻繖浜涙暟瀛楀浣犻夋嫨涓縐嶆鏋跺紑濮嬩綘鐨勯」鐩潵璇翠笉鏄噸瑕佺殑銆傛垜鎯沖湪閫夋嫨涓縐嶆鏋舵椂鏈閲嶈鐨勬槸passion錛堟縺鎯咃級銆備綘鏈鎯充嬌鐢ㄥ摢涓涓鏋跺伐浣滃憿錛熸垨璁稿鏋滀綘瀵逛竴涓鏋跺緢鐑儏錛屼綘鐨勭敓浜у姏灝嗚幏寰楁瀬澶х殑鎻愰珮錛岃屼笉鏄箯鍛崇殑浣跨敤宸茬粡縐瘡鐨勬妧鏈?鍙﹀錛屽鏋滀綘鐢變簬鐢熶駭鍔涙帹鍔ㄨ屼笉鏄縺鎯咃紝閭d箞榪愮敤浣犲凡縐瘡鐨勬妧鏈幓瀹屾垚欏圭洰鍙兘鏄竴涓ソ涓繪剰銆?/FONT>
You might think that the number of skilled developers for framework X is important too. I don't think it is. I think the most important thing is to hire smart developers. A good developer can come up to speed on any framework in 2 weeks and be highly productive in 4 weeks. If not, the developer isn't that smart or the framework isn't that good.
浣犲彲鑳借涓烘煇涓鏋舵湁緇忛獙鐨勫紑鍙戣呯殑鏁伴噺涔熷緢閲嶈錛屾垜涓嶈繖涔堣涓猴紝鎴戣涓烘渶閲嶈鐨勪簨鎯呮槸闆囩敤綺炬槑鐨勫紑鍙戣呫備竴涓ソ鐨勫紑鍙戜漢鍛樿兘鍦ㄤ袱鍛ㄦ椂闂村唴浣跨敤浠諱綍妗嗘灦錛屽茍涓斿湪鍥涘懆鏃墮棿鍐呰兘鐔熺粌榪愮敤銆?濡傛灉涓嶆槸榪欐牱鐨勮瘽錛?榪欎釜寮鍙戜漢鍛樺氨涓嶆槸綺炬槑鐨勫紑鍙戣咃紝 鎴栬呰繖涓鏋朵笉鏄紭縐鐨勩?/FONT>
Just for kicks, I did some searching for other web frameworks as well:
Now the question is - what kind of rates are these skills getting? I'd like to know what the average Rails and ASP .NET developers make. In Denver, Java developers seem to make between 65-85/hour when they're experienced contractors