Java秒殺系統(tǒng)(四):待秒殺商品列表與詳情功能開發(fā)

作者: 修羅debug
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 by-sa 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。



摘要:本篇博文是“Java秒殺系統(tǒng)實(shí)戰(zhàn)系列文章”的第四篇,從這篇文章開始我們將進(jìn)入該秒殺系統(tǒng)相關(guān)業(yè)務(wù)模塊的代碼實(shí)戰(zhàn)!本篇博文將首先從最簡單的業(yè)務(wù)模塊入手,即如何實(shí)現(xiàn)“獲取待秒殺商品的列表以及查看待秒殺的商品詳情”功能!

內(nèi)容:對于“待秒殺商品列表及其詳情的展示”這一功能,我們將采用目前比較流行的mvc開發(fā)模式來實(shí)現(xiàn)!值得一提的是,這一功能模塊涉及的主要數(shù)據(jù)庫表為“商品信息表item”、“待秒殺商品信息item_kill”。

一、“待秒殺商品列表”代碼實(shí)戰(zhàn)

(1) 首先是在 ItemController控制器中開發(fā)“獲取待秒殺商品列表”的請求方法,其源代碼如下所示:

//獲取商品列表
@RequestMapping(value = {"/","/index",prefix+"/list",prefix+"/index.html"},method = RequestMethod.GET)
public String list(ModelMap modelMap){
try {
//獲取待秒殺商品列表
List<ItemKill> list=itemService.getKillItems();
modelMap.put("list",list);

log.info("獲取待秒殺商品列表-數(shù)據(jù):{}",list);
}catch (Exception e){
log.error("獲取待秒殺商品列表-發(fā)生異常:",e.fillInStackTrace());
return "redirect:/base/error";
}
return "list";
}

控制器的這一方法在獲取到待秒殺商品的列表信息后,將通過modelMap的形式將數(shù)據(jù)列表返回給到前端的頁面list.jsp中進(jìn)行渲染!其中,itemService.getKillItems() 主要用于獲取待秒殺商品的列表信息,其源代碼如下所示:

@Autowired
private ItemKillMapper itemKillMapper;
//獲取待秒殺商品列表
@Override
public List<ItemKill> getKillItems() throws Exception {
return itemKillMapper.selectAll();
}

(2) 緊接著是開發(fā) itemKillMapper.selectAll() 方法,其主要是基于Mybatis在配置文件中寫動態(tài)Sql,該Sql的作用在于“獲取待秒殺商品的列表”,其源代碼如下所示:  

<!--查詢待秒殺的活動商品列表-->
<select id="selectAll" resultType="com.debug.kill.model.entity.ItemKill">
SELECT
a.*,
b.name AS itemName,
(
CASE WHEN (now() BETWEEN a.start_time AND a.end_time AND a.total > 0)
THEN 1
ELSE 0
END
) AS canKill
FROM item_kill AS a LEFT JOIN item AS b ON b.id = a.item_id
WHERE a.is_active = 1
</select>

在這里的Sql,Debug是采用了Left Join左關(guān)聯(lián)查詢的方式獲取列表信息,目的是為了獲取“商品信息表”中的商品信息,如“商品名稱”等等。

值得一提的是,在這里Debug還使用了一個(gè)小技巧,即采用一個(gè)字段 canKill 來表示當(dāng)前“待秒殺的商品”是否可以被秒殺/被搶購!其判斷的標(biāo)準(zhǔn)為:

當(dāng)待秒殺的商品的剩余數(shù)量/庫存,即 total 字段的取值大于0時(shí),并且 “當(dāng)前的服務(wù)器時(shí)間now()處于待秒殺商品的搶購開始時(shí)間 和 搶購結(jié)束時(shí)間的范圍內(nèi)”時(shí),canKill的取值將為1,即代表可以被搶購或者被秒殺。否則canKill的取值將為0。

(3) 至此,“待秒殺商品列表”這一功能模塊的后端代碼開發(fā)已經(jīng)完成了!前端發(fā)起請求后,請求將首先到達(dá)controller,通過請求路徑url映射到某個(gè)方法進(jìn)行調(diào)用,controller的方法首先會進(jìn)行最基本的數(shù)據(jù)校驗(yàn),然后通過調(diào)用service提供的接口獲取真正的業(yè)務(wù)數(shù)據(jù),最后是在service中執(zhí)行真正的dao層層面的數(shù)據(jù)查詢或者數(shù)據(jù)操作邏輯,最終完成整個(gè)業(yè)務(wù)流的操作。

(4) 接下來是開發(fā)一個(gè)頁面list.jsp用于展示“待秒殺商品列表的信息”,下面展示了該頁面的部分核心源碼,如下圖所示:  


從該代碼中可以看出,當(dāng)canKill字段取值為1時(shí),將可以點(diǎn)擊“詳情”進(jìn)行查看;否則,將會提示相應(yīng)的信息!即“判斷是否可以秒殺”的邏輯Debug是將其放在了后端來實(shí)現(xiàn)!

