锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
澶ч儴鍒嗕唬鐮佷篃鏄弬鑰冩枃涓殑銆?
鍦ㄤ綘鐨凟ntryPoint涓閰嶅ソ浣犵殑indicator
榪欐牱璋冪敤銆?
]]>
When a GWT application loads, nothing is actually displayed by your application until all the generated JavaScript has been downloaded by the browser. I was looking for way to display a loading screen while my GWT application was loading, and then remove it once the GWT application is loaded.
Since every GWT application has to be embedded in an HTML Host Page, an easy way to display a loading message is to place the loading message in a <div> in the HTML Host Page. Once all the GWT application JavaScript is done loading, we can have the GWT application remove the loading message by doing some DOM manipulation on the HTML Host Page.
Here is a sample HTML Host Page. The loading message, along with a loading animation image is contained in a <div> named “Loading-Message”.
1: <html>
2:
3: <head>
4: <title>GWT Application</title>
5: <link rel="stylesheet" href="style.css">
6: </head>
7:
8: <body>
9:
10: <script type="text/javascript" language="javascript" src="gwtapp.nocache.js"></script>
11:
12: <h2>GWT Application</h2>
13:
14: <!-- The loading message div -->
15: <div id="Loading-Message">
16: <img src="loading-animation.gif" alt="loading"> Loading GWT Application, please wait...
17: </div>
18:
19: <!-- The Application's UI elements will be placed in this div by the Application module's -->
20: <!-- entry point class when it is loaded -->
21: <div id="GWT-Application-Panel">
22: </div>
23:
24: </body>
25:
26: </html>
The “Loading-Message” <div> can be removed from the HTML Host Page using the following line of Java Code:
DOM.setInnerHTML(RootPanel.get("Loading-Message").getElement(), "");
Where would you put this line of code? You can put it anywhere in your GWT application. However, a good place to put it would be in your GWT application EntryPoint class’s onModuleLoad method. You can place it either before or after your application loads the UI elements. Here is an example onModuleLoad method:
1: public void onModuleLoad() {
2: // Remove the loading message
3: DOM.setInnerHTML(RootPanel.get(“Loading-Message”).getElement(), “”);
4:
5: // Get the Application Container div from the DOM
6: mainPanel = RootPanel.get(“GWT-Application_Panel”);
7:
8: // Add GWT UI components
9: addWidgetsTo(mainPanel);
10: }
If you aren’t the artistic type, here is a website you can use to download a customized animation image. Here is another website, where you can select some existing animations to use in your app.
If you haven’t already, please check out our continuing series of GWT Tutorials beginning with Introduction to GWT. You can find the rest of our GWT tutorials here.
蹇犲憡涔嬩竴: 鍒嗚屾不涔?
浼楁墍鍛ㄧ煡錛孏WT搴旂敤灝辨槸Java搴旂敤銆備笉榪囷紝闂鍦ㄤ簬鏄?#8220;鍝Java”錛屾垜浠渶瑕佺墷璁? GWT緙栬瘧鐨勬槸涓嶫2SE 1.4.2鎴栬呮洿鏃╃増鏈吋瀹圭殑Java婧愪唬鐮併傚彟澶栵紝鍙湁J2SE 1.4.2 API鐨勫瓙闆嗗緱鍒版敮鎸侊紝鍗砵ava.lang鍜宩ava.util紼嬪簭鍖呫傚嵆渚垮湪浣跨敤榪欎簺紼嬪簭鍖呮椂錛屼篃瑕侀潪甯歌鐪熷湴鐮旂┒Google鍦ㄨ繍琛屽簱鏀寔鏂歸潰鐨勬敞 閲婏紝騫朵笖鐗㈣鐩稿簲鐨勫繝鍛? 濡傛灉紜繚浠庝竴寮濮嬪氨鍙嬌鐢ㄥ鎴風浠g爜涓殑鍙漿鎹㈢被錛岄偅涔堝氨鍙互閬垮厤璁稿闂銆備負浜嗗強鏃╁彂鐜伴棶棰橈紝鍙鍦ㄥ涓繪ā寮忥紙hosted mode錛変笅榪愯錛屽氨瑕佸鐓RE浠跨湡搴撴楠屼唬鐮併傚洜鑰岋紝絎竴嬈¤繍琛屽簲鐢ㄦ椂錛屽氨浼氬彂鐜板ぇ閮ㄥ垎涓嶆敮鎸佺殑搴撱傛墍浠ワ紝瑕佸強鏃╁茍涓旂粡甯歌繍琛屻?
鐜板湪錛岀瑪鑰呯粰鍑虹殑蹇犲憡灝辨槸“鍒嗚屾不涔?#8221;錛屽叿浣撴剰鎬濆氨鏄竴寮濮嬪氨鎶婂簲鐢ㄤ唬鐮佸垎鎴愪笁涓笉鍚岀殑閮ㄥ垎: 瀹㈡埛绔唬鐮併丷PC鐩稿叧浠g爜鍜屾湇鍔″櫒绔唬鐮侊紝鐒跺悗鏋勫緩鐩稿簲鐨凟clipse欏圭洰錛屼粠鑰屽畬鎴愪換鍔°傝繖鏍蜂竴鏉ワ紝灝卞彲浠ュ埄鐢ㄤ笉鍚岀殑Java璇█鐗堟湰錛岀敤浜庡鎴風 鍜屾湇鍔″櫒閮ㄥ垎銆傜瑪鑰呯敤Java 5鏋勫緩浜嗗簲鐢ㄧ殑鏈嶅姟鍣ㄩ儴鍒嗭紙鏈嶅姟鍣ㄥ皬紼嬪簭浠g爜錛? 浣嗗鏋滀嬌鐢∕ustang鐗堟湰錛岄偅涔堝湪鏈枃鐨勪唬鐮佺墖孌典腑錛堢敱浜庣瘒騫呮湁闄愶紝鏈枃鎵娑夊強鐨勭▼搴忎唬鐮佸彲閫氳繃浠ヤ笅閾炬帴鏌ヨ: http://blog.ccw.com.cn/article-htm-itemid-17924-type-blog.html錛夛紝鍙互鐢↗ava 6鍙栦唬Java 5銆傚嵆渚垮湪鏈嶅姟鍣ㄧ浠嶇劧浣跨敤J2SE 1.4.2錛岃繖縐嶅垎娌繪硶涔熷彲浠ュ湪灝嗘潵鎻愪緵鏇村ぇ鐨勭伒媧繪э紝鏄庣‘鍒嗙浠g爜錛?#8220;鍒嗙闂”錛夛紝鑰屼笉浼氬湪GWT瀹夸富妯″紡涓嬮檺鍒惰皟璇曟搷浣溿傚鏋滄墍鏈夐儴鍒嗛兘鍦ㄤ竴涓? Eclipse欏圭洰涓紝鍒欓渶瑕侀潪甯鎬弗璋紝鐗瑰埆鏄湪鏈嶅姟鍣ㄧ涓? 涓嶇劧錛屽氨浼氬嚭鐜扮紪璇戞垨鑰呰繍琛岄棶棰樸?
闇瑕佷嬌鐢ㄧ壒孌婄殑鍛藉悕綰﹀畾錛岃繖鏍峰彲浠ユ竻妤氱‘璁や笉鍚岄」鐩紝騫朵笖綆鍖栭儴緗茶剼鏈傚彲浠ヤ嬌鐢ㄨ濡傚悕涓篏WT-< ModuleName>鐨凟clipse宸ヤ綔闆嗘潵鍖呮嫭鎵鏈変笁涓」鐩傝繖閲岋紝“ModuleName”鏄瘑鍒玏eb搴旂敤鐨凣WT妯″潡鐨勫悕縐般?
鈼?瀹㈡埛绔唬鐮? 鍖呭惈涓庣敤鎴風晫闈㈢浉鍏崇殑浠g爜錛屽彲浠ヨ漿鎹㈡垚JavaScript銆傚洜姝わ紝灞闄愪簬J2SE 1.4.2鍜孏WT榪愯鏃舵敮鎸併傚惎鐢ㄦ瘡涓」鐩殑Eclipse Java緙栬瘧鍣ㄨ緗拰“Java緙栬瘧鍣ㄩ敊璇?璀﹀憡”錛屾妸Java渚濅粠綰у埆璋冩暣鍒?.4銆佹妸婧愪唬鐮佸拰綾繪枃浠跺吋瀹規ц皟鏁村埌1.4錛堝亣璁句笉鏄嬌鐢?.4涔嬪墠鐨? JDK鐗堟湰錛夈傝欏圭洰鐨勫悕縐版槸< ModuleName>-client錛岃濡?#8220;JUnit2MR-client”錛屽畠渚濊禆浜庢瀯寤鴻礬寰勮緗腑鐨?lt; ModuleName>-rpc欏圭洰銆傜▼搴忓寘鍚嶇О綾諱技< com.company.project>.gwt.< moduleName>.client銆?
鈼?RPC鐩稿叧浠g爜: 鍖呭惈RPC鐩稿叧鐨勪唬鐮侊紝鍙互杞崲鎴怞avaScript銆傝欏圭洰閬典粠涓庝笂榪板鎴風浠g爜欏圭洰鍚屾牱鐨勬寚瀵煎噯鍒欍傞」鐩悕鏄?lt; ModuleName>-rpc錛岃濡?#8220;JUnit2MR-rpc”錛屽畠騫朵笉渚濊禆浜庡叾浠栦換浣曢」鐩傜▼搴忓寘鍚嶇О涓?lt; ModuleName>-client欏圭洰鐨勭▼搴忓寘鍚嶇О涓鏍楓俁PC欏圭洰鍖呭惈瀹㈡埛绔笂鐨勮繙紼嬫帴鍙c丷PC鏈熼棿鐢盙WT榪涜搴忓垪鍖栫殑鏁版嵁浼犺緭瀵硅薄錛屼互 鍙婂叏灞甯擱噺綾匯?
鈼?鏈嶅姟鍣ㄧ浠g爜: 鍚湁鏈嶅姟鍣ㄥ皬紼嬪簭浠g爜錛屽鏋滄湇鍔″櫒绔敱Java鏈嶅姟鍣ㄥ皬紼嬪簭緇勬垚鐨勮瘽銆傚鏋滀嬌鐢═omcat 5.5鎴栬匱omcat 6錛屽彲浠ュ厖鍒嗗埄鐢↗ava 5+鐨勫叏閮ㄥ姛鑳姐傚惎鐢ㄦ瘡涓」鐩殑Eclipse緙栬瘧鍣ㄨ緗紝鐒跺悗浣跨敤Java 5緙栬瘧鍣ㄨ緗紝渚濅粠綰у埆璁劇疆涓?.0銆傚鏋滀嬌鐢‥clipse 3.2.2錛岄偅涔堝叾鏂扮殑“婧愪唬鐮?#8594;娓呯悊”鐗規т篃鍊煎緱閰嶇疆銆傝欏圭洰鍚嶇О鏄?lt; ModuleName>-server錛岃濡?#8220;JUnit2MR-server”錛屽畠渚濊禆浜庢瀯寤鴻礬寰勮緗腑鐨?lt; ModuleName>-rpc欏圭洰銆傚鏋滄寜鐓WT鐨勯粯璁ょ▼搴忓寘鎻愭榪涜緙栫▼錛岀▼搴忓寘鍚嶇О鏄?lt; com.company.project>.gwt.< moduleName>.server銆?
蹇犲憡涔嬩簩: 璋冭瘯鍜岄敊璇姤鍛婁笉浠呬粎鍙湁Window.alert ()
鍦ㄥ垱寤篏WT搴旂敤鏃訛紝鍏跺疄鍙互浣跨敤IDE鐨勫叏閮ㄨ皟璇曞姛鑳姐備絾鍦ㄦ繁鍏ュ垎鏋愪綍澶勫彲鑳藉嚭鐜伴敊璇箣鍓嶏紝闇瑕佷唬鐮佺殑瀹㈡埛绔拰 鏈嶅姟鍣ㄧ閮芥湁鍙潬鐨勫紓甯告姤鍛婃満鍒躲備嬌鐢╰ry/catch浠g爜鍧楅氬父鍙互鍋氬埌榪欎竴鐐廣傚湪瀹㈡埛绔殑catch浠g爜鍧椾腑錛屽簲褰撴敞鎰忚繖涓鐜板疄: 榛樿鐨勬柟娉曡皟鐢╡.printStackTrace()騫朵笉鏄湪鎵鏈夋儏鍐典笅閮介傚悎鐨勮В鍐沖姙娉曘傚畠閫傜敤浜庡簲鐢ㄨ繍琛屽湪GWT瀹夸富妯″紡涓嬶紝鎶婃枃鏈緭鍑哄埌 Eclipse鎺у埗鍙般備笉榪囧湪Web妯″紡涓嬶紝瑕侀棶闂嚜宸? “鎴戝彂閫佸埌stdout鎴栬卻tderr鐨勫爢鏍堣窡韙俊鎭拰閿欒淇℃伅浼氬湪浠涔堝湴鏂規樉紺猴紵”涓縐嶅彲鑳界殑瑙e喅鏂規硶灝辨槸浣跨敤Mat Gessel鐨勮皟璇曞疄鐢ㄧ▼搴忕被錛坔ttp://www.asquare.net/gwttk錛夛紝浣嗘槸闇瑕佹祻瑙堝櫒JavaScript鎺у埗鍙版潵鏌ョ湅Web妯? 寮忎笅鐨勭粨鏋溿?
鍦ㄥ鎴風錛屽緩璁鍋氱殑涓浠朵簨灝辨槸錛屼嬌鐢℅WT.setUncaughtExceptionHandler()鏂? 娉曪紝涓轟換浣曟湭琚彂鐜扮殑寮傚父鎻愪緵鑷繁鐨勫紓甯稿鐞嗙▼搴忋傚彂鐜頒簡榪欏嚑縐嶅紓甯稿悗錛屾湁鍑犱釜閫夋嫨: GWT.log錛坢essage, caught錛夈丏ebug.println (message_with_stacktrace); 濡傛灉浣跨敤Mat Gessel鐨凞ebug綾伙紝鍙夋嫨Window.alert錛坢essage_with_stacktrace錛夛紝鎴栬呰嚜宸卞畾鍒剁殑閿欒鎶ュ憡銆?
瑙嗘潵婧愯屽畾錛屼細寰楀埌“鏃犳硶瑁呭叆妯″潡”鎴栬?#8220;鏈鍙戠幇鐨勫紓甯歌婕忚繃”鐨勪俊鎭傜瑪鑰呯紪鍐欎簡涓涓皬灝忕殑DebugUtility綾伙紝瀹冩彁渚涗簡鏄撲簬瀹氬埗鐨勯粯璁ゅ鎴風閿欒澶勭悊鏈哄埗錛堣浠g爜鐗囨1錛夈?
鍦ㄦ湇鍔″櫒绔紝鍙互浣跨敤java.util.logging API鎴栬卨og4j鐨勫箍娉涘姛鑳斤紝鍏蜂綋鍙栧喅浜庝釜浜哄亸濂芥垨鑰呴」鐩殑綰︽潫鏉′歡銆備絾瑕佹槸娌℃湁涓篏WT鐨? com.google.gwt.user.server.rpc.RemoteServiceServlet綾繪墦琛ヤ竵錛屽浜庢湭琚彂鐜般佹湭琚鏌ョ殑寮傚父錛屽彧 浼氬湪鍫嗘爤璺熻釜閲岄潰寰楀埌鎻愮ず錛屾寚鍚戠敓鎴愯閿欒鐨勬湇鍔″櫒绔被銆傚浜巆atch()浠g爜鍧楅噷闈㈠彂鐜板強鎶ュ憡鐨勮媯鏌ョ殑寮傚父錛屼竴鍒囬兘姝e父銆?
蹇犲憡涔嬩笁: 褰撳績GWT Shell鐨?#8220;鍒鋒柊”鎸夐挳闄烽槺
鍦ㄥ涓繪ā寮忎笅鍚姩搴旂敤鏃訛紝浼氬湪嫻忚鍣ㄤ換鍔℃爮涓婄湅鍒?#8220;鍒鋒柊”鎸夐挳銆傝鏄憗浜嗚繖涓寜閽紝GWT灝變細鎶婁慨鏀硅繃鐨凧ava 瀹㈡埛绔簮浠g爜閲嶆柊緙栬瘧鎴怞ava瀛楄妭鐮侊紙浣滀負.gwt.-cache/bytecode鐩綍涓殑.tmp鏂囦歡錛夛紝鐒跺悗閲嶆柊瑁呭叆妯″潡銆傚彲浠ヤ嬌鐢ㄨ繖涓寜閽潵緙? 鐭紪杈?#8594;緙栬瘧→璋冭瘯鍛ㄦ湡錛屼絾鍦ㄤ嬌鐢ㄨ繖欏圭壒鎬ф椂瑕佺墷璁板嚑涓柟闈?
鈼?鍙湁淇敼榪囩殑婧愪唬鐮佹墠閲嶆柊緙栬瘧錛屼篃灝辨槸璇達紝涓嶄細涓轟緷璧栦慨鏀硅繃浠g爜鐨勬枃浠剁敓鎴愭柊鐨勫瓧鑺傜爜銆傛墍浠ワ紝濡傛灉鏀瑰彉浜嗗叏灞甯擱噺鐨勫鹼紝鍋囪public final int瀛楁鐨勫鹼紝涓嶄細绔嬪嵆鍦ㄧ浉鍏蟲枃浠剁湅鍒拌繖涓彉鍖栥?
鈼?鍙湁淇敼榪囩殑婧愪唬鐮佹墠鐢盙WT閲嶆柊緙栬瘧銆傝繖鎰忓懗鐫錛屽嵆渚縀clipse IDE閲岄潰鐨?#8220;Project clean”涔熷府涓嶄笂蹇? 瑕佸獎鍝嶅埌鎵鏈夌殑鐩稿叧婧愪唬鐮侊紝璀閫氳繃娣誨姞鏂扮殑絀鴻銆?
鍥犱負榪欎釜榪囩▼鐩稿綋絎ㄦ嫏錛岀瑪鑰呯殑蹇犲憡鏄湪淇敼鍏ㄥ眬甯擱噺鏃墮伒寰互涓嬪洓涓楠?
1錛庡湪鐩稿簲鐨勬簮鏂囦歡閲岄潰鏀瑰彉public final constant鍊?
2錛庨噸鏂扮紪璇戞敼鍙樺悗鐨勬簮浠g爜;
3錛庣Щ闄ゆ暣涓?lt; ModuleName>-client/.get-cache/bytecode鐩綍錛屼粠鑰屽垹闄WT緙撳瓨鍐呭;
4銆佷嬌鐢‥clipse閲岄潰鐨?#8220;Run as”錛岄噸鏂板紑濮嬪惎鍔ㄥ簲鐢紝浠庤屽垱寤哄甫閲嶆柊緙栬瘧鍚庡瓧絎︾爜鐨勬柊GWT緙撳瓨鍐呭錛岃繖縐嶆儏鍐典笅錛屾渶濂藉拷瑙?#8220;鍒鋒柊”鎸夐挳錛屼笉榪囧湪鏈変簺鎯呭喌涓嬶紝鍒犻櫎鏁翠釜< ModuleName>-client/.get-cache/bytecode鐩綍鍚庡彲浠ヤ嬌鐢?#8220;鍒鋒柊”鎸夐挳銆?
鍦ㄤ慨鏀規湇鍔″櫒绔唬鐮佹椂錛孏WT瀛楄妭鐮佺紦瀛樺唴瀹逛笉鍙楀獎鍝嶃備笉榪囷紝宓屽叆鐨凾omcat瀹炰緥浼氱紦瀛樺畠錛屽洜鑰屽湪浣跨敤“鍒鋒柊”鎸夐挳鍚庯紝鍙湁閲嶆柊寮濮嬪惎鍔ㄥ簲鐢ㄥ悗鏈鍒濇敼鍙樼殑浠g爜鎵嶄細寰楀埌璁ゅ彲銆傛墍浠ヤ負浜嗗畨鍏ㄨ搗瑙侊紝鏀瑰彉鏈嶅姟鍣ㄧ浠g爜鍚庯紝鏈濂借繕鏄噸鏂板紑濮嬪惎鍔ㄥ簲鐢ㄣ?
蹇犲憡涔嬪洓: 鍦ㄥ涓繪ā寮忎笅璇誨彇Servlet Init鍙傛暟
鍦ㄥ鐞嗘暟鎹簱緋葷粺鏃訛紝涓鑸笉甯屾湜鏈嶅姟鍣ㄥ皬紼嬪簭婧愪唬鐮佷腑鏈夌‖緙栫爜鐨勬暟鎹簱榪炴帴鍙傛暟銆傞氬父浼氫粠灞炴ф枃浠惰鍙栬繖浜涘弬鏁? 鎴栬呮洿濂界殑鏄紝鎶婂畠浠綔涓篿nit鍙傛暟鎻愪緵緇欐湇鍔″櫒灝忕▼搴忥紙浣滀負搴旂敤鐨刉eb.xml鏂囦歡鐨勪竴閮ㄥ垎錛夈傚鏋滃湪Web妯″紡涓嬭繍琛屽簲鐢ㄩ偅娌℃湁浠涔堬紝浣嗗湪瀹夸富妯? 寮忎笅浼氬嚭闂錛岃繖鏄敱浜嶨WT瀹夸富妯″紡涓嬬殑鏈嶅姟鍣ㄥ皬紼嬪簭澶勭悊瀛樺湪闄愬埗銆?
濂芥秷鎭槸錛屽彧瑕佷慨鏀圭敱宓屽叆寮廡omcat瀹炰緥浣跨敤鐨刉eb.xml鏂囦歡錛屽氨鍙互瑙e喅榪欎釜闂銆備負姝わ紝淇? 鏀?lt; ModuleName>-client/tomcat/webapps/ROOT/WEB-INF鐩綍涓殑Web.xml鏂囦歡錛堟垨鑰呭繀瑕佹椂鍒涘緩涓 涓級: 闄や簡宓屽叆寮廡omcat鐨凣WTShellServlet鏄犲皠澶栵紝娣誨姞甯︽湁init鍙傛暟鐨勪笂涓嬫枃閮ㄥ垎銆傚洜涓轟笂涓嬫枃淇℃伅鏄?#8220;鍏ㄥ眬鎬х殑”錛岃屼笉鏄拡瀵圭壒瀹氱殑鏈? 鍔″櫒灝忕▼搴忥紝鍦ㄨ繖閲屽彧鏈変竴閮ㄥ垎鐨刬nit鍙傛暟淇℃伅錛屾垨鑰呬嬌鐢ㄧ壒孌婄殑鍛藉悕鏂規錛屾妸鍙傛暟涓庝笉鍚岀殑鏈嶅姟鍣ㄥ皬紼嬪簭鑱旂郴璧鋒潵銆傚鏋滀嬌鐢ㄨ繖涓柊鐨剋eb.xml鏂囦歡錛? 鍙互鍒犻櫎src/web/WEB-INF鏂囦歡澶逛腑鐨勯偅涓棫鏂囦歡銆?
鍦ㄦ湇鍔″櫒灝忕▼搴忎唬鐮佷腑錛岃闂甶nit鍙傛暟鐨勬柟寮忎笌Web妯″紡涓嬭鍙栧畠浠殑鏂瑰紡涓鏍鳳紝璀final String host = getInitParameter("host")銆傜瑪鑰呭疄鐜拌繖涓鐐圭殑鍔炴硶灝辨槸淇敼GWT鐨凴emoteServiceServlet錛屾柟娉曡窡絎簩涓繝鍛? 閲岄潰鐨勫鍑轟竴杈欍傜幇鍦紝鍙瑕嗙洊GenericServlet鐨刧etInitParameter()鏂規硶錛屼互渚夸嬌鐢? getServletContext()錛岃屼笉鏄?getServletConfig()銆?
鍙︿竴涓繝鍛婃槸錛屽鏋滃湪瀹夸富妯″紡涓嬪拰Web妯″紡涓嬫祴璇曚笉鍚岀殑鏈嶅姟鍣ㄤ唬鐮侊紝鐣ヨ繃Gant鑴氭湰涓殑GWT緙栬瘧閮ㄥ垎錛屼粠“temp”浣嶇疆鎷瘋礉緙栬瘧鍓嶇殑JavaScript浠g爜錛屽垯鍙互鑺傜渷鏃墮棿銆傝繖閫傜敤浜庡鎴風浠g爜澶嶆潅銆佺紪璇戞椂闂磋秴榪?0鍒嗛挓鐨勬儏褰€?
蹇犲憡涔嬩簲: 鍦ㄦ祻瑙堝櫒閲岄潰鏄劇ずPDF鏂囦歡
澶у鏁板疄闄呯殑Web搴旂敤鎻愪緵浜嗙敓鎴愬強闃呰PDF鏂囦歡鐨勬柟娉曘傛湰鏂囧亣璁捐繖涓狿DF鏂囦歡鐢辨湇鍔″櫒灝忕▼搴忕敓鎴愶紝璀閫氳繃 JasperReport銆備互鍚庡彧瑕佺偣鍑繪煇涓秴鏂囨湰閾炬帴錛屽氨鍙互鍦ㄦ祻瑙堝櫒閲岄潰闃呰鐢熸垚鐨勬枃浠躲傚鏋滄兂鍦ㄥ涓繪ā寮忎笅鍜學eb妯″紡涓嬫祴璇曡繖欏圭壒鎬э紝寤鴻閲囧彇浠? 涓嬫楠?
1錛庤璁′竴涓猂PC鎺ュ彛錛屾帴鍙楀憡璇夋湇鍔″櫒鏄湪瀹夸富妯″紡涓嬭繍琛岃繕鏄湪Web妯″紡涓嬭繍琛岀殑甯冨皵鍙傛暟銆傛帴鍙f柟娉曚細榪斿洖鐨勫瓧絎︿覆搴斿綋甯︽湁鏈嶅姟鍣ㄥ皬紼嬪簭鐢熸垚鐨凱DF鏂囦歡鐨勫悕縐幫紙鍗蟲枃浠跺悕鐨勬渶鍚庝竴閮ㄥ垎錛夈?
2錛庢牴鎹唬鐮佺墖孌?鏄劇ず鐨勪唬鐮侊紝瀹炵幇鏈嶅姟鍣ㄥ皬紼嬪簭浠g爜錛岃繖鍙栧喅浜庡竷灝斿弬鏁?#8220;isScript”銆?
3錛庡湪瀹㈡埛绔? 鍦ㄧ獥鍙g粍浠朵唬鐮侀噷闈紝浣跨敤GWT.isScript()鍙傛暟璋冪敤createXyzPDF()鏂規硶錛屼粠鑰岀敓鎴愬寘鍚湇鍔″櫒灝忕▼搴忕粨鏋滃瓧絎︿覆鐨勫閮ㄨ秴鏂囨湰閾炬帴銆?
浠g爜鐗囨4鏄劇ず浜嗘帴鍙f柟娉曞悕涓篶reateSummaryPDF()鐨勭ず渚嬨備粠鏈嶅姟鍣ㄥ皬紼嬪簭榪斿洖鐨勫瓧絎︿覆鏄?#8220;summary.pdf”銆?
榪欏綋鐒朵笉鏄鐞嗚繖縐嶆儏鍐電殑鎯熶竴鍔炴硶錛屼絾鐩墠閫傜敤浜庢垜浠繖涓ず渚嬨傝娉ㄦ剰: 鍦ㄥ涓繪ā寮忎笅鍚姩搴旂敤涔嬪墠錛屽繀欏誨湪< ModuleName>-client project's src/…/public鏂囦歡澶逛腑鑷沖皯鍒涘緩涓涓櫄鍋囩殑“summary.pdf”鏂囦歡錛堟枃浠跺悕浠庢湇鍔″櫒灝忕▼搴忚繑鍥烇級銆備笉鐒訛紝鍦ㄦ祻瑙堝櫒涓偣鍑諱簡瓚呮枃鏈摼鎺? 鍚庯紝GWT璇曞浘璇誨彇PDF鏂囦歡鏃訛紝浼氬嚭鐜?#8220;HTTP 404錛嶆壘涓嶅埌緗戦〉”鐨勪俊鎭?
蹇犲憡涔嬪叚:鍔涙眰鑾峰緱鏃犵姸鎬佹湇鍔″櫒
璁捐瀹㈡埛鏈?鏈嶅姟鍣╓eb搴旂敤鏃惰鑰冭檻鐨勪竴涓叧閿棶棰樺氨鏄? 濡備綍澶勭悊浼氳瘽鍜岀姸鎬佺鐞嗭紵鍦╓eb 1.0鏃朵唬錛岀瓟妗堝緢鏄劇劧: 浼氳瘽鍜岀姸鎬佺鐞嗘槸涓涓湇鍔″櫒闂銆備絾鑻ヤ嬌鐢℅WT錛屽氨鏈夊彟涓涓夋嫨銆傛湇鍔″櫒鍐嶄篃涓嶆槸鍙彁渚汬TML鍐呭鐨?#8220;web”鏈嶅姟銆備嬌鐢℅WT RPC錛屾湇鍔″櫒鐜板湪鍙互鏀寔鍙彁渚涚粨鏋勫寲鏁版嵁鐨勬湇鍔♀斺斺斿湪鏈枃紺轟緥涓紝鏈嶅姟鐢辨湇鍔″櫒灝忕▼搴忓疄鐜般?
閭d箞錛孏WT瀵逛細璇濆拰鐘舵佺鐞嗘湁浣曞獎鍝嶅憿錛烥WT鐨勬妧鏈瀵糂ruce Johnson鍦ㄥ幓騫寸殑JAOO澶т細涓婃寚鍑猴紝鑻ヤ嬌鐢℅WT錛屼細璇濈鐞嗙幇鍦ㄥ簲褰撴槸涓涓鎴風闂銆傞檮鍥炬樉紺虹殑騫葷伅鐗囪瘎榪頒簡縐嶇鍙樺寲銆?
鍦ㄦ湰鏂囩殑JUnit2MR GWT搴旂敤涓紝絎旇呬竴寮濮嬩嬌鐢ㄤ紶緇熸柟娉曟潵澶勭悊鏈嶅姟鍣ㄥ皬紼嬪簭涓殑浼氳瘽鐘舵併備絾榪欐槸鐩稿綋絎ㄦ嫏鐨勪換鍔★紝浜庢槸瀵繪壘鍙︿竴縐嶉夋嫨銆傚洜姝わ紝鐪嬩簡Bruce鐨勫夠鐏墖鍚庯紝鍐? 瀹氶噸鏂拌璁℃暣涓簲鐢ㄣ備絾榪欎竴姝ラ渶瑕佹敼鍙樻墍鏈塕PC鎺ュ彛銆佺紦瀛樼瓥鐣? 鏈閲嶈鐨勬槸錛岃繕瑕佹敼鍙樻墍鏈夌殑鏈嶅姟鍣ㄥ皬紼嬪簭銆傚洜姝ょ瑪鑰呯殑寤鴻鏄? 鍙婃棭鑰冭檻鍦ㄤ綍澶勫疄鏂戒細璇濆拰鐘舵佺鐞嗭紝涓嶅Θ璇曡瘯Bruce Johnson鐨勮瘈紿嶃傛渶緇堜細鏀跺埌鎴愭晥銆?
鐢變簬榪欎釜鍐沖畾錛屽鎴風瀵硅薄涔嬮棿鏈変簡鏇村鐨勮仈緋匯備簬鏄瑪鑰呬嬌鐢ㄤ簡鏈夊悕鐨凣oF涓粙鑰呮ā寮忥紙mediator pattern錛夈備笉榪囷紝鍦ㄥ鎴風鏈変竴浜汮DK 1.4鍜孏WT榪愯搴撶殑闄愬埗銆傚洜姝わ紝閲嶆柊瀹炵幇浜哖ropertyChangeEvent綾誨拰涓粙鑰呮敮鎸侊紝鏉ュ鐞嗙洃鍚▼搴忔敞鍐屽拰娑堟伅騫挎挱銆?
蹇犲憡涔嬩竷: 浣跨敤Selenium瀹炵幇GWT Web嫻嬭瘯鐨勮嚜鍔ㄥ寲
Selenium鏄竴縐嶅紑婧愬伐鍏鳳紝瀹冭兘澶熻交鏉炬祴璇曞寘鍚赴瀵屻佷簰鍔ㄧ殑瀹㈡埛绔唴瀹圭殑Web搴旂敤銆?鎵浠ワ紝瀹冮潪甯擱傜敤浜庢祴璇曞儚鐢℅WT鍒涘緩鐨勫簲鐢ㄩ偅鏍風殑Ajax搴旂敤銆?
褰撶劧錛孏WT閲岄潰浠嶆湁JUnit鍜孞Unit鏀寔鍔熻兘錛岀壒鍒槸閽堝緋葷粺鐨勫紓姝ラ儴鍒嗐傝繖閲岀潃閲嶄粙緇? Selenium錛屽洜涓哄畠鏄撲簬浣跨敤錛堣嚦灝戝畠鐨処DE鏄繖鏍鳳級銆佸姛鑳藉己澶с傛渶鍚庝絾騫墮潪鏈涓嶉噸瑕佺殑涓鐐規槸錛屽畠涓嶫Unit鏈夎澶氬叡鍚屼箣澶勩傚彲浠ヤ嬌鐢? Selenium IDE鏉ヨ褰旼UI鐢ㄤ緥錛岀劧鍚庝嬌鐢ㄥ叾“Play”鐗規ф潵榪愯璁板綍涓嬫潵鐨勬搷浣溿傛瘡涓搷浣滀箣鍚庤窡鐫綾諱技JUnit鐨?#8220;assert”鍛戒護錛岃礋璐g‘璁ら〉闈笂鐨勬煇 浜涙枃鏈傝IDE鏄疐irefox鐨勬墿灞曟彃浠訛紝浣嗗姟蹇呰浣跨敤鏈鏂扮増鏈殑Selenium: Selenium IDE 0 .8 .7錛屽洜涓哄畠鍖呭惈浜?#8220;waitFor…”鍛戒護鐨勯噸澶т慨姝g増銆傝鍒版祴璇旳jax搴旂敤錛岃繖浜涘懡浠や互鍙?#8220;pause”鍛戒護闈炲父閲嶈銆?
蹇犲憡涔嬪叓: 浣跨敤Groovy Gant鑴氭湰閮ㄧ講搴旂敤
鍦℅WT瀹夸富妯″紡涓嬭瘯榪愯搴旂敤錛岃繖紜疄寰堝ソ錛屼絾鎶婂簲鐢ㄩ儴緗插埌搴旂敤鏈嶅姟鍣ㄤ笂鎴栬呯被浼糡omcat鐨勬湇鍔″櫒灝忕▼搴忓鍣? 涓婏紝GWT鐨勭湡瀹炲姛鑳芥墠浼氫綋鐜板嚭鏉ャ傚湪榪欎竴姝ワ紝闇瑕佸垱寤轟竴涓獁ar鏂囦歡錛屽畠浼氳嚜鍔ㄦ嫹璐濆埌Tomcat“webapps”鐩綍銆傚綋鐒訛紝鍙互浣跨敤Ant鍜? ant-contrib榪涜鎵鏈夊繀瑕佺殑鍑嗗銆佺紪璇戙佹嫹璐濆強鍏朵粬浠誨姟銆備絾鐢變簬Ant鑴氭湰鍙樺緱鏇村鏉傚悗錛? ant-contrib鎺у埗緇撴瀯鍜屽睘鎬egex澶勭悊鏈変竴鐐圭鎷欍備簬鏄彲浠ヤ嬌鐢ㄩ泦Groovy鍜孉nt涓よ呬箣鎵闀跨殑Gant銆傚畨瑁匞roovy鍜孏ant 鐢ㄤ笉浜?0鍒嗛挓錛岀劧鍚庯紝浣跨敤鏉ヨ嚜“build.properties”鏂囦歡鐨勬櫘閫氬睘鎬э紝鍗沖彲瀹氬埗“build.gant”鑴氭湰銆傦紙灝忛粦緙栬瘧錛?
錛堣綆楁満涓栫晫鎶?2007騫?鏈?5鏃?絎?4鏈?B22銆丅23錛?
The Google Web Toolkit has been out for a while now, and yet there is still basic functionality that is missing from the toolkit. Don’t get me started on the lack of draggable/resizable columns for the FlexTable, because that’s a rant and a half. Given that GWT’s event handling model isn’t bad, you’d think they’d have included from the get-go the ability to handle right-clicks and bringing up a context menu or popup menu. Well, even with 1.6 on the doorstep it seems they forgot again or just don’t care. Now some people will spout out “web apps don’t need or shouldn’t have right-clicks handled or context menus overridden”……and for those I say STFU! Web apps are used for more than just banking, news, forums and dare I say blogs. The browser is becoming the new medium for running applications and just because an application is running in a browser doesn’t mean we should limit functionality. That’s about as narrow minded as saying that we’ve only had one mouse button for this long, why add a second one? Duh!
Anyway, enough with the blabbing. I’ve put together a simple example
to add a right click context menu and override the default browser
context menu using GWT.
In the box below you can try it out, right-click in there and you can demo it.
|
|
In case the iframe doesn’t show up in your browser you can see and try the example here.
Now here’s how it’s done.
I used a DeckPanel to switch between several panels. The popup context menu is used to choose. To allow the DeckPanel to catch the right-click event (and you can also listen for double-clicks and several other things) I extended the DeckPanel. For simplicity I added “Adv” (Advanced) in front of the several classes I’ve extended so this one will be AdvDeckPanel. The first thing to do in the constructor is add sinkEvents(). Then we’ll override onBrowserEvent() in the class. Here’s the code:
public AdvDeckPanel() {
super();
sinkEvents(Event.ONMOUSEUP | Event.ONDBLCLICK | Event.ONCONTEXTMENU);
}
public void onBrowserEvent(Event event) {
GWT.log("onBrowserEvent", null);
event.cancelBubble(true);//This will stop the event from being propagated
event.preventDefault();
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEUP:
if (DOM.eventGetButton(event) == Event.BUTTON_LEFT) {
GWT.log("Event.BUTTON_LEFT", null);
listener.onClick(this, event);
}
if (DOM.eventGetButton(event) == Event.BUTTON_RIGHT) {
GWT.log("Event.BUTTON_RIGHT", null);
listener.onRightClick(this, event);
}
break;
case Event.ONDBLCLICK:
break;
case Event.ONCONTEXTMENU:
GWT.log("Event.ONCONTEXTMENU", null);
break;
default:
break; // Do nothing
}//end switch
}
Notice the two lines in onBrowserEvent():
event.cancelBubble(true);
event.preventDefault();
These are the two lines that tell the browser not to show it’s default context popup menu. Also note that overriding the default context menu doesn’t work in all browsers, I’m not sure if this is a bug in GWT. If you’re using firefox then you’ll have no problems, with IE you may need to add the following to your html:
<body oncontextmenu="return false;">
Other than that there’s just a switch statement that checks the event type, in this case we’re interested with ONMOUSEUP, and we’ll call the listener’s onClick() or onRightClick() based on the Event’s fields.
AdvDeckPanel also has a reference to AdvClickListener which looks like:
public interface AdvClickListener extends ClickListener {
void onClick(Widget sender, Event event);
void onRightClick(Widget sender, Event event);
}
This reference is basically the same as ClickListener, but has a separate method to handle the right-click. I also pass the Event object so I can get the x and y from the click so the context menu shows up at that location instead of the top-left of the screen.
AdvDeckPanel implements AdvClickNotifier which does the same thing as GWT’s SourcesClickEvents interface, but handles the AdvClickListener instead.
public interface AdvClickNotifier {
public void addClickListener(AdvClickListener listener);
public void removeClickListener(AdvClickListener listener);
}
So, once you have your widget (in this case the AdvDeckPanel) and the listeners set up to handle the right-click, then we add in the code to build the popup menu and commands that go with it. I put all of this in the EntryPoint. I have three widgets (panels) and a Command for each like this:
private AdvDeckPanel deckPanel = new AdvDeckPanel();
final private PopupPanel popupPanel = new PopupPanel(true);
private VerticalPanel defaultPanel = new VerticalPanel();
private SimplePanel imagePanel = new SimplePanel();
private SimplePanel sponserPanel = new SimplePanel();
Command showAlertCommand = new Command() {
public void execute() {
deckPanel.showWidget(0);
popupPanel.hide();
Window.alert("Hope this example helps.");
}
};
Command showImageCommand = new Command() {
public void execute() {
deckPanel.showWidget(1);
popupPanel.hide();
}
};
Command showSponserCommand = new Command() {
public void execute() {
deckPanel.showWidget(2);
popupPanel.hide();
}
};
A Command is called when the MenuItem is clicked.
Now the code to build the menu, link the commands, and handle the right-click:
private void createPopupMenu() {
MenuBar popupMenuBar = new MenuBar(true);
MenuItem alertItem = new MenuItem("Show alert", true, showAlertCommand);
MenuItem imageItem = new MenuItem("Show Oliver ", true, showImageCommand);
MenuItem sponserItem = new MenuItem("Show sponser ", true, showSponserCommand);
popupPanel.setStyleName("popup");
alertItem.addStyleName("popup-item");
imageItem.addStyleName("popup-item");
sponserItem.addStyleName("popup-item");
popupMenuBar.addItem(alertItem);
popupMenuBar.addItem(imageItem);
popupMenuBar.addItem(sponserItem);
popupMenuBar.setVisible(true);
popupPanel.add(popupMenuBar);
}
public void onRightClick(Widget sender, Event event) {
int x = DOM.eventGetClientX(event);
int y = DOM.eventGetClientY(event);
popupPanel.setPopupPosition(x, y);
popupPanel.show();
}
Lastly, to make the menu actually look like a popup menu I modified the CSS like so:
.popup {
background-color: gray;
border-color: gray gray gray gray;
border-width: 1px 3px 3px 1px;
border-style: solid solid solid solid;
}
.popup-item {
font-weight: normal;
font-size: 80%;
}
What this does is makes it so the border isn’t the thick default GWT blue, and uses a thin border with the right and bottom borders a bit thicker. This gives the popup that shadowed look.
A couple of books worth checking out are: GWT in Actionand GWT in Practice
Here’s the source and more links.
This entry was posted on Tuesday, February 17th, 2009 at 8:12 pm and is filed under GWT, Java, Programming. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
Of course you can debug with a JavaScript debugger (Venkman or Microsoft's Script Debugger), but generated JavaScript is really complex, for people and for those unstable debuggers.
But, wait, we have a debugger, is our state-of-the-art debugger, integrated in our IDE and GWT can use it, if only you could run client into the Shell and server side into your preferred development envinroment !!!
We could deploy our web-app into the integrated Tomcat, but it's not easy to do (and an hell to mantain) and also can be that you don't want (or you can't) use Tomcat for your Web Application.
I think that everyone should do his work, so let's Google Shell do the client, and your application server run the server side code. It's not difficult, you only need to follow these few steps.
First thing do to it's a little (I promise really little and only one) change to your GWT code, so that the client will always use absolute urls for your web-app, allowing us to use the ContextPath without problems, whatever it's the relative position of your Google client inside your root context.
To do that we have to register this way the end-point of the remote service:
endpoint.setServiceEntryPoint( GWT.getModuleBaseURL()+"/myRemoteService" );
now we must also remember to change our servlet path inside the GWT module file (*.gwt.xml) putting the complete service name at the top, in this case /mypackage.google.GWTClient:
<servlet path="/mypackage.google.GWTClient/myRemoteService" class="mypackage.google.server.MyRemoteServiceImpl"/>
No other change to your client side code, I promise again.
Now let's start to modify the web-app to run our services. The first thing is to include in our WEB-INF/lib the gwt-user.jar.
Unfortunately the one supplied by Google doesn't work, because it includes the javax.servlet.* classes to simplify the automatic generation of development projects.
We must strip that out (with an ANT Task obviously):
Now we can also add that to our IDE build-path.
Everything is ready to begin the configuration of our web-app, beginning with the registration of the remote service inside web.xml, remembering the module name we used in the *.gwt.xml file:
We don't have yet finished, we must also "simulate" one of the call implemented by GWTServlet, registering its path into web.xml and with the help of a JSP::
the gwt-hosted.jsp JSP it's only a simple script with a row of scriptlet that export our web-app context to the GWT client::
We did it !!!!The good thing is that we don't even have to "Compile" our JavaScript in the destination context during debug. Infact the GWT Shell callback will always call our Java classes and not the JavaScript code.
So we have together maximum flexibility on client-side project for our debugging purposes, and only at the very finish of the development cycle we will produce the JavaScript code.
Could we be in a better position as web developer ?
Now some tips about GWT's Shell:
Are we in debug mode or not ? The answer is yes, so we should configure the Shell log to a more verbose level (if you have used GWT.log in your code):
-logLevel ERROR|WARN|INFO|TRACE|DEBUG|SPAM|ALL
We should also disable the integrated Tomcat:
-noserver
and configure the Shell to generate JavaScript code directly inside our web-app project:
-out <web-app-project-dir>
Also can be useful to open directly the Shell browser to our web-app at startup, simply putting the http url as the last parameter of the command line that start the Shell.
But what if all this it's not enough to solve our problems, may be because the generated JavaScript is not working fine ? Well, together with much luck, we can try to switch the generation code to DETAILED:
-style DETAILED
and use traditional JavaScript debugging tecnique.
Ok, now everything it's integrated with your web-application and you're in love with GWT. You did really a great work, a prototype that it's working fine and looks pretty. But when time comes that you must put it into your old fashioned Struts/Tiles web-application it stops working and sure you can't write everything from scratch again, but do a step after another and start with a single functionality done with GWT.
Well, I don't know you, but I suffered from this problem, but at the end, thank to some little tips, I was able to let Struts and GWT not only to live together, but to cooperate to make my application look better.
It was like having an old fashioned B&W TV Set and a new HDMI on the same bench, side by side !!!
Well, to achieve this, we have to do some simple steps:
- In web.xml add another Struts action mapping, this time it must be extension based, for instance I choosed *.gwt:
- In struts-config.xml write the new Struts action that will render the GWT page, taking care to put at the top of the path the complete GWT's module name, so that the script will be able to find internal files with no problems:
- (only if you use Tiles as view)Add a Tiles definition that will include GWT's (in my example into the body of the layout JSP):
- (if you used filters for Struts Action mapping)Update your filters so that they will be able to do their work also with the new GWT module:
That's all, the game is made.
The life-cycle of a GWT's Service is managed by your
servlet-container, because as a design choice Google opted for the
portabily and simplicity of the Servlet model.
In our code this mean that our service implementations will all inherit (indirectly) from HttpServlet. This means also that to integrate them in our Spring managed container we have to play dirty. I decided to use static property inside our Google Service implementation, so that Spring will be able to assign it at startup time.
Pratically, if we want to inject something in GWT's service mypackage.google.server.MyRemoteServiceImpl's myProperty property, it's enough to declare it static:
Then to let Spring works, we also need an instance setter:
In our applicationContext.xml we can inject the myPropertyBean Bean simply with a dummy bean declaration of the GWT implementation class:
This works because at startup Spring will instantiate an
instance of the MyRemoteServiceImpl class, this instance will never be
used by the servlet-container, but the bean property is contained into
a static variable, so every instance will have it !!!
Now, if your business bean myPropertyBean uses Hibernate and you usually use Spring's OpenSessionInViewFilter/Interceptor
to manage your Session, you need a further step and use an AOP
Interceptor. But we are lucky in this, because all is done by Spring
out-of-the-box only with few lines of configuration::
With this configuration, if myPropertyBean is used outside a transaction scope, a new Hibernate transaction will be created and assigned to it. In our case this is also the span of the Hibernate's Session (thanks to HibernateTransactionManager). The myHibernateInterceptor will also take charge of eventually close the Session at the end of the business method.