基於 Java EE 階段的小型購物車項目
麻雀雖小,五臟俱全,UI 寫的比較 low,這個就不要太在意了
項目已經放在 Github 倉庫中:ShoppingMall
一、項目搭建
- 構建一個 Java Web 項目
- 數據庫 mysql 5.7 版本
- 開發工具 idea 2019, sqlyog
- 服務器版本 Tomcat 9.0.34
- 涉及到第三方 JAR 包:
- mysql 驅動 5.1.44 版本以上
- Tomcat 的所有 lib 包支持
- jstl 1.2 標籤庫支持
- 支付寶 SDK 提供的 jar 包
- 其他:
- BootStrap 庫支持
- Jquery 庫支持 (完成 ajax 操作)
二、商品界面展示
2.1 登錄界面
用戶需要輸入正確的賬號密碼,以及驗證碼,經後端校驗通過即可通過
- 驗證碼由後端生成,驗證碼點擊圖片或者 文字 都可以通過 js 進行交換
- 用戶名 ajax 校驗
- 沒有編寫註冊功能,因爲我比較懶 hhhh
2.2 商城主頁
- 用戶登錄成功就會進入該界面,用戶登錄信息經過 session 域進行保存
- 商品界面採用了 分頁處理
- 用戶可以選擇將商品添加至購物車 或者直接查詢購物車
2.3 購物車頁面
- 用戶選中項目可以對數量進行 添加 和 修改,修改的數據會通過 ajax 傳至後臺進行同步修改(這樣做並不是合理,所以有點小 bug)
- 商品如果不想要點擊刪除,會通過 ajax 進行刪除,然後頁面的 dom 也會刪除,但是有個小 個 bug,因爲沒有對數據進行重新查詢,所以,頁面會恢復原樣,但是數據庫的數據是已經刪除了該購物車信息了
- 因爲數據是動態渲染出來的,所以我使用 Jquery 完成購物車的 js 邏輯時,可能會有些小 bug, 所以我只用了一個產品進行購物
2.4 確認支付環節
- 支付採用了支付寶的沙箱環境,我們需要配置一些信息到 沙箱頁面 和自己的本地環境即可完成沙箱環境接入
這個頁面其實可以直接跳過去的,不知道爲啥就寫進來了
2.5 真正的支付環境了
這裏可以看到前面購物車的賬單信息
這裏就和真真的支付沒啥關係了,但是千萬別傻乎乎的用自己的支付寶付錢,因爲支付寶的沙箱環境已經提供了虛擬賣家賬號 和 虛擬商家賬號了,在這裏我們可以快樂的充值,體驗一把有錢人的快樂,也可以下載對應的沙箱環境支付寶進行支付
和真實的支付環境基本有區別
三、後端重點
3.1 數據庫設計
這個 小小商城 只用到了三張表,總體邏輯也不是很複雜
3.1.1 用戶表 (user)
這是單獨的一張表
3.1.2 商品表 (product)
用於顯示對應的數據
3.1.3 購物車(Shopcart)
3.2 Java Web 後端邏輯難點分析
3.2.1 驗證碼實現
使用 java 的 2d 繪圖工具,繪製一張 png,我的代碼對驗證碼的繪製做了比較好的封裝,所以看起來比較舒服
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* 生成一個 6位數的驗證碼,並存放到 session 域中 valiCode
* 並通過 response 返回
* */
@WebServlet("/CodeServlet")
public class CodeServlet extends HttpServlet {
private Random random = new Random();
private int width = 80;//寬度
private int height = 40;//高度
private int fontsize = 20;//字體大小
private String str = "0123456789abcdefghijklmnxnlopiiqusdakljnalwABCDEFGHIJKLMNOPQRSTUVWXYZ";
//----------- 簡單版本 -------------
private String randCode() { //生成 4個字符 隨機字符串代碼
String code = "";
for (int i=0; i<4; i++) {
code +=str.charAt(random.nextInt(str.length()));
}
return code;
}
//------------ 生成至少四個字符的隨機字符串 --
private String randCode1(int len) {
if (len < 4) {
len = 4;
}
//更改寬度
width = 5 + fontsize*len ;
String code = "";
for (int i=0; i<len; i++) {
code +=str.charAt(random.nextInt(str.length()));
}
return code;
}
//------------- 返回隨機字符串的顏色
private Color randColor() {
int r = random.nextInt(256);
int g = random.nextInt(256);
int b = random.nextInt(256);
return new Color(r,g,b);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 設置 servlet 的顯示類型
response.setContentType("image/png");
// 2. 大致設置一個虛擬的驗證碼
//1. 創建畫板
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//2.創建畫筆
Graphics2D pen = (Graphics2D)img.getGraphics();
//3.生成隨機內容
String code = randCode1(4); //生成 4位數驗證碼
System.out.println(code);
request.getSession().setAttribute("valiCode", code); //保存 code到 session,和後面的內容對應
//4.繪製內容
// 4.1 設置繪製區域
pen.fillRect(0, 0, width, height);
// 4.2設置字體
pen.setFont(new Font("微軟雅黑",Font.BOLD,fontsize));
// 4.3 按順序逐個繪製字符
for (int i = 0;i<code.length();i++) {
pen.setColor(randColor());//每個字符使用不同的顏色
//繪製字符
//code.charAt(i) 獲得的是單個字符,因此加一個 "" 使其變成字符串
pen.drawString(code.charAt(i)+"", 5+i*fontsize,(fontsize + height)/2);
}
// 4.4 繪製噪音線 ------------------ 增加驗證碼難度
for (int i = 0;i < 2;#### i++) {
pen.setColor(randColor());//設置畫筆顏色
pen.setStroke(new BasicStroke(3));//設置線條爲 3個像素
//劃線的座標:x1,y1 x2,y2
pen.drawLine(random.nextInt(width/2), random.nextInt(height), random.nextInt(width), random.nextInt(width));
}
//5.存爲圖片併發送
ServletOutputStream out = response.getOutputStream();//數據通過 response 返回
ImageIO.write(img, "png", out);
out.flush();//緩存刷新
out.close();//緩存關閉
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
3.2.2 分頁邏輯實現
分頁邏輯實際就是對數據庫的數據進行分條查詢,選擇 mysql 數據庫,是因爲它有較好的分頁邏輯
- 我們需要一個參數 pageNo 表示當前是第幾頁的數據,這個我們需要從前端獲取,如果是第一次獲取,就得給一個默認值
- 再給一個 pageSize ,表示每頁固定展示的數據的條數
- 再給一個 count ,代表數據庫中數據的總記錄數,所以這裏需要進行聚合查詢的(select count(*) from xxx) 的到總記錄數
- 還沒完,還需要一個 pageCount,這個值代表當前頁面能顯示多少條數據,也是從後端數據庫進行獲取的
給大家舉一個例子,假設我的數據庫裏有 11 條記錄,也就是第一次展示前 5條,當我們要看第二頁的時候就查詢第 6 到 10條數據,在翻頁就是查詢最後一頁的數據,因此這個 pageCount 是需要計算的,每次查詢出來的數據,告訴前端要顯示幾條數據
計算邏輯:
int pageCount = 0;
if (count%pageSize == 0) {
pageCount = count/pageSize;
} else {
pageCount = count/pageSize+1;
}
- 數據庫分頁查詢語句:
select * from xxx limit pageSize*(pageNo-1), pageSize
這樣就可以做到上面的例子的邏輯
前端的分頁邏輯,採用 BootStrap 的分頁標籤 + jstl 標籤庫 共同實現分頁邏輯
<nav>
<ul id="pagination" class="pagination">
<c:choose>
<c:when test="${pageNo>1}">
<li class="page-item"><a class="page-link" href="GetAllServlet?pageNo=${pageNo-1 }">上一頁</a></li>
</c:when>
<c:otherwise>
<li class="page-item"><a class="page-link" href="javascript:void(0);">上一頁</a></li>
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${pageNo<pageCount}">
<li class="page-item"><a class="page-link" href="GetAllServlet?pageNo=${pageNo+1 }">下一頁</a></li>
</c:when>
<c:otherwise>
<li class="page-item"><a class="page-link" href="javascript:void(0);">下一頁</a></li>
</c:otherwise>
</c:choose>
</ul>
</nav>
3.2.3 支付寶沙箱支付環境接入
當時在接入的時候,也踩了比較多的坑,現在我把我的解決方案分享給大家(如果嫌麻煩,可以直接到 我的 ShoppingMall 倉庫下載這個 購物車的小 demo,裏面都是 配置好了的)
- 下載 支付寶手機支付 API 的 SDK,我們是 Java 開發者,當然要下載 java 的 SDK:手機網站支付 SDK
- 然後可以大致預覽一下支付寶接入流程:接入流程
- 然後登陸支付寶開放平臺,填寫配置,不然後續就無法進行接入的相關工作
- 閱讀沙箱環境支付接入流程:沙箱支付接入介紹
- 沙箱環境頁面介紹:
- 然後是下載簽名工具:簽名工具使用
下載好就是這樣子的
因爲我們是個人開發者,沒有企業的資質,所以無法生成證書的,所以就默認點這個就可以了
然後將生成的公鑰添加到 沙箱環境的應用公鑰裏,就算是和支付寶環境接入完成了。
7. 然後是 java 代碼配置
將下載好的 sdk導入我們的項目
這裏替換上面兩個對應密鑰
到這裏就基本配置完成了,然後根據你的項目邏輯進行修改即可
- 差點忘記了,我們還需要將 SDK 提供的 jar 包導入進來
四、總結
學到這裏 jsp 階段也算是告一段落了,目前是在學習 Vue 前端 + 後端 SpringBoot 交互的一些內容,目前進度,大愛 Vue,希望下次的項目能夠做的更加精彩,加油