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

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



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

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

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

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

//獲取商品列表
@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";
}

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

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

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

<!--查詢待秒殺的活動(dòng)商品列表-->
<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 來(lái)表示當(dāng)前“待秒殺的商品”是否可以被秒殺/被搶購(gòu)!其判斷的標(biāo)準(zhǔn)為:

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

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

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


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

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


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

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

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

/**
* 獲取待秒殺商品的詳情
* @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";
}

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

(2) 緊接著是itemService.getKillDetail(id) 的開(kāi)發(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在配置文件中寫(xiě)動(dòng)態(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) 最后是在頁(yè)面info.jsp渲染展示該詳情信息,如下圖所示為該頁(yè)面的部分核心源代碼:



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


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

補(bǔ)充:

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

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

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