Github:github.com/nnngu
項目源代碼:github.com/nnngu/nguSe…php
這是一個整合IDEA+Maven+SSM框架的高併發的商品秒殺項目。咱們將分爲如下幾篇文章來進行詳細的講解:java
以IntelliJ IDEA爲例,點擊File > New > Project > Maven
git
而後點擊Next繼續;github
填寫相關信息,點擊Next;web
最後點擊Finish,完成建立。sql
若是右下角彈出下面這個提示,點擊Enable Auto-Import
數據庫
點擊File > Project Structure
apache
步驟1mybatis
步驟2併發
步驟3
步驟4
步驟5
步驟6
步驟7
步驟8
Maven項目建立好了,接下來咱們要添加一些jar包的依賴,也就是在pom.xml
中添加各類開源組件的座標。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nnngu</groupId>
<artifactId>nguSeckill</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 代碼省略,請參照項目的源代碼 -->
... ...
複製代碼
完整的代碼,請查看項目裏的pom.xml
文件
到此,咱們項目的初始化工做完成。
秒殺系統業務流程以下:
由圖能夠發現,整個系統實際上是針對庫存作的系統。用戶成功秒殺商品,對於咱們系統的操做就是:
減庫存
記錄用戶的購買明細。下面看看咱們用戶對庫存的業務分析:
記錄用戶的秒殺成功信息,咱們須要記錄:一、誰購買成功了。二、購買成功的時間/有效期。三、付款/發貨信息。這些數據組成了用戶的秒殺成功信息,也就是用戶的購買行爲。
爲何咱們的系統須要事務?看以下這些故障:一、如果用戶成功秒殺商品咱們記錄了其購買明細卻沒有減庫存。致使商品的超賣。二、減了庫存卻沒有記錄用戶的購買明細。致使商品的少賣。對於上述兩個故障,如果沒有事務的支持,損失最大的無疑是咱們的用戶和商家。在MySQL中,它內置的事務機制,能夠準確的幫咱們完成減庫存和記錄用戶購買明細的過程。
MySQL實現秒殺的難點分析:當用戶A秒殺id爲10的商品時,此時MySQL須要進行的操做是:一、開啓事務。二、更新商品的庫存信息。三、添加用戶的購買明細,包括用戶秒殺的商品id以及惟一標識用戶身份的信息如電話號碼等。四、提交事務。若此時有另外一個用戶B也在秒殺這件id爲10的商品,他就須要等待,等待到用戶A成功秒殺到這件商品而後MySQL成功的提交了事務他才能拿到這個id爲10的商品的鎖從而進行秒殺,而同一時間是不可能只有用戶B在等待,確定是有不少不少的用戶都在等待拿到這個行級鎖。秒殺的難點就在這裏,如何高效的處理這些競爭?如何高效的完成事務?在後面第4個模塊如何進行高併發的優化爲你們講解。
咱們這個系統須要完成秒殺的哪些功能?先來看看天貓的一個秒殺庫存系統:
你們看了是否是以爲很複雜?固然不用擔憂,咱們只是實現秒殺的一些功能:一、秒殺接口的暴露。二、執行秒殺的操做。三、相關查詢,好比說列表查詢,詳情頁查詢。咱們實現這三個功能便可。接下來進行具體的編碼工做,首先是創建數據庫以及Dao層的編碼。
-- 建立一個數據庫
CREATE DATABASE ngu_seckill;
-- 使用數據庫
USE ngu_seckill;
-- 省略...
... ...
複製代碼
完整的數據庫sql代碼,在項目的sql
文件夾裏的ngu_seckill.sql
先建立秒殺商品類com/nnngu/entity/Seckill.java
package com.nnngu.entity;
import java.io.Serializable;
import java.time.LocalDateTime;
/** * 秒殺商品 */
public class Seckill implements Serializable {
private static final long serialVersionUID = 2912164127598660137L;
/* 主鍵ID*/
private long seckillId;
/* 秒殺商品名字 */
private String name;
/* 代碼省略,請參照項目的源代碼 */
... ...
複製代碼
建立秒殺狀態類com/nnngu/entity/SuccessKilled.java
package com.nnngu.entity;
import java.io.Serializable;
import java.time.LocalDateTime;
/** * 秒殺後的狀態 */
public class SuccessKilled implements Serializable {
private static final long serialVersionUID = 1834437127882846202L;
private long seckillId;
/* 用戶的手機號碼*/
private long userPhone;
/* 代碼省略,請參照項目的源代碼 */
... ...
複製代碼
com/nnngu/dao/SeckillMapper.java
package com.nnngu.dao;
import com.nnngu.entity.Seckill;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
public interface SeckillMapper {
/* 代碼省略,請參照項目的源代碼 */
... ...
}
複製代碼
com/nnngu/dao/SuccessKilledMapper.java
package com.nnngu.dao;
import com.nnngu.entity.SuccessKilled;
import org.apache.ibatis.annotations.Param;
public interface SuccessKilledMapper {
/* 代碼省略,請參照項目的源代碼 */
... ...
}
複製代碼
mapper.xml
在resources
目錄下建立com.nnngu.dao
包,而後建立SeckillMapper.xml
和 SuccessKilledMapper.xml
,以下圖:
com.nnngu.dao/SeckillMapper.xml
<!-- 這裏的代碼省略 -->
<!-- 請參照項目的源代碼 -->
複製代碼
com.nnngu.dao/SuccessKilledMapper.xml
<!-- 這裏的代碼省略 -->
<!-- 請參照項目的源代碼 -->
複製代碼
mybatis-config.xml
配置文件的內容參照項目的源代碼
jdbc.properties
注意: jdbc.properties
裏面的屬性要根據本身的狀況進行修改。
建立applicationContext-dao.xml
以下圖:
applicationContext-dao.xml
文件的具體代碼請參照項目的源代碼。
建立測試類 com/nnngu/dao/SeckillMapperTest.java
以下圖:
該文件的具體代碼請參照項目的源代碼。
測試查詢全部商品的方法queryAll()
測試結果以下:
到此,咱們成功完成了Dao層開發及測試。下篇文章 02 Java高併發秒殺項目之Service層