秒殺系統中通常會避免使用者之間訪問下單頁面的URL(避免使用爬蟲來造成不公平)。所有需要將URL動態化,即使秒殺系統的開發人員也無法在知曉在秒殺開始時的URL。解決辦法是在擷取秒殺URL的介面中,返回一個伺服器端產生的隨機數,並在下單URL中傳遞該參數完成下單。
首先構造一個擷取下單URL的modle
public class Exposer { //加密措施 private String md5; //其中必要欄位,如是否開啟秒殺,時間等省}
擷取秒殺URL的conntroller:
@RequestMapping(value = "/{goodsId}/getUrl") public Exposer exposer(@PathVariable("goodsId") Long seckillGoodsId) { //goodsId表示是什麼商品,然後根據該商品的資料庫依次獲得尚未被秒殺的每個商品的唯一ID,然後根據商品的唯一ID來產生唯一的秒殺URL seckillGoodsId為某個商品的唯一id其中這一步可以省,之間將goodsId表示的傳遞給exportSeckillUrl也可以完成 //異常判斷省掉,返回上述的model對象。即包含md5的對象 Exposer result =seckillService.exportSeckillUrl(seckillGoodsId); return result; }
Service的方法實現:
//加入一個混淆字串(秒殺介面)的salt,為了我避免使用者猜出我們的md5值,值任意給,越複雜越好private final String salt="12sadasadsafafsafs。/。,";public Exposer exportSeckillUrl(long seckillGoodsId) { //首頁根據該seckillGoodsId判斷商品是否還存在。 //如果不存在則表示已經被秒殺 String md5 = getMD5(seckillGoodsId); return new Exposer(md5);} private String getMD5(long seckillGoodsId) { //結合秒殺的商品id與混淆字串產生通過md5加密 String base=seckillGoodsId+"/"+salt; String md5= DigestUtils.md5DigestAsHex(base.getBytes()); return md5; }
使用者在擷取擷取到下單URL的時候,當秒殺開啟後則會得到一個md5值。通過該md5值來完成下單具體的秒殺交易:
具體執行秒殺操作的介面
@RequestMapping(value = "/{seckillGoodsId}/{md5}/execution") public Boolean execution(@PathVariable("seckillGoodsId") Long seckillGoodsId,@PathVariable("md5") String md5){ Boolean result = seckillService.executionSeckillId(seckillId,md5); //executionSeckillId的操作是強事務,操作為減庫存+增加購買明細,最終返回是否秒殺成功,秒殺成功的商品訊息等。這裡省,只返回是否介面合理的資訊。 return result; }
Service 執行秒殺的過程:
public Boolean executionSeckillId(long seckillID,String md5){ if(md5==null||!md5.equals(getMD5(seckillID))){ //表示介面錯誤,不會執行秒殺操作 return false; } //介面正確,排隊執行秒殺操作。減庫存+增加購買明細等資訊,這裡只返回false return true; }}