(5) 至此,“獲取待秒殺商品列表”這一功能模塊的前后端代碼實(shí)戰(zhàn)已經(jīng)完畢了,點(diǎn)擊運(yùn)行整個(gè)項(xiàng)目,將整個(gè)系統(tǒng)運(yùn)行在外置的tomcat服務(wù)器中,觀察控制臺的輸出信息,如果沒有報(bào)錯(cuò),這說明整個(gè)系統(tǒng)的代碼在語法級別層面是木有問題的。如下圖所示為整個(gè)秒殺系統(tǒng)、項(xiàng)目在運(yùn)行起來之后的首頁:  


雖然不是很美觀,但是Debug覺得還是湊合著用吧 哈哈??!  

二、“待秒殺商品詳情”代碼實(shí)戰(zhàn)

(1) 接下來是點(diǎn)擊“詳情”,查看“待秒殺商品的詳情信息”,對于這個(gè)功能模塊,其實(shí)還是比較簡單的,其核心主要是根據(jù)“主鍵”進(jìn)行查詢。同樣的道理,首先需要在 ItemController控制器中開發(fā)接收前端請求的功能方法,其源代碼如下所示:

/**
* 獲取待秒殺商品的詳情
* @return
*/
@RequestMapping(value = prefix+"/detail/{id}",method = RequestMethod.GET)
public String detail(@PathVariable Integer id,ModelMap modelMap){
if (id==null || id<=0){
return "redirect:/base/error";
}
try {
ItemKill detail=itemService.getKillDetail(id);
modelMap.put("detail",detail);
}catch (Exception e){
log.error("獲取待秒殺商品的詳情-發(fā)生異常:id={}",id,e.fillInStackTrace());
return "redirect:/base/error";
}
return "info";
}

該控制器的方法在獲取到待秒殺商品的詳情后,將通過modelMap把詳情信息塞回info.jsp前端頁面中進(jìn)行渲染展示!

(2) 緊接著是itemService.getKillDetail(id) 的開發(fā),即用于獲取“待秒殺商品的詳情”,其源代碼如下所示:

/**
* 獲取待秒殺商品詳情
*/
@Override
public ItemKill getKillDetail(Integer id) throws Exception {
ItemKill entity=itemKillMapper.selectById(id);
if (entity==null){
throw new Exception("獲取秒殺詳情-待秒殺商品記錄不存在");
}
return entity;
}

其中,itemKillMapper.selectById(id); 主要是基于Mybatis在配置文件中寫動態(tài)Sql,該Sql的主要功能為根據(jù)主鍵查詢待秒殺商品的詳情,其源代碼如下所示:   

<!--獲取秒殺詳情-->
<select id="selectById" resultType="com.debug.kill.model.entity.ItemKill">
SELECT
a.*,
b.name AS itemName,
(
CASE WHEN (now() BETWEEN a.start_time AND a.end_time AND a.total > 0)
THEN 1
ELSE 0
END
) AS canKill
FROM item_kill AS a LEFT JOIN item AS b ON b.id = a.item_id
WHERE a.is_active = 1 AND a.id= #{id}
</select>

從該Sql中不難看出,其實(shí)就是在“獲取待秒殺商品列表”的Sql中加入“主鍵的精準(zhǔn)查詢”!

(3) 最后是在頁面info.jsp渲染展示該詳情信息,如下圖所示為該頁面的部分核心源代碼:



從該頁面的部分核心源代碼中可以看出,為了避免有人“跳過頁面的請求,直接惡意刷后端接口”,在該頁面仍然再次進(jìn)行了一次判斷(在后面執(zhí)行“搶購/秒殺”請求時(shí),后端接口還會再次進(jìn)行判斷的,所有這些都是為了安全考慮?。?br>
(4) 至此,關(guān)于“待秒殺商品的詳情展示”的功能的前后端代碼實(shí)戰(zhàn)已經(jīng)完成了!再次將整個(gè)系統(tǒng)/項(xiàng)目運(yùn)行在外置的tomcat服務(wù)器中,點(diǎn)擊列表頁中的“詳情”按鈕,可以看到待秒殺商品的詳情信息,如下圖所示:  


至此,本文所要分享介紹的內(nèi)容已經(jīng)完成了,即主要分享介紹了“獲取待秒殺商品的列表”和“查看待秒殺商品的詳情”功能!  

補(bǔ)充:

1、目前,這一秒殺系統(tǒng)的整體構(gòu)建與代碼實(shí)戰(zhàn)已經(jīng)全部完成了,該秒殺系統(tǒng)對應(yīng)的視頻教程的鏈接地址為:https://www.fightjava.com/web/index/course/detail/6,可以點(diǎn)擊鏈接進(jìn)行試看以及學(xué)習(xí),實(shí)戰(zhàn)期間有任何問題都可以留言或者與Debug聯(lián)系、交流!

2、另外,Debug也開源了該秒殺系統(tǒng)對應(yīng)的完整的源代碼以及數(shù)據(jù)庫,其地址可以來這里下載:https://gitee.com/steadyjack/SpringBoot-SecondKill 記得Fork跟Star?。。。?/span>

3、最后,不要忘記了關(guān)注一下Debug的技術(shù)微信公眾號: