亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

JSP+Servlet早餐外賣系統(tǒng)開發(fā)實(shí)戰(zhàn):從數(shù)據(jù)庫(kù)到部署全流程解析

JSP+Servlet早餐外賣系統(tǒng)開發(fā)實(shí)戰(zhàn):從數(shù)據(jù)庫(kù)到部署全流程解析 早餐外賣這個(gè)場(chǎng)景特別適合JSPServlet這套老牌技術(shù)棧來(lái)練手業(yè)務(wù)鏈路完整從前臺(tái)點(diǎn)餐到后臺(tái)出餐都有又不至于復(fù)雜到失控。今天把這個(gè)基于JavaWeb和MySQL的JSPServlet早餐外賣店管理系統(tǒng)拆開揉碎講一遍從數(shù)據(jù)庫(kù)設(shè)計(jì)到前端交互從本機(jī)部署到常見報(bào)錯(cuò)所有流程都是可以照著重現(xiàn)的不是那種飄在PPT上的概念方案。想把這套系統(tǒng)吃透的人我大概分成兩類一類是剛學(xué)完JavaWeb正在找完整項(xiàng)目做課程設(shè)計(jì)或畢業(yè)設(shè)計(jì)的同學(xué)另一類是工作里被Spring Boot“慣壞了”想回頭補(bǔ)一補(bǔ)原生Servlet、JSP、會(huì)話管理這些底層原理的開發(fā)者。這個(gè)項(xiàng)目能解決的核心問(wèn)題就是讓你完全不用框架純靠Servlet控制請(qǐng)求流轉(zhuǎn)、JSP渲染頁(yè)面、JDBC操作MySQL自己手工拼出一套能用的外賣管理系統(tǒng)。這么做最大的價(jià)值不是“代碼能跑”而是你能真正看清楚一個(gè)Web應(yīng)用在瀏覽器和數(shù)據(jù)庫(kù)之間到底干了些什么。項(xiàng)目本身的業(yè)務(wù)不復(fù)雜顧客瀏覽早餐分類和菜品加入購(gòu)物車提交訂單填寫收貨地址和期望送達(dá)時(shí)間管理員在后臺(tái)維護(hù)菜品、處理訂單狀態(tài)、查看每日營(yíng)業(yè)額。技術(shù)點(diǎn)覆蓋了JavaWeb幾乎全部核心內(nèi)容Filter過(guò)濾器做登錄攔截、Session維護(hù)登錄態(tài)和購(gòu)物車、JDBC做增刪改查、事務(wù)保證下單扣庫(kù)存的一致性、AJAX局部刷新、JSP標(biāo)簽庫(kù)遍歷列表。下面按我的實(shí)際開發(fā)順序把每個(gè)環(huán)節(jié)的關(guān)鍵細(xì)節(jié)和坑都說(shuō)清楚。1. 整體架構(gòu)與設(shè)計(jì)取舍 —— 為什么堅(jiān)持用 JSPServlet 做外賣系統(tǒng)1.1 技術(shù)選型背后的真實(shí)考量有人會(huì)問(wèn)都2025年了誰(shuí)還用JSPServlet寫新項(xiàng)目這個(gè)質(zhì)疑本身沒錯(cuò)但得分場(chǎng)景。如果是公司里的正式產(chǎn)品我絕對(duì)推薦Spring Boot MyBatis / JPA那一套但如果是用來(lái)學(xué)習(xí)JavaWeb、理解HTTP請(qǐng)求如何被處理、Session如何維持狀態(tài)、SQL如何被程序調(diào)用那JSPServlet是最直接的地圖。把所有自動(dòng)化都去掉之后底層的輪廓才會(huì)浮出水面。這個(gè)早餐外賣系統(tǒng)的業(yè)務(wù)規(guī)模也不大屬于典型的“高并發(fā)需求低、業(yè)務(wù)邏輯直觀、頁(yè)面數(shù)量適中”的項(xiàng)目。早餐店高峰時(shí)段就是早上七點(diǎn)到九點(diǎn)單量密集但總量有限用Servlet線程池處理完全夠用。反而如果用Spring Boot起步你會(huì)發(fā)現(xiàn)大部分精力耗在理解自動(dòng)配置上而不是業(yè)務(wù)本身。所以我刻意選擇了“裸奔”方案MVC三層全部手寫連接池用簡(jiǎn)單的DBCP或者干脆自己封裝JDBC工具類分頁(yè)邏輯自己計(jì)算事務(wù)邊界自己在Service層控制。寫完之后再回頭看Spring Boot很多概念都是自然而然的對(duì)應(yīng)關(guān)系。1.2 系統(tǒng)模塊劃分與角色權(quán)限我把系統(tǒng)拆成前臺(tái)門戶和后臺(tái)管理兩大塊對(duì)應(yīng)兩種角色普通用戶和管理員。前臺(tái)給顧客看菜單、下單、查自己的訂單后臺(tái)給店員管理菜品類別、上下架早餐、處理訂單狀態(tài)。權(quán)限控制的核心就一句話Session里有沒有登錄用戶以及這個(gè)用戶的role字段是不是1。目錄結(jié)構(gòu)我建議這樣組織注意包名要語(yǔ)義清晰com.food ├── controller // Servlet類處理請(qǐng)求轉(zhuǎn)發(fā)和重定向 ├── service // 業(yè)務(wù)邏輯層事務(wù)控制在這里 ├── dao // JDBC數(shù)據(jù)訪問(wèn)層 ├── entity // 實(shí)體類對(duì)應(yīng)數(shù)據(jù)庫(kù)表 ├── filter // 編碼過(guò)濾器、登錄攔截過(guò)濾器 ├── util // DBUtil、MD5工具類等 └── listener // 可選啟動(dòng)時(shí)加載分類緩存JSP頁(yè)面放在webapp目錄下前臺(tái)頁(yè)面和后臺(tái)頁(yè)面用文件夾區(qū)分webapp/front、webapp/admin。這樣的好處是路徑清晰寫Servlet重定向時(shí)不會(huì)把前臺(tái)后臺(tái)弄混。1.3 一個(gè)Servlet還是多個(gè)Servlet這個(gè)點(diǎn)是新手最容易糾結(jié)的地方。我見過(guò)不少人圖省事寫一個(gè)DishServlet里面用if (list.equals(action))、else if (add.equals(action))分別處理不同請(qǐng)求。項(xiàng)目小的時(shí)候這么寫沒問(wèn)題但早餐外賣系統(tǒng)做到后面至少有十幾個(gè)功能動(dòng)作——菜品增刪改查、分類管理、訂單處理、登錄注冊(cè)、購(gòu)物車操作——全塞一個(gè)Servlet會(huì)讓代碼膨脹到幾百行排查問(wèn)題非常痛苦。我采用的方案是“一個(gè)業(yè)務(wù)實(shí)體一個(gè)Servlet”。菜品相關(guān)操作放DishServlet訂單相關(guān)放OrderServlet用戶相關(guān)放UserServlet購(gòu)物車相關(guān)放CartServlet。每個(gè)Servlet里用action參數(shù)通過(guò)request.getParameter(action)獲取區(qū)分具體方法。這個(gè)模式其實(shí)已經(jīng)非常接近Spring MVC的RequestMapping思路了理解這種對(duì)應(yīng)關(guān)系之后以后學(xué)框架會(huì)輕松很多。2. 數(shù)據(jù)庫(kù)設(shè)計(jì)與核心建模 —— 一份能應(yīng)付答辯的 MySQL 表結(jié)構(gòu)2.1 分類表與菜品表的設(shè)計(jì)早餐外賣店的菜單很有特點(diǎn)品類固定、單品價(jià)格不高、常有“豆?jié){油條”這種套餐邏輯。所以我的設(shè)計(jì)是“分類表菜品表”的主從結(jié)構(gòu)分類表在前臺(tái)渲染成導(dǎo)航欄分類菜品表按分類展示。分類表結(jié)構(gòu)簡(jiǎn)單重點(diǎn)是狀態(tài)字段和排序字段CREATE TABLE category ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 分類ID, name VARCHAR(50) NOT NULL COMMENT 分類名稱粥品/煎餅/豆?jié){/套餐, sort_order INT DEFAULT 0 COMMENT 排序權(quán)重值小的靠前, status TINYINT DEFAULT 1 COMMENT 1啟用 0停用, create_time DATETIME DEFAULT CURRENT_TIMESTAMP );菜品表要注意的字段多一些我把關(guān)鍵字段貼出來(lái)CREATE TABLE dish ( id INT PRIMARY KEY AUTO_INCREMENT, category_id INT NOT NULL COMMENT 所屬分類ID, name VARCHAR(100) NOT NULL COMMENT 菜品名稱, description VARCHAR(500) COMMENT 菜品描述前臺(tái)列表展示, price DECIMAL(10,2) NOT NULL COMMENT 現(xiàn)價(jià), original_price DECIMAL(10,2) DEFAULT NULL COMMENT 原價(jià)用于劃線價(jià)展示, image VARCHAR(200) COMMENT 圖片路徑存相對(duì)路徑, stock INT DEFAULT 0 COMMENT 當(dāng)日庫(kù)存賣完自動(dòng)下架, sales_count INT DEFAULT 0 COMMENT 累計(jì)銷量用于“熱銷”排序, status TINYINT DEFAULT 1 COMMENT 1在售 0下架, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );兩個(gè)細(xì)節(jié)必須強(qiáng)調(diào)第一金額字段統(tǒng)一用DECIMAL(10,2)絕對(duì)不要用FLOAT或DOUBLE外賣訂單涉及大量金額累加和單價(jià)比較浮點(diǎn)誤差會(huì)帶來(lái)對(duì)不上賬的問(wèn)題第二圖片存的是webapp/upload下的相對(duì)路徑比如/upload/youitao.jpg頁(yè)面渲染時(shí)用request.getContextPath()拼接成完整路徑。千萬(wàn)別把完整URL寫死進(jìn)數(shù)據(jù)庫(kù)換域名、換端口的時(shí)候會(huì)瘋掉的。2.2 訂單主表與訂單明細(xì)表建模早餐外賣的訂單和正餐外賣有區(qū)別用戶可能是前一天晚上預(yù)訂第二天早上的餐所以“期望送達(dá)時(shí)間”是必須的字段而且前臺(tái)下單時(shí)要限制只能選明天及以后的時(shí)間。訂單設(shè)計(jì)成主從兩張表主表存一次訂單的整體信息明細(xì)表存這單里每種餐品的數(shù)量、單價(jià)、小計(jì)。CREATE TABLE orders ( id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE COMMENT 訂單號(hào)年月日隨機(jī)數(shù), user_id INT NOT NULL COMMENT 下單用戶ID, total_amount DECIMAL(10,2) NOT NULL COMMENT 訂單總金額, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待支付 1已支付備餐中 2配送中 3已完成 4已取消, receiver_name VARCHAR(50) NOT NULL COMMENT 收貨人姓名, receiver_phone VARCHAR(20) NOT NULL COMMENT 聯(lián)系電話, delivery_address VARCHAR(200) NOT NULL COMMENT 配送地址, expected_time DATETIME NOT NULL COMMENT 期望送達(dá)時(shí)間, remark VARCHAR(200) COMMENT 訂單備注比如“不要香菜”, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_user_id(user_id), INDEX idx_status(status), INDEX idx_expected_time(expected_time) ); CREATE TABLE order_item ( id INT PRIMARY KEY AUTO_INCREMENT, order_id INT NOT NULL COMMENT 訂單ID, dish_id INT NOT NULL COMMENT 菜品ID, dish_name VARCHAR(100) NOT NULL COMMENT 下單時(shí)的菜品名稱快照, price DECIMAL(10,2) NOT NULL COMMENT 下單時(shí)的單價(jià)快照, quantity INT NOT NULL COMMENT 數(shù)量, subtotal DECIMAL(10,2) NOT NULL COMMENT 小計(jì)金額 );這里有一個(gè)菜鳥經(jīng)常忽略的設(shè)計(jì)為什么訂單明細(xì)表里要冗余dish_name和price這兩個(gè)字段因?yàn)樵绮偷甑牟似肥菚?huì)改價(jià)、甚至?xí)h除的。如果訂單只存dish_id一個(gè)月后店長(zhǎng)把豆?jié){從兩塊錢漲到三塊錢你再回去看一個(gè)月前的訂單報(bào)表金額全變了。這叫“歷史數(shù)據(jù)快照”外賣系統(tǒng)的訂單明細(xì)必須保留下單那一刻的商品信息這是行業(yè)通用做法。2.3 外鍵、索引和命名規(guī)范的實(shí)操建議外鍵約束在學(xué)術(shù)上很漂亮但在實(shí)際項(xiàng)目里我建議盡量不要加物理外鍵尤其是訂單明細(xì)表關(guān)聯(lián)菜品表、訂單表關(guān)聯(lián)用戶表這種高頻查詢鏈路。理由有兩條一是早餐外賣高峰期密集下單物理外鍵在插入和刪除時(shí)會(huì)有額外的完整性檢查開銷二是做訂單刪除或菜品歸檔時(shí)物理外鍵會(huì)擋住操作還得先處理關(guān)聯(lián)數(shù)據(jù)。業(yè)務(wù)上的一致性通過(guò)Service層事務(wù)來(lái)控制數(shù)據(jù)庫(kù)只加普通索引。索引方面訂單表里user_id、status、create_time這三個(gè)字段是查詢高頻字段前臺(tái)用戶查“我的訂單”、后臺(tái)管理員按狀態(tài)篩選訂單、按時(shí)間范圍統(tǒng)計(jì)營(yíng)業(yè)額都靠這三個(gè)索引。但注意不要無(wú)腦加索引——訂單狀態(tài)只有幾個(gè)固定值區(qū)分度很低單獨(dú)加索引收益不大我更推薦建聯(lián)合索引(status, create_time)這樣既能按狀態(tài)篩也能按時(shí)間排一個(gè)索引覆蓋兩種場(chǎng)景。命名規(guī)范方面我習(xí)慣表名用單數(shù)字段名全部小寫加下劃線user_id不寫成userIdcreate_time不寫成createTime。Java實(shí)體類的駝峰命名和數(shù)據(jù)庫(kù)下劃線命名之間在DAO層寫映射時(shí)手動(dòng)轉(zhuǎn)換即可項(xiàng)目不大沒必要引入ORM框架但字段命名統(tǒng)一能讓代碼審查不鬧心。主鍵一律叫id邏輯外鍵直接叫xxx_id一看就能明白關(guān)聯(lián)關(guān)系。3. 核心功能模塊實(shí)現(xiàn)細(xì)節(jié) —— 從登錄到結(jié)算的完整閉環(huán)3.1 用戶登錄與會(huì)話管理登錄是幾乎所有Web系統(tǒng)的入口早餐外賣系統(tǒng)也不例外。我在UserServlet里寫了個(gè)login方法流程就是拿到用戶名和密碼先做非空校驗(yàn)然后調(diào)Service層的login()方法返回用戶對(duì)象或null。密碼存儲(chǔ)那邊用了MD5加鹽的方式注冊(cè)時(shí)把鹽和密碼哈希一起存庫(kù)登錄時(shí)用同規(guī)則哈希后比對(duì)——雖然是老技術(shù)但配合鹽值仍然能擋住大部分“拖庫(kù)撞庫(kù)”的低級(jí)攻擊。加鹽的核心是一人一鹽讓彩虹表失效。登錄成功后做法是request.getSession().setAttribute(loginUser, user)。退出登錄時(shí)不僅要session.invalidate()還要記得把Cookie里的JSESSIONID清理掉不然瀏覽器還會(huì)在響應(yīng)頭里帶一個(gè)無(wú)效的會(huì)話ID。Session這塊要提醒一個(gè)容易踩的坑不要把整個(gè)User對(duì)象直接塞在Session里當(dāng)JSON用然后在JSP里取${loginUser.password}這種危險(xiǎn)操作。正確做法是把密碼字段設(shè)為null再放入Session或者單獨(dú)建一個(gè)SafeUser對(duì)象只保留id、用戶名、手機(jī)號(hào)、角色這些安全字段。登錄攔截用Filter來(lái)實(shí)現(xiàn)最合適。我建了一個(gè)LoginFilter在web.xml里配置映射路徑WebFilter(/*) public class LoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; String uri request.getRequestURI(); // 放行登錄頁(yè)、注冊(cè)頁(yè)、靜態(tài)資源、前臺(tái)瀏覽接口 if (uri.endsWith(login.jsp) || uri.endsWith(register.jsp) || uri.contains(/static/) || uri.contains(/upload/) || uri.contains(userServlet?actionlogin) || uri.contains(userServlet?actionregister) || uri.contains(dishServlet?actionlist)) { chain.doFilter(request, response); return; } // 其余頁(yè)面必須登錄 HttpSession session request.getSession(false); if (session ! null session.getAttribute(loginUser) ! null) { chain.doFilter(request, response); } else { response.sendRedirect(request.getContextPath() /front/login.jsp); } } }注意request.getSession(false)里的false——意思是如果沒有Session就返回null而不是新創(chuàng)建一個(gè)。這個(gè)細(xì)節(jié)很關(guān)鍵未登錄用戶訪問(wèn)后臺(tái)頁(yè)面時(shí)不應(yīng)該被“強(qiáng)行創(chuàng)建Session”白白浪費(fèi)服務(wù)器內(nèi)存還讓會(huì)話ID有了可乘之機(jī)。3.2 菜單展示、分頁(yè)搜索與圖片坐標(biāo)定位前臺(tái)的菜單頁(yè)是整個(gè)系統(tǒng)門面也是JSP標(biāo)簽庫(kù)用得最密集的地方。我用JSTL的c:forEach遍歷菜品列表加上c:choose實(shí)現(xiàn)“有圖顯示圖、無(wú)圖顯示占位圖”的邏輯。分類導(dǎo)航欄用c:if判斷當(dāng)前選中分類高亮。分頁(yè)必須自己寫清楚頁(yè)面?zhèn)鱬ageNum參數(shù)每頁(yè)固定6個(gè)菜品因?yàn)樵绮偷陻?shù)量不大一頁(yè)放太少顯得空曠放太多又太長(zhǎng)DAO層先用SELECT COUNT(*)算總量再執(zhí)行帶LIMIT的查詢int pageSize 6; int totalCount dishDao.countByCategory(categoryId); int totalPages (int) Math.ceil(totalCount * 1.0 / pageSize); int offset (pageNum - 1) * pageSize; ListDish dishList dishDao.findByCategory(categoryId, offset, pageSize);頁(yè)碼導(dǎo)航怎么做我的方案是直接用c:forEach從1循環(huán)到totalPages生成?pageNum${i}categoryId${categoryId}的鏈接。這里有個(gè)細(xì)節(jié)翻頁(yè)時(shí)一定要把categoryId也帶上并且當(dāng)前頁(yè)碼要控制在1和totalPages之間防止用戶直接在地址欄輸入pageNum999導(dǎo)致SQL越界。圖片坐標(biāo)定位這個(gè)需求在早餐外賣里有實(shí)際應(yīng)用場(chǎng)景——比如菜單頁(yè)的一張菜品展示圖上標(biāo)注“豆?jié){ 2元 / 油條 3元 / 茶葉蛋 1.5元”點(diǎn)擊不同坐標(biāo)區(qū)域跳到對(duì)應(yīng)菜品分類。原生JSP做這個(gè)很簡(jiǎn)單不算復(fù)雜給圖片設(shè)置usemap屬性用HTML的map和area標(biāo)簽劃定多個(gè)圓形或矩形熱區(qū)每個(gè)熱區(qū)的href指向不同查詢鏈接img src${ctx}/upload/breakfast_map.png usemap#breakfastMap alt早餐地圖 map namebreakfastMap area shaperect coords10,10,120,120 href${ctx}/dishServlet?actionlistcategoryId1 alt粥品 area shapecircle coords180,80,40 href${ctx}/dishServlet?actionlistcategoryId2 alt煎餅 /mapcoordinates的四個(gè)數(shù)字分別代表矩形左上角和右下角的x、y坐標(biāo)值確定區(qū)域時(shí)直接對(duì)著圖片坐標(biāo)量就行。如果要求更細(xì)致的交互可以嵌入一小段JavaScript監(jiān)聽圖片的click事件用event.offsetX和event.offsetY判斷點(diǎn)擊位置落入哪個(gè)區(qū)域范圍再手動(dòng)跳轉(zhuǎn)。兩種方式對(duì)比HTML map標(biāo)簽簡(jiǎn)單可靠但不靈活JS判斷可以加高亮提示、彈窗預(yù)覽體驗(yàn)更好代價(jià)是要自己寫邏輯。3.3 購(gòu)物車實(shí)現(xiàn)——為什么用Session而不用數(shù)據(jù)庫(kù)表購(gòu)物車這環(huán)節(jié)錯(cuò)誤答案最多。有些人習(xí)慣性地建一張cart_item表用戶加一次購(gòu)物車就寫一次數(shù)據(jù)庫(kù)提交訂單時(shí)再逐條讀出來(lái)、刪除。這個(gè)方案在體驗(yàn)上有個(gè)硬傷用戶逛了半天加了一堆菜中途瀏覽器直接關(guān)掉或者Session超時(shí)這些購(gòu)物車數(shù)據(jù)就成了垃圾數(shù)據(jù)你還得定時(shí)清理。而且早餐外賣的場(chǎng)景里購(gòu)物車生命周期極短從加餐到下單往往不超過(guò)幾分鐘根本犯不著落到數(shù)據(jù)庫(kù)。我在這個(gè)項(xiàng)目里把購(gòu)物車直接放在Session里結(jié)構(gòu)是MapInteger, CartItem——key是菜品idvalue是包含菜品信息、數(shù)量、小計(jì)的購(gòu)物車項(xiàng)。實(shí)現(xiàn)思路是MapInteger, CartItem cart (MapInteger, CartItem) session.getAttribute(cart); if (cart null) { cart new HashMapInteger, CartItem(); session.setAttribute(cart, cart); } // 加購(gòu)時(shí)判斷key存在就數(shù)量1不存在就新建一項(xiàng)這個(gè)方案的好處和柜臺(tái)點(diǎn)餐的體驗(yàn)一致加購(gòu)不需要訪問(wèn)數(shù)據(jù)庫(kù)零延遲購(gòu)物車數(shù)據(jù)隨Session自然銷毀沒有臟數(shù)據(jù)積壓。缺點(diǎn)你也能想到——用戶在手機(jī)上逛著逛著把瀏覽器關(guān)了購(gòu)物車就沒了。但在早餐外賣這種低決策成本、即點(diǎn)即走的場(chǎng)景下這是完全可以接受的取舍。購(gòu)物車頁(yè)面的“數(shù)量加減”按鈕要實(shí)現(xiàn)一個(gè)細(xì)節(jié)數(shù)量減少到0時(shí)這一項(xiàng)自動(dòng)從Map里移除。營(yíng)業(yè)額統(tǒng)計(jì)和庫(kù)存扣減都依賴購(gòu)物車數(shù)據(jù)的準(zhǔn)確性不要在頁(yè)面上顯示數(shù)量為0的餐品后還能提交會(huì)讓訂單金額算錯(cuò)。3.4 訂單提交流程與事務(wù)控制下單是整個(gè)系統(tǒng)的核心交易環(huán)節(jié)最容易出數(shù)據(jù)不一致的地方。我按下面的步驟設(shè)計(jì)Service層的submitOrder方法從Session里拿購(gòu)物車校驗(yàn)非空從Session里拿登錄用戶校驗(yàn)非空遍歷購(gòu)物車明細(xì)逐項(xiàng)檢查菜品仍在售、庫(kù)存夠數(shù)計(jì)算訂單總金額循環(huán)累加每個(gè)明細(xì)的subtotal生成訂單號(hào)形如20250127093000001純數(shù)字避免和字母混淆插入訂單主表拿到自增id遍歷購(gòu)物車明細(xì)批量插入訂單明細(xì)表扣減庫(kù)存UPDATE dish SET stock stock - ? WHERE id ? AND stock ?清空Session里的購(gòu)物車返回訂單號(hào)跳轉(zhuǎn)到支付模擬頁(yè)。這十步里第5、6、7、8四步必須處于同一個(gè)事務(wù)里。如果只插了主表、明細(xì)表插入失敗主表訂單就是一條“孤兒訂單”如果下單成功但庫(kù)存沒扣商品就可能超賣。早餐店雖然單量不大但邏輯上不能有這種漏洞。我用最樸素的方式管理事務(wù)在DBUtil里封裝getConnection()、beginTransaction()、commit()、rollback()然后在Service層手動(dòng)控制Connection conn DBUtil.getConnection(); try { conn.setAutoCommit(false); // 插入訂單主表、明細(xì)表、扣庫(kù)存 DBUtil.commit(conn); } catch (Exception e) { DBUtil.rollback(conn); throw new RuntimeException(下單失敗, e); } finally { DBUtil.release(conn); }由于DAO層的每個(gè)方法內(nèi)部都會(huì)獨(dú)立拿連接和釋放連接開事務(wù)時(shí)必須用一個(gè)外部傳入的連接。方法簽名設(shè)計(jì)成insertOrder(Connection conn, Order order)或者在DAO內(nèi)部增加一個(gè)重載方法透?jìng)鬟B接。新手在這個(gè)地方很容易犯的錯(cuò)是Service層開啟事務(wù)后調(diào)用DAO方法DAO又自己DriverManager.getConnection()新拿了一個(gè)連接導(dǎo)致事務(wù)根本沒作用在同一個(gè)數(shù)據(jù)庫(kù)會(huì)話上。務(wù)必保證整個(gè)業(yè)務(wù)鏈路用的是同一個(gè)Connection。訂單狀態(tài)流轉(zhuǎn)我設(shè)計(jì)為0待支付 → 1已支付/備餐中 → 2配送中 → 3已完成或者0待支付 → 4已取消。后臺(tái)管理員操作按鈕根據(jù)當(dāng)前狀態(tài)顯示對(duì)應(yīng)的下一步操作。這個(gè)狀態(tài)機(jī)的實(shí)現(xiàn)原則是狀態(tài)只能往后走不能回退例如不能從“配送中”改成“待支付”否則財(cái)務(wù)數(shù)據(jù)就亂了。3.5 后臺(tái)訂單管理與營(yíng)業(yè)額統(tǒng)計(jì)后臺(tái)管理員的首頁(yè)是一個(gè)輕量?jī)x表盤今日訂單數(shù)、今日營(yíng)業(yè)額、待處理訂單數(shù)、菜品銷量Top5。這些數(shù)據(jù)如果用一條SQL硬拼會(huì)很痛苦我的做法是拆成多個(gè)SQL聚合查詢分別查COUNT(*)、SUM(total_amount)等。營(yíng)業(yè)額統(tǒng)計(jì)有一個(gè)大坑訂單金額的累加時(shí)機(jī)。如果統(tǒng)計(jì)口徑是“訂單創(chuàng)建時(shí)間”那就要排除已取消狀態(tài)如果統(tǒng)計(jì)口徑是“訂單完成時(shí)間”那所有狀態(tài)都得列入“待支付”但未支付的也算異常。我最終采用的口徑是“只統(tǒng)計(jì)狀態(tài)為已支付、配送中、已完成的訂單”把待支付和已取消排除掉。SQL寫法類似SELECT DATE_FORMAT(create_time, %Y-%m-%d) AS day, COUNT(*) AS order_count, COALESCE(SUM(total_amount), 0) AS revenue FROM orders WHERE status IN (1, 2, 3) AND create_time DATE_SUB(CURDATE(), INTERVAL 7 DAY) GROUP BY DATE_FORMAT(create_time, %Y-%m-%d) ORDER BY day;COALESCE必須加上——某一天沒有任何訂單時(shí)SUM返回null頁(yè)面直接顯示空白用0填充才合理。統(tǒng)計(jì)圖不建議后端生成圖片太重了。我的方案是后臺(tái)JSP頁(yè)面把統(tǒng)計(jì)結(jié)果轉(zhuǎn)換成JSON數(shù)組用原生JavaScript畫簡(jiǎn)單的柱狀圖或者引入輕量Chart.js庫(kù)。早餐店老板最關(guān)心的是“今天賣了多少單”“哪幾樣賣得好”柱狀圖和排名列表就夠了不需要炫酷的3D圖表。4. 前端交互與JavaScript細(xì)節(jié) —— 讓頁(yè)面活起來(lái)的小技巧4.1 表單校驗(yàn)從正則到提交攔截外賣系統(tǒng)的表單主要集中在登錄、注冊(cè)、下單這三個(gè)場(chǎng)景登錄只需要用戶名密碼非空但注冊(cè)和下單必須做格式校驗(yàn)。我在前端用JavaScript做首道防線在Servlet端做第二道防線絕不信前端的校驗(yàn)結(jié)果。手機(jī)號(hào)校驗(yàn)是最常見的需求我用一個(gè)正則function isValidPhone(phone) { var reg /^1[3-9]\d{9}$/; return reg.test(phone); }這個(gè)正則代表第一位是1第二位在3到9之間后面跟著9位數(shù)字總計(jì)11位。它基本覆蓋了目前國(guó)內(nèi)用戶手機(jī)號(hào)的規(guī)律能在用戶輸入錯(cuò)誤時(shí)立刻提示減少無(wú)效請(qǐng)求到達(dá)服務(wù)器。但正則只是“格式校驗(yàn)”不是“真實(shí)驗(yàn)證”——如果項(xiàng)目需要驗(yàn)證號(hào)碼真的存在那就要接短信驗(yàn)證碼服務(wù)早餐店系統(tǒng)用不上這個(gè)級(jí)別。下單表單里的“期望送達(dá)時(shí)間”必須用JavaScript校驗(yàn)不能選過(guò)去的日期不能選今天之前的時(shí)間。我的做法是用new Date()獲取當(dāng)前時(shí)間戳然后和輸入框的值做對(duì)比時(shí)間早于當(dāng)前時(shí)間直接彈框攔截。4.2 AJAX局部刷新消息提示和購(gòu)物車角標(biāo)JSP頁(yè)面默認(rèn)是同步刷新但有幾個(gè)場(chǎng)景用AJAX體驗(yàn)?zāi)芴嵘粋€(gè)檔次。最典型的是“加入購(gòu)物車”用戶點(diǎn)一下“加入購(gòu)物車”按鈕如果整頁(yè)刷新頁(yè)面滾動(dòng)位置會(huì)重置用戶要重新找到剛才那個(gè)菜很煩。我改成用fetch或XMLHttpRequest異步提交返回JSON前端根據(jù)結(jié)果更新頁(yè)面上的“購(gòu)物車商品數(shù)量”角標(biāo)同時(shí)彈一個(gè)提示條“已加入購(gòu)物車”。原生JavaScript里可以用這個(gè)方式實(shí)現(xiàn)AJAX請(qǐng)求function addToCart(dishId) { fetch(ctx /cartServlet?actionadddishId dishId, { method: GET, credentials: same-origin }) .then(function(resp) { return resp.json(); }) .then(function(data) { if (data.success) { document.getElementById(cartCount).textContent data.cartCount; showMsg(已加入購(gòu)物車); } else { showMsg(data.message || 加入失敗); } }); }這里有個(gè)細(xì)節(jié)要注意AJAX請(qǐng)求同樣會(huì)被LoginFilter攔截。如果用戶沒登錄就直接點(diǎn)“加購(gòu)”返回的不是JSON而是一個(gè)重定向到登錄頁(yè)的HTML頁(yè)面前端解析resp.json()會(huì)報(bào)錯(cuò)。我的處理方案是在Filter里對(duì)AJAX請(qǐng)求做單獨(dú)分支判斷通過(guò)X-Requested-With請(qǐng)求頭識(shí)別未登錄時(shí)返回{success:false,message:請(qǐng)先登錄}前端的提示條會(huì)展示這個(gè)信息。購(gòu)物車角標(biāo)更新的本質(zhì)是后端addToCart邏輯執(zhí)行完成后計(jì)算cart.size()把數(shù)值放進(jìn)JSON返回。前端拿到后直接textContent賦值這樣不用刷新頁(yè)面就能看到角標(biāo)變化。4.3 圖片坐標(biāo)交互和旋轉(zhuǎn)的實(shí)用技巧前面提到了HTML map做圖片熱區(qū)這里再補(bǔ)充一種方案用JavaScript監(jiān)聽圖片點(diǎn)擊位置實(shí)現(xiàn)更復(fù)雜的交互。比如菜品詳情頁(yè)有一張“套餐搭配示意圖”用戶點(diǎn)擊圖上的某個(gè)位置系統(tǒng)判斷點(diǎn)擊點(diǎn)落在哪個(gè)菜品的圓形區(qū)域內(nèi)然后彈出該菜品的詳情卡片再點(diǎn)一次可以加購(gòu)。核心代碼是這樣的document.getElementById(dishMap).addEventListener(click, function(e) { var rect e.target.getBoundingClientRect(); var x e.clientX - rect.left; var y e.clientY - rect.top; // 判斷坐標(biāo)是否落在某個(gè)圓內(nèi)比如圓心(100,80) 半徑40 var dx x - 100; var dy y - 80; if (dx * dx dy * dy 40 * 40) { window.location.href ctx /dishServlet?actiondetailid3; } });判斷一個(gè)圓要計(jì)算距離平方這是初中幾何——點(diǎn)到圓心的距離小于半徑就在圓內(nèi)。這套邏輯比HTML map靈活在與后端數(shù)據(jù)聯(lián)動(dòng)菜品坐標(biāo)可以存在數(shù)據(jù)庫(kù)里前端循環(huán)讀取后在canvas或div上動(dòng)態(tài)繪制熱區(qū)而不需要改HTML代碼。另外提一個(gè)小技巧有些早餐店會(huì)拍豎版圖片但頁(yè)面上想展示橫版的效果。傳統(tǒng)做法是后端處理圖片旋轉(zhuǎn)其實(shí)前端一行JavaScript就能搞定旋轉(zhuǎn)例如document.getElementById(menuImg).style.rotate -90deg;CSS的rotate屬性可以直接用角度值注意設(shè)置旋轉(zhuǎn)變換后也要配合transform-origin調(diào)整旋轉(zhuǎn)中心不然圖片會(huì)繞著左上角轉(zhuǎn)視覺上偏了。這類前端小技巧在處理一些手機(jī)拍攝的早餐實(shí)拍圖時(shí)特別實(shí)用。4.4 跨瀏覽器兼容的幾個(gè)注意點(diǎn)現(xiàn)在的瀏覽器都是現(xiàn)代瀏覽器了大部分標(biāo)準(zhǔn)API都能直接用但做JavaWeb課程設(shè)計(jì)時(shí)要考慮用戶可能用IE或者老內(nèi)核瀏覽器訪問(wèn)。兼容性風(fēng)險(xiǎn)最高的有四個(gè)地方fetch、Promise、let/const、Arrow Function。如果項(xiàng)目沒有引入任何框架和庫(kù)我建議寫原生JavaScript時(shí)采用ES5語(yǔ)法或者用最基礎(chǔ)的XMLHttpRequest封裝。比如上面的addToCart函數(shù)改成原生寫法var xhr new XMLHttpRequest(); xhr.open(GET, ctx /cartServlet?actionadddishId dishId, true); xhr.onreadystatechange function() { if (xhr.readyState 4 xhr.status 200) { var data JSON.parse(xhr.responseText); ... } }; xhr.send();這里不是讓你退回老技術(shù)而是在選型階段就想清楚目標(biāo)用戶是誰(shuí)。如果這個(gè)系統(tǒng)只是校內(nèi)課程設(shè)計(jì)運(yùn)行環(huán)境就是Chrome那用fetch完全沒問(wèn)題。如果是要交付給某個(gè)早餐店實(shí)際使用店里的電腦可能是十年前的老機(jī)器、瀏覽器從來(lái)沒升級(jí)過(guò)這時(shí)候ES5的兼容性優(yōu)勢(shì)立刻體現(xiàn)出來(lái)。5. 本地環(huán)境部署實(shí)操 —— IDEA MySQL 從零跑通項(xiàng)目5.1 MySQL 安裝與版本選擇這個(gè)項(xiàng)目用哪個(gè)版本的MySQL合適我推薦5.7 LTS版本例如5.7.44原因有三點(diǎn)5.7還是目前大量高校和中小公司的穩(wěn)定主力版本網(wǎng)上教程最多和8.0相比5.7的連接驅(qū)動(dòng)配置相對(duì)簡(jiǎn)單不會(huì)碰到8.0的caching_sha2_password驗(yàn)證插件兼容問(wèn)題早餐外賣項(xiàng)目的SQL語(yǔ)句沒有8.0特有的窗口函數(shù)需求完全不需要硬上8.0。但如果你電腦上已經(jīng)裝了8.0也不用卸掉重裝。只要在JDBC連接串里額外配置兩項(xiàng)useSSLfalse和allowPublicKeyRetrievaltrue。8.0默認(rèn)使用caching_sha2_password認(rèn)證老版本的MySQL驅(qū)動(dòng)5.1.x系列連接會(huì)報(bào)“Public Key Retrieval is not allowed”這個(gè)錯(cuò)加上allowPublicKeyRetrievaltrue就能解決。安裝MySQL時(shí)有兩個(gè)大坑必須提前說(shuō)。第一個(gè)是初始密碼Windows用ZIP壓縮包方式安裝時(shí)解壓后執(zhí)行mysqld --initialize-insecure會(huì)生成一個(gè)root空密碼這樣第一次登錄不用費(fèi)勁找臨時(shí)密碼直接打mysql -uroot就能進(jìn)。第二個(gè)是my.ini配置文件里的字符集default-character-set要配合MySQL 5.7的寫法服務(wù)端設(shè)置character-set-serverutf8mb4客戶端連接時(shí)在連接串里追加useUnicodetruecharacterEncodingutf8否則JSP頁(yè)面顯示中文全是問(wèn)號(hào)。Linux服務(wù)器上部署時(shí)RPM包安裝有一個(gè)常見問(wèn)題——MySQL 5.7官方倉(cāng)庫(kù)有時(shí)只顯示最新小版本比如搜索“mysql 5.7.44”可能找不到對(duì)應(yīng)RPM包。我的建議是直接到MySQL官方下載站挑mysql-community-server-5.7.44-1.el7.x86_64.rpm這種完整包安裝不要依賴yum源自動(dòng)解析版本。5.2 IDEA 配置 Tomcat 與項(xiàng)目結(jié)構(gòu)在IDEA里跑JSPServlet項(xiàng)目新手被卡住的地方新建項(xiàng)目時(shí)選錯(cuò)了類型。正確姿勢(shì)是創(chuàng)建一個(gè)普通的“Java Enterprise”項(xiàng)目勾選Web Application模板然后配置Tomcat。如果你手里是已經(jīng)寫好的項(xiàng)目代碼導(dǎo)入時(shí)要注意三個(gè)地方第一項(xiàng)目必須包含webapp目錄且該目錄被正確標(biāo)記為Web資源目錄。IDEA里右鍵webapp→ “Add Framework Support” → 選擇“Web”是可以補(bǔ)救的。第二WEB-INF/web.xml文件必須存在Servlet全注解開發(fā)時(shí)代甚至可以沒有web.xml但I(xiàn)DEA的Artifact打包默認(rèn)依賴這個(gè)文件。第三Tomcat的Lib目錄要確認(rèn)IDEA里配置Tomcat的“Server”選項(xiàng)時(shí)“Libraries”標(biāo)簽頁(yè)如果沒有把servlet-api.jar加進(jìn)來(lái)所有Servlet類都會(huì)編譯報(bào)錯(cuò)找不到HttpServlet。5.3 JDBC 連接與SSL錯(cuò)誤處理JDBC連接MySQL的代碼是我見過(guò)報(bào)錯(cuò)頻率最高的地方。核心連接串如下以MySQL 5.7為例private static final String URL jdbc:mysql://localhost:3306/food_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD yourpassword; Class.forName(com.mysql.jdbc.Driver); Connection conn DriverManager.getConnection(URL, USER, PASSWORD);useSSLfalse幾乎必寫。如果你裝的是MySQL 8.0卻下載了5.x的驅(qū)動(dòng)如果不加這個(gè)參數(shù)會(huì)報(bào)“SSL connection error: java.net.SocketException: Connection reset”看起來(lái)像網(wǎng)絡(luò)問(wèn)題實(shí)際是SSL握手失敗。serverTimezoneAsia/Shanghai也要寫因?yàn)镸ySQL 5.7之后驅(qū)動(dòng)要求明確時(shí)區(qū)不寫會(huì)報(bào)The server time zone value ?D1ú±ê×?ê±?? is unrecognized這種亂碼時(shí)區(qū)錯(cuò)誤。驅(qū)動(dòng)包的jar文件放置位置也是入門常見問(wèn)題正確的放法是復(fù)制到webapp/WEB-INF/lib目錄下而不是項(xiàng)目根目錄某處。IDEA里雖然可以通過(guò)“Add as Library”讓編譯通過(guò)但Tomcat部署時(shí)如果驅(qū)動(dòng)只在編譯classpath里、不在WEB-INF/lib運(yùn)行時(shí)就會(huì)報(bào)ClassNotFoundException: com.mysql.jdbc.Driver。保險(xiǎn)起見同時(shí)放到外部的Tomcat lib目錄也可以但我更推薦跟隨項(xiàng)目打包這樣換一臺(tái)電腦拉代碼不會(huì)丟依賴。5.4 部署過(guò)程中最常見的幾個(gè)404/500問(wèn)題部署跑起來(lái)之后如果頁(yè)面出現(xiàn)404或500先別慌按以下列表排查大部分情況是低級(jí)配置問(wèn)題現(xiàn)象可能原因解決方案瀏覽器訪問(wèn)localhost:8080顯示404 Tomcat首頁(yè)項(xiàng)目沒有正確部署到Tomcat的webapps目錄IDEA里檢查Artifact輸出或者直接把項(xiàng)目打成war包放到Tomcat/webapps下Servlet訪問(wèn)時(shí)404注解WebServlet的URL路徑寫錯(cuò)或web.xml里沒有正確配置映射確認(rèn)注解路徑以/開頭比如WebServlet(/dishServlet)訪問(wèn)時(shí)500 ClassNotFoundExceptionJDBC驅(qū)動(dòng)jar不在WEB-INF/lib下把jar復(fù)制進(jìn)webapp/WEB-INF/lib后Rebuild Artifact中文亂碼頁(yè)面編碼、請(qǐng)求編碼、數(shù)據(jù)庫(kù)編碼不一致統(tǒng)一設(shè)置JSP頁(yè)面pageEncodingUTF-8Servlet里request.setCharacterEncoding(UTF-8)Filter全局接管訪問(wèn)jsp頁(yè)面直接變成源碼下載Tomcat沒有配置JSP支持檢查是否誤把JSP文件放到了webapp/static或直接用瀏覽器訪問(wèn)了未編譯的源文件報(bào)錯(cuò)端口被占用Tomcat默認(rèn)8080被其他程序占用用netstat -ano還有一個(gè)特別隱蔽的問(wèn)題IDEA重新部署項(xiàng)目時(shí)常常報(bào)“Address localhost:8080 is already in use”。這是因?yàn)橹安渴鸬腡omcat實(shí)例沒有正常關(guān)閉殺進(jìn)程時(shí)注意看java.exe進(jìn)程直接全殺容易誤傷IDEA自身我建議用netstat -ano查出監(jiān)聽8080端口的PID再taskkill /PID xxx /F。6. 實(shí)操過(guò)程實(shí)錄 —— 跑一遍核心流程看看每一步做了什么6.1 從建庫(kù)建表到后臺(tái)發(fā)布菜品的完整流程拿一臺(tái)全新的Windows機(jī)器舉例整個(gè)流程分七個(gè)步驟第一步安裝MySQL并啟動(dòng)服務(wù)。ZIP包解壓后在bin目錄執(zhí)行mysqld --install和net start mysql然后命令行執(zhí)行mysql -uroot -p登錄執(zhí)行建庫(kù)語(yǔ)句CREATE DATABASE food_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;。選擇utf8mb4而不是utf8的原因是utf8mb4能存emoji和生僻字早餐店鋪名和菜品里可能出現(xiàn)的特殊符號(hào)不會(huì)變成亂碼。第二步執(zhí)行表結(jié)構(gòu)SQL建表。依次執(zhí)行分類表、菜品表、用戶表、訂單主表、訂單明細(xì)表的建表語(yǔ)句然后插入測(cè)試數(shù)據(jù)。比如INSERT INTO category(name, sort_order) VALUES (粥品, 1), (煎餅, 2), (豆?jié){油條, 3); INSERT INTO dish(category_id, name, price, stock, status) VALUES (1, 皮蛋瘦肉粥, 6.00, 50, 1), (2, 加蛋煎餅, 8.00, 30, 1), (3, 豆?jié){, 2.00, 100, 1);第三步在IDEA里創(chuàng)建JavaWeb項(xiàng)目配置好Tomcat第四步編寫實(shí)體類。Dish實(shí)體類要包含所有表和前端展示需要的字段注意originalPrice和categoryName這類冗余展示字段可以加上——它對(duì)應(yīng)分類表的一對(duì)一關(guān)聯(lián)通常用JOIN查詢時(shí)在DAO層手動(dòng)組裝。第五步編寫JDBC工具類和DAO層第六步編寫Servlet層和JSP頁(yè)面第七步啟動(dòng)Tomcat訪問(wèn)http://localhost:8080/food_web/查看菜單頁(yè)。后臺(tái)發(fā)布菜品的流程管理員登錄后進(jìn)入/admin/dish_list.jsp點(diǎn)“新增菜品”填寫基本信息。這里圖片上傳是個(gè)必做的功能我建議先把圖片文件保存到webapp/upload目錄數(shù)據(jù)庫(kù)只存“上傳后返回的文件名”。實(shí)際上傳用ServletFileUpload解析multipart表單一個(gè)隱藏坑是Tomcat的默認(rèn)post體大小限制——maxPostSize默認(rèn)2MB早餐菜品圖片一般不大但也要注意如果上傳超過(guò)2MB的圖片會(huì)直接拋異常需要到conf/server.xml的Connector標(biāo)簽里設(shè)置maxPostSize-1-1表示不受限。6.2 顧客端模擬下單流程顧客打開首頁(yè)看到分類導(dǎo)航欄和菜品列表點(diǎn)“加入購(gòu)物車”按鈕。這里需要注意的是未登錄用戶點(diǎn)擊加購(gòu)時(shí)Filter會(huì)攔住并跳到登錄頁(yè)但URL參數(shù)丟失登錄后不會(huì)自動(dòng)回到加購(gòu)動(dòng)作。我的改進(jìn)方案是跳轉(zhuǎn)登錄頁(yè)前把原始請(qǐng)求URI存入Session登錄成功后sendRedirect回去session.setAttribute(returnUrl, request.getRequestURI() ? request.getQueryString());這樣用戶登錄一次就能回到剛才瀏覽的位置體驗(yàn)好不少。登錄后繼續(xù)加購(gòu)右上角購(gòu)物車角標(biāo)從0變1再點(diǎn)進(jìn)去看到購(gòu)物車明細(xì)列表修改數(shù)量后頁(yè)面底部實(shí)時(shí)刷新總金額——這一項(xiàng)我用JS計(jì)算因?yàn)槊總€(gè)菜的小計(jì)和總價(jià)都能從前端數(shù)據(jù)拿到不用每次改動(dòng)都請(qǐng)求后端。然后點(diǎn)擊“去結(jié)算”填寫收貨人、手機(jī)號(hào)、地址、期望送達(dá)時(shí)間。時(shí)間組件我用input typedatetime-local好處是瀏覽器自帶原生選擇器后端解析時(shí)用SimpleDateFormat按yyyy-MM-ddTHH:mm格式處理。提交訂單后頁(yè)面跳轉(zhuǎn)到支付模擬頁(yè)顯示訂單號(hào)和應(yīng)付金額點(diǎn)擊“模擬支付”按鈕Ajax請(qǐng)求后端把訂單狀態(tài)從0改成1頁(yè)面顯示“支付成功店鋪備餐中”。整個(gè)流程在后端做了什么提交時(shí)事務(wù)里插了主表和明細(xì)表扣了庫(kù)存清空購(gòu)物車支付時(shí)只更新訂單狀態(tài)字段一個(gè)UPDATE搞定。早餐店場(chǎng)景不需要真實(shí)接支付接口這個(gè)模擬流程已經(jīng)把業(yè)務(wù)閉環(huán)打通了。6.3 管理員端訂單處理流程管理員登錄后看到待處理訂單列表每個(gè)訂單顯示訂單號(hào)、用戶、餐品明細(xì)、總金額、期望送達(dá)時(shí)間。點(diǎn)擊“確認(rèn)接單”按鈕后端把status 1改成status 2。再點(diǎn)“完成配送”status 2改成status 3。這里有一個(gè)實(shí)際操作中的體會(huì)管理員頁(yè)面最好用定時(shí)刷新或手動(dòng)刷新方式更新列表不用做WebSocket實(shí)時(shí)推送。早餐店高峰時(shí)段可能同時(shí)來(lái)十幾個(gè)訂單管理員每接一單刷新一下頁(yè)面完全夠用WebSocket的實(shí)時(shí)性在這個(gè)場(chǎng)景里是偽需求還引入一堆復(fù)雜度。如果真想提升體驗(yàn)可以加一個(gè)前端定時(shí)器每分鐘自動(dòng)location.reload()或者用AJAX輪詢刷新訂單數(shù)量角標(biāo)實(shí)現(xiàn)簡(jiǎn)單效果也尚可。6.4 數(shù)據(jù)統(tǒng)計(jì)校驗(yàn)后臺(tái)統(tǒng)計(jì)頁(yè)要顯示每日營(yíng)收曲線和熱銷菜品榜。菜品類銷量我依賴訂單明細(xì)表里的quantity字段SELECT dish_name, SUM(quantity) AS total_sales FROM order_item WHERE order_id IN ( SELECT id FROM orders WHERE status IN (1,2,3) ) GROUP BY dish_name ORDER BY total_sales DESC LIMIT 5;這種SQL在數(shù)據(jù)量小的時(shí)候性能沒問(wèn)題。等訂單積累到萬(wàn)級(jí)子查詢的性能瓶頸會(huì)出現(xiàn)優(yōu)化方向是把統(tǒng)計(jì)邏輯拆到獨(dú)立報(bào)表表里每天夜里定時(shí)匯總。但在課程設(shè)計(jì)和創(chuàng)業(yè)初期完全夠用不必過(guò)度設(shè)計(jì)。7. 常見問(wèn)題與排查技巧速查表7.1 高頻報(bào)錯(cuò)的一線解決方案列舉一下我實(shí)際跑這個(gè)項(xiàng)目時(shí)遇到、以及幫別人排查過(guò)的最典型問(wèn)題直接按表格查就行癥狀根因處理方式j(luò)ava.sql.SQLException: Access denied for user rootlocalhost密碼錯(cuò)誤或root賬號(hào)授權(quán)問(wèn)題在命令行用mysql -uroot -p重設(shè)密碼或執(zhí)行ALTER USER rootlocalhost IDENTIFIED BY 新密碼;The server time zone value ... is unrecognized連接串沒指定時(shí)區(qū)連接串加serverTimezoneAsia/ShanghaiMySQL 8.0時(shí)加useSSLfalseallowPublicKeyRetrievaltrue中文亂碼多層編碼不一致Filter里統(tǒng)一request.setCharacterEncoding(UTF-8)JSP頂部pageEncodingUTF-8MySQL表字段用utf8mb4表單提交后原子性問(wèn)題沒有開啟事務(wù)Service層包事務(wù)確認(rèn)DAO方法復(fù)用同一個(gè)ConnectionTomcat運(yùn)行后無(wú)法訪問(wèn)項(xiàng)目頁(yè)面Artifact配置錯(cuò)誤IDEA里Project Structure → Artifacts → 確保輸出類型為war explodedDeployment里Application context填/MySQL 8.0連不上報(bào)Public Key Retrieval is not allowed8.0默認(rèn)認(rèn)證插件連接串加allowPublicKeyRetrievaltrue或創(chuàng)建MySQL用戶時(shí)指定mysql_native_password7.2 SQL層面的隱蔽坑早餐外賣系統(tǒng)的SQL并不復(fù)雜但幾個(gè)隱蔽問(wèn)題非常值得記錄。第一個(gè)是DELETE FROM orders WHERE id?這種刪除訂單的SQL一旦訂單有明細(xì)表關(guān)聯(lián)刪除主表會(huì)產(chǎn)生孤兒明細(xì)數(shù)據(jù)。項(xiàng)目里我的策略是不做物理刪除用status4已取消標(biāo)記后臺(tái)列表默認(rèn)過(guò)濾掉但數(shù)據(jù)完整保留。第二個(gè)是分頁(yè)排序混亂問(wèn)題如果一個(gè)頁(yè)面上菜品數(shù)據(jù)多次插入沒有明確的ORDER BY idMySQL返回順序可能隨機(jī)且不穩(wěn)定。所以我分頁(yè)SQL統(tǒng)一加ORDER BY id ASC避免用戶翻頁(yè)時(shí)看到菜品順序跳變。第三個(gè)是COUNT(*)和COUNT(1)的選擇——在這類小項(xiàng)目里性能差異可忽略但注意COUNT(column)會(huì)忽略NULL列統(tǒng)計(jì)訂單數(shù)量時(shí)如果列有NULL值就容易數(shù)錯(cuò)直接用COUNT(*)最穩(wěn)妥。7.3 前后端聯(lián)調(diào)時(shí)的數(shù)據(jù)格式問(wèn)題后端Servlet返回?cái)?shù)據(jù)給前端JavaScript時(shí)通常用JSON格式。我用的工具是阿里的Fastjson或者Google的Gson在Java里JSON.toJSONString(resultMap)然后通過(guò)response.getWriter().write(json)輸出。JSP的script塊里接收時(shí)有一個(gè)編碼陷阱如果JSP本身contentTypetext/html; charsetUTF-8但Servlet響應(yīng)的Content-Type沒設(shè)置前端JSON.parse可能因?yàn)榫幋a問(wèn)題解析失敗。穩(wěn)妥做法是Servlet端每次返回JSON都設(shè)置response.setContentType(application/json;charsetUTF-8);前端拿到中文后不用手動(dòng)轉(zhuǎn)碼JSON標(biāo)準(zhǔn)要求UTF-8。8. 從JSPServlet到框架的思維遷移如果這個(gè)系統(tǒng)你已經(jīng)完整寫過(guò)一遍我建議你做三個(gè)后續(xù)的小實(shí)驗(yàn)用最小的成本感受框架演進(jìn)思路。第一個(gè)實(shí)驗(yàn)把DishServlet的一個(gè)action方法改成Spring MVC的RequestMapping寫法對(duì)比一下URL映射和參數(shù)獲取的異同。你會(huì)發(fā)現(xiàn)Spring MVC的RequestParam本質(zhì)就是request.getParameter()的封裝ModelAndView本質(zhì)就是request.setAttribute() forward的封裝。第二個(gè)實(shí)驗(yàn)把JDBC手動(dòng)事務(wù)改成聲明式事務(wù)感受一下Transactional為什么能減少重復(fù)代碼。手寫事務(wù)要每次開連接、提交、回滾聲明式事務(wù)只用加一個(gè)注解底層是用AOP動(dòng)態(tài)代理做的同一件事。第三個(gè)實(shí)驗(yàn)把Session購(gòu)物車改成Redis緩存購(gòu)物車對(duì)比Session方案和獨(dú)立緩存方案的差異。Session方案天然綁定單臺(tái)服務(wù)器Redis方案可以讓用戶請(qǐng)求打到不同后端節(jié)點(diǎn)而不丟購(gòu)物車數(shù)據(jù)。這個(gè)對(duì)比做完后你會(huì)對(duì)無(wú)狀態(tài)設(shè)計(jì)和水平擴(kuò)展有切身理解。每次從老技術(shù)遷移到新技術(shù)時(shí)試著在代碼注釋里標(biāo)注“這個(gè)注解背后做了哪些事如果不用框架我會(huì)怎么寫”——堅(jiān)持這樣一個(gè)習(xí)慣技術(shù)底子會(huì)打得很扎實(shí)。我見過(guò)太多只會(huì)在Spring Boot里寫RestController、但連HTTP請(qǐng)求是怎么被Servlet容器接住的人。早餐外賣項(xiàng)目這種“裸寫”機(jī)會(huì)其實(shí)是性價(jià)比極高的自我訓(xùn)練。最后分享一點(diǎn)個(gè)人看法技術(shù)選型要看場(chǎng)景課程設(shè)計(jì)和畢業(yè)設(shè)計(jì)寫JSPServlet不是落后而是用最小的復(fù)雜度看清整個(gè)Web請(qǐng)求鏈路。你在IDEA里按部就班搭一次這個(gè)系統(tǒng)把Session透?jìng)鳌⑹聞?wù)邊界、Filter攔截這幾塊真正吃透再去學(xué)Spring Boot效率能翻倍。上面這些坑我基本都踩過(guò)一遍寫下來(lái)算是給后來(lái)者省點(diǎn)時(shí)間照著做應(yīng)該能少走不少?gòu)澛贰?
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
大香蕉在线SuP| 久久久性爱| 大香网站| 成人日韩3| 大香交| 狠狠色婷婷7777久| 国产精品欧美日韩久久| 97久久久久久久精| 成人看片网站| 91色久| 乱伦图av| 人人操 欧美| 青青草大香蕉视频| 毛片久久| 久久久久久九九九| 91色狼| 久久视频,这里只有精品| 日韩亚洲美女一区久久| 午夜免费视频1000| 国产按摩一区二区三区| 欧美亚洲日韩人妻在线观看| 久久久国产三级黄色片| 国产精品自拍欧美在线| 日逼视频日本| 夜色AV无码手机在线影院| 青娱乐福利99| 韩国免费播放一级毛片| 北约熟女超碰| 日日操丁香五月天| 久久精品欧美一区二区三区不卡| 国产亚洲精品无码三区| 亚洲av无码成电影在线播放| 老熟女乱伦片| 你懂的在线观看区国产| 男女性无套 免费九一| 91熟女丨91老女人| 人人弄人人摸| 无码高清少妇久久| 黄色激情电影在线观看| 男人的天堂日韩| 熟女欧美日韩综合婷婷| 亚洲国产青青| 人妻少妇久久中文字幕一区二区 麻豆| 特污精品女优骚货黄色视频在线免费观看| 91制服丝袜| 狠狠97| 東南亚性呦成人伦理资源在线视频| 免看60秒涩涩视频| 国产精品人妻无码久久久互動交流| 大香蕉草草| 亚洲动态色图| 久久国产在线一区二区| 色在线综合| 伊人久久综合影院| 噜噜吧,噜噜色,噜噜| 亚洲操人| 成 人 影视 一区 二区 三区 四区| 伊人AAA| 精品国产少妇高潮视频| 狠狠亚洲| 97资源亚洲| 久草这里只有精品| 久久黄色性爱视频| 三级片网站在线播放| 色爱综合网| 啊啊啊啊啊啊啊国| 亚州男人的天堂| 色婷婷一区二区三区久久午夜成人不| 老司机福利青青草| 精品v日韩欧美国产| 天色综合网| 操淫穴亚洲五月丁香| 9久9久9久9久视频网站| 欧美传媒| 艹我哪美一区无码| 欧美999999| 日产精品久久久一区二区| 中文字幕三四五区| 开心激情婷婷| 欧美亚洲宗合色性图| 欧美丝袜91| 美女操逼A A| 欧美黑人精品一区二区| 91在线美女| 人妻熟女一区二区| 明星性猛交ⅹxxx乱大交| 国产精品视频自拍在线| 国产肏屁眼视频| 欧成人在线| 欧美日韩大黄片| 亚洲国产激情国产av| 久久久久久91香蕉国产| 久久久新亚洲AV| 日韩AV无码中文一区二区| 日本熟妇熟色97一本在线观看| 樱花草社区www中国| 国产精品禁久久久精品| 中文字幕国产| 黑人精品久久97| 色欲av国内精品久久久久久| 丁香五月激情综合| 欧美淫乱视频| 国产精品区在线12p| 亚洲久热| 99re黄| 日本一级二级三级网站| 足交视频老司机| 国产美女在线精品免费看| 色婷婷香蕉| 亚欧美综合网。| 国产精品福利资源在线尤物| 射 色综合| 国产欧美另类久久久精品课程| 日本欧美一区二区三区免费| 色香在线| 成人三一级一片aaa| 偷拍欧美激情| 欧美一级美片在线观看免费| 亚洲色香| 久久人人爽爽人人爽人人片αV| 日韩天美| 国产黄色影片在线观看| 97 国产精品| 色在线亚洲视频www| 歐美一級亂黃99在綫精品| 熟女精品日韩一区二区三区 | 五月色综合| 国产精品91ai| 亚洲国产ⅴ高清在线观看| 欧美色图天堂在线| 香港澳门日本三级网站| 男人干美女| 校园春色 欧美| 亚洲情色五月天| 日本孕妇一区二区视频操逼免费看 | 国产精品91一样| 97久久久久| 婷婷色影院| 加勒比aⅴ| 五月丁香婷婷啪啪| 熟妇综合一区二区三区| 亚洲中文电影| 国产吞精a级片激情电影| 天天拍天| 亚洲一区二区麻豆影院| 丰满岳乱妇一区二区三区| 亚洲s色图| 久久精视频美日韩在线视频| 欧美大的香蕉有线电视视频| 天天操美美| 秋霞蝌科网日本一区| 丝袜美腿丝袜| 久久伊人网视频一区二区三区| 亚洲欧洲无码bt精品合集| 大香蕉伊在线久草麻豆天堂故事| 激情综合网激情五月天| 国产亚洲欧美每日在线| 九九九精品美女| 超碰天天操| 国产精选三级在线观看| 欧美高清18A片| 美女干逼2| 国产成人无码网站在线视频| 人人搞人人插人人操| 爱爱久久| 蜜桃久久久久久久| 色香色欲天天综合网天天来吧| 人人操欧美风骚| 一级黄碟| 欧美暴力猛交| 欧美视频在线第3页| 欧美另类综合久久| 9丨亚洲一区二区在线| 91大香蕉伊人| 欧美日韩国产人人| 精品人妻夜夜草| 乱伦系列一区二区| 精品人妻中文字幕4399| 亚洲欧洲自拍| 久久久偷拍| 91色色综合| 哈哈操电影AV| 中文字幕在线观看第二页| 亚洲AV无码黄色强奸| 69XX一中文字幕人妻91| 亚洲久9| 色五月AV在线| 久久久久久裸体| 欧美性爱一区| 美女高潮视频91| 久久久婷| 亚洲色图大香| 久久黄黄| 天天综合网国产| 欧美性爱一级操| AA级电影三区| 一中国女人毛片水真多| 蜜臀一区二区三区在线 | 欧洲综合无码| 黄色人人| 啊啊好多水| 大香蕉碰碰| 首页亚洲国产高跟丝袜诱惑视频| 强奸xx国产| 欧美日韩精品一区二区三区高清| 久操com| 色翁荡息又大又硬又粗又爽| 中文?日韩?免费?精品| 丝袜综合网| 天堂性色| 国产日韩手机视频在线| 熟女这里只有精品6| 天天激情综合站| A片A5445444| 国产一级内射无挡观看| 91艹B视频| av日韩手机在线影视| 大香蕉视频一二三区| 亚洲欧洲日本精品中文a∨| 天天上日日上日韩精品| 正在播放国产精品一区| 五月天玖玖资源站| 综合色99| 动漫片子网站3黄| GVH-003 母子姦 青木玲-麻豆视频,麻豆视传媒短视频网站入口,麻豆视传媒官网直 | 美女裸体无遮挡永久免费观看网站| 97chaopengongkai| 26UUU欧美日本| 秋霞久久亚洲精品成人| 国产精品岛国片在线观看| 天天看,天天做| www.狠狠干.coom| AAAA级日本片免费视频| 国产午夜福利电影免费在线观看 | 激情丁香五月| 日韩激情视频| 啊啊啊慢点| 欧美色乱| 能在线播放的国产三级| 天天综合网国产| 老师充足的奶水小说| 日韩钢筋无码高清啾啾啾| 中文熟女五十乱码在线| dy888午夜老子影视达达兔| 色婷婷六月丁香七月婷婷| 亚洲精品影视老司机| 激情久久久| 大香蕉在线86| 黄页av| 国产精品无码久久久久2025| 五月天大香蕉| 欧美暴力猛交| 免费视频一二三区| 乱伦图av| av亚洲天堂资源网站| 久久久无码精品人妻二区| 一起草三级AV电影在线观看 | 亚洲自拍一区夜夜操| 怡红院久久老司机| 超碰国产精品久| 亚洲激情综合| 综合色区偷拍| 人人操人人摸人 | 欧美第五页| 欧美18 在线观看| 亚洲乱码尤物193YW| 国产怡红院| 91欧美少妇| 国产女同视频在线播放| 亚洲人精| 超碰九区| 欧美性爱五月天| 精品九九淫乱男| 天天影视色香欲综合网小说| 久99热| 国产精品网站www| 国产久久久久久| 性爱1区| 欧美熟女妇同| 男女激情黄色网址| 亚洲情色一区二区三区| 亚洲国产欧美一区二区潘金莲| 少妇超碰在线| 人人操人人肉久久精品| 激情五月天视频| 日本久久久精品电影| 午夜亚洲WWW湿好大| 色色色综合网| 亚州性色| 欧美色图亚洲色图成人在在线| 亚洲午夜精品久久久中文影院| 精品国产91av一区二区三区 | 日日干天天干夜夜爽| 色97| 91综合色| 欧美美女在线高潮999| 欧美高清第一页| 欧美一区91大爱| 天美传媒AV在线| 亚洲精品一区中文字幕乱码| 夜夜躁狠狠躁日日躁av| 日本久久久久久久久| 97在线观| 精品久久久久瑟瑟| 大香蕉www.超碰| 天天日天天操VV| 伊人精品久久网站| 超碰综合97在线| 99天堂网| 中文精品一区二去| 美女天天干| 99热久| 超碰在线一区二区三区| 日韩一999精品| 狠狠色噜噜狠狠狠狠2018| 久久久久9999妇女| 五月婷婷爱六月丁香色| 久久精品久| 东北女人被操| 日本片日本片祼观看网站在线看中文版网页在线看 | 992视频一区| 夜夜中出国产| 欧美黄色片在线播放| 中文字幕在线2| a级理论午夜日本| 亚洲日韩美女丝袜美腿人妻视频| 91日日| 国产成人无码高清| 懂色中文一区二区三区| 欧美激情 亚洲色图| 一本一道人妻久久一区二区三区 | 五月天我淫我色av| 五十路成人在线视频二区三区| 日本亚洲熟女视频| 国产精品分类在线观看| 91欧美少妇| 伊人久久国产免费观看视频| 美女一区二区国产精品| 国产精品操| 999 久久久| 日本熟妇一区二区三区| 午夜一级免费毛片| av网站免费看| 啊啊啊啊免费视频| 日韩丝袜高跟制服在线观看| 蜜臀久久一区二区| 高清无码 国产精品| 综合 亚洲 欧美| 330dv亚洲成年视频网| 色综合色色| 午夜.DJ高清在线观看免费7| 中文字幕精品码亚洲| 制服诱惑亚洲一区二区三区在线观看| 少妇超碰在线| 亚洲第一成人影院色播| 中文字幕国产| 一区二区免费电影久久| 色玖玖| 一级做a爰片久久毛片图片| 一二三区视频在线观看| 亚洲日本大香蕉1| 性爱欧美五月| 人妻内射一区二区在线视频| 国产蜜臀精品一区免费尤物| 国产精品老师| 亚洲欧美国产其他二区| 特级丰满少妇一级AAAA爱毛片| 色综合一本| 1区2区3区视频| 清纯唯美综合| 欧美 日韩第一性色| 国产乱码精品久久久久久| 欧美中文字幕男人天堂久久精品| 大香蕉伊人色偷偷在线| 激情婷婷五月天| 久久亚洲婷婷| 曰韩av中文字幕专区| 狼狼色丁香久久婷婷综合五月| 无码国产精品96久久久久孕妇| 亚洲无码一区成人免费午夜 | 国产在线精品偷| 亚洲啪啪视频一区二区| 男人的天堂一区三区| japan日本高清乱xxxx| 三级特黄60分钟播放| 日本 色 导航| 日本激情免费大片| 欧美人妻一区| 人妻av在线| www.yw尤物| 91美女丝袜诱惑视频| 天天色综合图片| 亚洲图片欧美91N| 日本韩国一本产品小视频日本韩国一本产品久久久产品小视频日本韩国一本产品久 | 久久精品人妻一区| 国产成年女人免费视频播放a| 国产欧美日本亚洲精品| 国产黄色小视频网站| 欧美一级美片在线观看免费| 国产精品熟女九色九色蜜臀| 熟妇操花| 91亚洲黑人| 嗯嗯嗯嗯啊啊啊好紧好大| 一区,二区,三区网站| 欧美色图亚洲特色| 香蕉色网| 九九亚洲| 无码丰满熟妇一区二区浪潮AV| 国产中文精品一区二区在线观看| 国产CHASE男男GAYGA 毛多色婷婷| 九九黄色网| 男人的天堂成人的社区| 色九九九综合| 中文字幕在线免费观看 | 成人av免费观看| 99热综合在线| 亚洲精品1区| 91白虎| 国产强奸乱伦无码视频| 91三级理论片播放器| 91久久久久久| 九九自拍伦理| 伊人超碰97| 国产操伦| 乱日视频| 热热色综合网| 亚洲 欧美 日韩 国产一区二区 | 97在线免费公开视频| 久久9久| 午夜啪啪片| 91色情黑丝搞鸡在线观看一区二区三区三州 | 欧美激情久久久久| 日韩色| 亚洲精品无码成人久久久99| 国产少妇与亚洲av| 舔人妻中文免费视频| 美国日韩黄片| 国产亚洲一黄| 国产精品动态一区二区三区四四| 影音先锋每日最新资源在线观看| 激情五月综合| 夜夜嗨TV| 人人妻人人色| 凹凸视频在线一区二区| 亚洲成av人片色午夜乱码| 神马午夜久久久| 极品肉射| 91蜜桃婷婷狠狠久久综合9色| 一本一首道人妻少妇免费久久| 成人国产二区三区在线,男女精品。| 黄片视频,下载| 顶级少妇BT天堂| 中欧人妻丝袜中文字幕| 99色在线| 亚洲高潮影院| 黄色片大香蕉| 日韩内| 欧美日韩性爱视屏免费看了| AV色五月天| 操逼片国产| 欧美日本天堂| 影视综合无码少妇| 色超碰综合| av网站在线观看了| 久久日本熟女精品一区| 欧美日韩电影成人在线| 四虎884a| 黄页网站免费高清在线观看| 小骚逼被操的爽不爽| 国产三级在线现体验区| 99www.bibizy香蕉资源国产一区二区三区高清 | 97一区二区三区视频| 国产精品不卡一区二区三区av| 日夜啪电影| 超碰免费人妻在线| 宅男91视频在线播放| 草草草视频在线免费看| 97碰碰日本乱偷人妻中文的| 国产传媒操逼视频| 夜夜国自区| 久热大香蕉| 91性情| 精品视频123区小说区| 大学生美女口爆| 综合网亚| 欧美亚洲日本激情在线| 四方色播| juliaann丝袜大战黑鬼| 亞洲久久直播| 亚洲成人ab| 日韩欧美加勒比| 久操99| 在线一道啪| 91天美免费| 嗯啊不要在线| 久操凹凸视频| 另类欧美色| 大香蕉十区| 可以在线观看AV的网站| 国产精品久久久久久久久久久久久久吹 | 一本一道波多野毛片中文在线| 97超级色碰碰| 日韩紧密久久| 999国产精品999| 91亚洲欧美| 91天天爱| 亚洲一区日韩| 久久精品福利影院| 91劲爆| 麻豆视频test| 国产亚洲精品农村妇女| 九九操久久国产免费视频| 97se综合网| 美女网站黄页| 校园春色欧美色图| 日本Suv精品一区二区| 人妻久久久久久久久久久久久久久 | 亚洲精品骚逼| 日本肉体xxxx裸交| 日本欧美一区二区三区视频麻豆| 亚洲少妇激情一区二区三区| 亚洲综合另类欧美久久久| 天堂а√在线最新版在线| 欧美日日夜夜| 99性爱视频| 久久久精品电影| 性欧美91| 日本熟妇色熟妇在线视频播放| 少妇滛荡视频| 色眯眯射| 十八禁视频网站| 无码不卡亚洲成?人片| 亚洲伊人青青草| 67194无码不卡| 强奸乱伦亚洲第一页| 亚洲欧美在线丝袜| 天美一区在线| 69人妻精品丰满熟女区| 啊啊啊操一区| 亚洲一区二区性爱电影| 人人操人人操草草| 色屁屁影院www国产| 性欧美| 亚洲欧美一区二区不卡视频播放| 日韩免费人妻色情网站| 激情五月综合| 日日碰狠狠添天天爽超| 亚洲一区二区三区中文字幕| 无码精品久久| 中日韩免费看男女操逼大全| 欧美色图人妻| 亚洲日韩XXX| 欧美狠狠弄| 久久久久久久 九九九九九九九| 国产精品自在自拍视频| 脫衣舞一区二区三区| av在线播放国产一区| 中文字幕三四区| 青青久久艹| 青青草中出视频| 另类成人首页一区| 夜夜爽夜夜摸夜夜操免费视频| 91中文精品日韩欧美在线| http://qxhbdz.com| 天堂av2019| 日韩成人色图| 天天α片| 日韩丝袜高跟制服在线观看| 久操九九九九九九九九九九九九九九九九九九九九九九九九九九九九 | 国内一级精品| 日本二区不卡| 综合网 欧美| 熟女人妻精品一区二区视频| 欧美高清色| 日本不卡一区| Sekablack无码一区| 又大又长又粗又爽又黄| 中文字幕亚洲热播人妻| 夜色AV无码手机在线影院| 立川理惠无码一区二区| 99综合免费视频| 九九热免费国产视频婷婷伊人| 日日夜夜天天| 少妇99成人麻豆| 欧美精品97| 亚州男人天堂| 黄色免费一级在线毛片| 少妇干B| 五月激情视频| 欧中日成人免费影视| 黄色不卡视频| 91九色丰满高潮| 日韩猛交| 国产午夜福利电影免费在线观看| 特级丰满少妇一级AAAA爱毛片| 日韩丝袜二区| 婷婷日韩一区二区三区中文字幕在线| 60秒试看最爽10分钟网站| 久草精品视频| 97干97色| 久久综合资源一区二区| 婷婷视频网| 伊人久久大香线蕉亚洲五月天,青草青草欧美日本一区二区,欧美日产欧美日产国产 | 淫荡网址| 久久精品欧美一区二区三区不卡| 久久激情五月| 久久熟妇五十路一区| 桃色人妻在线视频| 欧美狠狠| 日韩乱中文| 美腿色图| 超碰九九| 色欲av一区二区三区蜜芽| 91日本在线观看| 白丝AV网站| 极品色综合| 7777奇米影视久久| 婷婷精品| 色哟哟av| 激情无码日韩| 久久精品天美| 992视频一区| 日韩操啪| 久久久久久久 九九九九九九九| 97网址97| 亚洲成人免费中文字幕| 嗯嗯嗯啊啊啊在线免费观看| 长久操视频| 久久久久久久人妻丝袜| 国产欧美日韩在线不卡第一页| 中国黑人三级片网站上区| 竹菊影视国产一区二区| 国产成人主播| 探花精品 一区二区| 国产精品午夜高潮呻吟久久av| 2019AV天堂| 男人天堂电影院| 好吊妞转入那个网| 97资源站国产精品| 日韩精品 视频一区二区| 久久久久久久国产| J?P?NESEHD熟女熟妇伦| 欧美日韩人人精品| 久草午夜| 日韩黄色成人性爱| 青青草影视蜜久久| 自拍偷拍 日韩无码| 97精品97久久| 久久久久亚洲?V片无码V| 国产 大胆 对白| 岛国福利在线精品播放| 日韩欧亚太美不卡| 激情五月综合开心五月| 久久久久精| www.av家庭乱伦| 1区2区3区在线视频| 美女久久久| 久久人妻视频网| 天天夜夜rb| 极品色社| 在线视频亚洲无码| 超碰 av 女人天堂| 国产不良强奸视频免费看| 亚洲 中文 女同| se吧提供91精品国产91久久久久久 | 天天干天天爽| 成人怡红院| 日韩精品99999| 欧美宗合色| 人妻一区久久二区三区色播| 亚洲国产精品V?在线播放| 加勒比日本在线| 白天啪啪晚上啪啪视频| 情色五月天久久久| 国产精品香蕉热久久新品| 日韩精品三级片长长久久| 伊人网综合在线视频| 久操| 婷婷成人五月天| 欧美三四五区| 人妻熟女午夜精品在线| 1人人看人人摸人人操| 校园春色综合香蕉| 丁香六月婷婷久久综合| 国产成人亚洲精品自产在线| 国产一区二区成人av在线播放| 午夜呻吟欧美| 九月丁香婷婷色| 玖玖久久久| 蜜桃精久三区| 立川理惠加勒比无码| 中文字幕后石码四区五区| 亚码人妻| 青青草中文-久久青草精品一区二区三| 色99999| 夜夜嗨免费视频| 亚洲男人天堂2019| 无码在线亚洲| 91伊人| 精品国产综合久久福利,热99这里有精品综合久久,99热这里只有免费国产精品,精 | 熟女熟妇一区二区三区视频| 丁香六月啪啪| 大香网站| 97爱爱爱| 欧美性色欧美| 久久综合超碰| 岛国小电影| 亚洲熟女av日韩熟女| 国产三级资源在线观看| 麻豆av一区二区| 色天堂综合| 伊人影院在线理论播放| 天天做日日爱夜夜爽| 人人玩人人添人人澡免费| 日韩射图| 久久中文字幕女同性恋一区| 亚洲成人一二三区| 蜜臀久久一区二区| 天天操天天舔| 久久久久亚洲三级电影| 97jingpin| 99热官网| 国产一区二区三区导航| wwwxxx日本爽| 日韩福利电影网| 午夜精品久久久久久久久久久久久 | 天天操天天日天天干| 国产老熟女| 99热思思| 91粉芽高清在线一区二区| 国产不卡免费在线视频| 女人被男人桶爽视频网站| 久久精品| 免费操逼91| 久久9精品| 久久97视频| 天天操熟妇| 欧亚性爱在线视频| 无码高清少妇久久| 久久久久久网址| 欧美人体性爱互联网第一页婷婷日本| 日韩精品午夜操呦呦不卡影院| 黑白配性爱AV成| 亚洲综合一| 亚洲中文字幕一区| 91伊人久久在线| 99在线精品观看视频中文| 色香欲天天天天综合色| A一级色女| 加勒比海成人视频网| 欧美一二三区四五区| 麻豆精品A片免费观看| 欧美制服网站美腿丝袜| 欧美熟妇精品黑人巨大一二三区| 欧洲无码一区二区| 成人综合网 欧美| 麻豆AV一区二区| 九九九久久久久| 欧美中字二区| 天天干夜夜操一区二区| 大香蕉日韩欧美| 天天综合中文字幕 91| 人妻丝袜一区二区三区在线| 亚洲色婷婷久久91| 麻豆综合一区av| 蜜臀久久99精品久久久| 久久国产逼| 性爱综合一区二区| 国产亚洲日本精品在线| 亚洲色图欧美视频| 午夜精品99久久久久传媒| 天天摸天天插天天日| 色网在线| 久久9999| 久久久性| 秋霞久久亚洲精品成人| www99热| 人人手机欧洲亚洲国产人妻| 日韩少妇在线视频| 91精品91久久久久77777| 久久国产成人精品国产成人亚洲| 青青操网| 亚洲av乱伦色图网站| 无码免费一区二区三区啪啪| 91狠狠色丁香婷婷综合久久精品| 伊人大香蕉在线| 亚洲男人的天堂在线看| 人人妻人人玩人人澡人人爽| 综合伊人网12色| 天天色播亚洲综合网站| 水澄无码AV| 综合激情一一91| 91骚熟女| 中日高清无码操逼视频| 蜜桃传媒一区二区亚洲| 亚洲综合校园春色| 偷拍 欧美 日韩| 人人扣人人操| 日韩免费中文字幕视频| 精品一区二区在线针对华人免费观看这里只有精品免费观看 | 亚洲情色视频| 久久亚洲精品成人av| 99热综合在线| 色九九久九九| 日本一区视频在线观看| 亚洲 欧美 中文 日韩超碰| 91少妇香蕉久久精品| 国产强奸乱伦无码视频| 亚洲精品a人片在线观看视| 午夜性| 丰满人妻-区二区三区免费看 | 青青草视频爽一爽| 91久热| 无码av永久免费专区网站| 囯产精品一区二区三区线|亚洲人成无码网WWW动漫|国产精品免费一级... | 久久超碰国产一区二区三区| 亚洲福利中文字幕在线| 欧美视频第二页| 天堂v无码免费视频| 女人高潮抽搐喷水视频网站| 九九国产| 欧美片第一页| 久久久久精| 久久久免费高清中文视频| 亚洲最大的综合性av| 中文字幕在在线观看网站| 国产熟妇 码视频户外直播| 亚洲乱码尤物193YW| 是还免费视频1727我| 人人妻碰人人免费| 蜜桃视频精品一区二区三区| 欧美亚洲今日在线| 日本久久99| 超碰社区97| 日本污ww视频网站| 国产热av| 婷婷色影院| 男人的天堂色偷偷青青草视频婷婷网| 啪啪视频免费在线观看| 日韩欧美亚洲一区二区三区影院| 久久熟女久| 日韩人妻一二三区视频| 好爽免费视频,| 欧美极品性爱天天射| 色拍偷亚洲| 欧美综合国产精品久久丁香| 国产91精品久久久久久久网曝门| 国语精品av| 天天操夜夜操| 国产熟码AV| 婷婷五月天影院| 91熟女视频网| 成人婷婷丁香| 午夜成人爽爽爽爽A片李冰冰| 99热免费| 日韩精品碰碰| 日韩 欧美 国产 麻豆| 丁香五月天激情网站| 久久噜噜噜精品国产亚洲综合| 91粉嫩萝控精品福利网站_精品影音先锋国 | 中文字幕片| 国产精品人妻熟女aⅴ| 激情视频一二三| av天堂手机版追回| 阿姨一区二区免费视频-高清正片西瓜视频下载app-T450AV | 九九玖玖精品| 日韩操逼性鲍| 91精品国| 亚洲激情网一二三四区| 日韩黄片影院| 国产视频大全| 综合婷婷| 91国产操逼视频| 欧美熟女逼久久久久久| 欧洲熟妇xxXx欧美老妇裸体| 国产色产精品在线观看| 日韩精品99久久久久久中文字幕| 国产午夜激片Av毛片不卡| 久久久青草青青国产亚洲免观精品高清完整版_97久久综合区小说区图片区,国精品 | 婷婷情色综合网| 国产色综合亚洲色综合吹潮| 2020中文字幕在线| 天天操天天插| 国产精品嫩草影院免费| 91综合天天看| 男人天堂.AB| 日本道久久综合色色| 91性感在线| 日韩精品国模| 欧美有码激情视频一区二区三区| 天天艹天天日| 久久久亚洲精品中文字幕人妻| 欧美久久久15P| 国产成人精品亚洲日本| 人妻一二三区| 91亚洲图片| 久欲AV| 天天欧美色| 91色色色| 97操B| 日韩综合97P| 干b在线性社区| 综合色色网| 日本Xx性爱| 男女一进一出视频久久| 欧美激情亚洲| 国产精品网站www| 亚洲天堂人妻一区二区| av日韩在线观看电影| 国产精品嫩草影院午夜两性| 2017天天操天天日| Aa东京男人的天堂| AV一二区| 青娱乐亚洲热| 激激五月| 911粉嫩人妻| 中日韩久久久| 中文字幕人妻丝袜乱一区三区| 97日视频| 操b网站亚洲无码| 69超碰综合| 正在播放:深夜激情大战,自带黑丝袜全力输出骚穴 | 久久久久久欧美精品se一二三四| 亚洲第一页欧美| 成人黑料社久久| 欧美v亚洲v日韩v最新在线二区| 中国特猛少妇色xxx| 亚州黄站| 中文字幕一区二区无码成人| 人妻熟女一区二区| 亚洲色情在线影视| 女人一区| 亚欧中文字幕在线视频| 91大神电影天堂| 99热精品青草在线| www.狠狠干.coom| 无码免费一区二区三区啪啪| 91蜜臀熟女| 这里只有精品久久| 欧美毛片在线网| 色色色欧美| 国产原创自拍| 男人的天堂亚洲| 午夜激情床戏激情| 日本欧美亚洲高清在线看| 久久久久久久亚洲Av无码| 囯产操逼片| 午夜福利精品| 日韩人妻一区二区精品| 欧美成人性爱视频免费观看| 国产超碰人人爽人人做| 日本视频一区二区三区| 国产AV高清AV无码| 这里只有精品久久| 920日本午夜免费| 91 丝袜在线| 草久久久| 91精品操美女| 青青草一区二区高清无码视频| 欧美色乱| av在线播放国产一区| 色就色综合| 极品白嫩美女白浆成人福利在线看| 久精品无码av一区二免费国产在线观看| 亚洲精品三| 99爱精品| 精品然女一区二区| 超碰社区97| 偷拍盗拍亚洲色图图片| 国产AAAAAABBBBB| 欧美日韩国产三级黄色| 久99| 福利风月五月天影院| Julia Annxxxxx| 日韩精品-原创伙伴| 亚洲中文字幕精品一区| 国产大学生口爆吞精合集| 丰满人妻av一区二区三区| 久超碰在| 99re6国产精品99re| 97在线播放 | 97天堂| 亚洲精品乱码线路中文字幕| 岛国片国产成人亚洲播放| 久久精品美女一区| 大香蕉五月天| 有码人妻系列| 欧美熟妇精品黑人巨大一二三区| 日韩美女高潮喷水视频| 91操熟妇| 亚洲美女精品九九视频| 亚洲精品自拍| 黄色视频特级毛片| 狠狠干狠狠色| 亚洲色性情三级| 伦在线97| 东京太热男人的天堂久久久| 欧美日韩*字幕一区| 婷婷在线视频| 日本蜜桃| 翔田千里AV无码秘 三区| 色牛牛AV| 国产SV一线| 欧美超碰97| 亚洲中文字母在线播放| 人妻大相焦在线| 91色综合| 亚洲性爱无码乱伦av| 香港日本韩国人妇99www.wccm20| 男人的天堂久久| AV网站高清无码在线观看| av大香蕉网站| 超碰99在线| 欧美刺激色黄片免费看| 日韩超碰精品综合| 精品视频一区二区| 26uuu欧美| 97精品97久久| 欧美激情另类一区二区| 懂色AV一区二区三区| 国产伊人精品在线| 国产亚洲日本精品在线| 欧美精品91| 国产精品白领在线观看| 综合色播| 蜜区区视频79| 精品黑人一区二区| 亚洲欧美一区二区不卡视频播放| 国产无码三级视频在线观看| 欧美系列在线一区二区| 成人黄页| 女人 A一级| 亚洲一区二区专区-国产丝袜精品丝袜-成人AV | 久久精品一区二区一8| 欧美色色色| 精品久久97| 亚洲色图日韩精品| 97久久天天综合色天天综合色电影| 伊人久久综合精品欧美| 色狠人在线99| 成人免费看吃奶视频网站| 国产九区| 国产日韩精品无码去免费专区国产| 国产一区二区三区影片| 九九九九免费视频| 18禁中文字幕| 欧美91精彩| 久久精品国产亚洲AV片多多| 久久大陆| 国产无码一二三区| 粉嫩AV一区二区夜夜| 婷婷九月色| 97国产人人| 日本日日色视频| 成人免费毛片| 国产视频大全| 一区二区三区四区免费视频| 97AV在线免费观看| 干婷婷综合网| 97 国产精品| 美国美女AV在线| 欧美伊人久久综合网| 国产十八禁视频| 日韩午夜啪啪视频| 99无码| 亚洲色图 欧美热图 清纯唯美 另类自拍 | 啊a一区在线| 不卡av免费在线网址| 2017大香蕉国产精品久久| 亚欧性爱ab| 香蕉精品二区二区| 91在线视频免费中出| AV天堂国产| 久9综合在线| 欧美大香蕉在线观看| 极品综合| 日韩本不卡视频在线观看| 天天干天天操天天拍| 久久久国产av美女私房| 素人伊尹大香蕉免费下载视频| 亚洲国产欧美日韩人妻日中文| jazzjazz国产精品麻豆| 欧美亚洲综合999| 韩国黄片aaaa| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 久久最新视频免费观看| 亚洲AV无码国产精品久久久久 | 日韩av一级黄片| 国产精品人妻无码久久久老鸭窝| 欧色综合| 婷婷操逼| 91在线超高颜值国产| 九九九九精品在线| 久久只有精品一区二区三区| 国产做?爰片久久毛片?片美国| 亚洲最大无码中文字幕网站| 影音先锋每日最新资源在线观看 | 日韩黄色电影网站| 久久精品国产亚洲5555| 久久色激情一区二区三区| 日韩视频啪啪| 亚洲av综合伊人久久| 色97综合中文字幕| 99re69综合| 欧美性爱五月天| 在线综合 亚洲 欧美中文字幕| 不卡视频一区蜜桃视频 | 男人天堂网站| 日韩精品人妻中文字幕不卡乱码| 天无日色综合| 超碰在线人妻| 伊人五月天激情| 国产精品女aA片爽爽视频| 精品少妇一区二区| 天天看特黄的免费网站| 亚洲操逼网| 秋霞曰韩R级| 黄片www视频免费| 9久9久| 另类成人首页一区| 黄色小说亚洲| 99在线精品视频| 日韩中文字幕二区| 国产亚州高清国产拍精| 国产精品4p在线观看| 女性喷水高潮在线观看| 国产久久久| 亚欧美综合| 国产精品午夜精品| 久久精品视频一区三区小泽玛利亚| 小草三级久久观看| 亚洲情色电影网| 成人欧美一区二区三区黑人一| 黑人无码一区二区| 黄页视频网站野外| 亚洲小电影免费涩涩成人在线高清| 69精品| 爱逼综合| 夜夜骑夜夜操| 青娱乐黄色录像| 农村妇女精品一二区| 91性网| 欧美高清91| 人妻第一页| 欧美懂色综合网| 野狼福利社区| 亚洲天堂一区| 国产精品久久久久久亚洲色欲| 超碰色图| 欧美色图20P| 欧美日韩中文视频播放| 欧美激情激情xxxx欧美专区| 96久久久久久久| 91 丝袜在线播放| 欧美一区二区男人天堂| 久草加勒比一区在线| 亚洲伊人久久综合97| 亚洲av无码成电影在线播放| 99精品国产户外露出| 日韩无码三级影院|