怎么感覺web倒計時交互不該像老師這樣寫,我感覺這樣不太合適,難道我的想法錯誤?
關于課程:
《Java高并發秒殺API之web層》
怎么感覺web倒計時交互不該像老師這樣寫,我感覺這樣不太合適,難道我的想法錯誤?
一、controller里的 /time/now 這個方法完全沒有必要,獲取秒殺地址Exposer里就包含了當前系統時間
下面看Exposer的屬性:
public?class?Exposer?{ //?是否要暴露的,表示是否開啟秒殺 private?boolean?exposed; //?md5加密措施 private?String?md5; //?秒殺的id private?long?seckillId; //?系統當前時間?毫秒 private?long?now; //?秒殺開始時間?毫秒 private?long?start; //?秒殺結束時間?毫秒 private?long?end; .......
倒計時交互流程我覺得應該是下面這樣:
在詳情頁jsp通過“/{seckillId}/exposer"直接獲取這個Exposer 的封裝json對象SeckillResult<Exposer>。
判斷exposed屬性,
1.如果是false,則拿now分別比較start和end,如果在start前面則開始倒計時,如果在end后面則顯示秒殺結束。
2.如果是true,則處于秒殺有效時間內,顯示秒殺按鈕。
獲取的Exposer對象中的數據,已經是服務端執行了業務邏輯才放入的,直接可以拿來用。我不明白為什么jsp里還要寫這么多邏輯,jsp最大的作用只是用來展示。而且對于以后維護也不方便,需要服務端和客戶端都要改。
二、另外關于異常處理,我也感覺不合理。比如在SeckillController的方法executeSeckill中:
try?{????? SeckillExecution?execution?=?seckillService.executeSeckill(seckillId,?userPhone,?md5); return?new?SeckillResult<SeckillExecution>(true,execution);???? }catch?(RepeatkillException?e){???? SeckillExecution?execution?=?new?SeckillExecution(seckillId,?SeckillStateEnum.REPEAT_KILL);???? return?new?SeckillResult<SeckillExecution>(false,execution);???? }catch?(SeckillCloseException?e){???? SeckillExecution?execution?=?new?SeckillExecution(seckillId,?SeckillStateEnum.END);???? return?new?SeckillResult<SeckillExecution>(false,execution);???? }catch?(Exception?e){???? logger.error(e.getMessage(),e);???? SeckillExecution?execution?=?new?SeckillExecution(seckillId,?SeckillStateEnum.INNER_ERROR);???? return?new?SeckillResult<SeckillExecution>(false,execution);???? }
catch到異常就應該把秒殺失敗的標志,以及錯誤信息返回給前段就行了,為什么是SeckillResult<SeckillExecution>(false,execution); ?其中false我可以理解,但是execution有什么用,SeckillResult不是有(boolean success, String error)的構造器嗎?一個String的信息就行,需要傳對象過去嗎?
三、還有SeckillResult的boolean success,SeckillExecution 的?int state,Exposer的boolean exposed;我覺得概念設計的很混亂,老師講解的也不是很清楚。
我認為,SeckillResult有boolean success和String error表示是否執行成功和異常信息就好,Exposer的boolean exposed表示秒殺是否開啟。SeckillExecution 的?int state完全沒有必要,枚舉應該用在異常類里(可以給父類SeckillException加一個state的屬性),這些信息只會在秒殺失敗的時候返回給前段,直接捕捉異常,得到異常的message以字符轉返回就行了,秒殺失敗的時候根本不需要返回SeckillResult對象。
感覺有些混亂和冗余。
以上只是我個人的一些想法,希望大家可以看一下我想的對不對,如果有不對指正。如果本課的老師可以看到,真誠希望可以解疑,拜謝。
另外:
這是我參考老師的代碼,按照自己的理解寫的seckil.js邏輯代碼,我感覺這樣更好理解一些,經測試可以實現功能。
//存放主要的交互邏輯js代碼 //javaScript模塊化,可以模擬java的分包。 //seckill?對象有屬性?URL(URL本身可能還有別的屬性),屬性也可以為函數,因為在script中函數也是對象。 //調用方法類似:seckill.detail.init(params); var?seckill?=?{ //?:(冒號)對象表達法?冒號在這里用來分割對象的屬性和屬性值。 //?秒殺相關ajax的url URL?:?{ nowUrl?:?function?()?{ return?'/seckill/seckill/time/now'; }, exposerUrl?:?function?(seckillId)?{ return?"/seckill/seckill/"?+?seckillId?+?"/exposer"; }, seckillUrl?:?function?(seckillId,?md5)?{ return?"/seckill/seckill/"?+?seckillId?+?"/"?+?md5?+?"/execution"; } }, //?校驗手機號 validatePhone?:?function?(phone)?{ //?if(phone){}表示不為空,isNaN(phone)表示非數字 if?(phone?&&?phone.length?==?11?&&?!isNaN(phone))?{ return?true; }?else?{ return?false; } }, seckillView?:?function?(seckillId)?{ $ .post( seckill.URL.exposerUrl(seckillId),?{}, function?(result)?{ if?(result?&&?result['success'])?{?//?請求成功 var?exposer?=?result['data']; var?seckillId?=?exposer['seckillId']; var?seckillBox?=?$('#seckill-box'); if?(exposer['exposed'])?{?//?可以秒殺 var?md5?=?exposer['md5']; var?killUrl?=?seckill.URL.seckillUrl( seckillId,?md5); seckillBox .html('<button?class="btn?btn-primary?btn-lg"?id="killBtn">開始秒殺</button>');?//?按鈕 //?綁定點擊事件(綁定一次) $("#killBtn") .one( 'click', function?()?{ //?執行秒殺的請求操作 $(this).addClass( 'disabled'); //?發送秒殺的請求 $ .post( killUrl,?{}, function?( result)?{ if?(result ?&&?result['success'])?{ var?seckillExecution?=?result['data']; var?state?=?seckillExecution['state']; var?stateInfo?=?seckillExecution['stateInfo']; //?顯示秒殺結果 seckillBox .html('<span?class="label?label-success">' ?+?stateInfo ?+?'</span>'); } }) }) }?else?{?//?不可以秒殺 var?now?=?exposer['now']; var?start?=?exposer['start']; var?end?=?exposer['end']; if?(now?<?start)?{?//?還未開始?倒計時 seckill.countdown(seckillId,?now, start,?seckillBox); }?else?{?//?已經結束(exposed為false只能是未開始或者結束) seckillBox.html('秒殺結束'); } } }?else?{?//?請求失敗 console.log("result:"?+?result); } }) }, //?倒計時處理 countdown?:?function?(seckillId,?now,?start,?seckillBox)?{ //?計時事件綁定 var?killTime?=?new?Date(Number(start)?+?1000);?//?加一秒的時間偏移。(運算計時的消耗時間,后來細想應該是減去消耗時間,但是因為無法知道消耗的時間多少,減多了會提前顯示出點擊按鈕,并不合理,所以最好不加不減。) //?jquery倒計時插件,監聽時間變化循環回調函數 seckillBox.countdown(killTime,?function?(event)?{ //?格式化時間 var?format?=?event.strftime('秒殺計時:?%D天??%H小時??%M分鐘??%S秒'); //?更新倒計時節點組件 seckillBox.html(format); }).on('finish.countdown',?function?()?{?//?倒計時結束的回調函數 //?倒計時結束,以防倒計時誤差,需要重新請求exposer,判斷是否已經開始,來顯示秒殺按鈕或者更正倒計時 seckill.seckillView(seckillId); }); }, //?詳情頁秒殺邏輯 detail?:?{ //?詳情頁初始化 init?:?function?(params)?{ //?******1。手機驗證和登錄,2。計時交互 //?*******規劃我們的交互流程 //?利用jquery的cookie插件在cookie中查找手機號 var?killPhone?=?$.cookie('killPhone'); //?訪問參數中對應的數據(javascript的訪問方式) var?seckillId?=?params['seckillId']; var?startTime?=?params['startTime']; var?endTime?=?params['endTime']; //?驗證手機號 if?(!seckill.validatePhone(killPhone))?{?//?未登錄 //?獲取彈出層對象 var?killPhoneModal?=?$("#killPhoneModal"); //?顯示彈出層 killPhoneModal.modal({ show?:?true,?//?顯示彈出層 backdrop?:?'static',?//?禁止位置關閉 keyboard?:?false //?關閉鍵盤事件 }); //?為手機號的提交按鈕綁定點擊事件 $('#submitPhone') .click( function?()?{ //?獲取用戶輸入的手機號 var?inputPhone?=?$('#killPhone').val(); //?提交的電話號碼有效 if?(seckill.validatePhone(inputPhone))?{ //?電話寫入cookie //?{expires:7,path:'/seckill'}表示這個cookie的有效期為7天, //?只有訪問本域名下/seckill路徑才會在request中帶上這個數據到cookie $.cookie('killPhone',?inputPhone,?{ expires?:?7, path?:?'/seckill' }) //?刷新頁面 window.location.reload(); }?else?{?//?提交的電話號碼無效 //?顯示手機號輸入錯誤的提示信息(先隱藏節點,再寫入數據,再顯示出來,添加緩慢出現的顯示效果) $('#killPhoneMessage') .hide() .html( '<label?class="label?label-danger">手機號錯誤!</label>') .show(500); } }); } //?已經登錄 seckill.seckillView(seckillId); } } }
2016-09-19
一,用/time/now可以減輕服務器負擔,exposer還得每一秒都查詢數據庫
其余不知道
2016-09-11
這是我參考老師的代碼,按照自己的理解寫的邏輯代碼,我感覺這樣更好理解一些,經測試可以實現功能。