java 板


LINE

网志版:http://pt2club.blogspot.com/2010/08/gwt_26.html 跟电脑(web server)对战的故事大概是这样的: 1.跟 server 要求开始一场游戏 2.跟 server 取得游戏资讯 3.根据游戏资讯绘制画面 4.将玩家踩的地点传送给 server 4.1命中地雷→更新游戏资讯 4.2没有命中→轮到 AI 踩地雷→更新游戏资讯 5.检查是否有某方获胜? 5.1有→结束。 5.2没有→回到步骤 3 黄色的部份是跟 server 有关的部份。 那麽,以 RPC、或说以程式的讲法 server 只需要提供两个 method startGame():负责开游戏 回传:该场 game 的 uid shoot():传送玩家踩的地点 参数:uid, x, y 回传:GameInfo 物件 因为懒得多设计一堆有的没的 所以开场之後让 client 端程式自动踩 (-1,-1) 这个非法位置 就会进入到步骤 2~4 的循环当中 [逃] 好了,终於要进入到 GWT RPC 的部份了。 这里打算跳过理论、架构的部份 直接以程式码来说明一切... 首先,是要有一个 MineService 的 interface 继承自 com.google.gwt.user.client.rpc.RemoteService 里头就是宣告上头说得那两个 method @RemoteServiceRelativePath("mineRPC") public interface MineService extends RemoteService { public String startGame(); public GameInfo shoot(String id, int x, int y) throws Exception; } 至於那个 annotation 先跳过,後头会解释 再来是一个对应的 interface,名称通常是後头补 Async public interface MineServiceAsync { void startGame(AsyncCallback<String> callback); void shoot(String id, int x, int y, AsyncCallback<GameInfo> callback); } 这两个 class 必须放在 gwt compiler 会处理的目录下(例如 client) 有 interface 自然有实做的 class MineService 对应实做 class 通常叫做 MineServiceImpl 会长成这样子: public class MineServiceImpl extends RemoteServiceServlet implements MineService { //FIXME change your ai here! private AI_Interface ai = new RandomAI(); @Override public String startGame() { String id = UUID.randomUUID().toString(); MineGM setting = new MineGM(); setServer(id, setting); return id+",Random"; } private HttpSession getSession(){ return this.getThreadLocalRequest().getSession(); } private void setServer(String id, MineGM setting){ getSession().setAttribute(id+"ID", setting); } private MineGM getServer(String id) throws Exception{ String name = id+"ID"; if(getSession().getAttribute(name)!=null){ return (MineGM) getSession().getAttribute(name); }else{ throw new Exception("还没开局"); } } @Override public GameInfo shoot(String id, int x, int y) throws Exception{ MineGM server = getServer(id); if(x==-1 || y==-1 || server.getMap()[x][y]!=-1){ return MineGM.toGameInfo(server); } if(!server.shoot(x, y, MineGM.USER)){ int[] xy = new int[2]; do{ ai.guess(MineGM.toGameInfo(server), xy); }while(server.shoot(xy[0], xy[1], MineGM.AI)); } setServer(id, server); return MineGM.toGameInfo(server); } } 这个 class 还会继承 RemoteServiceServlet 往上追溯,parent 是 HttpServlet 也就是说,MineServiceImpl 也是一个 HttpServlet 虽然 GWT RPC 很神奇地包装好许多东西 但终究还是 base on JSP 所以写这个 class 时,就不用管 GWT 的重重限制 只要 web.xml 有设定正确就好 讲到 web.xml,回头讲一下 MineService 的 annotation 用 RemoteServiceRelativePath 设定 servlet-mapping 会比较方便 <!-- in web.xml --> <servlet-mapping> <servlet-name>mineRPC</servlet-name> <url-pattern>/_mine/mineRPC</url-pattern> </servlet-mapping> url-pattern 的值,前半段 _mine 是在 gwt.xml 中 设定 <module rename-to='_mine' > 後半段 mineRPC 就是在 MineService 设定的值 (没有用这个 annotation,得要多好几行烦死人的 code) 至於游戏资讯,我选择塞在 session 当中 在 RemoteServiceServlet 要取得 session 比较罗唆一点 得要这样才能取得 session this.getThreadLocalRequest().getSession() 其余的程式码... 嗯... 不在 GWT 的范围当中,跳过 XD server 端的程式码解决了,现在来看 client 端 client 端必须透过 MineServiceAsync 来呼叫 RPC 不过用法有点奇怪...... Orz 首先要先这样写,取得一个 MineServiceAsync 的 object MineServiceAsync msa = GWT.create(MineService.class); 然後就可以用 msa.shoot() 来告诉 server 要踩哪个位置 但是事情还没完,除了标准的 parameter 得要传一个为 AsyncCallback 的 parameter 这是让 server 端处理完毕後可以 callback 的一个手段 初期通常都会用 anonymous class 来解决 所以程式码会长得像这样: msa.shoot(this.gameID, hitX, hitY, new AsyncCallback<GameInfo>(){ @Override public void onFailure(Throwable caught) { Window.alert("shoot : "+caught.getLocalizedMessage()); } @Override public void onSuccess(GameInfo result) { setShootResult(result); } }); 这边要注意两件事情 其一,RPC 传递/回传的 class(及其 field) 除了 primitive data type 外 一定得 implements IsSerializable 还必须是 GWT 允许的 class 此外,自订的 class 还必须让在 GWT compiler 会处理的目录下 不然实际跑起来就会有(很难看懂的)错误讯息 其二,呼叫完 msa.shoot() 之後 下一步并不会执行 onSuccess()/onFailure() 更正确来说,在写 client 端程式码的时候 并不会知道 onSuccess()/onFailure() 什麽时候会呼叫到 端看 server 处理以及网路传输的速度... etc 这是 callback 的特性,在踩地雷的 case 当中并不会造成困扰 但在其他实务上,如果发现怎麽 RPC 回传值都不正确 那大概就是忘记这个性质所导致的...... Orz 喔对... 都忘记讲一个大前提了 要用 GWT RPC,server 必须是 JSP container 同时也来讲讲 GWT RPC 的好处 \囧/ 一言以蔽之就是「通通传便便」 client 不用组 query string 或 post 内容 server 端不用准备对应的 url client/server 都不需要剖析传递的资料 甚至可以传递(客制化的) exception 在 client 端的 onFailure() 可以分门别类处理...... 程式码看起来、写起来都很 OO、都很 Java 以一个 Java Programmer 来说,有什麽比这个更快乐的事情呢? XD (连 xml 都没有用到呢! [握拳]) 好了,「对抗电脑版的踩地雷」拆解到这里 只剩下地雷区要设定 click 的 handler 收到 GameInfo 之後要更新画面 以及电脑 AI 设计这些功能 相信你一定可以自己写的很开心的,就跳过不细谈了 如果你想偷懒想拿写好的程式码来执行看看, 可以到 http://wiki.psmonkey.org/changelog/mine 下载。 也欢迎投稿你的 AI 设计 http://www.psmonkey.org/gwt-product/mineAI_wanted.jsp Enjoy GWT and have fun! \囧/ -- 钱锺书: 说出来的话 http://www.psmonkey.org 比不上不说出来的话 Java 版 cookcomic 版 只影射着说不出来的话 and more...... --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 219.70.214.149
1F:推 nvidia:好文监赏 08/26 10:48
※ 编辑: PsMonkey 来自: 219.70.214.149 (08/26 12:25) update 档案下载... 之前的版本实在太糟糕了 XD ※ 编辑: PsMonkey 来自: 219.70.214.149 (08/26 21:38)
2F:推 kanandg1:推~不过能否帮GameInfo的method加注解:) 08/27 16:29
※ 编辑: PsMonkey 来自: 219.70.183.212 (09/02 16:18)
3F:推 psychedelico:GOOD 09/10 01:28







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:iOS站内搜寻

TOP